hiredis 0.4.1 → 0.4.2.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +0 -1
- data/lib/hiredis/ruby/reader.rb +7 -4
- data/lib/hiredis/version.rb +1 -1
- data/vendor/hiredis/Makefile +76 -52
- data/vendor/hiredis/async.c +83 -17
- data/vendor/hiredis/async.h +1 -1
- data/vendor/hiredis/fmacros.h +5 -3
- data/vendor/hiredis/hiredis.c +79 -31
- data/vendor/hiredis/hiredis.h +2 -2
- data/vendor/hiredis/net.c +79 -56
- data/vendor/hiredis/net.h +1 -0
- data/vendor/hiredis/test.c +268 -143
- metadata +10 -7
data/Rakefile
CHANGED
data/lib/hiredis/ruby/reader.rb
CHANGED
@@ -32,14 +32,17 @@ module Hiredis
|
|
32
32
|
method_index[?*] = :process_multi_bulk_reply
|
33
33
|
METHOD_INDEX = method_index.freeze
|
34
34
|
|
35
|
-
|
35
|
+
attr_reader :parent
|
36
|
+
attr_reader :depth
|
36
37
|
attr_accessor :multi_bulk
|
37
38
|
|
38
39
|
def initialize(buffer, parent = nil, depth = 0)
|
39
|
-
@buffer, @parent = buffer, parent
|
40
|
+
@buffer, @parent, @depth = buffer, parent, depth
|
41
|
+
end
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
+
# Note: task depth is not checked.
|
44
|
+
def child
|
45
|
+
@child ||= Task.new(@buffer, self, depth + 1)
|
43
46
|
end
|
44
47
|
|
45
48
|
def root
|
data/lib/hiredis/version.rb
CHANGED
data/vendor/hiredis/Makefile
CHANGED
@@ -1,58 +1,46 @@
|
|
1
1
|
# Hiredis Makefile
|
2
|
-
# Copyright (C) 2010 Salvatore Sanfilippo <antirez at gmail dot com>
|
2
|
+
# Copyright (C) 2010-2011 Salvatore Sanfilippo <antirez at gmail dot com>
|
3
|
+
# Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>
|
3
4
|
# This file is released under the BSD license, see the COPYING file
|
4
5
|
|
5
6
|
OBJ=net.o hiredis.o sds.o async.o
|
6
7
|
BINS=hiredis-example hiredis-test
|
7
8
|
LIBNAME=libhiredis
|
8
9
|
|
9
|
-
|
10
|
+
HIREDIS_MAJOR=0
|
11
|
+
HIREDIS_MINOR=10
|
12
|
+
|
13
|
+
# Fallback to gcc when $CC is not in $PATH.
|
14
|
+
CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
|
10
15
|
OPTIMIZATION?=-O3
|
16
|
+
WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
|
17
|
+
DEBUG?= -g -ggdb
|
18
|
+
REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG)
|
19
|
+
REAL_LDFLAGS=$(LDFLAGS)
|
20
|
+
|
21
|
+
DYLIBSUFFIX=so
|
22
|
+
STLIBSUFFIX=a
|
23
|
+
DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)
|
24
|
+
DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)
|
25
|
+
DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
|
26
|
+
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
27
|
+
STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
|
28
|
+
STLIB_MAKE_CMD=ar rcs $(STLIBNAME)
|
29
|
+
|
30
|
+
# Platform-specific overrides
|
31
|
+
uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
11
32
|
ifeq ($(uname_S),SunOS)
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
STLIBSUFFIX=a
|
17
|
-
DYLIBNAME?=$(LIBNAME).$(DYLIBSUFFIX)
|
18
|
-
DYLIB_MAKE_CMD?=$(CC) -G -o $(DYLIBNAME)
|
19
|
-
STLIBNAME?=$(LIBNAME).$(STLIBSUFFIX)
|
20
|
-
STLIB_MAKE_CMD?=ar rcs $(STLIBNAME)
|
21
|
-
else
|
33
|
+
REAL_LDFLAGS+= -ldl -lnsl -lsocket
|
34
|
+
DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)
|
35
|
+
INSTALL= cp -r
|
36
|
+
endif
|
22
37
|
ifeq ($(uname_S),Darwin)
|
23
|
-
CFLAGS?=$(OPTIMIZATION) -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings $(ARCH) $(PROF)
|
24
|
-
CCLINK?=-lm -pthread
|
25
|
-
LDFLAGS?=-L.
|
26
|
-
OBJARCH?=-arch i386 -arch x86_64
|
27
38
|
DYLIBSUFFIX=dylib
|
28
|
-
|
29
|
-
|
30
|
-
DYLIB_MAKE_CMD
|
31
|
-
STLIBNAME?=$(LIBNAME).$(STLIBSUFFIX)
|
32
|
-
STLIB_MAKE_CMD?=libtool -static -o $(STLIBNAME) -
|
33
|
-
else
|
34
|
-
CFLAGS?=$(OPTIMIZATION) -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings $(ARCH) $(PROF)
|
35
|
-
CCLINK?=-lm -pthread
|
36
|
-
LDFLAGS?=-L.
|
37
|
-
DYLIBSUFFIX=so
|
38
|
-
STLIBSUFFIX=a
|
39
|
-
DYLIBNAME?=$(LIBNAME).$(DYLIBSUFFIX)
|
40
|
-
DYLIB_MAKE_CMD?=gcc -shared -Wl,-soname,$(DYLIBNAME) -o $(DYLIBNAME)
|
41
|
-
STLIBNAME?=$(LIBNAME).$(STLIBSUFFIX)
|
42
|
-
STLIB_MAKE_CMD?=ar rcs $(STLIBNAME)
|
43
|
-
endif
|
39
|
+
DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)
|
40
|
+
DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)
|
41
|
+
DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
|
44
42
|
endif
|
45
43
|
|
46
|
-
CCOPT= $(CFLAGS) $(CCLINK)
|
47
|
-
DEBUG?= -g -ggdb
|
48
|
-
|
49
|
-
PREFIX?=/usr/local
|
50
|
-
INCLUDE_PATH?=include/hiredis
|
51
|
-
LIBRARY_PATH?=lib
|
52
|
-
INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH)
|
53
|
-
INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH)
|
54
|
-
INSTALL= cp -a
|
55
|
-
|
56
44
|
all: $(DYLIBNAME) $(BINS)
|
57
45
|
|
58
46
|
# Deps (use make dep to generate this)
|
@@ -74,10 +62,10 @@ static: $(STLIBNAME)
|
|
74
62
|
|
75
63
|
# Binaries:
|
76
64
|
hiredis-example-libevent: example-libevent.c adapters/libevent.h $(STLIBNAME)
|
77
|
-
$(CC) -o $@ $(
|
65
|
+
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -levent example-libevent.c $(STLIBNAME)
|
78
66
|
|
79
67
|
hiredis-example-libev: example-libev.c adapters/libev.h $(STLIBNAME)
|
80
|
-
$(CC) -o $@ $(
|
68
|
+
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -lev example-libev.c $(STLIBNAME)
|
81
69
|
|
82
70
|
ifndef AE_DIR
|
83
71
|
hiredis-example-ae:
|
@@ -85,17 +73,29 @@ hiredis-example-ae:
|
|
85
73
|
@false
|
86
74
|
else
|
87
75
|
hiredis-example-ae: example-ae.c adapters/ae.h $(STLIBNAME)
|
88
|
-
$(CC) -o $@ $(
|
76
|
+
$(CC) -o $@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I$(AE_DIR) $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o example-ae.c $(STLIBNAME)
|
89
77
|
endif
|
90
78
|
|
91
79
|
hiredis-%: %.o $(STLIBNAME)
|
92
|
-
$(CC) -o $@ $(
|
80
|
+
$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
|
93
81
|
|
94
82
|
test: hiredis-test
|
95
83
|
./hiredis-test
|
96
84
|
|
85
|
+
check: hiredis-test
|
86
|
+
echo \
|
87
|
+
"daemonize yes\n" \
|
88
|
+
"pidfile /tmp/hiredis-test-redis.pid\n" \
|
89
|
+
"port 56379\n" \
|
90
|
+
"bind 127.0.0.1\n" \
|
91
|
+
"unixsocket /tmp/hiredis-test-redis.sock" \
|
92
|
+
| redis-server -
|
93
|
+
./hiredis-test -h 127.0.0.1 -p 56379 -s /tmp/hiredis-test-redis.sock || \
|
94
|
+
( kill `cat /tmp/hiredis-test-redis.pid` && false )
|
95
|
+
kill `cat /tmp/hiredis-test-redis.pid`
|
96
|
+
|
97
97
|
.c.o:
|
98
|
-
$(CC) -std=c99 -pedantic -c $(
|
98
|
+
$(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
|
99
99
|
|
100
100
|
clean:
|
101
101
|
rm -rf $(DYLIBNAME) $(STLIBNAME) $(BINS) hiredis-example* *.o *.gcda *.gcno *.gcov
|
@@ -103,22 +103,46 @@ clean:
|
|
103
103
|
dep:
|
104
104
|
$(CC) -MM *.c
|
105
105
|
|
106
|
+
# Installation related variables and target
|
107
|
+
PREFIX?=/usr/local
|
108
|
+
INCLUDE_PATH?=include/hiredis
|
109
|
+
LIBRARY_PATH?=lib
|
110
|
+
INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH)
|
111
|
+
INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH)
|
112
|
+
|
113
|
+
ifeq ($(uname_S),SunOS)
|
114
|
+
INSTALL?= cp -r
|
115
|
+
endif
|
116
|
+
|
117
|
+
INSTALL?= cp -a
|
118
|
+
|
106
119
|
install: $(DYLIBNAME) $(STLIBNAME)
|
107
120
|
mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
|
108
121
|
$(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH)
|
109
|
-
$(INSTALL) $(DYLIBNAME) $(
|
122
|
+
$(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
|
123
|
+
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)
|
124
|
+
cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)
|
125
|
+
$(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
|
110
126
|
|
111
127
|
32bit:
|
112
128
|
@echo ""
|
113
|
-
@echo "WARNING: if
|
129
|
+
@echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386"
|
114
130
|
@echo ""
|
115
|
-
$(MAKE)
|
131
|
+
$(MAKE) CFLAGS="-m32" LDFLAGS="-m32"
|
116
132
|
|
117
133
|
gprof:
|
118
|
-
$(MAKE)
|
134
|
+
$(MAKE) CFLAGS="-pg" LDFLAGS="-pg"
|
119
135
|
|
120
136
|
gcov:
|
121
|
-
$(MAKE)
|
137
|
+
$(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs"
|
138
|
+
|
139
|
+
coverage: gcov
|
140
|
+
make check
|
141
|
+
mkdir -p tmp/lcov
|
142
|
+
lcov -d . -c -o tmp/lcov/hiredis.info
|
143
|
+
genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info
|
122
144
|
|
123
145
|
noopt:
|
124
146
|
$(MAKE) OPTIMIZATION=""
|
147
|
+
|
148
|
+
.PHONY: all test check clean dep install 32bit gprof gcov noopt
|
data/vendor/hiredis/async.c
CHANGED
@@ -29,14 +29,34 @@
|
|
29
29
|
* POSSIBILITY OF SUCH DAMAGE.
|
30
30
|
*/
|
31
31
|
|
32
|
+
#include "fmacros.h"
|
33
|
+
#include <stdlib.h>
|
32
34
|
#include <string.h>
|
33
35
|
#include <strings.h>
|
34
36
|
#include <assert.h>
|
35
37
|
#include <ctype.h>
|
38
|
+
#include <errno.h>
|
36
39
|
#include "async.h"
|
40
|
+
#include "net.h"
|
37
41
|
#include "dict.c"
|
38
42
|
#include "sds.h"
|
39
43
|
|
44
|
+
#define _EL_ADD_READ(ctx) do { \
|
45
|
+
if ((ctx)->ev.addRead) (ctx)->ev.addRead((ctx)->ev.data); \
|
46
|
+
} while(0)
|
47
|
+
#define _EL_DEL_READ(ctx) do { \
|
48
|
+
if ((ctx)->ev.delRead) (ctx)->ev.delRead((ctx)->ev.data); \
|
49
|
+
} while(0)
|
50
|
+
#define _EL_ADD_WRITE(ctx) do { \
|
51
|
+
if ((ctx)->ev.addWrite) (ctx)->ev.addWrite((ctx)->ev.data); \
|
52
|
+
} while(0)
|
53
|
+
#define _EL_DEL_WRITE(ctx) do { \
|
54
|
+
if ((ctx)->ev.delWrite) (ctx)->ev.delWrite((ctx)->ev.data); \
|
55
|
+
} while(0)
|
56
|
+
#define _EL_CLEANUP(ctx) do { \
|
57
|
+
if ((ctx)->ev.cleanup) (ctx)->ev.cleanup((ctx)->ev.data); \
|
58
|
+
} while(0);
|
59
|
+
|
40
60
|
/* Forward declaration of function in hiredis.c */
|
41
61
|
void __redisAppendCommand(redisContext *c, char *cmd, size_t len);
|
42
62
|
|
@@ -142,7 +162,7 @@ int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn
|
|
142
162
|
/* The common way to detect an established connection is to wait for
|
143
163
|
* the first write event to be fired. This assumes the related event
|
144
164
|
* library functions are already set. */
|
145
|
-
|
165
|
+
_EL_ADD_WRITE(ac);
|
146
166
|
return REDIS_OK;
|
147
167
|
}
|
148
168
|
return REDIS_ERR;
|
@@ -230,7 +250,7 @@ static void __redisAsyncFree(redisAsyncContext *ac) {
|
|
230
250
|
dictRelease(ac->sub.patterns);
|
231
251
|
|
232
252
|
/* Signal event lib to clean up */
|
233
|
-
|
253
|
+
_EL_CLEANUP(ac);
|
234
254
|
|
235
255
|
/* Execute disconnect callback. When redisAsyncFree() initiated destroying
|
236
256
|
* this context, the status will always be REDIS_OK. */
|
@@ -361,7 +381,20 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
|
361
381
|
/* Even if the context is subscribed, pending regular callbacks will
|
362
382
|
* get a reply before pub/sub messages arrive. */
|
363
383
|
if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {
|
364
|
-
/*
|
384
|
+
/* A spontaneous reply in a not-subscribed context can only be the
|
385
|
+
* error reply that is sent when a new connection exceeds the
|
386
|
+
* maximum number of allowed connections on the server side. This
|
387
|
+
* is seen as an error instead of a regular reply because the
|
388
|
+
* server closes the connection after sending it. To prevent the
|
389
|
+
* error from being overwritten by an EOF error the connection is
|
390
|
+
* closed here. See issue #43. */
|
391
|
+
if ( !(c->flags & REDIS_SUBSCRIBED) && ((redisReply*)reply)->type == REDIS_REPLY_ERROR ) {
|
392
|
+
c->err = REDIS_ERR_OTHER;
|
393
|
+
snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
|
394
|
+
__redisAsyncDisconnect(ac);
|
395
|
+
return;
|
396
|
+
}
|
397
|
+
/* No more regular callbacks and no errors, the context *must* be subscribed. */
|
365
398
|
assert(c->flags & REDIS_SUBSCRIBED);
|
366
399
|
__redisGetSubscribeCallback(ac,reply,&cb);
|
367
400
|
}
|
@@ -389,17 +422,48 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
|
|
389
422
|
__redisAsyncDisconnect(ac);
|
390
423
|
}
|
391
424
|
|
425
|
+
/* Internal helper function to detect socket status the first time a read or
|
426
|
+
* write event fires. When connecting was not succesful, the connect callback
|
427
|
+
* is called with a REDIS_ERR status and the context is free'd. */
|
428
|
+
static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
|
429
|
+
redisContext *c = &(ac->c);
|
430
|
+
|
431
|
+
if (redisCheckSocketError(c,c->fd) == REDIS_ERR) {
|
432
|
+
/* Try again later when connect(2) is still in progress. */
|
433
|
+
if (errno == EINPROGRESS)
|
434
|
+
return REDIS_OK;
|
435
|
+
|
436
|
+
if (ac->onConnect) ac->onConnect(ac,REDIS_ERR);
|
437
|
+
__redisAsyncDisconnect(ac);
|
438
|
+
return REDIS_ERR;
|
439
|
+
}
|
440
|
+
|
441
|
+
/* Mark context as connected. */
|
442
|
+
c->flags |= REDIS_CONNECTED;
|
443
|
+
if (ac->onConnect) ac->onConnect(ac,REDIS_OK);
|
444
|
+
return REDIS_OK;
|
445
|
+
}
|
446
|
+
|
392
447
|
/* This function should be called when the socket is readable.
|
393
448
|
* It processes all replies that can be read and executes their callbacks.
|
394
449
|
*/
|
395
450
|
void redisAsyncHandleRead(redisAsyncContext *ac) {
|
396
451
|
redisContext *c = &(ac->c);
|
397
452
|
|
453
|
+
if (!(c->flags & REDIS_CONNECTED)) {
|
454
|
+
/* Abort connect was not successful. */
|
455
|
+
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
456
|
+
return;
|
457
|
+
/* Try again later when the context is still not connected. */
|
458
|
+
if (!(c->flags & REDIS_CONNECTED))
|
459
|
+
return;
|
460
|
+
}
|
461
|
+
|
398
462
|
if (redisBufferRead(c) == REDIS_ERR) {
|
399
463
|
__redisAsyncDisconnect(ac);
|
400
464
|
} else {
|
401
465
|
/* Always re-schedule reads */
|
402
|
-
|
466
|
+
_EL_ADD_READ(ac);
|
403
467
|
redisProcessCallbacks(ac);
|
404
468
|
}
|
405
469
|
}
|
@@ -408,24 +472,26 @@ void redisAsyncHandleWrite(redisAsyncContext *ac) {
|
|
408
472
|
redisContext *c = &(ac->c);
|
409
473
|
int done = 0;
|
410
474
|
|
475
|
+
if (!(c->flags & REDIS_CONNECTED)) {
|
476
|
+
/* Abort connect was not successful. */
|
477
|
+
if (__redisAsyncHandleConnect(ac) != REDIS_OK)
|
478
|
+
return;
|
479
|
+
/* Try again later when the context is still not connected. */
|
480
|
+
if (!(c->flags & REDIS_CONNECTED))
|
481
|
+
return;
|
482
|
+
}
|
483
|
+
|
411
484
|
if (redisBufferWrite(c,&done) == REDIS_ERR) {
|
412
485
|
__redisAsyncDisconnect(ac);
|
413
486
|
} else {
|
414
487
|
/* Continue writing when not done, stop writing otherwise */
|
415
|
-
if (!done)
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
}
|
488
|
+
if (!done)
|
489
|
+
_EL_ADD_WRITE(ac);
|
490
|
+
else
|
491
|
+
_EL_DEL_WRITE(ac);
|
420
492
|
|
421
493
|
/* Always schedule reads after writes */
|
422
|
-
|
423
|
-
|
424
|
-
/* Fire onConnect when this is the first write event. */
|
425
|
-
if (!(c->flags & REDIS_CONNECTED)) {
|
426
|
-
c->flags |= REDIS_CONNECTED;
|
427
|
-
if (ac->onConnect) ac->onConnect(ac);
|
428
|
-
}
|
494
|
+
_EL_ADD_READ(ac);
|
429
495
|
}
|
430
496
|
}
|
431
497
|
|
@@ -503,7 +569,7 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
|
|
503
569
|
__redisAppendCommand(c,cmd,len);
|
504
570
|
|
505
571
|
/* Always schedule a write when the write buffer is non-empty */
|
506
|
-
|
572
|
+
_EL_ADD_WRITE(ac);
|
507
573
|
|
508
574
|
return REDIS_OK;
|
509
575
|
}
|
data/vendor/hiredis/async.h
CHANGED
@@ -55,7 +55,7 @@ typedef struct redisCallbackList {
|
|
55
55
|
|
56
56
|
/* Connection callback prototypes */
|
57
57
|
typedef void (redisDisconnectCallback)(const struct redisAsyncContext*, int status);
|
58
|
-
typedef void (redisConnectCallback)(const struct redisAsyncContext
|
58
|
+
typedef void (redisConnectCallback)(const struct redisAsyncContext*, int status);
|
59
59
|
|
60
60
|
/* Context for an async connection to Redis */
|
61
61
|
typedef struct redisAsyncContext {
|
data/vendor/hiredis/fmacros.h
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
#ifndef __HIREDIS_FMACRO_H
|
2
2
|
#define __HIREDIS_FMACRO_H
|
3
3
|
|
4
|
-
#
|
4
|
+
#if !defined(_BSD_SOURCE)
|
5
5
|
#define _BSD_SOURCE
|
6
6
|
#endif
|
7
7
|
|
8
|
-
#
|
9
|
-
#define
|
8
|
+
#if defined(__sun__)
|
9
|
+
#define _POSIX_C_SOURCE 200112L
|
10
|
+
#elif defined(__linux__)
|
11
|
+
#define _XOPEN_SOURCE 600
|
10
12
|
#else
|
11
13
|
#define _XOPEN_SOURCE
|
12
14
|
#endif
|
data/vendor/hiredis/hiredis.c
CHANGED
@@ -77,7 +77,7 @@ void freeReplyObject(void *reply) {
|
|
77
77
|
case REDIS_REPLY_INTEGER:
|
78
78
|
break; /* Nothing to free */
|
79
79
|
case REDIS_REPLY_ARRAY:
|
80
|
-
if (r->
|
80
|
+
if (r->element != NULL) {
|
81
81
|
for (j = 0; j < r->elements; j++)
|
82
82
|
if (r->element[j] != NULL)
|
83
83
|
freeReplyObject(r->element[j]);
|
@@ -133,10 +133,12 @@ static void *createArrayObject(const redisReadTask *task, int elements) {
|
|
133
133
|
if (r == NULL)
|
134
134
|
return NULL;
|
135
135
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
136
|
+
if (elements > 0) {
|
137
|
+
r->element = calloc(elements,sizeof(redisReply*));
|
138
|
+
if (r->element == NULL) {
|
139
|
+
freeReplyObject(r);
|
140
|
+
return NULL;
|
141
|
+
}
|
140
142
|
}
|
141
143
|
|
142
144
|
r->elements = elements;
|
@@ -444,10 +446,10 @@ static int processMultiBulkItem(redisReader *r) {
|
|
444
446
|
long elements;
|
445
447
|
int root = 0;
|
446
448
|
|
447
|
-
/* Set error for nested multi bulks with depth >
|
448
|
-
if (r->ridx ==
|
449
|
+
/* Set error for nested multi bulks with depth > 2 */
|
450
|
+
if (r->ridx == 3) {
|
449
451
|
__redisReaderSetError(r,REDIS_ERR_PROTOCOL,
|
450
|
-
"No support for nested multi bulk replies with depth >
|
452
|
+
"No support for nested multi bulk replies with depth > 2");
|
451
453
|
return REDIS_ERR;
|
452
454
|
}
|
453
455
|
|
@@ -768,33 +770,79 @@ int redisvFormatCommand(char **target, const char *format, va_list ap) {
|
|
768
770
|
while (*_p != '\0' && isdigit(*_p)) _p++;
|
769
771
|
}
|
770
772
|
|
771
|
-
/*
|
772
|
-
|
773
|
-
|
774
|
-
|
775
|
-
|
776
|
-
|
773
|
+
/* Copy va_list before consuming with va_arg */
|
774
|
+
va_copy(_cpy,ap);
|
775
|
+
|
776
|
+
/* Integer conversion (without modifiers) */
|
777
|
+
if (strchr("diouxX",*_p) != NULL) {
|
778
|
+
va_arg(ap,int);
|
779
|
+
goto fmt_valid;
|
780
|
+
}
|
781
|
+
|
782
|
+
/* Double conversion (without modifiers) */
|
783
|
+
if (strchr("eEfFgGaA",*_p) != NULL) {
|
784
|
+
va_arg(ap,double);
|
785
|
+
goto fmt_valid;
|
786
|
+
}
|
787
|
+
|
788
|
+
/* Size: char */
|
789
|
+
if (_p[0] == 'h' && _p[1] == 'h') {
|
790
|
+
_p += 2;
|
791
|
+
if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
|
792
|
+
va_arg(ap,int); /* char gets promoted to int */
|
793
|
+
goto fmt_valid;
|
777
794
|
}
|
795
|
+
goto fmt_invalid;
|
778
796
|
}
|
779
797
|
|
780
|
-
/*
|
781
|
-
if (
|
782
|
-
|
783
|
-
if (
|
784
|
-
|
785
|
-
|
786
|
-
va_copy(_cpy,ap);
|
787
|
-
newarg = sdscatvprintf(curarg,_format,_cpy);
|
788
|
-
va_end(_cpy);
|
789
|
-
|
790
|
-
/* Update current position (note: outer blocks
|
791
|
-
* increment c twice so compensate here) */
|
792
|
-
c = _p-1;
|
798
|
+
/* Size: short */
|
799
|
+
if (_p[0] == 'h') {
|
800
|
+
_p += 1;
|
801
|
+
if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
|
802
|
+
va_arg(ap,int); /* short gets promoted to int */
|
803
|
+
goto fmt_valid;
|
793
804
|
}
|
805
|
+
goto fmt_invalid;
|
806
|
+
}
|
807
|
+
|
808
|
+
/* Size: long long */
|
809
|
+
if (_p[0] == 'l' && _p[1] == 'l') {
|
810
|
+
_p += 2;
|
811
|
+
if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
|
812
|
+
va_arg(ap,long long);
|
813
|
+
goto fmt_valid;
|
814
|
+
}
|
815
|
+
goto fmt_invalid;
|
816
|
+
}
|
817
|
+
|
818
|
+
/* Size: long */
|
819
|
+
if (_p[0] == 'l') {
|
820
|
+
_p += 1;
|
821
|
+
if (*_p != '\0' && strchr("diouxX",*_p) != NULL) {
|
822
|
+
va_arg(ap,long);
|
823
|
+
goto fmt_valid;
|
824
|
+
}
|
825
|
+
goto fmt_invalid;
|
826
|
+
}
|
827
|
+
|
828
|
+
fmt_invalid:
|
829
|
+
va_end(_cpy);
|
830
|
+
goto err;
|
831
|
+
|
832
|
+
fmt_valid:
|
833
|
+
_l = (_p+1)-c;
|
834
|
+
if (_l < sizeof(_format)-2) {
|
835
|
+
memcpy(_format,c,_l);
|
836
|
+
_format[_l] = '\0';
|
837
|
+
newarg = sdscatvprintf(curarg,_format,_cpy);
|
838
|
+
|
839
|
+
/* Update current position (note: outer blocks
|
840
|
+
* increment c twice so compensate here) */
|
841
|
+
c = _p-1;
|
794
842
|
}
|
795
843
|
|
796
|
-
|
797
|
-
|
844
|
+
va_end(_cpy);
|
845
|
+
break;
|
798
846
|
}
|
799
847
|
}
|
800
848
|
|
@@ -1049,10 +1097,10 @@ int redisBufferRead(redisContext *c) {
|
|
1049
1097
|
*
|
1050
1098
|
* Returns REDIS_OK when the buffer is empty, or (a part of) the buffer was
|
1051
1099
|
* succesfully written to the socket. When the buffer is empty after the
|
1052
|
-
* write operation, "
|
1100
|
+
* write operation, "done" is set to 1 (if given).
|
1053
1101
|
*
|
1054
1102
|
* Returns REDIS_ERR if an error occured trying to write and sets
|
1055
|
-
* c->
|
1103
|
+
* c->errstr to hold the appropriate error string.
|
1056
1104
|
*/
|
1057
1105
|
int redisBufferWrite(redisContext *c, int *done) {
|
1058
1106
|
int nwritten;
|