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
|
# TEST_PREFIX: valgrind --error-exitcode=99 --track-origins=yes --leak-check=full
|
||||||
# run: $GITHUB_WORKSPACE/test.sh
|
# 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:
|
centos8:
|
||||||
name: RockyLinux 8
|
name: RockyLinux 8
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@ -76,13 +112,13 @@ jobs:
|
|||||||
run: $GITHUB_WORKSPACE/test.sh
|
run: $GITHUB_WORKSPACE/test.sh
|
||||||
|
|
||||||
freebsd:
|
freebsd:
|
||||||
runs-on: ubuntu-latest
|
runs-on: macos-12
|
||||||
name: FreeBSD
|
name: FreeBSD
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Build in FreeBSD
|
- name: Build in FreeBSD
|
||||||
uses: vmactions/freebsd-vm@v1.0.5
|
uses: vmactions/freebsd-vm@v0
|
||||||
with:
|
with:
|
||||||
prepare: pkg install -y gmake cmake
|
prepare: pkg install -y gmake cmake
|
||||||
run: |
|
run: |
|
||||||
@ -97,8 +133,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
brew install openssl redis@7.2
|
brew install openssl redis@7.0
|
||||||
brew link redis@7.2 --force
|
brew link redis@7.0 --force
|
||||||
|
|
||||||
- name: Build hiredis
|
- name: Build hiredis
|
||||||
run: USE_SSL=1 make
|
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
|
/*.pc
|
||||||
*.dSYM
|
*.dSYM
|
||||||
tags
|
tags
|
||||||
compile_commands.json
|
|
||||||
|
|||||||
@ -1,5 +1,12 @@
|
|||||||
CMAKE_MINIMUM_REQUIRED(VERSION 3.0.0)
|
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)
|
MACRO(getVersionBit name)
|
||||||
SET(VERSION_REGEX "^#define ${name} (.+)$")
|
SET(VERSION_REGEX "^#define ${name} (.+)$")
|
||||||
FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredis.h"
|
FILE(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/hiredis.h"
|
||||||
@ -17,16 +24,6 @@ MESSAGE("Detected version: ${VERSION}")
|
|||||||
PROJECT(hiredis LANGUAGES "C" VERSION "${VERSION}")
|
PROJECT(hiredis LANGUAGES "C" VERSION "${VERSION}")
|
||||||
INCLUDE(GNUInstallDirs)
|
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
|
# Hiredis requires C99
|
||||||
SET(CMAKE_C_STANDARD 99)
|
SET(CMAKE_C_STANDARD 99)
|
||||||
SET(CMAKE_DEBUG_POSTFIX d)
|
SET(CMAKE_DEBUG_POSTFIX d)
|
||||||
@ -108,11 +105,9 @@ if (MSVC AND BUILD_SHARED_LIBS)
|
|||||||
CONFIGURATIONS Debug RelWithDebInfo)
|
CONFIGURATIONS Debug RelWithDebInfo)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (ENABLE_NUGET)
|
# For NuGet packages
|
||||||
# For NuGet packages
|
INSTALL(FILES hiredis.targets
|
||||||
INSTALL(FILES hiredis.targets
|
DESTINATION build/native)
|
||||||
DESTINATION build/native)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
INSTALL(FILES hiredis.h read.h sds.h async.h alloc.h sockcompat.h
|
INSTALL(FILES hiredis.h read.h sds.h async.h alloc.h sockcompat.h
|
||||||
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/hiredis)
|
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')
|
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++')
|
CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++')
|
||||||
OPTIMIZATION?=-O3
|
OPTIMIZATION?=-O3
|
||||||
WARNINGS=-Wall -Wextra -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
WARNINGS=-Wall -Wextra -Werror -Wstrict-prototypes -Wwrite-strings -Wno-missing-field-initializers
|
||||||
USE_WERROR?=1
|
|
||||||
ifeq ($(USE_WERROR),1)
|
|
||||||
WARNINGS+=-Werror
|
|
||||||
endif
|
|
||||||
DEBUG_FLAGS?= -g -ggdb
|
DEBUG_FLAGS?= -g -ggdb
|
||||||
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) $(PLATFORM_FLAGS)
|
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CPPFLAGS) $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS) $(PLATFORM_FLAGS)
|
||||||
REAL_LDFLAGS=$(LDFLAGS)
|
REAL_LDFLAGS=$(LDFLAGS)
|
||||||
@ -141,10 +137,7 @@ endif
|
|||||||
ifeq ($(uname_S),Darwin)
|
ifeq ($(uname_S),Darwin)
|
||||||
DYLIBSUFFIX=dylib
|
DYLIBSUFFIX=dylib
|
||||||
DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX)
|
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)
|
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)
|
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
|
DYLIB_PLUGIN=-Wl,-undefined -Wl,dynamic_lookup
|
||||||
endif
|
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
|
The library comes with multiple APIs. There is the
|
||||||
*synchronous API*, the *asynchronous API* and the *reply parsing API*.
|
*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`
|
## Upgrading to `1.1.0`
|
||||||
|
|
||||||
Almost all users will simply need to recompile their applications against the newer version of hiredis.
|
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.
|
These functions return `REDIS_OK` on success.
|
||||||
On failure, `REDIS_ERR` is returned and the underlying connection is closed.
|
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
|
```C
|
||||||
int redisEnableKeepAlive(redisContext *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
|
This function immediately closes the socket and then frees the allocations done in
|
||||||
creating the context.
|
creating the context.
|
||||||
|
|
||||||
### Sending commands (continued)
|
### Sending commands (cont'd)
|
||||||
|
|
||||||
Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.
|
Together with `redisCommand`, the function `redisCommandArgv` can be used to issue commands.
|
||||||
It has the following prototype:
|
It has the following prototype:
|
||||||
|
|||||||
@ -159,7 +159,6 @@ static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
|
|||||||
memset(p, 0, sizeof(*p));
|
memset(p, 0, sizeof(*p));
|
||||||
|
|
||||||
if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) {
|
if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) {
|
||||||
hi_free(p);
|
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,35 +1,7 @@
|
|||||||
/*
|
//
|
||||||
* Copyright (c) 2015 Дмитрий Бахвалов (Dmitry Bakhvalov)
|
// Created by Дмитрий Бахвалов on 13.07.15.
|
||||||
*
|
// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __HIREDIS_MACOSX_H__
|
#ifndef __HIREDIS_MACOSX_H__
|
||||||
#define __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.
|
/* Match reply with the expected format of a pushed message.
|
||||||
* The type and number of elements (3 to 4) are specified at:
|
* 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) ||
|
if ((reply->type == REDIS_REPLY_ARRAY && !(c->flags & REDIS_SUPPORTS_PUSH) && reply->elements >= 3) ||
|
||||||
reply->type == REDIS_REPLY_PUSH) {
|
reply->type == REDIS_REPLY_PUSH) {
|
||||||
assert(reply->element[0]->type == REDIS_REPLY_STRING);
|
assert(reply->element[0]->type == REDIS_REPLY_STRING);
|
||||||
|
|||||||
@ -1,35 +1,7 @@
|
|||||||
/*
|
//
|
||||||
* Copyright (c) 2015 Дмитрий Бахвалов (Dmitry Bakhvalov)
|
// Created by Дмитрий Бахвалов on 13.07.15.
|
||||||
*
|
// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|||||||
@ -102,7 +102,6 @@ void freeReplyObject(void *reply) {
|
|||||||
break; /* Nothing to free */
|
break; /* Nothing to free */
|
||||||
case REDIS_REPLY_ARRAY:
|
case REDIS_REPLY_ARRAY:
|
||||||
case REDIS_REPLY_MAP:
|
case REDIS_REPLY_MAP:
|
||||||
case REDIS_REPLY_ATTR:
|
|
||||||
case REDIS_REPLY_SET:
|
case REDIS_REPLY_SET:
|
||||||
case REDIS_REPLY_PUSH:
|
case REDIS_REPLY_PUSH:
|
||||||
if (r->element != NULL) {
|
if (r->element != NULL) {
|
||||||
@ -161,7 +160,6 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_ATTR ||
|
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -194,7 +192,6 @@ static void *createArrayObject(const redisReadTask *task, size_t elements) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_ATTR ||
|
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -215,7 +212,6 @@ static void *createIntegerObject(const redisReadTask *task, long long value) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_ATTR ||
|
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -253,7 +249,6 @@ static void *createDoubleObject(const redisReadTask *task, double value, char *s
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_ATTR ||
|
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -272,7 +267,6 @@ static void *createNilObject(const redisReadTask *task) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_ATTR ||
|
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
@ -293,7 +287,6 @@ static void *createBoolObject(const redisReadTask *task, int bval) {
|
|||||||
parent = task->parent->obj;
|
parent = task->parent->obj;
|
||||||
assert(parent->type == REDIS_REPLY_ARRAY ||
|
assert(parent->type == REDIS_REPLY_ARRAY ||
|
||||||
parent->type == REDIS_REPLY_MAP ||
|
parent->type == REDIS_REPLY_MAP ||
|
||||||
parent->type == REDIS_REPLY_ATTR ||
|
|
||||||
parent->type == REDIS_REPLY_SET ||
|
parent->type == REDIS_REPLY_SET ||
|
||||||
parent->type == REDIS_REPLY_PUSH);
|
parent->type == REDIS_REPLY_PUSH);
|
||||||
parent->element[task->idx] = r;
|
parent->element[task->idx] = r;
|
||||||
|
|||||||
60
net.c
60
net.c
@ -41,7 +41,6 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "sds.h"
|
#include "sds.h"
|
||||||
@ -173,10 +172,6 @@ int redisKeepAlive(redisContext *c, int interval) {
|
|||||||
int val = 1;
|
int val = 1;
|
||||||
redisFD fd = c->fd;
|
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
|
#ifndef _WIN32
|
||||||
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val)) == -1){
|
||||||
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
__redisSetError(c,REDIS_ERR_OTHER,strerror(errno));
|
||||||
@ -276,54 +271,37 @@ static int redisContextTimeoutMsec(redisContext *c, long *result)
|
|||||||
return REDIS_OK;
|
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) {
|
static int redisContextWaitReady(redisContext *c, long msec) {
|
||||||
struct pollfd wfd;
|
struct pollfd wfd[1];
|
||||||
long end;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (errno != EINPROGRESS) {
|
wfd[0].fd = c->fd;
|
||||||
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
wfd[0].events = POLLOUT;
|
||||||
redisNetClose(c);
|
|
||||||
return REDIS_ERR;
|
|
||||||
}
|
|
||||||
|
|
||||||
wfd.fd = c->fd;
|
if (errno == EINPROGRESS) {
|
||||||
wfd.events = POLLOUT;
|
int res;
|
||||||
end = msec >= 0 ? redisPollMillis() + msec : 0;
|
|
||||||
|
|
||||||
while ((res = poll(&wfd, 1, msec)) <= 0) {
|
if ((res = poll(wfd, 1, msec)) == -1) {
|
||||||
if (res < 0 && errno != EINTR) {
|
|
||||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
__redisSetErrorFromErrno(c, REDIS_ERR_IO, "poll(2)");
|
||||||
redisNetClose(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
} else if (res == 0 || (msec >= 0 && redisPollMillis() >= end)) {
|
} else if (res == 0) {
|
||||||
errno = ETIMEDOUT;
|
errno = ETIMEDOUT;
|
||||||
__redisSetErrorFromErrno(c, REDIS_ERR_IO, NULL);
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||||
redisNetClose(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
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) {
|
__redisSetErrorFromErrno(c,REDIS_ERR_IO,NULL);
|
||||||
redisCheckSocketError(c);
|
redisNetClose(c);
|
||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
|
||||||
|
|
||||||
return REDIS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int redisCheckConnectDone(redisContext *c, int *completed) {
|
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;
|
sa->sun_family = AF_UNIX;
|
||||||
strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1);
|
strncpy(sa->sun_path, path, sizeof(sa->sun_path) - 1);
|
||||||
if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) {
|
if (connect(c->fd, (struct sockaddr*)sa, sizeof(*sa)) == -1) {
|
||||||
if ((errno == EAGAIN || errno == EINPROGRESS) && !blocking) {
|
if (errno == EINPROGRESS && !blocking) {
|
||||||
/* This is ok. */
|
/* This is ok. */
|
||||||
} else {
|
} else {
|
||||||
if (redisContextWaitReady(c,timeout_msec) != REDIS_OK)
|
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];
|
prv = r->task[r->ridx-1];
|
||||||
assert(prv->type == REDIS_REPLY_ARRAY ||
|
assert(prv->type == REDIS_REPLY_ARRAY ||
|
||||||
prv->type == REDIS_REPLY_MAP ||
|
prv->type == REDIS_REPLY_MAP ||
|
||||||
prv->type == REDIS_REPLY_ATTR ||
|
|
||||||
prv->type == REDIS_REPLY_SET ||
|
prv->type == REDIS_REPLY_SET ||
|
||||||
prv->type == REDIS_REPLY_PUSH);
|
prv->type == REDIS_REPLY_PUSH);
|
||||||
if (cur->idx == prv->elements-1) {
|
if (cur->idx == prv->elements-1) {
|
||||||
@ -535,7 +534,7 @@ static int processAggregateItem(redisReader *r) {
|
|||||||
|
|
||||||
moveToNextTask(r);
|
moveToNextTask(r);
|
||||||
} else {
|
} 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)
|
if (r->fn && r->fn->createArray)
|
||||||
obj = r->fn->createArray(cur,elements);
|
obj = r->fn->createArray(cur,elements);
|
||||||
@ -603,9 +602,6 @@ static int processItem(redisReader *r) {
|
|||||||
case '%':
|
case '%':
|
||||||
cur->type = REDIS_REPLY_MAP;
|
cur->type = REDIS_REPLY_MAP;
|
||||||
break;
|
break;
|
||||||
case '|':
|
|
||||||
cur->type = REDIS_REPLY_ATTR;
|
|
||||||
break;
|
|
||||||
case '~':
|
case '~':
|
||||||
cur->type = REDIS_REPLY_SET;
|
cur->type = REDIS_REPLY_SET;
|
||||||
break;
|
break;
|
||||||
@ -646,7 +642,6 @@ static int processItem(redisReader *r) {
|
|||||||
return processBulkItem(r);
|
return processBulkItem(r);
|
||||||
case REDIS_REPLY_ARRAY:
|
case REDIS_REPLY_ARRAY:
|
||||||
case REDIS_REPLY_MAP:
|
case REDIS_REPLY_MAP:
|
||||||
case REDIS_REPLY_ATTR:
|
|
||||||
case REDIS_REPLY_SET:
|
case REDIS_REPLY_SET:
|
||||||
case REDIS_REPLY_PUSH:
|
case REDIS_REPLY_PUSH:
|
||||||
return processAggregateItem(r);
|
return processAggregateItem(r);
|
||||||
|
|||||||
4
sds.c
4
sds.c
@ -692,10 +692,10 @@ fmt_error:
|
|||||||
* Output will be just "Hello World".
|
* Output will be just "Hello World".
|
||||||
*/
|
*/
|
||||||
sds sdstrim(sds s, const char *cset) {
|
sds sdstrim(sds s, const char *cset) {
|
||||||
char *end, *sp, *ep;
|
char *start, *end, *sp, *ep;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
|
||||||
sp = s;
|
sp = start = s;
|
||||||
ep = end = s+sdslen(s)-1;
|
ep = end = s+sdslen(s)-1;
|
||||||
while(sp <= end && strchr(cset, *sp)) sp++;
|
while(sp <= end && strchr(cset, *sp)) sp++;
|
||||||
while(ep > sp && strchr(cset, *ep)) ep--;
|
while(ep > sp && strchr(cset, *ep)) ep--;
|
||||||
|
|||||||
9
ssl.c
9
ssl.c
@ -167,8 +167,8 @@ static int initOpensslLocks(void) {
|
|||||||
|
|
||||||
int redisInitOpenSSL(void)
|
int redisInitOpenSSL(void)
|
||||||
{
|
{
|
||||||
#ifdef HIREDIS_USE_CRYPTO_LOCKS
|
|
||||||
SSL_library_init();
|
SSL_library_init();
|
||||||
|
#ifdef HIREDIS_USE_CRYPTO_LOCKS
|
||||||
initOpensslLocks();
|
initOpensslLocks();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -364,6 +364,7 @@ static int redisSSLConnect(redisContext *c, SSL *ssl) {
|
|||||||
return REDIS_ERR;
|
return REDIS_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c->funcs = &redisContextSSLFuncs;
|
||||||
rssl->ssl = ssl;
|
rssl->ssl = ssl;
|
||||||
|
|
||||||
SSL_set_mode(rssl->ssl, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
|
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);
|
SSL_set_connect_state(rssl->ssl);
|
||||||
|
|
||||||
ERR_clear_error();
|
ERR_clear_error();
|
||||||
|
|
||||||
int rv = SSL_connect(rssl->ssl);
|
int rv = SSL_connect(rssl->ssl);
|
||||||
if (rv == 1) {
|
if (rv == 1) {
|
||||||
c->funcs = &redisContextSSLFuncs;
|
|
||||||
c->privctx = rssl;
|
c->privctx = rssl;
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = SSL_get_error(rssl->ssl, rv);
|
rv = SSL_get_error(rssl->ssl, rv);
|
||||||
if (((c->flags & REDIS_BLOCK) == 0) &&
|
if (((c->flags & REDIS_BLOCK) == 0) &&
|
||||||
(rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE))
|
(rv == SSL_ERROR_WANT_READ || rv == SSL_ERROR_WANT_WRITE)) {
|
||||||
{
|
|
||||||
c->funcs = &redisContextSSLFuncs;
|
|
||||||
c->privctx = rssl;
|
c->privctx = rssl;
|
||||||
return REDIS_OK;
|
return REDIS_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
72
test.c
72
test.c
@ -104,13 +104,6 @@ static long long usec(void) {
|
|||||||
#define assert(e) (void)(e)
|
#define assert(e) (void)(e)
|
||||||
#endif
|
#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. */
|
/* Helper to extract Redis version information. Aborts on any failure. */
|
||||||
#define REDIS_VERSION_FIELD "redis_version:"
|
#define REDIS_VERSION_FIELD "redis_version:"
|
||||||
void get_redis_version(redisContext *c, int *majorptr, int *minorptr) {
|
void get_redis_version(redisContext *c, int *majorptr, int *minorptr) {
|
||||||
@ -156,7 +149,7 @@ static redisContext *select_database(redisContext *c) {
|
|||||||
assert(reply != NULL);
|
assert(reply != NULL);
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
|
|
||||||
/* Make sure the DB is empty */
|
/* Make sure the DB is emtpy */
|
||||||
reply = redisCommand(c,"DBSIZE");
|
reply = redisCommand(c,"DBSIZE");
|
||||||
assert(reply != NULL);
|
assert(reply != NULL);
|
||||||
if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {
|
if (reply->type == REDIS_REPLY_INTEGER && reply->integer == 0) {
|
||||||
@ -239,7 +232,7 @@ static redisContext *do_connect(struct config config) {
|
|||||||
c = redisConnectFd(fd);
|
c = redisConnectFd(fd);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
redisTestPanic("Unknown connection type!");
|
assert(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == NULL) {
|
if (c == NULL) {
|
||||||
@ -431,24 +424,6 @@ static void test_tcp_options(struct config cfg) {
|
|||||||
redisFree(c);
|
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) {
|
static void test_reply_reader(void) {
|
||||||
redisReader *reader;
|
redisReader *reader;
|
||||||
void *reply, *root;
|
void *reply, *root;
|
||||||
@ -795,26 +770,6 @@ static void test_reply_reader(void) {
|
|||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
redisReaderFree(reader);
|
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: ");
|
test("Can parse RESP3 set: ");
|
||||||
reader = redisReaderCreate();
|
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);
|
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;
|
redisContext *c;
|
||||||
redisReply *reply;
|
redisReply *reply;
|
||||||
ssize_t s;
|
ssize_t s;
|
||||||
const char *sleep_cmd = "DEBUG SLEEP 1\r\n";
|
const char *sleep_cmd = "DEBUG SLEEP 3\r\n";
|
||||||
struct timeval tv = {.tv_sec = 0, .tv_usec = 10000};
|
struct timeval tv;
|
||||||
|
|
||||||
c = do_connect(config);
|
c = do_connect(config);
|
||||||
test("Successfully completes a command when the timeout is not exceeded: ");
|
test("Successfully completes a command when the timeout is not exceeded: ");
|
||||||
reply = redisCommand(c,"SET foo fast");
|
reply = redisCommand(c,"SET foo fast");
|
||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 10000;
|
||||||
redisSetTimeout(c, tv);
|
redisSetTimeout(c, tv);
|
||||||
reply = redisCommand(c, "GET foo");
|
reply = redisCommand(c, "GET foo");
|
||||||
test_cond(reply != NULL && reply->type == REDIS_REPLY_STRING && memcmp(reply->str, "fast", 4) == 0);
|
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);
|
sdsfree(c->obuf);
|
||||||
c->obuf = sdsempty();
|
c->obuf = sdsempty();
|
||||||
|
|
||||||
|
tv.tv_sec = 0;
|
||||||
|
tv.tv_usec = 10000;
|
||||||
redisSetTimeout(c, tv);
|
redisSetTimeout(c, tv);
|
||||||
reply = redisCommand(c, "GET foo");
|
reply = redisCommand(c, "GET foo");
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
@ -1312,7 +1271,7 @@ static void test_blocking_connection_timeouts(struct config config) {
|
|||||||
freeReplyObject(reply);
|
freeReplyObject(reply);
|
||||||
|
|
||||||
// wait for the DEBUG SLEEP to complete so that Redis server is unblocked for the following tests
|
// wait for the DEBUG SLEEP to complete so that Redis server is unblocked for the following tests
|
||||||
millisleep(1100);
|
millisleep(3000);
|
||||||
} else {
|
} else {
|
||||||
test_skipped();
|
test_skipped();
|
||||||
}
|
}
|
||||||
@ -1381,7 +1340,7 @@ static void test_blocking_io_errors(struct config config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void test_invalid_timeout_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: ");
|
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) {
|
} else if(config.type == CONN_UNIX) {
|
||||||
c = redisConnectUnixWithTimeout(config.unix_sock.path, config.connect_timeout);
|
c = redisConnectUnixWithTimeout(config.unix_sock.path, config.connect_timeout);
|
||||||
} else {
|
} 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);
|
redisFree(c);
|
||||||
|
|
||||||
test("Set error when an invalid timeout sec value is used during connect: ");
|
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) {
|
} else if(config.type == CONN_UNIX) {
|
||||||
c = redisConnectUnixWithTimeout(config.unix_sock.path, config.connect_timeout);
|
c = redisConnectUnixWithTimeout(config.unix_sock.path, config.connect_timeout);
|
||||||
} else {
|
} 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);
|
redisFree(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2294,7 +2253,7 @@ static void test_async_polling(struct config config) {
|
|||||||
*/
|
*/
|
||||||
test("Ping/Pong from onConnected callback (Issue #931): ");
|
test("Ping/Pong from onConnected callback (Issue #931): ");
|
||||||
c = do_aconnect(config, ASTEST_ISSUE_931_PING);
|
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)
|
while(astest.ac)
|
||||||
redisPollTick(c, 0.1);
|
redisPollTick(c, 0.1);
|
||||||
assert(astest.connected == 0);
|
assert(astest.connected == 0);
|
||||||
@ -2397,7 +2356,6 @@ int main(int argc, char **argv) {
|
|||||||
test_blocking_connection_timeouts(cfg);
|
test_blocking_connection_timeouts(cfg);
|
||||||
test_blocking_io_errors(cfg);
|
test_blocking_io_errors(cfg);
|
||||||
test_invalid_timeout_errors(cfg);
|
test_invalid_timeout_errors(cfg);
|
||||||
test_unix_keepalive(cfg);
|
|
||||||
if (throughput) test_throughput(cfg);
|
if (throughput) test_throughput(cfg);
|
||||||
} else {
|
} else {
|
||||||
test_skipped();
|
test_skipped();
|
||||||
|
|||||||
4
test.sh
4
test.sh
@ -11,7 +11,7 @@ SKIPS_ARG=${SKIPS_ARG:-}
|
|||||||
REDIS_DOCKER=${REDIS_DOCKER:-}
|
REDIS_DOCKER=${REDIS_DOCKER:-}
|
||||||
|
|
||||||
# We need to enable the DEBUG command for redis-server >= 7.0.0
|
# 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
|
if [ "$REDIS_MAJOR_VERSION" -gt "6" ]; then
|
||||||
ENABLE_DEBUG_CMD="enable-debug-command local"
|
ENABLE_DEBUG_CMD="enable-debug-command local"
|
||||||
fi
|
fi
|
||||||
@ -98,7 +98,7 @@ if [ -n "${REDIS_DOCKER}" ] ; then
|
|||||||
-p ${REDIS_SSL_PORT}:${REDIS_SSL_PORT} \
|
-p ${REDIS_SSL_PORT}:${REDIS_SSL_PORT} \
|
||||||
-v ${tmpdir}:${tmpdir} \
|
-v ${tmpdir}:${tmpdir} \
|
||||||
${REDIS_DOCKER} \
|
${REDIS_DOCKER} \
|
||||||
${REDIS_SERVER} ${tmpdir}/redis.conf
|
redis-server ${tmpdir}/redis.conf
|
||||||
else
|
else
|
||||||
${REDIS_SERVER} ${tmpdir}/redis.conf
|
${REDIS_SERVER} ${tmpdir}/redis.conf
|
||||||
fi
|
fi
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user