Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
redis
Commits
d5c54f0b
Commit
d5c54f0b
authored
Dec 04, 2018
by
antirez
Browse files
RESP3: hiredis updated with recent version + some RESP3 support.
parent
809e3a44
Changes
16
Hide whitespace changes
Inline
Side-by-side
deps/hiredis/CHANGELOG.md
View file @
d5c54f0b
### 1.0.0 (unreleased)
**Fixes**
:
**BREAKING CHANGES**
:
*
Bulk and multi-bulk lengths less than -1 or greater than
`LLONG_MAX`
are now
protocol errors. This is consistent with the RESP specification. On 32-bit
platforms, the upper bound is lowered to
`SIZE_MAX`
.
*
Change
`redisReply.len`
to
`size_t`
, as it denotes the the size of a string
User code should compare this to
`size_t`
values as well. If it was used to
compare to other values, casting might be necessary or can be removed, if
casting was applied before.
### 0.14.0 (2018-09-25)
*
Make string2ll static to fix conflict with Redis (Tom Lee [c3188b])
*
Use -dynamiclib instead of -shared for OSX (Ryan Schmidt [a65537])
*
Use string2ll from Redis w/added tests (Michael Grunder [7bef04, 60f622])
*
Makefile - OSX compilation fixes (Ryan Schmidt [881fcb, 0e9af8])
*
Remove redundant NULL checks (Justin Brewer [54acc8, 58e6b8])
*
Fix bulk and multi-bulk length truncation (Justin Brewer [109197])
*
Fix SIGSEGV in OpenBSD by checking for NULL before calling freeaddrinfo (Justin Brewer [546d94])
*
Several POSIX compatibility fixes (Justin Brewer [bbeab8, 49bbaa, d1c1b6])
*
Makefile - Compatibility fixes (Dimitri Vorobiev [3238cf, 12a9d1])
*
Makefile - Fix make install on FreeBSD (Zach Shipko [a2ef2b])
*
Makefile - don't assume $(INSTALL) is cp (Igor Gnatenko [725a96])
*
Separate side-effect causing function from assert and small cleanup (amallia [b46413, 3c3234])
*
Don't send negative values to
`__redisAsyncCommand`
(Frederik Deweerdt [706129])
*
Fix leak if setsockopt fails (Frederik Deweerdt [e21c9c])
*
Fix libevent leak (zfz [515228])
*
Clean up GCC warning (Ichito Nagata [2ec774])
*
Keep track of errno in
`__redisSetErrorFromErrno()`
as snprintf may use it (Jin Qing [25cd88])
*
Solaris compilation fix (Donald Whyte [41b07d])
*
Reorder linker arguments when building examples (Tustfarm-heart [06eedd])
*
Keep track of subscriptions in case of rapid subscribe/unsubscribe (Hyungjin Kim [073dc8, be76c5, d46999])
*
libuv use after free fix (Paul Scott [cbb956])
*
Properly close socket fd on reconnect attempt (WSL [64d1ec])
*
Skip valgrind in OSX tests (Jan-Erik Rediger [9deb78])
*
Various updates for Travis testing OSX (Ted Nyman [fa3774, 16a459, bc0ea5])
*
Update libevent (Chris Xin [386802])
*
Change sds.h for building in C++ projects (Ali Volkan ATLI [f5b32e])
*
Use proper format specifier in redisFormatSdsCommandArgv (Paulino Huerta, Jan-Erik Rediger [360a06, 8655a6])
*
Better handling of NULL reply in example code (Jan-Erik Rediger [1b8ed3])
*
Prevent overflow when formatting an error (Jan-Erik Rediger [0335cb])
*
Compatibility fix for strerror_r (Tom Lee [bb1747])
*
Properly detect integer parse/overflow errors (Justin Brewer [93421f])
*
Adds CI for Windows and cygwin fixes (owent, [6c53d6, 6c3e40])
*
Catch a buffer overflow when formatting the error message
*
Import latest upstream sds. This breaks applications that are linked against the old hiredis v0.13
*
Fix warnings, when compiled with -Wshadow
...
...
@@ -9,11 +53,6 @@
**BREAKING CHANGES**
:
*
Change
`redisReply.len`
to
`size_t`
, as it denotes the the size of a string
User code should compare this to
`size_t`
values as well.
If it was used to compare to other values, casting might be necessary or can be removed, if casting was applied before.
*
Remove backwards compatibility macro's
This removes the following old function aliases, use the new name now:
...
...
@@ -94,7 +133,7 @@ The parser, standalone since v0.12.0, can now be compiled on Windows
*
Add IPv6 support
*
Remove possiblity of multiple close on same fd
*
Remove possib
i
lity of multiple close on same fd
*
Add ability to bind source address on connect
...
...
deps/hiredis/Makefile
View file @
d5c54f0b
...
...
@@ -36,13 +36,13 @@ endef
export
REDIS_TEST_CONFIG
# Fallback to gcc when $CC is not in $PATH.
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++'
)
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
-W
-Wstrict-prototypes
-Wwrite-strings
DEBUG_FLAGS
?=
-g
-ggdb
REAL_CFLAGS
=
$(OPTIMIZATION)
-fPIC
$(CFLAGS)
$(WARNINGS)
$(DEBUG_FLAGS)
$(ARCH)
REAL_LDFLAGS
=
$(LDFLAGS)
$(ARCH)
REAL_CFLAGS
=
$(OPTIMIZATION)
-fPIC
$(CPPFLAGS)
$(CFLAGS)
$(WARNINGS)
$(DEBUG_FLAGS)
REAL_LDFLAGS
=
$(LDFLAGS)
DYLIBSUFFIX
=
so
STLIBSUFFIX
=
a
...
...
@@ -58,12 +58,11 @@ uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
ifeq
($(uname_S),SunOS)
REAL_LDFLAGS
+=
-ldl
-lnsl
-lsocket
DYLIB_MAKE_CMD
=
$(CC)
-G
-o
$(DYLIBNAME)
-h
$(DYLIB_MINOR_NAME)
$(LDFLAGS)
INSTALL
=
cp
-r
endif
ifeq
($(uname_S),Darwin)
DYLIBSUFFIX
=
dylib
DYLIB_MINOR_NAME
=
$(LIBNAME)
.
$(HIREDIS_SONAME)
.
$(DYLIBSUFFIX)
DYLIB_MAKE_CMD
=
$(CC)
-
shared
-Wl
,-install_name,
$(DYLIB_MINOR_NAME)
-o
$(DYLIBNAME)
$(LDFLAGS)
DYLIB_MAKE_CMD
=
$(CC)
-
dynamiclib
-Wl
,-install_name,
$(
PREFIX)
/
$(LIBRARY_PATH)
/
$(
DYLIB_MINOR_NAME)
-o
$(DYLIBNAME)
$(LDFLAGS)
endif
all
:
$(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME)
...
...
@@ -94,7 +93,7 @@ hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
-lev
$(STLIBNAME)
hiredis-example-glib
:
examples/example-glib.c adapters/glib.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
$(
shell
pkg-config
--cflags
--libs
glib-2.0
)
-I
.
$<
$(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
$(
shell
pkg-config
--cflags
--libs
glib-2.0
)
$(STLIBNAME)
hiredis-example-ivykis
:
examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME)
$(CC)
-o
examples/
$@
$(REAL_CFLAGS)
$(REAL_LDFLAGS)
-I
.
$<
-livykis
$(STLIBNAME)
...
...
@@ -161,11 +160,7 @@ clean:
dep
:
$(CC)
-MM
*
.c
ifeq
($(uname_S),SunOS)
INSTALL
?=
cp
-r
endif
INSTALL
?=
cp
-a
INSTALL
?=
cp
-pPR
$(PKGCONFNAME)
:
hiredis.h
@
echo
"Generating
$@
for pkgconfig..."
...
...
@@ -181,8 +176,9 @@ $(PKGCONFNAME): hiredis.h
@
echo
Cflags:
-I
\$
${includedir}
-D_FILE_OFFSET_BITS
=
64
>>
$@
install
:
$(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
mkdir
-p
$(INSTALL_INCLUDE_PATH)
$(INSTALL_LIBRARY_PATH)
$(INSTALL)
hiredis.h async.h read.h sds.h adapters
$(INSTALL_INCLUDE_PATH)
mkdir
-p
$(INSTALL_INCLUDE_PATH)
$(INSTALL_INCLUDE_PATH)
/adapters
$(INSTALL_LIBRARY_PATH)
$(INSTALL)
hiredis.h async.h read.h sds.h
$(INSTALL_INCLUDE_PATH)
$(INSTALL)
adapters/
*
.h
$(INSTALL_INCLUDE_PATH)
/adapters
$(INSTALL)
$(DYLIBNAME)
$(INSTALL_LIBRARY_PATH)
/
$(DYLIB_MINOR_NAME)
cd
$(INSTALL_LIBRARY_PATH)
&&
ln
-sf
$(DYLIB_MINOR_NAME)
$(DYLIBNAME)
$(INSTALL)
$(STLIBNAME)
$(INSTALL_LIBRARY_PATH)
...
...
deps/hiredis/adapters/libevent.h
View file @
d5c54f0b
...
...
@@ -73,8 +73,8 @@ static void redisLibeventDelWrite(void *privdata) {
static
void
redisLibeventCleanup
(
void
*
privdata
)
{
redisLibeventEvents
*
e
=
(
redisLibeventEvents
*
)
privdata
;
event_
del
(
e
->
rev
);
event_
del
(
e
->
wev
);
event_
free
(
e
->
rev
);
event_
free
(
e
->
wev
);
free
(
e
);
}
...
...
deps/hiredis/adapters/libuv.h
View file @
d5c54f0b
...
...
@@ -15,15 +15,12 @@ typedef struct redisLibuvEvents {
static
void
redisLibuvPoll
(
uv_poll_t
*
handle
,
int
status
,
int
events
)
{
redisLibuvEvents
*
p
=
(
redisLibuvEvents
*
)
handle
->
data
;
int
ev
=
(
status
?
p
->
events
:
events
);
if
(
status
!=
0
)
{
return
;
}
if
(
p
->
context
!=
NULL
&&
(
events
&
UV_READABLE
))
{
if
(
p
->
context
!=
NULL
&&
(
ev
&
UV_READABLE
))
{
redisAsyncHandleRead
(
p
->
context
);
}
if
(
p
->
context
!=
NULL
&&
(
ev
ents
&
UV_WRITABLE
))
{
if
(
p
->
context
!=
NULL
&&
(
ev
&
UV_WRITABLE
))
{
redisAsyncHandleWrite
(
p
->
context
);
}
}
...
...
deps/hiredis/appveyor.yml
View file @
d5c54f0b
# Appveyor configuration file for CI build of hiredis on Windows (under Cygwin)
environment
:
matrix
:
-
CYG_ROOT
:
C:\cygwin64
CYG_SETUP
:
setup-x86_64.exe
CYG_MIRROR
:
http://cygwin.mirror.constant.com
CYG_CACHE
:
C:\cygwin64\var\cache\setup
CYG_BASH
:
C:\cygwin64\bin\bash
-
CYG_BASH
:
C:\cygwin64\bin\bash
CC
:
gcc
-
CYG_ROOT
:
C:\cygwin
CYG_SETUP
:
setup-x86.exe
CYG_MIRROR
:
http://cygwin.mirror.constant.com
CYG_CACHE
:
C:\cygwin\var\cache\setup
CYG_BASH
:
C:\cygwin\bin\bash
-
CYG_BASH
:
C:\cygwin\bin\bash
CC
:
gcc
TARGET
:
32bit
TARGET_VARS
:
32bit-vars
# Cache Cygwin files to speed up build
cache
:
-
'
%CYG_CACHE%'
clone_depth
:
1
# Attempt to ensure we don't try to convert line endings to Win32 CRLF as this will cause build to fail
...
...
@@ -27,8 +16,6 @@ init:
# Install needed build dependencies
install
:
-
ps
:
'
Start-FileDownload
"http://cygwin.com/$env:CYG_SETUP"
-FileName
"$env:CYG_SETUP"'
-
'
%CYG_SETUP%
--quiet-mode
--no-shortcuts
--only-site
--root
"%CYG_ROOT%"
--site
"%CYG_MIRROR%"
--local-package-dir
"%CYG_CACHE%"
--packages
automake,bison,gcc-core,libtool,make,gettext-devel,gettext,intltool,pkg-config,clang,llvm
>
NUL
2>&1'
-
'
%CYG_BASH%
-lc
"cygcheck
-dc
cygwin"'
build_script
:
...
...
deps/hiredis/async.c
View file @
d5c54f0b
...
...
@@ -336,7 +336,8 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
if
(
ac
->
err
==
0
)
{
/* For clean disconnects, there should be no pending callbacks. */
assert
(
__redisShiftCallback
(
&
ac
->
replies
,
NULL
)
==
REDIS_ERR
);
int
ret
=
__redisShiftCallback
(
&
ac
->
replies
,
NULL
);
assert
(
ret
==
REDIS_ERR
);
}
else
{
/* Disconnection is caused by an error, make sure that pending
* callbacks cannot call new commands. */
...
...
@@ -364,6 +365,7 @@ void redisAsyncDisconnect(redisAsyncContext *ac) {
static
int
__redisGetSubscribeCallback
(
redisAsyncContext
*
ac
,
redisReply
*
reply
,
redisCallback
*
dstcb
)
{
redisContext
*
c
=
&
(
ac
->
c
);
dict
*
callbacks
;
redisCallback
*
cb
;
dictEntry
*
de
;
int
pvariant
;
char
*
stype
;
...
...
@@ -387,16 +389,28 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
sname
=
sdsnewlen
(
reply
->
element
[
1
]
->
str
,
reply
->
element
[
1
]
->
len
);
de
=
dictFind
(
callbacks
,
sname
);
if
(
de
!=
NULL
)
{
memcpy
(
dstcb
,
dictGetEntryVal
(
de
),
sizeof
(
*
dstcb
));
cb
=
dictGetEntryVal
(
de
);
/* If this is an subscribe reply decrease pending counter. */
if
(
strcasecmp
(
stype
+
pvariant
,
"subscribe"
)
==
0
)
{
cb
->
pending_subs
-=
1
;
}
memcpy
(
dstcb
,
cb
,
sizeof
(
*
dstcb
));
/* If this is an unsubscribe message, remove it. */
if
(
strcasecmp
(
stype
+
pvariant
,
"unsubscribe"
)
==
0
)
{
dictDelete
(
callbacks
,
sname
);
if
(
cb
->
pending_subs
==
0
)
dictDelete
(
callbacks
,
sname
);
/* If this was the last unsubscribe message, revert to
* non-subscribe mode. */
assert
(
reply
->
element
[
2
]
->
type
==
REDIS_REPLY_INTEGER
);
if
(
reply
->
element
[
2
]
->
integer
==
0
)
/* Unset subscribed flag only when no pipelined pending subscribe. */
if
(
reply
->
element
[
2
]
->
integer
==
0
&&
dictSize
(
ac
->
sub
.
channels
)
==
0
&&
dictSize
(
ac
->
sub
.
patterns
)
==
0
)
c
->
flags
&=
~
REDIS_SUBSCRIBED
;
}
}
...
...
@@ -410,7 +424,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
void
redisProcessCallbacks
(
redisAsyncContext
*
ac
)
{
redisContext
*
c
=
&
(
ac
->
c
);
redisCallback
cb
=
{
NULL
,
NULL
,
NULL
};
redisCallback
cb
=
{
NULL
,
NULL
,
0
,
NULL
};
void
*
reply
=
NULL
;
int
status
;
...
...
@@ -492,22 +506,22 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
* write event fires. When connecting was not successful, the connect callback
* is called with a REDIS_ERR status and the context is free'd. */
static
int
__redisAsyncHandleConnect
(
redisAsyncContext
*
ac
)
{
int
completed
=
0
;
redisContext
*
c
=
&
(
ac
->
c
);
if
(
redisCheckSocketError
(
c
)
==
REDIS_ERR
)
{
/* Try again later when connect(2) is still in progress. */
if
(
errno
==
EINPROGRESS
)
return
REDIS_OK
;
if
(
ac
->
onConnect
)
ac
->
onConnect
(
ac
,
REDIS_ERR
);
if
(
redisCheckConnectDone
(
c
,
&
completed
)
==
REDIS_ERR
)
{
/* Error! */
redisCheckSocketError
(
c
);
if
(
ac
->
onConnect
)
ac
->
onConnect
(
ac
,
REDIS_ERR
);
__redisAsyncDisconnect
(
ac
);
return
REDIS_ERR
;
}
else
if
(
completed
==
1
)
{
/* connected! */
if
(
ac
->
onConnect
)
ac
->
onConnect
(
ac
,
REDIS_OK
);
c
->
flags
|=
REDIS_CONNECTED
;
return
REDIS_OK
;
}
else
{
return
REDIS_OK
;
}
/* Mark context as connected. */
c
->
flags
|=
REDIS_CONNECTED
;
if
(
ac
->
onConnect
)
ac
->
onConnect
(
ac
,
REDIS_OK
);
return
REDIS_OK
;
}
/* This function should be called when the socket is readable.
...
...
@@ -583,6 +597,9 @@ static const char *nextArgument(const char *start, const char **str, size_t *len
static
int
__redisAsyncCommand
(
redisAsyncContext
*
ac
,
redisCallbackFn
*
fn
,
void
*
privdata
,
const
char
*
cmd
,
size_t
len
)
{
redisContext
*
c
=
&
(
ac
->
c
);
redisCallback
cb
;
struct
dict
*
cbdict
;
dictEntry
*
de
;
redisCallback
*
existcb
;
int
pvariant
,
hasnext
;
const
char
*
cstr
,
*
astr
;
size_t
clen
,
alen
;
...
...
@@ -596,6 +613,7 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
/* Setup callback */
cb
.
fn
=
fn
;
cb
.
privdata
=
privdata
;
cb
.
pending_subs
=
1
;
/* Find out which command will be appended. */
p
=
nextArgument
(
cmd
,
&
cstr
,
&
clen
);
...
...
@@ -612,9 +630,18 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
while
((
p
=
nextArgument
(
p
,
&
astr
,
&
alen
))
!=
NULL
)
{
sname
=
sdsnewlen
(
astr
,
alen
);
if
(
pvariant
)
ret
=
dictReplace
(
ac
->
sub
.
patterns
,
sname
,
&
cb
)
;
cbdict
=
ac
->
sub
.
patterns
;
else
ret
=
dictReplace
(
ac
->
sub
.
channels
,
sname
,
&
cb
);
cbdict
=
ac
->
sub
.
channels
;
de
=
dictFind
(
cbdict
,
sname
);
if
(
de
!=
NULL
)
{
existcb
=
dictGetEntryVal
(
de
);
cb
.
pending_subs
=
existcb
->
pending_subs
+
1
;
}
ret
=
dictReplace
(
cbdict
,
sname
,
&
cb
);
if
(
ret
==
0
)
sdsfree
(
sname
);
}
...
...
@@ -676,6 +703,8 @@ int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *priv
int
len
;
int
status
;
len
=
redisFormatSdsCommandArgv
(
&
cmd
,
argc
,
argv
,
argvlen
);
if
(
len
<
0
)
return
REDIS_ERR
;
status
=
__redisAsyncCommand
(
ac
,
fn
,
privdata
,
cmd
,
len
);
sdsfree
(
cmd
);
return
status
;
...
...
deps/hiredis/async.h
View file @
d5c54f0b
...
...
@@ -45,6 +45,7 @@ typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);
typedef
struct
redisCallback
{
struct
redisCallback
*
next
;
/* simple singly linked list */
redisCallbackFn
*
fn
;
int
pending_subs
;
void
*
privdata
;
}
redisCallback
;
...
...
@@ -92,6 +93,10 @@ typedef struct redisAsyncContext {
/* Regular command callbacks */
redisCallbackList
replies
;
/* Address used for connect() */
struct
sockaddr
*
saddr
;
size_t
addrlen
;
/* Subscription callbacks */
struct
{
redisCallbackList
invalid
;
...
...
deps/hiredis/fmacros.h
View file @
d5c54f0b
#ifndef __HIREDIS_FMACRO_H
#define __HIREDIS_FMACRO_H
#if defined(__linux__)
#define _BSD_SOURCE
#define _DEFAULT_SOURCE
#endif
#if defined(__CYGWIN__)
#include <sys/cdefs.h>
#endif
#if defined(__sun__)
#define _POSIX_C_SOURCE 200112L
#else
#if !(defined(__APPLE__) && defined(__MACH__)) && !(defined(__FreeBSD__))
#define _XOPEN_SOURCE 600
#endif
#endif
#define _POSIX_C_SOURCE 200112L
#if defined(__APPLE__) && defined(__MACH__)
#define _OSX
/* Enable TCP_KEEPALIVE */
#define _DARWIN_C_SOURCE
#endif
#endif
deps/hiredis/hiredis.c
View file @
d5c54f0b
...
...
@@ -84,16 +84,14 @@ void freeReplyObject(void *reply) {
case
REDIS_REPLY_ARRAY
:
if
(
r
->
element
!=
NULL
)
{
for
(
j
=
0
;
j
<
r
->
elements
;
j
++
)
if
(
r
->
element
[
j
]
!=
NULL
)
freeReplyObject
(
r
->
element
[
j
]);
freeReplyObject
(
r
->
element
[
j
]);
free
(
r
->
element
);
}
break
;
case
REDIS_REPLY_ERROR
:
case
REDIS_REPLY_STATUS
:
case
REDIS_REPLY_STRING
:
if
(
r
->
str
!=
NULL
)
free
(
r
->
str
);
free
(
r
->
str
);
break
;
}
free
(
r
);
...
...
@@ -432,11 +430,7 @@ cleanup:
}
sdsfree
(
curarg
);
/* No need to check cmd since it is the last statement that can fail,
* but do it anyway to be as defensive as possible. */
if
(
cmd
!=
NULL
)
free
(
cmd
);
free
(
cmd
);
return
error_type
;
}
...
...
@@ -581,7 +575,7 @@ void __redisSetError(redisContext *c, int type, const char *str) {
}
else
{
/* Only REDIS_ERR_IO may lack a description! */
assert
(
type
==
REDIS_ERR_IO
);
__redis_
strerror_r
(
errno
,
c
->
errstr
,
sizeof
(
c
->
errstr
));
strerror_r
(
errno
,
c
->
errstr
,
sizeof
(
c
->
errstr
));
}
}
...
...
@@ -596,14 +590,8 @@ static redisContext *redisContextInit(void) {
if
(
c
==
NULL
)
return
NULL
;
c
->
err
=
0
;
c
->
errstr
[
0
]
=
'\0'
;
c
->
obuf
=
sdsempty
();
c
->
reader
=
redisReaderCreate
();
c
->
tcp
.
host
=
NULL
;
c
->
tcp
.
source_addr
=
NULL
;
c
->
unix_sock
.
path
=
NULL
;
c
->
timeout
=
NULL
;
if
(
c
->
obuf
==
NULL
||
c
->
reader
==
NULL
)
{
redisFree
(
c
);
...
...
@@ -618,18 +606,14 @@ void redisFree(redisContext *c) {
return
;
if
(
c
->
fd
>
0
)
close
(
c
->
fd
);
if
(
c
->
obuf
!=
NULL
)
sdsfree
(
c
->
obuf
);
if
(
c
->
reader
!=
NULL
)
redisReaderFree
(
c
->
reader
);
if
(
c
->
tcp
.
host
)
free
(
c
->
tcp
.
host
);
if
(
c
->
tcp
.
source_addr
)
free
(
c
->
tcp
.
source_addr
);
if
(
c
->
unix_sock
.
path
)
free
(
c
->
unix_sock
.
path
);
if
(
c
->
timeout
)
free
(
c
->
timeout
);
sdsfree
(
c
->
obuf
);
redisReaderFree
(
c
->
reader
);
free
(
c
->
tcp
.
host
);
free
(
c
->
tcp
.
source_addr
);
free
(
c
->
unix_sock
.
path
);
free
(
c
->
timeout
);
free
(
c
->
saddr
);
free
(
c
);
}
...
...
@@ -710,6 +694,8 @@ redisContext *redisConnectNonBlock(const char *ip, int port) {
redisContext
*
redisConnectBindNonBlock
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisContext
*
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
&=
~
REDIS_BLOCK
;
redisContextConnectBindTcp
(
c
,
ip
,
port
,
NULL
,
source_addr
);
return
c
;
...
...
@@ -718,6 +704,8 @@ redisContext *redisConnectBindNonBlock(const char *ip, int port,
redisContext
*
redisConnectBindNonBlockWithReuse
(
const
char
*
ip
,
int
port
,
const
char
*
source_addr
)
{
redisContext
*
c
=
redisContextInit
();
if
(
c
==
NULL
)
return
NULL
;
c
->
flags
&=
~
REDIS_BLOCK
;
c
->
flags
|=
REDIS_REUSEADDR
;
redisContextConnectBindTcp
(
c
,
ip
,
port
,
NULL
,
source_addr
);
...
...
@@ -789,7 +777,7 @@ int redisEnableKeepAlive(redisContext *c) {
/* Use this function to handle a read event on the descriptor. It will try
* and read some bytes from the socket and feed them to the reply parser.
*
* After this function is called, you may use redis
ContextReadReply
to
* After this function is called, you may use redis
GetReplyFromReader
to
* see if there is a reply available. */
int
redisBufferRead
(
redisContext
*
c
)
{
char
buf
[
1024
*
16
];
...
...
@@ -1007,9 +995,8 @@ void *redisvCommand(redisContext *c, const char *format, va_list ap) {
void
*
redisCommand
(
redisContext
*
c
,
const
char
*
format
,
...)
{
va_list
ap
;
void
*
reply
=
NULL
;
va_start
(
ap
,
format
);
reply
=
redisvCommand
(
c
,
format
,
ap
);
void
*
reply
=
redisvCommand
(
c
,
format
,
ap
);
va_end
(
ap
);
return
reply
;
}
...
...
deps/hiredis/hiredis.h
View file @
d5c54f0b
...
...
@@ -40,9 +40,9 @@
#include "sds.h"
/* for sds */
#define HIREDIS_MAJOR 0
#define HIREDIS_MINOR 1
3
#define HIREDIS_PATCH
3
#define HIREDIS_SONAME 0.1
3
#define HIREDIS_MINOR 1
4
#define HIREDIS_PATCH
0
#define HIREDIS_SONAME 0.1
4
/* Connection type can be blocking or non-blocking and is set in the
* least significant bit of the flags field in redisContext. */
...
...
@@ -80,30 +80,6 @@
* SO_REUSEADDR is being used. */
#define REDIS_CONNECT_RETRIES 10
/* strerror_r has two completely different prototypes and behaviors
* depending on system issues, so we need to operate on the error buffer
* differently depending on which strerror_r we're using. */
#ifndef _GNU_SOURCE
/* "regular" POSIX strerror_r that does the right thing. */
#define __redis_strerror_r(errno, buf, len) \
do { \
strerror_r((errno), (buf), (len)); \
} while (0)
#else
/* "bad" GNU strerror_r we need to clean up after. */
#define __redis_strerror_r(errno, buf, len) \
do { \
char *err_str = strerror_r((errno), (buf), (len)); \
/* If return value _isn't_ the start of the buffer we passed in, \
* then GNU strerror_r returned an internal static buffer and we \
* need to copy the result into our private buffer. */
\
if (err_str != (buf)) { \
strncpy((buf), err_str, ((len) - 1)); \
buf[(len)-1] = '\0'; \
} \
} while (0)
#endif
#ifdef __cplusplus
extern
"C"
{
#endif
...
...
@@ -158,6 +134,9 @@ typedef struct redisContext {
char
*
path
;
}
unix_sock
;
/* For non-blocking connect */
struct
sockadr
*
saddr
;
size_t
addrlen
;
}
redisContext
;
redisContext
*
redisConnect
(
const
char
*
ip
,
int
port
);
...
...
deps/hiredis/net.c
View file @
d5c54f0b
...
...
@@ -65,12 +65,13 @@ static void redisContextCloseFd(redisContext *c) {
}
static
void
__redisSetErrorFromErrno
(
redisContext
*
c
,
int
type
,
const
char
*
prefix
)
{
int
errorno
=
errno
;
/* snprintf() may change errno */
char
buf
[
128
]
=
{
0
};
size_t
len
=
0
;
if
(
prefix
!=
NULL
)
len
=
snprintf
(
buf
,
sizeof
(
buf
),
"%s: "
,
prefix
);
__redis_
strerror_r
(
errno
,
(
char
*
)(
buf
+
len
),
sizeof
(
buf
)
-
len
);
strerror_r
(
err
or
no
,
(
char
*
)(
buf
+
len
),
sizeof
(
buf
)
-
len
);
__redisSetError
(
c
,
type
,
buf
);
}
...
...
@@ -135,14 +136,13 @@ int redisKeepAlive(redisContext *c, int interval) {
val
=
interval
;
#ifdef
_OSX
#if
def
ined(__APPLE__) && defined(__MACH__)
if
(
setsockopt
(
fd
,
IPPROTO_TCP
,
TCP_KEEPALIVE
,
&
val
,
sizeof
(
val
))
<
0
)
{
__redisSetError
(
c
,
REDIS_ERR_OTHER
,
strerror
(
errno
));
return
REDIS_ERR
;
}
#else
#if defined(__GLIBC__) && !defined(__FreeBSD_kernel__)
val
=
interval
;
if
(
setsockopt
(
fd
,
IPPROTO_TCP
,
TCP_KEEPIDLE
,
&
val
,
sizeof
(
val
))
<
0
)
{
__redisSetError
(
c
,
REDIS_ERR_OTHER
,
strerror
(
errno
));
return
REDIS_ERR
;
...
...
@@ -221,8 +221,10 @@ static int redisContextWaitReady(redisContext *c, long msec) {
return
REDIS_ERR
;
}
if
(
redisCheckSocketError
(
c
)
!=
REDIS_OK
)
if
(
redisCheckConnectDone
(
c
,
&
res
)
!=
REDIS_OK
||
res
==
0
)
{
redisCheckSocketError
(
c
);
return
REDIS_ERR
;
}
return
REDIS_OK
;
}
...
...
@@ -232,8 +234,28 @@ static int redisContextWaitReady(redisContext *c, long msec) {
return
REDIS_ERR
;
}
int
redisCheckConnectDone
(
redisContext
*
c
,
int
*
completed
)
{
int
rc
=
connect
(
c
->
fd
,
(
const
struct
sockaddr
*
)
c
->
saddr
,
c
->
addrlen
);
if
(
rc
==
0
)
{
*
completed
=
1
;
return
REDIS_OK
;
}
switch
(
errno
)
{
case
EISCONN
:
*
completed
=
1
;
return
REDIS_OK
;
case
EALREADY
:
case
EINPROGRESS
:
case
EWOULDBLOCK
:
*
completed
=
0
;
return
REDIS_OK
;
default:
return
REDIS_ERR
;
}
}
int
redisCheckSocketError
(
redisContext
*
c
)
{
int
err
=
0
;
int
err
=
0
,
errno_saved
=
errno
;
socklen_t
errlen
=
sizeof
(
err
);
if
(
getsockopt
(
c
->
fd
,
SOL_SOCKET
,
SO_ERROR
,
&
err
,
&
errlen
)
==
-
1
)
{
...
...
@@ -241,6 +263,10 @@ int redisCheckSocketError(redisContext *c) {
return
REDIS_ERR
;
}
if
(
err
==
0
)
{
err
=
errno_saved
;
}
if
(
err
)
{
errno
=
err
;
__redisSetErrorFromErrno
(
c
,
REDIS_ERR_IO
,
NULL
);
...
...
@@ -285,8 +311,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
* This is a bit ugly, but atleast it works and doesn't leak memory.
**/
if
(
c
->
tcp
.
host
!=
addr
)
{
if
(
c
->
tcp
.
host
)
free
(
c
->
tcp
.
host
);
free
(
c
->
tcp
.
host
);
c
->
tcp
.
host
=
strdup
(
addr
);
}
...
...
@@ -299,8 +324,7 @@ static int _redisContextConnectTcp(redisContext *c, const char *addr, int port,
memcpy
(
c
->
timeout
,
timeout
,
sizeof
(
struct
timeval
));
}
}
else
{
if
(
c
->
timeout
)
free
(
c
->
timeout
);
free
(
c
->
timeout
);
c
->
timeout
=
NULL
;
}
...
...
@@ -356,6 +380,7 @@ addrretry:
n
=
1
;
if
(
setsockopt
(
s
,
SOL_SOCKET
,
SO_REUSEADDR
,
(
char
*
)
&
n
,
sizeof
(
n
))
<
0
)
{
freeaddrinfo
(
bservinfo
);
goto
error
;
}
}
...
...
@@ -374,12 +399,27 @@ addrretry:
goto
error
;
}
}
/* For repeat connection */
if
(
c
->
saddr
)
{
free
(
c
->
saddr
);
}
c
->
saddr
=
malloc
(
p
->
ai_addrlen
);
memcpy
(
c
->
saddr
,
p
->
ai_addr
,
p
->
ai_addrlen
);
c
->
addrlen
=
p
->
ai_addrlen
;
if
(
connect
(
s
,
p
->
ai_addr
,
p
->
ai_addrlen
)
==
-
1
)
{
if
(
errno
==
EHOSTUNREACH
)
{
redisContextCloseFd
(
c
);
continue
;
}
else
if
(
errno
==
EINPROGRESS
&&
!
blocking
)
{
/* This is ok. */
}
else
if
(
errno
==
EINPROGRESS
)
{
if
(
blocking
)
{
goto
wait_for_ready
;
}
/* This is ok.
* Note that even when it's in blocking mode, we unset blocking
* for `connect()`
*/
}
else
if
(
errno
==
EADDRNOTAVAIL
&&
reuseaddr
)
{
if
(
++
reuses
>=
REDIS_CONNECT_RETRIES
)
{
goto
error
;
...
...
@@ -388,6 +428,7 @@ addrretry:
goto
addrretry
;
}
}
else
{
wait_for_ready:
if
(
redisContextWaitReady
(
c
,
timeout_msec
)
!=
REDIS_OK
)
goto
error
;
}
...
...
@@ -411,7 +452,10 @@ addrretry:
error:
rv
=
REDIS_ERR
;
end:
freeaddrinfo
(
servinfo
);
if
(
servinfo
)
{
freeaddrinfo
(
servinfo
);
}
return
rv
;
// Need to return REDIS_OK if alright
}
...
...
@@ -431,7 +475,7 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
struct
sockaddr_un
sa
;
long
timeout_msec
=
-
1
;
if
(
redisCreateSocket
(
c
,
AF_
LOCAL
)
<
0
)
if
(
redisCreateSocket
(
c
,
AF_
UNIX
)
<
0
)
return
REDIS_ERR
;
if
(
redisSetBlocking
(
c
,
0
)
!=
REDIS_OK
)
return
REDIS_ERR
;
...
...
@@ -448,15 +492,14 @@ int redisContextConnectUnix(redisContext *c, const char *path, const struct time
memcpy
(
c
->
timeout
,
timeout
,
sizeof
(
struct
timeval
));
}
}
else
{
if
(
c
->
timeout
)
free
(
c
->
timeout
);
free
(
c
->
timeout
);
c
->
timeout
=
NULL
;
}
if
(
redisContextTimeoutMsec
(
c
,
&
timeout_msec
)
!=
REDIS_OK
)
return
REDIS_ERR
;
sa
.
sun_family
=
AF_
LOCAL
;
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
==
EINPROGRESS
&&
!
blocking
)
{
...
...
deps/hiredis/net.h
View file @
d5c54f0b
...
...
@@ -37,10 +37,6 @@
#include "hiredis.h"
#if defined(__sun)
#define AF_LOCAL AF_UNIX
#endif
int
redisCheckSocketError
(
redisContext
*
c
);
int
redisContextSetTimeout
(
redisContext
*
c
,
const
struct
timeval
tv
);
int
redisContextConnectTcp
(
redisContext
*
c
,
const
char
*
addr
,
int
port
,
const
struct
timeval
*
timeout
);
...
...
@@ -49,5 +45,6 @@ int redisContextConnectBindTcp(redisContext *c, const char *addr, int port,
const
char
*
source_addr
);
int
redisContextConnectUnix
(
redisContext
*
c
,
const
char
*
path
,
const
struct
timeval
*
timeout
);
int
redisKeepAlive
(
redisContext
*
c
,
int
interval
);
int
redisCheckConnectDone
(
redisContext
*
c
,
int
*
completed
);
#endif
deps/hiredis/read.c
View file @
d5c54f0b
...
...
@@ -39,6 +39,7 @@
#include <assert.h>
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include "read.h"
#include "sds.h"
...
...
@@ -52,11 +53,9 @@ static void __redisReaderSetError(redisReader *r, int type, const char *str) {
}
/* Clear input buffer on errors. */
if
(
r
->
buf
!=
NULL
)
{
sdsfree
(
r
->
buf
);
r
->
buf
=
NULL
;
r
->
pos
=
r
->
len
=
0
;
}
sdsfree
(
r
->
buf
);
r
->
buf
=
NULL
;
r
->
pos
=
r
->
len
=
0
;
/* Reset task stack. */
r
->
ridx
=
-
1
;
...
...
@@ -143,33 +142,79 @@ static char *seekNewline(char *s, size_t len) {
return
NULL
;
}
/* Read a long long value starting at *s, under the assumption that it will be
* terminated by \r\n. Ambiguously returns -1 for unexpected input. */
static
long
long
readLongLong
(
char
*
s
)
{
long
long
v
=
0
;
int
dec
,
mult
=
1
;
char
c
;
if
(
*
s
==
'-'
)
{
mult
=
-
1
;
s
++
;
}
else
if
(
*
s
==
'+'
)
{
mult
=
1
;
s
++
;
/* Convert a string into a long long. Returns REDIS_OK if the string could be
* parsed into a (non-overflowing) long long, REDIS_ERR otherwise. The value
* will be set to the parsed value when appropriate.
*
* Note that this function demands that the string strictly represents
* a long long: no spaces or other characters before or after the string
* representing the number are accepted, nor zeroes at the start if not
* for the string "0" representing the zero number.
*
* Because of its strictness, it is safe to use this function to check if
* you can convert a string into a long long, and obtain back the string
* from the number without any loss in the string representation. */
static
int
string2ll
(
const
char
*
s
,
size_t
slen
,
long
long
*
value
)
{
const
char
*
p
=
s
;
size_t
plen
=
0
;
int
negative
=
0
;
unsigned
long
long
v
;
if
(
plen
==
slen
)
return
REDIS_ERR
;
/* Special case: first and only digit is 0. */
if
(
slen
==
1
&&
p
[
0
]
==
'0'
)
{
if
(
value
!=
NULL
)
*
value
=
0
;
return
REDIS_OK
;
}
while
((
c
=
*
(
s
++
))
!=
'\r'
)
{
dec
=
c
-
'0'
;
if
(
dec
>=
0
&&
dec
<
10
)
{
v
*=
10
;
v
+=
dec
;
}
else
{
/* Should not happen... */
return
-
1
;
}
if
(
p
[
0
]
==
'-'
)
{
negative
=
1
;
p
++
;
plen
++
;
/* Abort on only a negative sign. */
if
(
plen
==
slen
)
return
REDIS_ERR
;
}
return
mult
*
v
;
/* First digit should be 1-9, otherwise the string should just be 0. */
if
(
p
[
0
]
>=
'1'
&&
p
[
0
]
<=
'9'
)
{
v
=
p
[
0
]
-
'0'
;
p
++
;
plen
++
;
}
else
if
(
p
[
0
]
==
'0'
&&
slen
==
1
)
{
*
value
=
0
;
return
REDIS_OK
;
}
else
{
return
REDIS_ERR
;
}
while
(
plen
<
slen
&&
p
[
0
]
>=
'0'
&&
p
[
0
]
<=
'9'
)
{
if
(
v
>
(
ULLONG_MAX
/
10
))
/* Overflow. */
return
REDIS_ERR
;
v
*=
10
;
if
(
v
>
(
ULLONG_MAX
-
(
p
[
0
]
-
'0'
)))
/* Overflow. */
return
REDIS_ERR
;
v
+=
p
[
0
]
-
'0'
;
p
++
;
plen
++
;
}
/* Return if not all bytes were used. */
if
(
plen
<
slen
)
return
REDIS_ERR
;
if
(
negative
)
{
if
(
v
>
((
unsigned
long
long
)(
-
(
LLONG_MIN
+
1
))
+
1
))
/* Overflow. */
return
REDIS_ERR
;
if
(
value
!=
NULL
)
*
value
=
-
v
;
}
else
{
if
(
v
>
LLONG_MAX
)
/* Overflow. */
return
REDIS_ERR
;
if
(
value
!=
NULL
)
*
value
=
v
;
}
return
REDIS_OK
;
}
static
char
*
readLine
(
redisReader
*
r
,
int
*
_len
)
{
...
...
@@ -220,10 +265,17 @@ static int processLineItem(redisReader *r) {
if
((
p
=
readLine
(
r
,
&
len
))
!=
NULL
)
{
if
(
cur
->
type
==
REDIS_REPLY_INTEGER
)
{
if
(
r
->
fn
&&
r
->
fn
->
createInteger
)
obj
=
r
->
fn
->
createInteger
(
cur
,
readLongLong
(
p
));
else
if
(
r
->
fn
&&
r
->
fn
->
createInteger
)
{
long
long
v
;
if
(
string2ll
(
p
,
len
,
&
v
)
==
REDIS_ERR
)
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Bad integer value"
);
return
REDIS_ERR
;
}
obj
=
r
->
fn
->
createInteger
(
cur
,
v
);
}
else
{
obj
=
(
void
*
)
REDIS_REPLY_INTEGER
;
}
}
else
{
/* Type will be error or status. */
if
(
r
->
fn
&&
r
->
fn
->
createString
)
...
...
@@ -250,7 +302,7 @@ static int processBulkItem(redisReader *r) {
redisReadTask
*
cur
=
&
(
r
->
rstack
[
r
->
ridx
]);
void
*
obj
=
NULL
;
char
*
p
,
*
s
;
long
len
;
long
long
len
;
unsigned
long
bytelen
;
int
success
=
0
;
...
...
@@ -259,9 +311,20 @@ static int processBulkItem(redisReader *r) {
if
(
s
!=
NULL
)
{
p
=
r
->
buf
+
r
->
pos
;
bytelen
=
s
-
(
r
->
buf
+
r
->
pos
)
+
2
;
/* include \r\n */
len
=
readLongLong
(
p
);
if
(
len
<
0
)
{
if
(
string2ll
(
p
,
bytelen
-
2
,
&
len
)
==
REDIS_ERR
)
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Bad bulk string length"
);
return
REDIS_ERR
;
}
if
(
len
<
-
1
||
(
LLONG_MAX
>
SIZE_MAX
&&
len
>
(
long
long
)
SIZE_MAX
))
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Bulk string length out of range"
);
return
REDIS_ERR
;
}
if
(
len
==
-
1
)
{
/* The nil object can always be created. */
if
(
r
->
fn
&&
r
->
fn
->
createNil
)
obj
=
r
->
fn
->
createNil
(
cur
);
...
...
@@ -299,12 +362,13 @@ static int processBulkItem(redisReader *r) {
return
REDIS_ERR
;
}
static
int
processMultiBulkItem
(
redisReader
*
r
)
{
/* Process the array, map and set types. */
static
int
processAggregateItem
(
redisReader
*
r
)
{
redisReadTask
*
cur
=
&
(
r
->
rstack
[
r
->
ridx
]);
void
*
obj
;
char
*
p
;
long
elements
;
int
root
=
0
;
long
long
elements
;
int
root
=
0
,
len
;
/* Set error for nested multi bulks with depth > 7 */
if
(
r
->
ridx
==
8
)
{
...
...
@@ -313,10 +377,21 @@ static int processMultiBulkItem(redisReader *r) {
return
REDIS_ERR
;
}
if
((
p
=
readLine
(
r
,
NULL
))
!=
NULL
)
{
elements
=
readLongLong
(
p
);
if
((
p
=
readLine
(
r
,
&
len
))
!=
NULL
)
{
if
(
string2ll
(
p
,
len
,
&
elements
)
==
REDIS_ERR
)
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Bad multi-bulk length"
);
return
REDIS_ERR
;
}
root
=
(
r
->
ridx
==
0
);
if
(
elements
<
-
1
||
elements
>
INT_MAX
)
{
__redisReaderSetError
(
r
,
REDIS_ERR_PROTOCOL
,
"Multi-bulk length out of range"
);
return
REDIS_ERR
;
}
if
(
elements
==
-
1
)
{
if
(
r
->
fn
&&
r
->
fn
->
createNil
)
obj
=
r
->
fn
->
createNil
(
cur
);
...
...
@@ -330,10 +405,12 @@ static int processMultiBulkItem(redisReader *r) {
moveToNextTask
(
r
);
}
else
{
if
(
cur
->
type
==
REDIS_REPLY_MAP
)
elements
*=
2
;
if
(
r
->
fn
&&
r
->
fn
->
createArray
)
obj
=
r
->
fn
->
createArray
(
cur
,
elements
);
else
obj
=
(
void
*
)
REDIS_REPLY_ARRAY
;
obj
=
(
void
*
)
(
long
)
cur
->
type
;
if
(
obj
==
NULL
)
{
__redisReaderSetErrorOOM
(
r
);
...
...
@@ -387,6 +464,12 @@ static int processItem(redisReader *r) {
case
'*'
:
cur
->
type
=
REDIS_REPLY_ARRAY
;
break
;
case
'%'
:
cur
->
type
=
REDIS_REPLY_MAP
;
break
;
case
'~'
:
cur
->
type
=
REDIS_REPLY_SET
;
break
;
default:
__redisReaderSetErrorProtocolByte
(
r
,
*
p
);
return
REDIS_ERR
;
...
...
@@ -406,7 +489,9 @@ static int processItem(redisReader *r) {
case
REDIS_REPLY_STRING
:
return
processBulkItem
(
r
);
case
REDIS_REPLY_ARRAY
:
return
processMultiBulkItem
(
r
);
case
REDIS_REPLY_MAP
:
case
REDIS_REPLY_SET
:
return
processAggregateItem
(
r
);
default:
assert
(
NULL
);
return
REDIS_ERR
;
/* Avoid warning. */
...
...
@@ -416,12 +501,10 @@ static int processItem(redisReader *r) {
redisReader
*
redisReaderCreateWithFunctions
(
redisReplyObjectFunctions
*
fn
)
{
redisReader
*
r
;
r
=
calloc
(
sizeof
(
redisReader
)
,
1
);
r
=
calloc
(
1
,
sizeof
(
redisReader
));
if
(
r
==
NULL
)
return
NULL
;
r
->
err
=
0
;
r
->
errstr
[
0
]
=
'\0'
;
r
->
fn
=
fn
;
r
->
buf
=
sdsempty
();
r
->
maxbuf
=
REDIS_READER_MAX_BUF
;
...
...
@@ -435,10 +518,11 @@ redisReader *redisReaderCreateWithFunctions(redisReplyObjectFunctions *fn) {
}
void
redisReaderFree
(
redisReader
*
r
)
{
if
(
r
==
NULL
)
return
;
if
(
r
->
reply
!=
NULL
&&
r
->
fn
&&
r
->
fn
->
freeObject
)
r
->
fn
->
freeObject
(
r
->
reply
);
if
(
r
->
buf
!=
NULL
)
sdsfree
(
r
->
buf
);
sdsfree
(
r
->
buf
);
free
(
r
);
}
...
...
deps/hiredis/read.h
View file @
d5c54f0b
...
...
@@ -53,6 +53,14 @@
#define REDIS_REPLY_NIL 4
#define REDIS_REPLY_STATUS 5
#define REDIS_REPLY_ERROR 6
#define REDIS_REPLY_DOUBLE 7
#define REDIS_REPLY_BOOL 8
#define REDIS_REPLY_VERB 9
#define REDIS_REPLY_MAP 9
#define REDIS_REPLY_SET 10
#define REDIS_REPLY_ATTR 11
#define REDIS_REPLY_PUSH 12
#define REDIS_REPLY_BIGNUM 13
#define REDIS_READER_MAX_BUF (1024*16)
/* Default max unused reader buffer. */
...
...
deps/hiredis/sds.c
View file @
d5c54f0b
...
...
@@ -219,7 +219,10 @@ sds sdsMakeRoomFor(sds s, size_t addlen) {
hdrlen
=
sdsHdrSize
(
type
);
if
(
oldtype
==
type
)
{
newsh
=
s_realloc
(
sh
,
hdrlen
+
newlen
+
1
);
if
(
newsh
==
NULL
)
return
NULL
;
if
(
newsh
==
NULL
)
{
s_free
(
sh
);
return
NULL
;
}
s
=
(
char
*
)
newsh
+
hdrlen
;
}
else
{
/* Since the header size changes, need to move the string forward,
...
...
@@ -592,6 +595,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
/* Make sure there is always space for at least 1 char. */
if
(
sdsavail
(
s
)
==
0
)
{
s
=
sdsMakeRoomFor
(
s
,
1
);
if
(
s
==
NULL
)
goto
fmt_error
;
}
switch
(
*
f
)
{
...
...
@@ -605,6 +609,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
l
=
(
next
==
's'
)
?
strlen
(
str
)
:
sdslen
(
str
);
if
(
sdsavail
(
s
)
<
l
)
{
s
=
sdsMakeRoomFor
(
s
,
l
);
if
(
s
==
NULL
)
goto
fmt_error
;
}
memcpy
(
s
+
i
,
str
,
l
);
sdsinclen
(
s
,
l
);
...
...
@@ -621,6 +626,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
l
=
sdsll2str
(
buf
,
num
);
if
(
sdsavail
(
s
)
<
l
)
{
s
=
sdsMakeRoomFor
(
s
,
l
);
if
(
s
==
NULL
)
goto
fmt_error
;
}
memcpy
(
s
+
i
,
buf
,
l
);
sdsinclen
(
s
,
l
);
...
...
@@ -638,6 +644,7 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
l
=
sdsull2str
(
buf
,
unum
);
if
(
sdsavail
(
s
)
<
l
)
{
s
=
sdsMakeRoomFor
(
s
,
l
);
if
(
s
==
NULL
)
goto
fmt_error
;
}
memcpy
(
s
+
i
,
buf
,
l
);
sdsinclen
(
s
,
l
);
...
...
@@ -662,6 +669,10 @@ sds sdscatfmt(sds s, char const *fmt, ...) {
/* Add null-term */
s
[
i
]
=
'\0'
;
return
s
;
fmt_error:
va_end
(
ap
);
return
NULL
;
}
/* Remove the part of the string from left and from right composed just of
...
...
@@ -1018,10 +1029,18 @@ sds *sdssplitargs(const char *line, int *argc) {
if
(
*
p
)
p
++
;
}
/* add the token to the vector */
vector
=
s_realloc
(
vector
,((
*
argc
)
+
1
)
*
sizeof
(
char
*
));
vector
[
*
argc
]
=
current
;
(
*
argc
)
++
;
current
=
NULL
;
{
char
**
new_vector
=
s_realloc
(
vector
,((
*
argc
)
+
1
)
*
sizeof
(
char
*
));
if
(
new_vector
==
NULL
)
{
s_free
(
vector
);
return
NULL
;
}
vector
=
new_vector
;
vector
[
*
argc
]
=
current
;
(
*
argc
)
++
;
current
=
NULL
;
}
}
else
{
/* Even on empty input string return something not NULL. */
if
(
vector
==
NULL
)
vector
=
s_malloc
(
sizeof
(
void
*
));
...
...
deps/hiredis/test.c
View file @
d5c54f0b
...
...
@@ -3,7 +3,9 @@
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netdb.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
...
...
@@ -91,7 +93,7 @@ static int disconnect(redisContext *c, int keep_fd) {
return
-
1
;
}
static
redisContext
*
connect
(
struct
config
config
)
{
static
redisContext
*
do_
connect
(
struct
config
config
)
{
redisContext
*
c
=
NULL
;
if
(
config
.
type
==
CONN_TCP
)
{
...
...
@@ -248,7 +250,7 @@ static void test_append_formatted_commands(struct config config) {
char
*
cmd
;
int
len
;
c
=
connect
(
config
);
c
=
do_
connect
(
config
);
test
(
"Append format command: "
);
...
...
@@ -302,6 +304,82 @@ static void test_reply_reader(void) {
strncasecmp
(
reader
->
errstr
,
"No support for"
,
14
)
==
0
);
redisReaderFree
(
reader
);
test
(
"Correctly parses LLONG_MAX: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
":9223372036854775807
\r\n
"
,
22
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_OK
&&
((
redisReply
*
)
reply
)
->
type
==
REDIS_REPLY_INTEGER
&&
((
redisReply
*
)
reply
)
->
integer
==
LLONG_MAX
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
test
(
"Set error when > LLONG_MAX: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
":9223372036854775808
\r\n
"
,
22
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_ERR
&&
strcasecmp
(
reader
->
errstr
,
"Bad integer value"
)
==
0
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
test
(
"Correctly parses LLONG_MIN: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
":-9223372036854775808
\r\n
"
,
23
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_OK
&&
((
redisReply
*
)
reply
)
->
type
==
REDIS_REPLY_INTEGER
&&
((
redisReply
*
)
reply
)
->
integer
==
LLONG_MIN
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
test
(
"Set error when < LLONG_MIN: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
":-9223372036854775809
\r\n
"
,
23
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_ERR
&&
strcasecmp
(
reader
->
errstr
,
"Bad integer value"
)
==
0
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
test
(
"Set error when array < -1: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
"*-2
\r\n
+asdf
\r\n
"
,
12
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_ERR
&&
strcasecmp
(
reader
->
errstr
,
"Multi-bulk length out of range"
)
==
0
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
test
(
"Set error when bulk < -1: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
"$-2
\r\n
asdf
\r\n
"
,
11
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_ERR
&&
strcasecmp
(
reader
->
errstr
,
"Bulk string length out of range"
)
==
0
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
test
(
"Set error when array > INT_MAX: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
"*9223372036854775807
\r\n
+asdf
\r\n
"
,
29
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_ERR
&&
strcasecmp
(
reader
->
errstr
,
"Multi-bulk length out of range"
)
==
0
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
#if LLONG_MAX > SIZE_MAX
test
(
"Set error when bulk > SIZE_MAX: "
);
reader
=
redisReaderCreate
();
redisReaderFeed
(
reader
,
"$9223372036854775807
\r\n
asdf
\r\n
"
,
28
);
ret
=
redisReaderGetReply
(
reader
,
&
reply
);
test_cond
(
ret
==
REDIS_ERR
&&
strcasecmp
(
reader
->
errstr
,
"Bulk string length out of range"
)
==
0
);
freeReplyObject
(
reply
);
redisReaderFree
(
reader
);
#endif
test
(
"Works with NULL functions for reply: "
);
reader
=
redisReaderCreate
();
reader
->
fn
=
NULL
;
...
...
@@ -358,18 +436,32 @@ static void test_free_null(void) {
static
void
test_blocking_connection_errors
(
void
)
{
redisContext
*
c
;
test
(
"Returns error when host cannot be resolved: "
);
c
=
redisConnect
((
char
*
)
"idontexist.test"
,
6379
);
test_cond
(
c
->
err
==
REDIS_ERR_OTHER
&&
(
strcmp
(
c
->
errstr
,
"Name or service not known"
)
==
0
||
strcmp
(
c
->
errstr
,
"Can't resolve: idontexist.test"
)
==
0
||
strcmp
(
c
->
errstr
,
"nodename nor servname provided, or not known"
)
==
0
||
strcmp
(
c
->
errstr
,
"No address associated with hostname"
)
==
0
||
strcmp
(
c
->
errstr
,
"Temporary failure in name resolution"
)
==
0
||
strcmp
(
c
->
errstr
,
"hostname nor servname provided, or not known"
)
==
0
||
strcmp
(
c
->
errstr
,
"no address associated with name"
)
==
0
));
redisFree
(
c
);
struct
addrinfo
hints
=
{.
ai_family
=
AF_INET
};
struct
addrinfo
*
ai_tmp
=
NULL
;
const
char
*
bad_domain
=
"idontexist.com"
;
int
rv
=
getaddrinfo
(
bad_domain
,
"6379"
,
&
hints
,
&
ai_tmp
);
if
(
rv
!=
0
)
{
// Address does *not* exist
test
(
"Returns error when host cannot be resolved: "
);
// First see if this domain name *actually* resolves to NXDOMAIN
c
=
redisConnect
(
"dontexist.com"
,
6379
);
test_cond
(
c
->
err
==
REDIS_ERR_OTHER
&&
(
strcmp
(
c
->
errstr
,
"Name or service not known"
)
==
0
||
strcmp
(
c
->
errstr
,
"Can't resolve: sadkfjaskfjsa.com"
)
==
0
||
strcmp
(
c
->
errstr
,
"nodename nor servname provided, or not known"
)
==
0
||
strcmp
(
c
->
errstr
,
"No address associated with hostname"
)
==
0
||
strcmp
(
c
->
errstr
,
"Temporary failure in name resolution"
)
==
0
||
strcmp
(
c
->
errstr
,
"hostname nor servname provided, or not known"
)
==
0
||
strcmp
(
c
->
errstr
,
"no address associated with name"
)
==
0
));
redisFree
(
c
);
}
else
{
printf
(
"Skipping NXDOMAIN test. Found evil ISP!
\n
"
);
freeaddrinfo
(
ai_tmp
);
}
test
(
"Returns error when the port is not open: "
);
c
=
redisConnect
((
char
*
)
"localhost"
,
1
);
...
...
@@ -387,7 +479,7 @@ static void test_blocking_connection(struct config config) {
redisContext
*
c
;
redisReply
*
reply
;
c
=
connect
(
config
);
c
=
do_
connect
(
config
);
test
(
"Is able to deliver commands: "
);
reply
=
redisCommand
(
c
,
"PING"
);
...
...
@@ -468,7 +560,7 @@ static void test_blocking_connection_timeouts(struct config config) {
const
char
*
cmd
=
"DEBUG SLEEP 3
\r\n
"
;
struct
timeval
tv
;
c
=
connect
(
config
);
c
=
do_
connect
(
config
);
test
(
"Successfully completes a command when the timeout is not exceeded: "
);
reply
=
redisCommand
(
c
,
"SET foo fast"
);
freeReplyObject
(
reply
);
...
...
@@ -480,7 +572,7 @@ static void test_blocking_connection_timeouts(struct config config) {
freeReplyObject
(
reply
);
disconnect
(
c
,
0
);
c
=
connect
(
config
);
c
=
do_
connect
(
config
);
test
(
"Does not return a reply when the command times out: "
);
s
=
write
(
c
->
fd
,
cmd
,
strlen
(
cmd
));
tv
.
tv_sec
=
0
;
...
...
@@ -514,7 +606,7 @@ static void test_blocking_io_errors(struct config config) {
int
major
,
minor
;
/* Connect to target given by config. */
c
=
connect
(
config
);
c
=
do_
connect
(
config
);
{
/* Find out Redis version to determine the path for the next test */
const
char
*
field
=
"redis_version:"
;
...
...
@@ -549,7 +641,7 @@ static void test_blocking_io_errors(struct config config) {
strcmp
(
c
->
errstr
,
"Server closed the connection"
)
==
0
);
redisFree
(
c
);
c
=
connect
(
config
);
c
=
do_
connect
(
config
);
test
(
"Returns I/O error on socket timeout: "
);
struct
timeval
tv
=
{
0
,
1000
};
assert
(
redisSetTimeout
(
c
,
tv
)
==
REDIS_OK
);
...
...
@@ -583,7 +675,7 @@ static void test_invalid_timeout_errors(struct config config) {
}
static
void
test_throughput
(
struct
config
config
)
{
redisContext
*
c
=
connect
(
config
);
redisContext
*
c
=
do_
connect
(
config
);
redisReply
**
replies
;
int
i
,
num
;
long
long
t1
,
t2
;
...
...
@@ -616,6 +708,17 @@ static void test_throughput(struct config config) {
free
(
replies
);
printf
(
"
\t
(%dx LRANGE with 500 elements: %.3fs)
\n
"
,
num
,
(
t2
-
t1
)
/
1000000
.
0
);
replies
=
malloc
(
sizeof
(
redisReply
*
)
*
num
);
t1
=
usec
();
for
(
i
=
0
;
i
<
num
;
i
++
)
{
replies
[
i
]
=
redisCommand
(
c
,
"INCRBY incrkey %d"
,
1000000
);
assert
(
replies
[
i
]
!=
NULL
&&
replies
[
i
]
->
type
==
REDIS_REPLY_INTEGER
);
}
t2
=
usec
();
for
(
i
=
0
;
i
<
num
;
i
++
)
freeReplyObject
(
replies
[
i
]);
free
(
replies
);
printf
(
"
\t
(%dx INCRBY: %.3fs)
\n
"
,
num
,
(
t2
-
t1
)
/
1000000
.
0
);
num
=
10000
;
replies
=
malloc
(
sizeof
(
redisReply
*
)
*
num
);
for
(
i
=
0
;
i
<
num
;
i
++
)
...
...
@@ -644,6 +747,19 @@ static void test_throughput(struct config config) {
free
(
replies
);
printf
(
"
\t
(%dx LRANGE with 500 elements (pipelined): %.3fs)
\n
"
,
num
,
(
t2
-
t1
)
/
1000000
.
0
);
replies
=
malloc
(
sizeof
(
redisReply
*
)
*
num
);
for
(
i
=
0
;
i
<
num
;
i
++
)
redisAppendCommand
(
c
,
"INCRBY incrkey %d"
,
1000000
);
t1
=
usec
();
for
(
i
=
0
;
i
<
num
;
i
++
)
{
assert
(
redisGetReply
(
c
,
(
void
*
)
&
replies
[
i
])
==
REDIS_OK
);
assert
(
replies
[
i
]
!=
NULL
&&
replies
[
i
]
->
type
==
REDIS_REPLY_INTEGER
);
}
t2
=
usec
();
for
(
i
=
0
;
i
<
num
;
i
++
)
freeReplyObject
(
replies
[
i
]);
free
(
replies
);
printf
(
"
\t
(%dx INCRBY (pipelined): %.3fs)
\n
"
,
num
,
(
t2
-
t1
)
/
1000000
.
0
);
disconnect
(
c
,
0
);
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment