hiredis 0.6.1 → 0.6.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9f5223293433c777928e04bd8c99236f393d6f84
4
- data.tar.gz: 2c915fb52bd73e9816f5acce51dd3c72c16da9cc
2
+ SHA256:
3
+ metadata.gz: 1f07127ae47561dfa27e69e75ec20141aea1ec0f25c9e0a6ebf85d28c0fd0ab5
4
+ data.tar.gz: 71b64366a9ec6eb8eaef1ca8c6dee1aaab91c1608198d2fbc0dd928d31e36cca
5
5
  SHA512:
6
- metadata.gz: 8ee5ef3080b1bd3231ebe60f5d2f76a59bfeee1281c0a642d48cffd6a408b86980f82a7b384288229bb788c2e0332db2f2bd92568c538c3042719d04cf8c2125
7
- data.tar.gz: 81c4474b55f788acded811dbefdc9b125a906eeb3c5008afd94f8663ff62eaae8f9d1939e58f89166624b7961e1433eeb3d971fde9c0ca6304370b325083f8ac
6
+ metadata.gz: e3e5d4387c7e4d625fc81349d1224ac34cc43aae5a6d49c648515462eab5404bd18bb0deae1a166ab42e0ab93f91ef7344dd1a8a0c4ea54fd040bfe97a4a983f
7
+ data.tar.gz: 59504af0292497549b26ae7f970e2495363d0a66b9e15cb8c98b1fdcc748805a11a2c7e800fc9cce41dc81a85dc08273d62558d5481f89b2625f8611bbb50019
@@ -27,9 +27,10 @@ static void parent_context_try_free(redisParentContext *pc) {
27
27
  }
28
28
 
29
29
  static void parent_context_mark(redisParentContext *pc) {
30
- VALUE root;
30
+ // volatile until rb_gc_mark
31
+ volatile VALUE root;
31
32
  if (pc->context && pc->context->reader) {
32
- root = (VALUE)redisReplyReaderGetObject(pc->context->reader);
33
+ root = (VALUE)redisReaderGetObject(pc->context->reader);
33
34
  if (root != 0 && TYPE(root) == T_ARRAY) {
34
35
  rb_gc_mark(root);
35
36
  }
@@ -448,7 +449,7 @@ static int __get_reply(redisParentContext *pc, VALUE *reply) {
448
449
 
449
450
  static VALUE connection_read(VALUE self) {
450
451
  redisParentContext *pc;
451
- VALUE reply;
452
+ volatile VALUE reply;
452
453
 
453
454
  Data_Get_Struct(self,redisParentContext,pc);
454
455
  if (!pc->context)
@@ -10,7 +10,7 @@ static ID str_force_encoding = 0;
10
10
  * Note that the parent should always be of type T_ARRAY. */
11
11
  static void *tryParentize(const redisReadTask *task, VALUE v) {
12
12
  if (task && task->parent != NULL) {
13
- VALUE parent = (VALUE)task->parent->obj;
13
+ volatile VALUE parent = (VALUE)task->parent->obj;
14
14
  assert(TYPE(parent) == T_ARRAY);
15
15
  rb_ary_store(parent,task->idx,v);
16
16
  }
@@ -18,7 +18,7 @@ static void *tryParentize(const redisReadTask *task, VALUE v) {
18
18
  }
19
19
 
20
20
  static void *createStringObject(const redisReadTask *task, char *str, size_t len) {
21
- VALUE v, enc;
21
+ volatile VALUE v, enc;
22
22
  v = rb_str_new(str,len);
23
23
 
24
24
  /* Force default external encoding if possible. */
@@ -35,12 +35,12 @@ static void *createStringObject(const redisReadTask *task, char *str, size_t len
35
35
  }
36
36
 
37
37
  static void *createArrayObject(const redisReadTask *task, int elements) {
38
- VALUE v = rb_ary_new2(elements);
38
+ volatile VALUE v = rb_ary_new2(elements);
39
39
  return tryParentize(task,v);
40
40
  }
41
41
 
42
42
  static void *createIntegerObject(const redisReadTask *task, long long value) {
43
- VALUE v = LL2NUM(value);
43
+ volatile VALUE v = LL2NUM(value);
44
44
  return tryParentize(task,v);
45
45
  }
46
46
 
@@ -62,7 +62,13 @@ redisReplyObjectFunctions redisExtReplyObjectFunctions = {
62
62
  };
63
63
 
64
64
  static void reader_mark(redisReader *reader) {
65
- VALUE root = (VALUE)reader->reply;
65
+ // volatile until rb_gc_mark
66
+ volatile VALUE root = (VALUE)reader->reply;
67
+ // FIXME - PCO - checking root for 0 is checkign to see if the value is
68
+ // Qfalse. I suspect that is not what is intended here. Checking the
69
+ // redisReader code might clarify. It would be unfortunate if the reply, a
70
+ // void* was using NULL to indicate not set but that may be the nature of
71
+ // the redisReader library. It is worth checking anyway.
66
72
  if (root != 0 && TYPE(root) == T_ARRAY) rb_gc_mark(root);
67
73
  }
68
74
 
@@ -85,7 +91,7 @@ static VALUE reader_feed(VALUE klass, VALUE str) {
85
91
 
86
92
  static VALUE reader_gets(VALUE klass) {
87
93
  redisReader *reader;
88
- VALUE reply;
94
+ volatile VALUE reply;
89
95
 
90
96
  Data_Get_Struct(klass, redisReader, reader);
91
97
  if (redisReaderGetReply(reader,(void**)&reply) != REDIS_OK)
@@ -1,3 +1,3 @@
1
1
  module Hiredis
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.3"
3
3
  end
@@ -12,15 +12,16 @@ PKGCONFNAME=hiredis.pc
12
12
  HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}')
13
13
  HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}')
14
14
  HIREDIS_PATCH=$(shell grep HIREDIS_PATCH hiredis.h | awk '{print $$3}')
15
+ HIREDIS_SONAME=$(shell grep HIREDIS_SONAME hiredis.h | awk '{print $$3}')
15
16
 
16
17
  # Installation related variables and target
17
18
  PREFIX?=/usr/local
18
19
  INCLUDE_PATH?=include/hiredis
19
20
  LIBRARY_PATH?=lib
20
21
  PKGCONF_PATH?=pkgconfig
21
- INSTALL_INCLUDE_PATH= $(PREFIX)/$(INCLUDE_PATH)
22
- INSTALL_LIBRARY_PATH= $(PREFIX)/$(LIBRARY_PATH)
23
- INSTALL_PKGCONF_PATH= $(LIBRARY_PATH)/$(PKGCONF_PATH)
22
+ INSTALL_INCLUDE_PATH= $(DESTDIR)$(PREFIX)/$(INCLUDE_PATH)
23
+ INSTALL_LIBRARY_PATH= $(DESTDIR)$(PREFIX)/$(LIBRARY_PATH)
24
+ INSTALL_PKGCONF_PATH= $(INSTALL_LIBRARY_PATH)/$(PKGCONF_PATH)
24
25
 
25
26
  # redis-server configuration used for testing
26
27
  REDIS_PORT=56379
@@ -35,16 +36,17 @@ endef
35
36
  export REDIS_TEST_CONFIG
36
37
 
37
38
  # Fallback to gcc when $CC is not in $PATH.
38
- CC:=$(shell sh -c 'type $(CC) >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
39
+ CC:=$(shell sh -c 'type $${CC%% *} >/dev/null 2>/dev/null && echo $(CC) || echo gcc')
40
+ CXX:=$(shell sh -c 'type $${CXX%% *} >/dev/null 2>/dev/null && echo $(CXX) || echo g++')
39
41
  OPTIMIZATION?=-O3
40
42
  WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
41
- DEBUG?= -g -ggdb
42
- REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)
43
- REAL_LDFLAGS=$(LDFLAGS) $(ARCH)
43
+ DEBUG_FLAGS?= -g -ggdb
44
+ REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG_FLAGS)
45
+ REAL_LDFLAGS=$(LDFLAGS)
44
46
 
45
47
  DYLIBSUFFIX=so
46
48
  STLIBSUFFIX=a
47
- DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR).$(HIREDIS_MINOR)
49
+ DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME)
48
50
  DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)
49
51
  DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
50
52
  DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
@@ -56,16 +58,14 @@ uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
56
58
  ifeq ($(uname_S),SunOS)
57
59
  REAL_LDFLAGS+= -ldl -lnsl -lsocket
58
60
  DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)
59
- INSTALL= cp -r
60
61
  endif
61
62
  ifeq ($(uname_S),Darwin)
62
63
  DYLIBSUFFIX=dylib
63
- DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(DYLIBSUFFIX)
64
- DYLIB_MAJOR_NAME=$(LIBNAME).$(HIREDIS_MAJOR).$(DYLIBSUFFIX)
65
- DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
64
+ DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX)
65
+ DYLIB_MAKE_CMD=$(CC) -dynamiclib -Wl,-install_name,$(PREFIX)/$(LIBRARY_PATH)/$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
66
66
  endif
67
67
 
68
- all: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
68
+ all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME)
69
69
 
70
70
  # Deps (use make dep to generate this)
71
71
  async.o: async.c fmacros.h async.h hiredis.h read.h sds.h net.h dict.c dict.h
@@ -93,7 +93,13 @@ hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)
93
93
  $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)
94
94
 
95
95
  hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME)
96
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) $(shell pkg-config --cflags --libs glib-2.0) -I. $< $(STLIBNAME)
96
+ $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(shell pkg-config --cflags --libs glib-2.0) $(STLIBNAME)
97
+
98
+ hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME)
99
+ $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis $(STLIBNAME)
100
+
101
+ hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME)
102
+ $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME)
97
103
 
98
104
  ifndef AE_DIR
99
105
  hiredis-example-ae:
@@ -110,7 +116,20 @@ hiredis-example-libuv:
110
116
  @false
111
117
  else
112
118
  hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)
113
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread $(STLIBNAME)
119
+ $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME)
120
+ endif
121
+
122
+ ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),)
123
+ hiredis-example-qt:
124
+ @echo "Please specify QT_MOC, QT_INCLUDE_DIR AND QT_LIBRARY_DIR"
125
+ @false
126
+ else
127
+ hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME)
128
+ $(QT_MOC) adapters/qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \
129
+ $(CXX) -x c++ -o qt-adapter-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore
130
+ $(QT_MOC) examples/example-qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \
131
+ $(CXX) -x c++ -o qt-example-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore
132
+ $(CXX) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore -L$(QT_LIBRARY_DIR) qt-adapter-moc.o qt-example-moc.o $< -pthread $(STLIBNAME) -lQtCore
114
133
  endif
115
134
 
116
135
  hiredis-example: examples/example.c $(STLIBNAME)
@@ -121,7 +140,7 @@ examples: $(EXAMPLES)
121
140
  hiredis-test: test.o $(STLIBNAME)
122
141
 
123
142
  hiredis-%: %.o $(STLIBNAME)
124
- $(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
143
+ $(CC) $(REAL_CFLAGS) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
125
144
 
126
145
  test: hiredis-test
127
146
  ./hiredis-test
@@ -141,31 +160,27 @@ clean:
141
160
  dep:
142
161
  $(CC) -MM *.c
143
162
 
144
- ifeq ($(uname_S),SunOS)
145
- INSTALL?= cp -r
146
- endif
163
+ INSTALL?= cp -pPR
147
164
 
148
- INSTALL?= cp -a
149
-
150
- $(PKGCONFNAME): $(PKGCONF_SRCNAME)
165
+ $(PKGCONFNAME): hiredis.h
151
166
  @echo "Generating $@ for pkgconfig..."
152
167
  @echo prefix=$(PREFIX) > $@
153
- @echo exec_prefix=$${prefix} >> $@
154
- @echo libdir=$(INSTALL_LIBRARY_PATH) >> $@
155
- @echo includedir=$(INSTALL_INCLUDE_PATH) >> $@
168
+ @echo exec_prefix=\$${prefix} >> $@
169
+ @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@
170
+ @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@
156
171
  @echo >> $@
157
172
  @echo Name: hiredis >> $@
158
- @echo Description: Minimalistic C client library for the Redis database. >> $@
173
+ @echo Description: Minimalistic C client library for Redis. >> $@
159
174
  @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@
160
- @echo Libs: -L$${libdir} -lhiredis >> $@
161
- @echo Cflags: -I$${includedir} -D_FILE_OFFSET_BITS=64 >> $@
175
+ @echo Libs: -L\$${libdir} -lhiredis >> $@
176
+ @echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@
162
177
 
163
- install: $(DYLIBNAME) $(STLIBNAME)
164
- mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
165
- $(INSTALL) hiredis.h async.h adapters $(INSTALL_INCLUDE_PATH)
178
+ install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
179
+ mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_INCLUDE_PATH)/adapters $(INSTALL_LIBRARY_PATH)
180
+ $(INSTALL) hiredis.h async.h read.h sds.h $(INSTALL_INCLUDE_PATH)
181
+ $(INSTALL) adapters/*.h $(INSTALL_INCLUDE_PATH)/adapters
166
182
  $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
167
- cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIB_MAJOR_NAME)
168
- cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MAJOR_NAME) $(DYLIBNAME)
183
+ cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME)
169
184
  $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
170
185
  mkdir -p $(INSTALL_PKGCONF_PATH)
171
186
  $(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
@@ -176,6 +191,10 @@ install: $(DYLIBNAME) $(STLIBNAME)
176
191
  @echo ""
177
192
  $(MAKE) CFLAGS="-m32" LDFLAGS="-m32"
178
193
 
194
+ 32bit-vars:
195
+ $(eval CFLAGS=-m32)
196
+ $(eval LDFLAGS=-m32)
197
+
179
198
  gprof:
180
199
  $(MAKE) CFLAGS="-pg" LDFLAGS="-pg"
181
200
 
@@ -191,4 +210,4 @@ coverage: gcov
191
210
  noopt:
192
211
  $(MAKE) OPTIMIZATION=""
193
212
 
194
- .PHONY: all test check clean dep install 32bit gprof gcov noopt
213
+ .PHONY: all test check clean dep install 32bit 32bit-vars gprof gcov noopt
@@ -336,7 +336,8 @@ static void __redisAsyncDisconnect(redisAsyncContext *ac) {
336
336
 
337
337
  if (ac->err == 0) {
338
338
  /* For clean disconnects, there should be no pending callbacks. */
339
- assert(__redisShiftCallback(&ac->replies,NULL) == REDIS_ERR);
339
+ int ret = __redisShiftCallback(&ac->replies,NULL);
340
+ assert(ret == REDIS_ERR);
340
341
  } else {
341
342
  /* Disconnection is caused by an error, make sure that pending
342
343
  * callbacks cannot call new commands. */
@@ -364,6 +365,7 @@ void redisAsyncDisconnect(redisAsyncContext *ac) {
364
365
  static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) {
365
366
  redisContext *c = &(ac->c);
366
367
  dict *callbacks;
368
+ redisCallback *cb;
367
369
  dictEntry *de;
368
370
  int pvariant;
369
371
  char *stype;
@@ -387,16 +389,28 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
387
389
  sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len);
388
390
  de = dictFind(callbacks,sname);
389
391
  if (de != NULL) {
390
- memcpy(dstcb,dictGetEntryVal(de),sizeof(*dstcb));
392
+ cb = dictGetEntryVal(de);
393
+
394
+ /* If this is an subscribe reply decrease pending counter. */
395
+ if (strcasecmp(stype+pvariant,"subscribe") == 0) {
396
+ cb->pending_subs -= 1;
397
+ }
398
+
399
+ memcpy(dstcb,cb,sizeof(*dstcb));
391
400
 
392
401
  /* If this is an unsubscribe message, remove it. */
393
402
  if (strcasecmp(stype+pvariant,"unsubscribe") == 0) {
394
- dictDelete(callbacks,sname);
403
+ if (cb->pending_subs == 0)
404
+ dictDelete(callbacks,sname);
395
405
 
396
406
  /* If this was the last unsubscribe message, revert to
397
407
  * non-subscribe mode. */
398
408
  assert(reply->element[2]->type == REDIS_REPLY_INTEGER);
399
- if (reply->element[2]->integer == 0)
409
+
410
+ /* Unset subscribed flag only when no pipelined pending subscribe. */
411
+ if (reply->element[2]->integer == 0
412
+ && dictSize(ac->sub.channels) == 0
413
+ && dictSize(ac->sub.patterns) == 0)
400
414
  c->flags &= ~REDIS_SUBSCRIBED;
401
415
  }
402
416
  }
@@ -410,7 +424,7 @@ static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply,
410
424
 
411
425
  void redisProcessCallbacks(redisAsyncContext *ac) {
412
426
  redisContext *c = &(ac->c);
413
- redisCallback cb = {NULL, NULL, NULL};
427
+ redisCallback cb = {NULL, NULL, 0, NULL};
414
428
  void *reply = NULL;
415
429
  int status;
416
430
 
@@ -418,7 +432,8 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
418
432
  if (reply == NULL) {
419
433
  /* When the connection is being disconnected and there are
420
434
  * no more replies, this is the cue to really disconnect. */
421
- if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0) {
435
+ if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0
436
+ && ac->replies.head == NULL) {
422
437
  __redisAsyncDisconnect(ac);
423
438
  return;
424
439
  }
@@ -454,6 +469,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
454
469
  if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {
455
470
  c->err = REDIS_ERR_OTHER;
456
471
  snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
472
+ c->reader->fn->freeObject(reply);
457
473
  __redisAsyncDisconnect(ac);
458
474
  return;
459
475
  }
@@ -487,7 +503,7 @@ void redisProcessCallbacks(redisAsyncContext *ac) {
487
503
  }
488
504
 
489
505
  /* Internal helper function to detect socket status the first time a read or
490
- * write event fires. When connecting was not succesful, the connect callback
506
+ * write event fires. When connecting was not successful, the connect callback
491
507
  * is called with a REDIS_ERR status and the context is free'd. */
492
508
  static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
493
509
  redisContext *c = &(ac->c);
@@ -581,6 +597,9 @@ static const char *nextArgument(const char *start, const char **str, size_t *len
581
597
  static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) {
582
598
  redisContext *c = &(ac->c);
583
599
  redisCallback cb;
600
+ struct dict *cbdict;
601
+ dictEntry *de;
602
+ redisCallback *existcb;
584
603
  int pvariant, hasnext;
585
604
  const char *cstr, *astr;
586
605
  size_t clen, alen;
@@ -594,6 +613,7 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
594
613
  /* Setup callback */
595
614
  cb.fn = fn;
596
615
  cb.privdata = privdata;
616
+ cb.pending_subs = 1;
597
617
 
598
618
  /* Find out which command will be appended. */
599
619
  p = nextArgument(cmd,&cstr,&clen);
@@ -610,9 +630,18 @@ static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void
610
630
  while ((p = nextArgument(p,&astr,&alen)) != NULL) {
611
631
  sname = sdsnewlen(astr,alen);
612
632
  if (pvariant)
613
- ret = dictReplace(ac->sub.patterns,sname,&cb);
633
+ cbdict = ac->sub.patterns;
614
634
  else
615
- ret = dictReplace(ac->sub.channels,sname,&cb);
635
+ cbdict = ac->sub.channels;
636
+
637
+ de = dictFind(cbdict,sname);
638
+
639
+ if (de != NULL) {
640
+ existcb = dictGetEntryVal(de);
641
+ cb.pending_subs = existcb->pending_subs + 1;
642
+ }
643
+
644
+ ret = dictReplace(cbdict,sname,&cb);
616
645
 
617
646
  if (ret == 0) sdsfree(sname);
618
647
  }
@@ -674,6 +703,8 @@ int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *priv
674
703
  int len;
675
704
  int status;
676
705
  len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen);
706
+ if (len < 0)
707
+ return REDIS_ERR;
677
708
  status = __redisAsyncCommand(ac,fn,privdata,cmd,len);
678
709
  sdsfree(cmd);
679
710
  return status;
@@ -45,6 +45,7 @@ typedef void (redisCallbackFn)(struct redisAsyncContext*, void*, void*);
45
45
  typedef struct redisCallback {
46
46
  struct redisCallback *next; /* simple singly linked list */
47
47
  redisCallbackFn *fn;
48
+ int pending_subs;
48
49
  void *privdata;
49
50
  } redisCallback;
50
51
 
@@ -161,7 +161,7 @@ static int dictReplace(dict *ht, void *key, void *val) {
161
161
  dictEntry *entry, auxentry;
162
162
 
163
163
  /* Try to add the element. If the key
164
- * does not exists dictAdd will suceed. */
164
+ * does not exists dictAdd will succeed. */
165
165
  if (dictAdd(ht, key, val) == DICT_OK)
166
166
  return 1;
167
167
  /* It already exists, get the entry */
@@ -293,7 +293,7 @@ static void dictReleaseIterator(dictIterator *iter) {
293
293
 
294
294
  /* Expand the hash table if needed */
295
295
  static int _dictExpandIfNeeded(dict *ht) {
296
- /* If the hash table is empty expand it to the intial size,
296
+ /* If the hash table is empty expand it to the initial size,
297
297
  * if the table is "full" dobule its size. */
298
298
  if (ht->size == 0)
299
299
  return dictExpand(ht, DICT_HT_INITIAL_SIZE);
@@ -1,21 +1,12 @@
1
1
  #ifndef __HIREDIS_FMACRO_H
2
2
  #define __HIREDIS_FMACRO_H
3
3
 
4
- #if defined(__linux__)
5
- #define _BSD_SOURCE
6
- #define _DEFAULT_SOURCE
7
- #endif
8
-
9
- #if defined(__sun__)
10
- #define _POSIX_C_SOURCE 200112L
11
- #elif defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__)
12
4
  #define _XOPEN_SOURCE 600
13
- #else
14
- #define _XOPEN_SOURCE
15
- #endif
5
+ #define _POSIX_C_SOURCE 200112L
16
6
 
17
- #if __APPLE__ && __MACH__
18
- #define _OSX
7
+ #if defined(__APPLE__) && defined(__MACH__)
8
+ /* Enable TCP_KEEPALIVE */
9
+ #define _DARWIN_C_SOURCE
19
10
  #endif
20
11
 
21
12
  #endif