Compare commits
1 Commits
master
...
bump-dev-v
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73e119025f |
29
.github/spellcheck-settings.yml
vendored
29
.github/spellcheck-settings.yml
vendored
@ -1,29 +0,0 @@
|
||||
matrix:
|
||||
- name: Markdown
|
||||
expect_match: false
|
||||
apsell:
|
||||
lang: en
|
||||
d: en_US
|
||||
ignore-case: true
|
||||
dictionary:
|
||||
wordlists:
|
||||
- .github/wordlist.txt
|
||||
output: wordlist.dic
|
||||
pipeline:
|
||||
- pyspelling.filters.markdown:
|
||||
markdown_extensions:
|
||||
- markdown.extensions.extra:
|
||||
- pyspelling.filters.html:
|
||||
comments: false
|
||||
attributes:
|
||||
- alt
|
||||
ignores:
|
||||
- ':matches(code, pre)'
|
||||
- code
|
||||
- pre
|
||||
- blockquote
|
||||
- img
|
||||
sources:
|
||||
- 'README.md'
|
||||
- 'FAQ.md'
|
||||
- 'docs/**'
|
||||
99
.github/wordlist.txt
vendored
99
.github/wordlist.txt
vendored
@ -1,99 +0,0 @@
|
||||
ABI
|
||||
ACLs
|
||||
alloc
|
||||
Allocator
|
||||
allocators
|
||||
antirez
|
||||
api
|
||||
APIs
|
||||
ASYNC
|
||||
asyncRedisContext
|
||||
asyncronous
|
||||
AUTOFREE
|
||||
autoload
|
||||
autoloader
|
||||
autoloading
|
||||
Autoloading
|
||||
backend
|
||||
backends
|
||||
behaviour
|
||||
boolean
|
||||
CAS
|
||||
Changelog
|
||||
customizable
|
||||
Customizable
|
||||
CVE
|
||||
dataset
|
||||
de
|
||||
deallocation
|
||||
ElastiCache
|
||||
extensibility
|
||||
FPM
|
||||
getaddrinfo
|
||||
gmail
|
||||
grunder
|
||||
Grunder
|
||||
hiredis
|
||||
Hiredis
|
||||
HIREDIS
|
||||
hostname
|
||||
IANA
|
||||
IPv
|
||||
IPV
|
||||
keepalive
|
||||
keyspace
|
||||
keyspaces
|
||||
KiB
|
||||
libc
|
||||
libev
|
||||
libevent
|
||||
localhost
|
||||
Lua
|
||||
michael
|
||||
minimalistic
|
||||
namespace
|
||||
NOAUTOFREE
|
||||
NOAUTOFREEREPLIES
|
||||
NONBLOCK
|
||||
Noordhuis
|
||||
OpenSSL
|
||||
Packagist
|
||||
pcnoordhuis
|
||||
PhpRedis
|
||||
Pieter
|
||||
pipelined
|
||||
pipelining
|
||||
pluggable
|
||||
Predis
|
||||
PRERELEASE
|
||||
printf
|
||||
PSR
|
||||
PSUBSCRIBE
|
||||
rb
|
||||
Readme
|
||||
README
|
||||
rebalanced
|
||||
rebalancing
|
||||
redis
|
||||
Redis
|
||||
redisAsyncContext
|
||||
redisContext
|
||||
redisOptions
|
||||
redisReader
|
||||
reusability
|
||||
REUSEADDR
|
||||
runtime
|
||||
Sanfilippo
|
||||
SHA
|
||||
sharding
|
||||
SONAME
|
||||
SSL
|
||||
struct
|
||||
stunnel
|
||||
subelements
|
||||
TCP
|
||||
TLS
|
||||
unparsed
|
||||
UNSPEC
|
||||
URI
|
||||
variadic
|
||||
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
@ -37,6 +37,42 @@ jobs:
|
||||
# TEST_PREFIX: valgrind --error-exitcode=99 --track-origins=yes --leak-check=full
|
||||
# run: $GITHUB_WORKSPACE/test.sh
|
||||
|
||||
centos7:
|
||||
name: CentOS 7
|
||||
runs-on: ubuntu-latest
|
||||
container: centos:7
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
|
||||
yum -y --enablerepo=remi install redis
|
||||
yum -y install gcc gcc-c++ make openssl openssl-devel cmake3 valgrind libevent-devel
|
||||
|
||||
- name: Build using cmake
|
||||
env:
|
||||
EXTRA_CMAKE_OPTS: -DENABLE_EXAMPLES:BOOL=ON -DENABLE_SSL:BOOL=ON -DENABLE_SSL_TESTS:BOOL=ON -DENABLE_ASYNC_TESTS:BOOL=ON
|
||||
CFLAGS: -Werror
|
||||
CXXFLAGS: -Werror
|
||||
run: mkdir build && cd build && cmake3 .. && make
|
||||
|
||||
- name: Build using Makefile
|
||||
run: USE_SSL=1 TEST_ASYNC=1 make
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
SKIPS_AS_FAILS: 1
|
||||
TEST_SSL: 1
|
||||
run: $GITHUB_WORKSPACE/test.sh
|
||||
|
||||
- name: Run tests under valgrind
|
||||
env:
|
||||
SKIPS_AS_FAILS: 1
|
||||
TEST_SSL: 1
|
||||
TEST_PREFIX: valgrind --error-exitcode=99 --track-origins=yes --leak-check=full
|
||||
run: $GITHUB_WORKSPACE/test.sh
|
||||
|
||||
centos8:
|
||||
name: RockyLinux 8
|
||||
runs-on: ubuntu-latest
|
||||
@ -76,13 +112,13 @@ jobs:
|
||||
run: $GITHUB_WORKSPACE/test.sh
|
||||
|
||||
freebsd:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: macos-12
|
||||
name: FreeBSD
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Build in FreeBSD
|
||||
uses: vmactions/freebsd-vm@v1.0.5
|
||||
uses: vmactions/freebsd-vm@v0
|
||||
with:
|
||||
prepare: pkg install -y gmake cmake
|
||||
run: |
|
||||
@ -97,8 +133,8 @@ jobs:
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install openssl redis@7.2
|
||||
brew link redis@7.2 --force
|
||||
brew install openssl redis@7.0
|
||||
brew link redis@7.0 --force
|
||||
|
||||
- name: Build hiredis
|
||||
run: USE_SSL=1 make
|
||||
|
||||
14
.github/workflows/spellcheck.yml
vendored
14
.github/workflows/spellcheck.yml
vendored
@ -1,14 +0,0 @@
|
||||
name: spellcheck
|
||||
on:
|
||||
pull_request:
|
||||
jobs:
|
||||
check-spelling:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Check Spelling
|
||||
uses: rojopolis/spellcheck-github-actions@0.33.1
|
||||
with:
|
||||
config_path: .github/spellcheck-settings.yml
|
||||
task_name: Markdown
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,4 +7,3 @@
|
||||
/*.pc
|
||||
*.dSYM
|
||||
tags
|
||||
compile_commands.json
|
||||
|
||||
@ -1,5 +1,12 @@
|
||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
|
||||
|
||||
OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
OPTION(ENABLE_SSL "Build hiredis_ssl for SSL support" OFF)
|
||||
OPTION(DISABLE_TESTS "If tests should be compiled or not" OFF)
|
||||
OPTION(ENABLE_SSL_TESTS "Should we test SSL connections" OFF)
|
||||
OPTION(ENABLE_EXAMPLES "Enable building hiredis examples" OFF)
|
||||
OPTION(ENABLE_ASYNC_TESTS "Should we run all asynchronous API tests" OFF)
|
||||
|
||||
MACRO(getVersionBit name)
|
||||
SET(VERSION_REGEX "^#define ${name} (.+)$")
|
||||
FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredis.h"
|
||||
@ -17,16 +24,6 @@ MESSAGE("Detected version: ${VERSION}")
|
||||
PROJECT(hiredis LANGUAGES "C" VERSION "${VERSION}")
|
||||
INCLUDE(GNUInstallDirs)
|
||||
|
||||
OPTION(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
OPTION(ENABLE_SSL "Build hiredis_ssl for SSL support" OFF)
|
||||
OPTION(DISABLE_TESTS "If tests should be compiled or not" OFF)
|
||||
OPTION(ENABLE_SSL_TESTS "Should we test SSL connections" OFF)
|
||||
OPTION(ENABLE_EXAMPLES "Enable building hiredis examples" OFF)
|
||||
OPTION(ENABLE_ASYNC_TESTS "Should we run all asynchronous API tests" OFF)
|
||||
# Historically, the NuGet file was always install; default
|
||||
# to ON for those who rely on that historical behaviour.
|
||||
OPTION(ENABLE_NUGET "Install NuGET packaging details" ON)
|
||||
|
||||
# Hiredis requires C99
|
||||
SET(CMAKE_C_STANDARD 99)
|
||||
SET(CMAKE_DEBUG_POSTFIX d)
|
||||
@ -108,11 +105,9 @@ if (MSVC AND BUILD_SHARED_LIBS)
|
||||
CONFIGURATIONS Debug RelWithDebInfo)
|
||||
endif()
|
||||
|
||||
if (ENABLE_NUGET)
|
||||
# For NuGet packages
|
||||
INSTALL(FILES hiredis.targets
|
||||
DESTINATION build/native)
|
||||
endif()
|
||||
# For NuGet packages
|
||||
INSTALL(FILES hiredis.targets
|
||||
DESTINATION build/native)
|
||||
|
||||
INSTALL(FILES hiredis.h read.h sds.h async.h alloc.h sockcompat.h
|
||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)
|
||||
|
||||
9
Makefile
9
Makefile
@ -39,11 +39,7 @@ export REDIS_TEST_CONFIG
|
||||
CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
||||
CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++')
|
||||
OPTIMIZATION?=-O3
|
||||
WARNINGS=-Wall -Wextra -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
||||
USE_WERROR?=1
|
||||
ifeq ($(USE_WERROR),1)
|
||||
WARNINGS+=-Werror
|
||||
endif
|
||||
WARNINGS=-Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
||||
DEBUG_FLAGS?= -g -ggdb
|
||||
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) $(PLATFORM_FLAGS)
|
||||
REAL_LDFLAGS=$(LDFLAGS)
|
||||
@ -141,10 +137,7 @@ endif
|
||||
ifeq ($(uname_S),Darwin)
|
||||
DYLIBSUFFIX=dylib
|
||||
DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX)
|
||||
DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)
|
||||
DYLIB_MAKE_CMD=$(CC) -dynamiclib -Wl,-install_name,$(PREFIX)/$(LIBRARY_PATH)/$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
||||
SSL_DYLIB_MINOR_NAME=$(SSL_LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX)
|
||||
SSL_DYLIB_MAJOR_NAME=$(SSL_LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)
|
||||
SSL_DYLIB_MAKE_CMD=$(CC) -dynamiclib -Wl,-install_name,$(PREFIX)/$(LIBRARY_PATH)/$(SSL_DYLIB_MINOR_NAME) -o $(SSL_DYLIBNAME) $(LDFLAGS) $(SSL_LDFLAGS)
|
||||
DYLIB_PLUGIN=-Wl,-undefined -Wl,dynamic_lookup
|
||||
endif
|
||||
|
||||
15
README.md
15
README.md
@ -23,17 +23,6 @@ Redis version >= 1.2.0.
|
||||
The library comes with multiple APIs. There is the
|
||||
*synchronous API*, the *asynchronous API* and the *reply parsing API*.
|
||||
|
||||
## Upgrading to > 1.2.0 (**PRERELEASE**)
|
||||
|
||||
* After v1.2.0 we modified how we invoke `poll(2)` to wait for connections to complete, such that we will now retry
|
||||
the call if it is interrupted by a signal until:
|
||||
|
||||
a) The connection succeeds or fails.
|
||||
b) The overall connection timeout is reached.
|
||||
|
||||
In previous versions, an interrupted `poll(2)` call would cause the connection to fail
|
||||
with `c->err` set to `REDIS_ERR_IO` and `c->errstr` set to `poll(2): Interrupted system call`.
|
||||
|
||||
## Upgrading to `1.1.0`
|
||||
|
||||
Almost all users will simply need to recompile their applications against the newer version of hiredis.
|
||||
@ -158,7 +147,7 @@ The values are not stored in the `redisContext`, so they are not automatically a
|
||||
These functions return `REDIS_OK` on success.
|
||||
On failure, `REDIS_ERR` is returned and the underlying connection is closed.
|
||||
|
||||
To configure these for an asynchronous context (see *Asynchronous API* below), use `ac->c` to get the redisContext out of an asyncRedisContext.
|
||||
To configure these for an asyncronous context (see *Asynchronous API* below), use `ac->c` to get the redisContext out of an asyncRedisContext.
|
||||
|
||||
```C
|
||||
int redisEnableKeepAlive(redisContext *c);
|
||||
@ -302,7 +291,7 @@ void redisFree(redisContext *c);
|
||||
This function immediately closes the socket and then frees the allocations done in
|
||||
creating the context.
|
||||
|
||||
### Sending commands (continued)
|
||||
### Sending commands (cont'd)
|
||||
|
||||
Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.
|
||||
It has the following prototype:
|
||||
|
||||
@ -159,7 +159,6 @@ static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
|
||||
memset(p, 0, sizeof(*p));
|
||||
|
||||
if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) {
|
||||
hi_free(p);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
|
||||
@ -1,35 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Дмитрий Бахвалов (Dmitry Bakhvalov)
|
||||
*
|
||||
* Permission for license update:
|
||||
* https://github.com/redis/hiredis/issues/1271#issuecomment-2258225227
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
//
|
||||
// Created by Дмитрий Бахвалов on 13.07.15.
|
||||
// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __HIREDIS_MACOSX_H__
|
||||
#define __HIREDIS_MACOSX_H__
|
||||
|
||||
2
async.c
2
async.c
@ -478,7 +478,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
|
||||
|
||||
/* Match reply with the expected format of a pushed message.
|
||||
* The type and number of elements (3 to 4) are specified at:
|
||||
* https://redis.io/docs/latest/develop/interact/pubsub/#format-of-pushed-messages */
|
||||
* https://redis.io/topics/pubsub#format-of-pushed-messages */
|
||||
if ((reply->type == REDIS_REPLY_ARRAY && !(c->flags & REDIS_SUPPORTS_PUSH) && reply->elements >= 3) ||
|
||||
reply->type == REDIS_REPLY_PUSH) {
|
||||
assert(reply->element[0]->type == REDIS_REPLY_STRING);
|
||||
|
||||
@ -1,35 +1,7 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Дмитрий Бахвалов (Dmitry Bakhvalov)
|
||||
*
|
||||
* Permission for license update:
|
||||
* https://github.com/redis/hiredis/issues/1271#issuecomment-2258225227
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of Redis nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
//
|
||||
// Created by Дмитрий Бахвалов on 13.07.15.
|
||||
// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
@ -102,7 +102,6 @@ void freeReplyObject(void *reply) {
|
||||
break; /* Nothing to free */
|
||||
case REDIS_REPLY_ARRAY:
|
||||
case REDIS_REPLY_MAP:
|
||||
case REDIS_REPLY_ATTR:
|
||||
case REDIS_REPLY_SET:
|
||||
case REDIS_REPLY_PUSH:
|
||||
if (r->element != NULL) {
|
||||
@ -161,7 +160,6 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
|
||||
parent = task->parent->obj;
|
||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||
parent->type == REDIS_REPLY_MAP ||
|
||||
parent->type == REDIS_REPLY_ATTR ||
|
||||
parent->type == REDIS_REPLY_SET ||
|
||||
parent->type == REDIS_REPLY_PUSH);
|
||||
parent->element[task->idx] = r;
|
||||
@ -194,7 +192,6 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
|
||||
parent = task->parent->obj;
|
||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||
parent->type == REDIS_REPLY_MAP ||
|
||||
parent->type == REDIS_REPLY_ATTR ||
|
||||
parent->type == REDIS_REPLY_SET ||
|
||||
parent->type == REDIS_REPLY_PUSH);
|
||||
parent->element[task->idx] = r;
|
||||
@ -215,7 +212,6 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
|
||||
parent = task->parent->obj;
|
||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||
parent->type == REDIS_REPLY_MAP ||
|
||||
parent->type == REDIS_REPLY_ATTR ||
|
||||
parent->type == REDIS_REPLY_SET ||
|
||||
parent->type == REDIS_REPLY_PUSH);
|
||||
parent->element[task->idx] = r;
|
||||
@ -253,7 +249,6 @@ static void *createDoubleObject(const redisReadTask *task, double value, char *s
|
||||
parent = task->parent->obj;
|
||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||
parent->type == REDIS_REPLY_MAP ||
|
||||
parent->type == REDIS_REPLY_ATTR ||
|
||||
parent->type == REDIS_REPLY_SET ||
|
||||
parent->type == REDIS_REPLY_PUSH);
|
||||
parent->element[task->idx] = r;
|
||||
@ -272,7 +267,6 @@ static void *createNilObject(const redisReadTask *task) {
|
||||
parent = task->parent->obj;
|
||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||
parent->type == REDIS_REPLY_MAP ||
|
||||
parent->type == REDIS_REPLY_ATTR ||
|
||||
parent->type == REDIS_REPLY_SET ||
|
||||
parent->type == REDIS_REPLY_PUSH);
|
||||
parent->element[task->idx] = r;
|
||||
@ -293,7 +287,6 @@ static void *createBoolObject(const redisReadTask *task, int bval) {
|
||||
parent = task->parent->obj;
|
||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||
parent->type == REDIS_REPLY_MAP ||
|
||||
parent->type == REDIS_REPLY_ATTR ||
|
||||
parent->type == REDIS_REPLY_SET ||
|
||||
parent->type == REDIS_REPLY_PUSH);
|
||||
parent->element[task->idx] = r;
|
||||
|
||||
60
net.c
60
net.c
@ -41,7 +41,6 @@
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "sds.h"
|
||||
@ -173,10 +172,6 @@ int redisKeepAlive(redisContext *c, int interval) {
|
||||
int val = 1;
|
||||
redisFD fd = c->fd;
|
||||
|
||||
/* TCP_KEEPALIVE makes no sense with AF_UNIX connections */
|
||||
if (c->connection_type == REDIS_CONN_UNIX)
|
||||
return REDIS_ERR;
|
||||
|
||||
#ifndef _WIN32
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||
@ -276,54 +271,37 @@ static int redisContextTimeoutMsec(redisContext *c, long *result)
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
static long redisPollMillis(void) {
|
||||
#ifndef _MSC_VER
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
return (now.tv_sec * 1000) + now.tv_nsec / 1000000;
|
||||
#else
|
||||
FILETIME ft;
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
return (((long long)ft.dwHighDateTime << 32) | ft.dwLowDateTime) / 10;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int redisContextWaitReady(redisContext *c, long msec) {
|
||||
struct pollfd wfd;
|
||||
long end;
|
||||
int res;
|
||||
struct pollfd wfd[1];
|
||||
|
||||
if (errno != EINPROGRESS) {
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
wfd[0].fd = c->fd;
|
||||
wfd[0].events = POLLOUT;
|
||||
|
||||
wfd.fd = c->fd;
|
||||
wfd.events = POLLOUT;
|
||||
end = msec >= 0 ? redisPollMillis() + msec : 0;
|
||||
if (errno == EINPROGRESS) {
|
||||
int res;
|
||||
|
||||
while ((res = poll(&wfd, 1, msec)) <= 0) {
|
||||
if (res < 0 && errno != EINTR) {
|
||||
if ((res = poll(wfd, 1, msec)) == -1) {
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
} else if (res == 0 || (msec >= 0 && redisPollMillis() >= end)) {
|
||||
} else if (res == 0) {
|
||||
errno = ETIMEDOUT;
|
||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
} else {
|
||||
/* res < 0 && errno == EINTR, try again */
|
||||
}
|
||||
|
||||
if (redisCheckConnectDone(c, &res) != REDIS_OK || res == 0) {
|
||||
redisCheckSocketError(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
if (redisCheckConnectDone(c, &res) != REDIS_OK || res == 0) {
|
||||
redisCheckSocketError(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
return REDIS_OK;
|
||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||
redisNetClose(c);
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
int redisCheckConnectDone(redisContext *c, int *completed) {
|
||||
@ -668,7 +646,7 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
|
||||
sa->sun_family = AF_UNIX;
|
||||
strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1);
|
||||
if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) {
|
||||
if ((errno == EAGAIN || errno == EINPROGRESS) && !blocking) {
|
||||
if (errno == EINPROGRESS && !blocking) {
|
||||
/* This is ok. */
|
||||
} else {
|
||||
if (redisContextWaitReady(c,timeout_msec) != REDIS_OK)
|
||||
|
||||
7
read.c
7
read.c
@ -250,7 +250,6 @@ static void moveToNextTask(redisReader *r) {
|
||||
prv = r->task[r->ridx-1];
|
||||
assert(prv->type == REDIS_REPLY_ARRAY ||
|
||||
prv->type == REDIS_REPLY_MAP ||
|
||||
prv->type == REDIS_REPLY_ATTR ||
|
||||
prv->type == REDIS_REPLY_SET ||
|
||||
prv->type == REDIS_REPLY_PUSH);
|
||||
if (cur->idx == prv->elements-1) {
|
||||
@ -535,7 +534,7 @@ static int processAggregateItem(redisReader *r) {
|
||||
|
||||
moveToNextTask(r);
|
||||
} else {
|
||||
if (cur->type == REDIS_REPLY_MAP || cur->type == REDIS_REPLY_ATTR) elements *= 2;
|
||||
if (cur->type == REDIS_REPLY_MAP) elements *= 2;
|
||||
|
||||
if (r->fn && r->fn->createArray)
|
||||
obj = r->fn->createArray(cur,elements);
|
||||
@ -603,9 +602,6 @@ static int processItem(redisReader *r) {
|
||||
case '%':
|
||||
cur->type = REDIS_REPLY_MAP;
|
||||
break;
|
||||
case '|':
|
||||
cur->type = REDIS_REPLY_ATTR;
|
||||
break;
|
||||
case '~':
|
||||
cur->type = REDIS_REPLY_SET;
|
||||
break;
|
||||
@ -646,7 +642,6 @@ static int processItem(redisReader *r) {
|
||||
return processBulkItem(r);
|
||||
case REDIS_REPLY_ARRAY:
|
||||
case REDIS_REPLY_MAP:
|
||||
case REDIS_REPLY_ATTR:
|
||||
case REDIS_REPLY_SET:
|
||||
case REDIS_REPLY_PUSH:
|
||||
return processAggregateItem(r);
|
||||
|
||||
4
sds.c
4
sds.c
@ -692,10 +692,10 @@ fmt_error:
|
||||
* Output will be just "Hello World".
|
||||
*/
|
||||
sds sdstrim(sds s, const char *cset) {
|
||||
char *end, *sp, *ep;
|
||||
char *start, *end, *sp, *ep;
|
||||
size_t len;
|
||||
|
||||
sp = s;
|
||||
sp = start = s;
|
||||
ep = end = s+sdslen(s)-1;
|
||||
while(sp <= end && strchr(cset, *sp)) sp++;
|
||||
while(ep > sp && strchr(cset, *ep)) ep--;
|
||||
|
||||
9
ssl.c
9
ssl.c
@ -167,8 +167,8 @@ static int initOpensslLocks(void) {
|
||||
|
||||
int redisInitOpenSSL(void)
|
||||
{
|
||||
#ifdef HIREDIS_USE_CRYPTO_LOCKS
|
||||
SSL_library_init();
|
||||
#ifdef HIREDIS_USE_CRYPTO_LOCKS
|
||||
initOpensslLocks();
|
||||
#endif
|
||||
|
||||
@ -364,6 +364,7 @@ static int redisSSLConnect(redisContext *c, SSL *ssl) {
|
||||
return REDIS_ERR;
|
||||
}
|
||||
|
||||
c->funcs = &redisContextSSLFuncs;
|
||||
rssl->ssl = ssl;
|
||||
|
||||
SSL_set_mode(rssl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
||||
@ -371,19 +372,15 @@ static int redisSSLConnect(redisContext *c, SSL *ssl) {
|
||||
SSL_set_connect_state(rssl->ssl);
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
int rv = SSL_connect(rssl->ssl);
|
||||
if (rv == 1) {
|
||||
c->funcs = &redisContextSSLFuncs;
|
||||
c->privctx = rssl;
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
rv = SSL_get_error(rssl->ssl, rv);
|
||||
if (((c->flags & REDIS_BLOCK) == 0) &&
|
||||
(rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE))
|
||||
{
|
||||
c->funcs = &redisContextSSLFuncs;
|
||||
(rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE)) {
|
||||
c->privctx = rssl;
|
||||
return REDIS_OK;
|
||||
}
|
||||
|
||||
72
test.c
72
test.c
@ -104,13 +104,6 @@ static long long usec(void) {
|
||||
#define assert(e) (void)(e)
|
||||
#endif
|
||||
|
||||
#define redisTestPanic(msg) \
|
||||
do { \
|
||||
fprintf(stderr, "PANIC: %s (In function \"%s\", file \"%s\", line %d)\n", \
|
||||
msg, __func__, __FILE__, __LINE__); \
|
||||
exit(1); \
|
||||
} while (1)
|
||||
|
||||
/* Helper to extract Redis version information. Aborts on any failure. */
|
||||
#define REDIS_VERSION_FIELD "redis_version:"
|
||||
void get_redis_version(redisContext *c, int *majorptr, int *minorptr) {
|
||||
@ -156,7 +149,7 @@ static redisContext *select_database(redisContext *c) {
|
||||
assert(reply != NULL);
|
||||
freeReplyObject(reply);
|
||||
|
||||
/* Make sure the DB is empty */
|
||||
/* Make sure the DB is emtpy */
|
||||
reply = redisCommand(c,"DBSIZE");
|
||||
assert(reply != NULL);
|
||||
if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {
|
||||
@ -239,7 +232,7 @@ static redisContext *do_connect(struct config config) {
|
||||
c = redisConnectFd(fd);
|
||||
}
|
||||
} else {
|
||||
redisTestPanic("Unknown connection type!");
|
||||
assert(NULL);
|
||||
}
|
||||
|
||||
if (c == NULL) {
|
||||
@ -431,24 +424,6 @@ static void test_tcp_options(struct config cfg) {
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
static void test_unix_keepalive(struct config cfg) {
|
||||
redisContext *c;
|
||||
redisReply *r;
|
||||
|
||||
c = do_connect(cfg);
|
||||
|
||||
test("Setting TCP_KEEPALIVE on a unix socket returns an error: ");
|
||||
test_cond(redisEnableKeepAlive(c) == REDIS_ERR && c->err == 0);
|
||||
|
||||
test("Setting TCP_KEEPALIVE on a unix socket doesn't break the connection: ");
|
||||
r = redisCommand(c, "PING");
|
||||
test_cond(r != NULL && r->type == REDIS_REPLY_STATUS && r->len == 4 &&
|
||||
!memcmp(r->str, "PONG", 4));
|
||||
freeReplyObject(r);
|
||||
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
static void test_reply_reader(void) {
|
||||
redisReader *reader;
|
||||
void *reply, *root;
|
||||
@ -795,26 +770,6 @@ static void test_reply_reader(void) {
|
||||
freeReplyObject(reply);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Can parse RESP3 attribute: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader, "|2\r\n+foo\r\n:123\r\n+bar\r\n#t\r\n",26);
|
||||
ret = redisReaderGetReply(reader,&reply);
|
||||
test_cond(ret == REDIS_OK &&
|
||||
((redisReply*)reply)->type == REDIS_REPLY_ATTR &&
|
||||
((redisReply*)reply)->elements == 4 &&
|
||||
((redisReply*)reply)->element[0]->type == REDIS_REPLY_STATUS &&
|
||||
((redisReply*)reply)->element[0]->len == 3 &&
|
||||
!strcmp(((redisReply*)reply)->element[0]->str,"foo") &&
|
||||
((redisReply*)reply)->element[1]->type == REDIS_REPLY_INTEGER &&
|
||||
((redisReply*)reply)->element[1]->integer == 123 &&
|
||||
((redisReply*)reply)->element[2]->type == REDIS_REPLY_STATUS &&
|
||||
((redisReply*)reply)->element[2]->len == 3 &&
|
||||
!strcmp(((redisReply*)reply)->element[2]->str,"bar") &&
|
||||
((redisReply*)reply)->element[3]->type == REDIS_REPLY_BOOL &&
|
||||
((redisReply*)reply)->element[3]->integer);
|
||||
freeReplyObject(reply);
|
||||
redisReaderFree(reader);
|
||||
|
||||
test("Can parse RESP3 set: ");
|
||||
reader = redisReaderCreate();
|
||||
redisReaderFeed(reader, "~5\r\n+orange\r\n$5\r\napple\r\n#f\r\n:100\r\n:999\r\n",40);
|
||||
@ -1276,13 +1231,15 @@ static void test_blocking_connection_timeouts(struct config config) {
|
||||
redisContext *c;
|
||||
redisReply *reply;
|
||||
ssize_t s;
|
||||
const char *sleep_cmd = "DEBUG SLEEP 1\r\n";
|
||||
struct timeval tv = {.tv_sec = 0, .tv_usec = 10000};
|
||||
const char *sleep_cmd = "DEBUG SLEEP 3\r\n";
|
||||
struct timeval tv;
|
||||
|
||||
c = do_connect(config);
|
||||
test("Successfully completes a command when the timeout is not exceeded: ");
|
||||
reply = redisCommand(c,"SET foo fast");
|
||||
freeReplyObject(reply);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
redisSetTimeout(c, tv);
|
||||
reply = redisCommand(c, "GET foo");
|
||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0);
|
||||
@ -1300,6 +1257,8 @@ static void test_blocking_connection_timeouts(struct config config) {
|
||||
sdsfree(c->obuf);
|
||||
c->obuf = sdsempty();
|
||||
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 10000;
|
||||
redisSetTimeout(c, tv);
|
||||
reply = redisCommand(c, "GET foo");
|
||||
#ifndef _WIN32
|
||||
@ -1312,7 +1271,7 @@ static void test_blocking_connection_timeouts(struct config config) {
|
||||
freeReplyObject(reply);
|
||||
|
||||
// wait for the DEBUG SLEEP to complete so that Redis server is unblocked for the following tests
|
||||
millisleep(1100);
|
||||
millisleep(3000);
|
||||
} else {
|
||||
test_skipped();
|
||||
}
|
||||
@ -1381,7 +1340,7 @@ static void test_blocking_io_errors(struct config config) {
|
||||
}
|
||||
|
||||
static void test_invalid_timeout_errors(struct config config) {
|
||||
redisContext *c = NULL;
|
||||
redisContext *c;
|
||||
|
||||
test("Set error when an invalid timeout usec value is used during connect: ");
|
||||
|
||||
@ -1393,10 +1352,10 @@ static void test_invalid_timeout_errors(struct config config) {
|
||||
} else if(config.type == CONN_UNIX) {
|
||||
c = redisConnectUnixWithTimeout(config.unix_sock.path, config.connect_timeout);
|
||||
} else {
|
||||
redisTestPanic("Unknown connection type!");
|
||||
assert(NULL);
|
||||
}
|
||||
|
||||
test_cond(c != NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
|
||||
test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
|
||||
redisFree(c);
|
||||
|
||||
test("Set error when an invalid timeout sec value is used during connect: ");
|
||||
@ -1409,10 +1368,10 @@ static void test_invalid_timeout_errors(struct config config) {
|
||||
} else if(config.type == CONN_UNIX) {
|
||||
c = redisConnectUnixWithTimeout(config.unix_sock.path, config.connect_timeout);
|
||||
} else {
|
||||
redisTestPanic("Unknown connection type!");
|
||||
assert(NULL);
|
||||
}
|
||||
|
||||
test_cond(c != NULL && c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
|
||||
test_cond(c->err == REDIS_ERR_IO && strcmp(c->errstr, "Invalid timeout specified") == 0);
|
||||
redisFree(c);
|
||||
}
|
||||
|
||||
@ -2294,7 +2253,7 @@ static void test_async_polling(struct config config) {
|
||||
*/
|
||||
test("Ping/Pong from onConnected callback (Issue #931): ");
|
||||
c = do_aconnect(config, ASTEST_ISSUE_931_PING);
|
||||
/* connect callback issues ping, response callback destroys context */
|
||||
/* connect callback issues ping, reponse callback destroys context */
|
||||
while(astest.ac)
|
||||
redisPollTick(c, 0.1);
|
||||
assert(astest.connected == 0);
|
||||
@ -2397,7 +2356,6 @@ int main(int argc, char **argv) {
|
||||
test_blocking_connection_timeouts(cfg);
|
||||
test_blocking_io_errors(cfg);
|
||||
test_invalid_timeout_errors(cfg);
|
||||
test_unix_keepalive(cfg);
|
||||
if (throughput) test_throughput(cfg);
|
||||
} else {
|
||||
test_skipped();
|
||||
|
||||
4
test.sh
4
test.sh
@ -11,7 +11,7 @@ SKIPS_ARG=${SKIPS_ARG:-}
|
||||
REDIS_DOCKER=${REDIS_DOCKER:-}
|
||||
|
||||
# We need to enable the DEBUG command for redis-server >= 7.0.0
|
||||
REDIS_MAJOR_VERSION="$(${REDIS_SERVER} --version|awk -F'[^0-9]+' '{ print $2 }')"
|
||||
REDIS_MAJOR_VERSION="$(redis-server --version|awk -F'[^0-9]+' '{ print $2 }')"
|
||||
if [ "$REDIS_MAJOR_VERSION" -gt "6" ]; then
|
||||
ENABLE_DEBUG_CMD="enable-debug-command local"
|
||||
fi
|
||||
@ -98,7 +98,7 @@ if [ -n "${REDIS_DOCKER}" ] ; then
|
||||
-p ${REDIS_SSL_PORT}:${REDIS_SSL_PORT} \
|
||||
-v ${tmpdir}:${tmpdir} \
|
||||
${REDIS_DOCKER} \
|
||||
${REDIS_SERVER} ${tmpdir}/redis.conf
|
||||
redis-server ${tmpdir}/redis.conf
|
||||
else
|
||||
${REDIS_SERVER} ${tmpdir}/redis.conf
|
||||
fi
|
||||
|
||||
Loading…
Reference in New Issue
Block a user