hiredis 0.4.1 → 0.4.2.pre
Sign up to get free protection for your applications and to get access to all the features.
- 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;
|