durable_rules 0.34.57 → 2.00.001

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.
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: durable_rules
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.34.57
4
+ version: 2.00.001
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jesus Ruiz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-28 00:00:00.000000000 Z
11
+ date: 2019-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4.0'
55
- - !ruby/object:Gem::Dependency
56
- name: sinatra
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.4'
62
- type: :runtime
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.4'
69
55
  description: A lightweight library for real-time, consistent and scalable coordination
70
56
  of events.
71
57
  email: jr3791@live.com
@@ -76,32 +62,12 @@ extra_rdoc_files: []
76
62
  files:
77
63
  - LICENSE
78
64
  - Rakefile
79
- - deps/hiredis/COPYING
80
- - deps/hiredis/Makefile
81
- - deps/hiredis/async.c
82
- - deps/hiredis/async.h
83
- - deps/hiredis/dict.c
84
- - deps/hiredis/dict.h
85
- - deps/hiredis/fmacros.h
86
- - deps/hiredis/hiredis.c
87
- - deps/hiredis/hiredis.h
88
- - deps/hiredis/net.c
89
- - deps/hiredis/net.h
90
- - deps/hiredis/read.c
91
- - deps/hiredis/read.h
92
- - deps/hiredis/sds.c
93
- - deps/hiredis/sds.h
94
- - deps/hiredis/test.c
95
- - deps/hiredis/win32.h
96
65
  - librb/durable.rb
97
66
  - librb/engine.rb
98
- - librb/interface.rb
99
67
  - src/rules/Makefile
100
68
  - src/rules/events.c
101
69
  - src/rules/json.c
102
70
  - src/rules/json.h
103
- - src/rules/net.c
104
- - src/rules/net.h
105
71
  - src/rules/regex.c
106
72
  - src/rules/regex.h
107
73
  - src/rules/rete.c
data/deps/hiredis/COPYING DELETED
@@ -1,29 +0,0 @@
1
- Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
2
- Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
3
-
4
- All rights reserved.
5
-
6
- Redistribution and use in source and binary forms, with or without
7
- modification, are permitted provided that the following conditions are met:
8
-
9
- * Redistributions of source code must retain the above copyright notice,
10
- this list of conditions and the following disclaimer.
11
-
12
- * Redistributions in binary form must reproduce the above copyright notice,
13
- this list of conditions and the following disclaimer in the documentation
14
- and/or other materials provided with the distribution.
15
-
16
- * Neither the name of Redis nor the names of its contributors may be used
17
- to endorse or promote products derived from this software without specific
18
- prior written permission.
19
-
20
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
21
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
24
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
27
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -1,217 +0,0 @@
1
- # Hiredis Makefile
2
- # Copyright (C) 2010-2011 Salvatore Sanfilippo <antirez at gmail dot com>
3
- # Copyright (C) 2010-2011 Pieter Noordhuis <pcnoordhuis at gmail dot com>
4
- # This file is released under the BSD license, see the COPYING file
5
-
6
- OBJ=net.o hiredis.o sds.o async.o read.o
7
- EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib
8
- TESTS=hiredis-test
9
- LIBNAME=libhiredis
10
- PKGCONFNAME=hiredis.pc
11
-
12
- HIREDIS_MAJOR=$(shell grep HIREDIS_MAJOR hiredis.h | awk '{print $$3}')
13
- HIREDIS_MINOR=$(shell grep HIREDIS_MINOR hiredis.h | awk '{print $$3}')
14
- HIREDIS_PATCH=$(shell grep HIREDIS_PATCH hiredis.h | awk '{print $$3}')
15
- HIREDIS_SONAME=$(shell grep HIREDIS_SONAME hiredis.h | awk '{print $$3}')
16
-
17
- # Installation related variables and target
18
- PREFIX?=/usr/local
19
- INCLUDE_PATH?=include/hiredis
20
- LIBRARY_PATH?=lib
21
- PKGCONF_PATH?=pkgconfig
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)
25
-
26
- # redis-server configuration used for testing
27
- REDIS_PORT=56379
28
- REDIS_SERVER=redis-server
29
- define REDIS_TEST_CONFIG
30
- daemonize yes
31
- pidfile /tmp/hiredis-test-redis.pid
32
- port $(REDIS_PORT)
33
- bind 127.0.0.1
34
- unixsocket /tmp/hiredis-test-redis.sock
35
- endef
36
- export REDIS_TEST_CONFIG
37
-
38
- # Fallback to gcc when $CC is not in $PATH.
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++')
41
- OPTIMIZATION?=-O3
42
- WARNINGS=-Wall -W -Wstrict-prototypes -Wwrite-strings
43
- DEBUG?= -g -ggdb
44
- REAL_CFLAGS=$(OPTIMIZATION) -fPIC $(CFLAGS) $(WARNINGS) $(DEBUG) $(ARCH)
45
- REAL_LDFLAGS=$(LDFLAGS) $(ARCH)
46
-
47
- DYLIBSUFFIX=so
48
- STLIBSUFFIX=a
49
- DYLIB_MINOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_SONAME)
50
- DYLIB_MAJOR_NAME=$(LIBNAME).$(DYLIBSUFFIX).$(HIREDIS_MAJOR)
51
- DYLIBNAME=$(LIBNAME).$(DYLIBSUFFIX)
52
- DYLIB_MAKE_CMD=$(CC) -shared -Wl,-soname,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
53
- STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
54
- STLIB_MAKE_CMD=ar rcs $(STLIBNAME)
55
-
56
- # Platform-specific overrides
57
- uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
58
- ifeq ($(uname_S),SunOS)
59
- REAL_LDFLAGS+= -ldl -lnsl -lsocket
60
- DYLIB_MAKE_CMD=$(CC) -G -o $(DYLIBNAME) -h $(DYLIB_MINOR_NAME) $(LDFLAGS)
61
- INSTALL= cp -r
62
- endif
63
- ifeq ($(uname_S),Darwin)
64
- DYLIBSUFFIX=dylib
65
- DYLIB_MINOR_NAME=$(LIBNAME).$(HIREDIS_SONAME).$(DYLIBSUFFIX)
66
- DYLIB_MAKE_CMD=$(CC) -shared -Wl,-install_name,$(DYLIB_MINOR_NAME) -o $(DYLIBNAME) $(LDFLAGS)
67
- endif
68
-
69
- all: $(DYLIBNAME) $(STLIBNAME) hiredis-test $(PKGCONFNAME)
70
-
71
- # Deps (use make dep to generate this)
72
- async.o: async.c fmacros.h async.h hiredis.h read.h sds.h net.h dict.c dict.h
73
- dict.o: dict.c fmacros.h dict.h
74
- hiredis.o: hiredis.c fmacros.h hiredis.h read.h sds.h net.h
75
- net.o: net.c fmacros.h net.h hiredis.h read.h sds.h
76
- read.o: read.c fmacros.h read.h sds.h
77
- sds.o: sds.c sds.h
78
- test.o: test.c fmacros.h hiredis.h read.h sds.h
79
-
80
- $(DYLIBNAME): $(OBJ)
81
- $(DYLIB_MAKE_CMD) $(OBJ)
82
-
83
- $(STLIBNAME): $(OBJ)
84
- $(STLIB_MAKE_CMD) $(OBJ)
85
-
86
- dynamic: $(DYLIBNAME)
87
- static: $(STLIBNAME)
88
-
89
- # Binaries:
90
- hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLIBNAME)
91
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -levent $(STLIBNAME)
92
-
93
- hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)
94
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)
95
-
96
- hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME)
97
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) $(shell pkg-config --cflags --libs glib-2.0) -I. $< $(STLIBNAME)
98
-
99
- hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME)
100
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis $(STLIBNAME)
101
-
102
- hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME)
103
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME)
104
-
105
- ifndef AE_DIR
106
- hiredis-example-ae:
107
- @echo "Please specify AE_DIR (e.g. <redis repository>/src)"
108
- @false
109
- else
110
- hiredis-example-ae: examples/example-ae.c adapters/ae.h $(STLIBNAME)
111
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(AE_DIR) $< $(AE_DIR)/ae.o $(AE_DIR)/zmalloc.o $(AE_DIR)/../deps/jemalloc/lib/libjemalloc.a -pthread $(STLIBNAME)
112
- endif
113
-
114
- ifndef LIBUV_DIR
115
- hiredis-example-libuv:
116
- @echo "Please specify LIBUV_DIR (e.g. ../libuv/)"
117
- @false
118
- else
119
- hiredis-example-libuv: examples/example-libuv.c adapters/libuv.h $(STLIBNAME)
120
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. -I$(LIBUV_DIR)/include $< $(LIBUV_DIR)/.libs/libuv.a -lpthread -lrt $(STLIBNAME)
121
- endif
122
-
123
- ifeq ($(and $(QT_MOC),$(QT_INCLUDE_DIR),$(QT_LIBRARY_DIR)),)
124
- hiredis-example-qt:
125
- @echo "Please specify QT_MOC, QT_INCLUDE_DIR AND QT_LIBRARY_DIR"
126
- @false
127
- else
128
- hiredis-example-qt: examples/example-qt.cpp adapters/qt.h $(STLIBNAME)
129
- $(QT_MOC) adapters/qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \
130
- $(CXX) -x c++ -o qt-adapter-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore
131
- $(QT_MOC) examples/example-qt.h -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore | \
132
- $(CXX) -x c++ -o qt-example-moc.o -c - $(REAL_CFLAGS) -I. -I$(QT_INCLUDE_DIR) -I$(QT_INCLUDE_DIR)/QtCore
133
- $(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
134
- endif
135
-
136
- hiredis-example: examples/example.c $(STLIBNAME)
137
- $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< $(STLIBNAME)
138
-
139
- examples: $(EXAMPLES)
140
-
141
- hiredis-test: test.o $(STLIBNAME)
142
-
143
- hiredis-%: %.o $(STLIBNAME)
144
- $(CC) $(REAL_CFLAGS) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
145
-
146
- test: hiredis-test
147
- ./hiredis-test
148
-
149
- check: hiredis-test
150
- @echo "$$REDIS_TEST_CONFIG" | $(REDIS_SERVER) -
151
- $(PRE) ./hiredis-test -h 127.0.0.1 -p $(REDIS_PORT) -s /tmp/hiredis-test-redis.sock || \
152
- ( kill `cat /tmp/hiredis-test-redis.pid` && false )
153
- kill `cat /tmp/hiredis-test-redis.pid`
154
-
155
- .c.o:
156
- $(CC) -std=c99 -pedantic -c $(REAL_CFLAGS) $<
157
-
158
- clean:
159
- rm -rf $(DYLIBNAME) $(STLIBNAME) $(TESTS) $(PKGCONFNAME) examples/hiredis-example* *.o *.gcda *.gcno *.gcov
160
-
161
- dep:
162
- $(CC) -MM *.c
163
-
164
- ifeq ($(uname_S),SunOS)
165
- INSTALL?= cp -r
166
- endif
167
-
168
- INSTALL?= cp -a
169
-
170
- $(PKGCONFNAME): hiredis.h
171
- @echo "Generating $@ for pkgconfig..."
172
- @echo prefix=$(PREFIX) > $@
173
- @echo exec_prefix=\$${prefix} >> $@
174
- @echo libdir=$(PREFIX)/$(LIBRARY_PATH) >> $@
175
- @echo includedir=$(PREFIX)/$(INCLUDE_PATH) >> $@
176
- @echo >> $@
177
- @echo Name: hiredis >> $@
178
- @echo Description: Minimalistic C client library for Redis. >> $@
179
- @echo Version: $(HIREDIS_MAJOR).$(HIREDIS_MINOR).$(HIREDIS_PATCH) >> $@
180
- @echo Libs: -L\$${libdir} -lhiredis >> $@
181
- @echo Cflags: -I\$${includedir} -D_FILE_OFFSET_BITS=64 >> $@
182
-
183
- install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
184
- mkdir -p $(INSTALL_INCLUDE_PATH) $(INSTALL_LIBRARY_PATH)
185
- $(INSTALL) hiredis.h async.h read.h sds.h adapters $(INSTALL_INCLUDE_PATH)
186
- $(INSTALL) $(DYLIBNAME) $(INSTALL_LIBRARY_PATH)/$(DYLIB_MINOR_NAME)
187
- cd $(INSTALL_LIBRARY_PATH) && ln -sf $(DYLIB_MINOR_NAME) $(DYLIBNAME)
188
- $(INSTALL) $(STLIBNAME) $(INSTALL_LIBRARY_PATH)
189
- mkdir -p $(INSTALL_PKGCONF_PATH)
190
- $(INSTALL) $(PKGCONFNAME) $(INSTALL_PKGCONF_PATH)
191
-
192
- 32bit:
193
- @echo ""
194
- @echo "WARNING: if this fails under Linux you probably need to install libc6-dev-i386"
195
- @echo ""
196
- $(MAKE) CFLAGS="-m32" LDFLAGS="-m32"
197
-
198
- 32bit-vars:
199
- $(eval CFLAGS=-m32)
200
- $(eval LDFLAGS=-m32)
201
-
202
- gprof:
203
- $(MAKE) CFLAGS="-pg" LDFLAGS="-pg"
204
-
205
- gcov:
206
- $(MAKE) CFLAGS="-fprofile-arcs -ftest-coverage" LDFLAGS="-fprofile-arcs"
207
-
208
- coverage: gcov
209
- make check
210
- mkdir -p tmp/lcov
211
- lcov -d . -c -o tmp/lcov/hiredis.info
212
- genhtml --legend -o tmp/lcov/report tmp/lcov/hiredis.info
213
-
214
- noopt:
215
- $(MAKE) OPTIMIZATION=""
216
-
217
- .PHONY: all test check clean dep install 32bit 32bit-vars gprof gcov noopt
data/deps/hiredis/async.c DELETED
@@ -1,687 +0,0 @@
1
- /*
2
- * Copyright (c) 2009-2011, Salvatore Sanfilippo <antirez at gmail dot com>
3
- * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
4
- *
5
- * All rights reserved.
6
- *
7
- * Redistribution and use in source and binary forms, with or without
8
- * modification, are permitted provided that the following conditions are met:
9
- *
10
- * * Redistributions of source code must retain the above copyright notice,
11
- * this list of conditions and the following disclaimer.
12
- * * Redistributions in binary form must reproduce the above copyright
13
- * notice, this list of conditions and the following disclaimer in the
14
- * documentation and/or other materials provided with the distribution.
15
- * * Neither the name of Redis nor the names of its contributors may be used
16
- * to endorse or promote products derived from this software without
17
- * specific prior written permission.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
- * POSSIBILITY OF SUCH DAMAGE.
30
- */
31
-
32
- #include "fmacros.h"
33
- #include <stdlib.h>
34
- #include <string.h>
35
- #include <strings.h>
36
- #include <assert.h>
37
- #include <ctype.h>
38
- #include <errno.h>
39
- #include "async.h"
40
- #include "net.h"
41
- #include "dict.c"
42
- #include "sds.h"
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
-
60
- /* Forward declaration of function in hiredis.c */
61
- int __redisAppendCommand(redisContext *c, const char *cmd, size_t len);
62
-
63
- /* Functions managing dictionary of callbacks for pub/sub. */
64
- static unsigned int callbackHash(const void *key) {
65
- return dictGenHashFunction((const unsigned char *)key,
66
- sdslen((const sds)key));
67
- }
68
-
69
- static void *callbackValDup(void *privdata, const void *src) {
70
- ((void) privdata);
71
- redisCallback *dup = malloc(sizeof(*dup));
72
- memcpy(dup,src,sizeof(*dup));
73
- return dup;
74
- }
75
-
76
- static int callbackKeyCompare(void *privdata, const void *key1, const void *key2) {
77
- int l1, l2;
78
- ((void) privdata);
79
-
80
- l1 = sdslen((const sds)key1);
81
- l2 = sdslen((const sds)key2);
82
- if (l1 != l2) return 0;
83
- return memcmp(key1,key2,l1) == 0;
84
- }
85
-
86
- static void callbackKeyDestructor(void *privdata, void *key) {
87
- ((void) privdata);
88
- sdsfree((sds)key);
89
- }
90
-
91
- static void callbackValDestructor(void *privdata, void *val) {
92
- ((void) privdata);
93
- free(val);
94
- }
95
-
96
- static dictType callbackDict = {
97
- callbackHash,
98
- NULL,
99
- callbackValDup,
100
- callbackKeyCompare,
101
- callbackKeyDestructor,
102
- callbackValDestructor
103
- };
104
-
105
- static redisAsyncContext *redisAsyncInitialize(redisContext *c) {
106
- redisAsyncContext *ac;
107
-
108
- ac = realloc(c,sizeof(redisAsyncContext));
109
- if (ac == NULL)
110
- return NULL;
111
-
112
- c = &(ac->c);
113
-
114
- /* The regular connect functions will always set the flag REDIS_CONNECTED.
115
- * For the async API, we want to wait until the first write event is
116
- * received up before setting this flag, so reset it here. */
117
- c->flags &= ~REDIS_CONNECTED;
118
-
119
- ac->err = 0;
120
- ac->errstr = NULL;
121
- ac->data = NULL;
122
-
123
- ac->ev.data = NULL;
124
- ac->ev.addRead = NULL;
125
- ac->ev.delRead = NULL;
126
- ac->ev.addWrite = NULL;
127
- ac->ev.delWrite = NULL;
128
- ac->ev.cleanup = NULL;
129
-
130
- ac->onConnect = NULL;
131
- ac->onDisconnect = NULL;
132
-
133
- ac->replies.head = NULL;
134
- ac->replies.tail = NULL;
135
- ac->sub.invalid.head = NULL;
136
- ac->sub.invalid.tail = NULL;
137
- ac->sub.channels = dictCreate(&callbackDict,NULL);
138
- ac->sub.patterns = dictCreate(&callbackDict,NULL);
139
- return ac;
140
- }
141
-
142
- /* We want the error field to be accessible directly instead of requiring
143
- * an indirection to the redisContext struct. */
144
- static void __redisAsyncCopyError(redisAsyncContext *ac) {
145
- if (!ac)
146
- return;
147
-
148
- redisContext *c = &(ac->c);
149
- ac->err = c->err;
150
- ac->errstr = c->errstr;
151
- }
152
-
153
- redisAsyncContext *redisAsyncConnect(const char *ip, int port) {
154
- redisContext *c;
155
- redisAsyncContext *ac;
156
-
157
- c = redisConnectNonBlock(ip,port);
158
- if (c == NULL)
159
- return NULL;
160
-
161
- ac = redisAsyncInitialize(c);
162
- if (ac == NULL) {
163
- redisFree(c);
164
- return NULL;
165
- }
166
-
167
- __redisAsyncCopyError(ac);
168
- return ac;
169
- }
170
-
171
- redisAsyncContext *redisAsyncConnectBind(const char *ip, int port,
172
- const char *source_addr) {
173
- redisContext *c = redisConnectBindNonBlock(ip,port,source_addr);
174
- redisAsyncContext *ac = redisAsyncInitialize(c);
175
- __redisAsyncCopyError(ac);
176
- return ac;
177
- }
178
-
179
- redisAsyncContext *redisAsyncConnectBindWithReuse(const char *ip, int port,
180
- const char *source_addr) {
181
- redisContext *c = redisConnectBindNonBlockWithReuse(ip,port,source_addr);
182
- redisAsyncContext *ac = redisAsyncInitialize(c);
183
- __redisAsyncCopyError(ac);
184
- return ac;
185
- }
186
-
187
- redisAsyncContext *redisAsyncConnectUnix(const char *path) {
188
- redisContext *c;
189
- redisAsyncContext *ac;
190
-
191
- c = redisConnectUnixNonBlock(path);
192
- if (c == NULL)
193
- return NULL;
194
-
195
- ac = redisAsyncInitialize(c);
196
- if (ac == NULL) {
197
- redisFree(c);
198
- return NULL;
199
- }
200
-
201
- __redisAsyncCopyError(ac);
202
- return ac;
203
- }
204
-
205
- int redisAsyncSetConnectCallback(redisAsyncContext *ac, redisConnectCallback *fn) {
206
- if (ac->onConnect == NULL) {
207
- ac->onConnect = fn;
208
-
209
- /* The common way to detect an established connection is to wait for
210
- * the first write event to be fired. This assumes the related event
211
- * library functions are already set. */
212
- _EL_ADD_WRITE(ac);
213
- return REDIS_OK;
214
- }
215
- return REDIS_ERR;
216
- }
217
-
218
- int redisAsyncSetDisconnectCallback(redisAsyncContext *ac, redisDisconnectCallback *fn) {
219
- if (ac->onDisconnect == NULL) {
220
- ac->onDisconnect = fn;
221
- return REDIS_OK;
222
- }
223
- return REDIS_ERR;
224
- }
225
-
226
- /* Helper functions to push/shift callbacks */
227
- static int __redisPushCallback(redisCallbackList *list, redisCallback *source) {
228
- redisCallback *cb;
229
-
230
- /* Copy callback from stack to heap */
231
- cb = malloc(sizeof(*cb));
232
- if (cb == NULL)
233
- return REDIS_ERR_OOM;
234
-
235
- if (source != NULL) {
236
- memcpy(cb,source,sizeof(*cb));
237
- cb->next = NULL;
238
- }
239
-
240
- /* Store callback in list */
241
- if (list->head == NULL)
242
- list->head = cb;
243
- if (list->tail != NULL)
244
- list->tail->next = cb;
245
- list->tail = cb;
246
- return REDIS_OK;
247
- }
248
-
249
- static int __redisShiftCallback(redisCallbackList *list, redisCallback *target) {
250
- redisCallback *cb = list->head;
251
- if (cb != NULL) {
252
- list->head = cb->next;
253
- if (cb == list->tail)
254
- list->tail = NULL;
255
-
256
- /* Copy callback from heap to stack */
257
- if (target != NULL)
258
- memcpy(target,cb,sizeof(*cb));
259
- free(cb);
260
- return REDIS_OK;
261
- }
262
- return REDIS_ERR;
263
- }
264
-
265
- static void __redisRunCallback(redisAsyncContext *ac, redisCallback *cb, redisReply *reply) {
266
- redisContext *c = &(ac->c);
267
- if (cb->fn != NULL) {
268
- c->flags |= REDIS_IN_CALLBACK;
269
- cb->fn(ac,reply,cb->privdata);
270
- c->flags &= ~REDIS_IN_CALLBACK;
271
- }
272
- }
273
-
274
- /* Helper function to free the context. */
275
- static void __redisAsyncFree(redisAsyncContext *ac) {
276
- redisContext *c = &(ac->c);
277
- redisCallback cb;
278
- dictIterator *it;
279
- dictEntry *de;
280
-
281
- /* Execute pending callbacks with NULL reply. */
282
- while (__redisShiftCallback(&ac->replies,&cb) == REDIS_OK)
283
- __redisRunCallback(ac,&cb,NULL);
284
-
285
- /* Execute callbacks for invalid commands */
286
- while (__redisShiftCallback(&ac->sub.invalid,&cb) == REDIS_OK)
287
- __redisRunCallback(ac,&cb,NULL);
288
-
289
- /* Run subscription callbacks callbacks with NULL reply */
290
- it = dictGetIterator(ac->sub.channels);
291
- while ((de = dictNext(it)) != NULL)
292
- __redisRunCallback(ac,dictGetEntryVal(de),NULL);
293
- dictReleaseIterator(it);
294
- dictRelease(ac->sub.channels);
295
-
296
- it = dictGetIterator(ac->sub.patterns);
297
- while ((de = dictNext(it)) != NULL)
298
- __redisRunCallback(ac,dictGetEntryVal(de),NULL);
299
- dictReleaseIterator(it);
300
- dictRelease(ac->sub.patterns);
301
-
302
- /* Signal event lib to clean up */
303
- _EL_CLEANUP(ac);
304
-
305
- /* Execute disconnect callback. When redisAsyncFree() initiated destroying
306
- * this context, the status will always be REDIS_OK. */
307
- if (ac->onDisconnect && (c->flags & REDIS_CONNECTED)) {
308
- if (c->flags & REDIS_FREEING) {
309
- ac->onDisconnect(ac,REDIS_OK);
310
- } else {
311
- ac->onDisconnect(ac,(ac->err == 0) ? REDIS_OK : REDIS_ERR);
312
- }
313
- }
314
-
315
- /* Cleanup self */
316
- redisFree(c);
317
- }
318
-
319
- /* Free the async context. When this function is called from a callback,
320
- * control needs to be returned to redisProcessCallbacks() before actual
321
- * free'ing. To do so, a flag is set on the context which is picked up by
322
- * redisProcessCallbacks(). Otherwise, the context is immediately free'd. */
323
- void redisAsyncFree(redisAsyncContext *ac) {
324
- redisContext *c = &(ac->c);
325
- c->flags |= REDIS_FREEING;
326
- if (!(c->flags & REDIS_IN_CALLBACK))
327
- __redisAsyncFree(ac);
328
- }
329
-
330
- /* Helper function to make the disconnect happen and clean up. */
331
- static void __redisAsyncDisconnect(redisAsyncContext *ac) {
332
- redisContext *c = &(ac->c);
333
-
334
- /* Make sure error is accessible if there is any */
335
- __redisAsyncCopyError(ac);
336
-
337
- if (ac->err == 0) {
338
- /* For clean disconnects, there should be no pending callbacks. */
339
- assert(__redisShiftCallback(&ac->replies,NULL) == REDIS_ERR);
340
- } else {
341
- /* Disconnection is caused by an error, make sure that pending
342
- * callbacks cannot call new commands. */
343
- c->flags |= REDIS_DISCONNECTING;
344
- }
345
-
346
- /* For non-clean disconnects, __redisAsyncFree() will execute pending
347
- * callbacks with a NULL-reply. */
348
- __redisAsyncFree(ac);
349
- }
350
-
351
- /* Tries to do a clean disconnect from Redis, meaning it stops new commands
352
- * from being issued, but tries to flush the output buffer and execute
353
- * callbacks for all remaining replies. When this function is called from a
354
- * callback, there might be more replies and we can safely defer disconnecting
355
- * to redisProcessCallbacks(). Otherwise, we can only disconnect immediately
356
- * when there are no pending callbacks. */
357
- void redisAsyncDisconnect(redisAsyncContext *ac) {
358
- redisContext *c = &(ac->c);
359
- c->flags |= REDIS_DISCONNECTING;
360
- if (!(c->flags & REDIS_IN_CALLBACK) && ac->replies.head == NULL)
361
- __redisAsyncDisconnect(ac);
362
- }
363
-
364
- static int __redisGetSubscribeCallback(redisAsyncContext *ac, redisReply *reply, redisCallback *dstcb) {
365
- redisContext *c = &(ac->c);
366
- dict *callbacks;
367
- dictEntry *de;
368
- int pvariant;
369
- char *stype;
370
- sds sname;
371
-
372
- /* Custom reply functions are not supported for pub/sub. This will fail
373
- * very hard when they are used... */
374
- if (reply->type == REDIS_REPLY_ARRAY) {
375
- assert(reply->elements >= 2);
376
- assert(reply->element[0]->type == REDIS_REPLY_STRING);
377
- stype = reply->element[0]->str;
378
- pvariant = (tolower(stype[0]) == 'p') ? 1 : 0;
379
-
380
- if (pvariant)
381
- callbacks = ac->sub.patterns;
382
- else
383
- callbacks = ac->sub.channels;
384
-
385
- /* Locate the right callback */
386
- assert(reply->element[1]->type == REDIS_REPLY_STRING);
387
- sname = sdsnewlen(reply->element[1]->str,reply->element[1]->len);
388
- de = dictFind(callbacks,sname);
389
- if (de != NULL) {
390
- memcpy(dstcb,dictGetEntryVal(de),sizeof(*dstcb));
391
-
392
- /* If this is an unsubscribe message, remove it. */
393
- if (strcasecmp(stype+pvariant,"unsubscribe") == 0) {
394
- dictDelete(callbacks,sname);
395
-
396
- /* If this was the last unsubscribe message, revert to
397
- * non-subscribe mode. */
398
- assert(reply->element[2]->type == REDIS_REPLY_INTEGER);
399
- if (reply->element[2]->integer == 0)
400
- c->flags &= ~REDIS_SUBSCRIBED;
401
- }
402
- }
403
- sdsfree(sname);
404
- } else {
405
- /* Shift callback for invalid commands. */
406
- __redisShiftCallback(&ac->sub.invalid,dstcb);
407
- }
408
- return REDIS_OK;
409
- }
410
-
411
- void redisProcessCallbacks(redisAsyncContext *ac) {
412
- redisContext *c = &(ac->c);
413
- redisCallback cb = {NULL, NULL, NULL};
414
- void *reply = NULL;
415
- int status;
416
-
417
- while((status = redisGetReply(c,&reply)) == REDIS_OK) {
418
- if (reply == NULL) {
419
- /* When the connection is being disconnected and there are
420
- * no more replies, this is the cue to really disconnect. */
421
- if (c->flags & REDIS_DISCONNECTING && sdslen(c->obuf) == 0
422
- && ac->replies.head == NULL) {
423
- __redisAsyncDisconnect(ac);
424
- return;
425
- }
426
-
427
- /* If monitor mode, repush callback */
428
- if(c->flags & REDIS_MONITORING) {
429
- __redisPushCallback(&ac->replies,&cb);
430
- }
431
-
432
- /* When the connection is not being disconnected, simply stop
433
- * trying to get replies and wait for the next loop tick. */
434
- break;
435
- }
436
-
437
- /* Even if the context is subscribed, pending regular callbacks will
438
- * get a reply before pub/sub messages arrive. */
439
- if (__redisShiftCallback(&ac->replies,&cb) != REDIS_OK) {
440
- /*
441
- * A spontaneous reply in a not-subscribed context can be the error
442
- * reply that is sent when a new connection exceeds the maximum
443
- * number of allowed connections on the server side.
444
- *
445
- * This is seen as an error instead of a regular reply because the
446
- * server closes the connection after sending it.
447
- *
448
- * To prevent the error from being overwritten by an EOF error the
449
- * connection is closed here. See issue #43.
450
- *
451
- * Another possibility is that the server is loading its dataset.
452
- * In this case we also want to close the connection, and have the
453
- * user wait until the server is ready to take our request.
454
- */
455
- if (((redisReply*)reply)->type == REDIS_REPLY_ERROR) {
456
- c->err = REDIS_ERR_OTHER;
457
- snprintf(c->errstr,sizeof(c->errstr),"%s",((redisReply*)reply)->str);
458
- c->reader->fn->freeObject(reply);
459
- __redisAsyncDisconnect(ac);
460
- return;
461
- }
462
- /* No more regular callbacks and no errors, the context *must* be subscribed or monitoring. */
463
- assert((c->flags & REDIS_SUBSCRIBED || c->flags & REDIS_MONITORING));
464
- if(c->flags & REDIS_SUBSCRIBED)
465
- __redisGetSubscribeCallback(ac,reply,&cb);
466
- }
467
-
468
- if (cb.fn != NULL) {
469
- __redisRunCallback(ac,&cb,reply);
470
- c->reader->fn->freeObject(reply);
471
-
472
- /* Proceed with free'ing when redisAsyncFree() was called. */
473
- if (c->flags & REDIS_FREEING) {
474
- __redisAsyncFree(ac);
475
- return;
476
- }
477
- } else {
478
- /* No callback for this reply. This can either be a NULL callback,
479
- * or there were no callbacks to begin with. Either way, don't
480
- * abort with an error, but simply ignore it because the client
481
- * doesn't know what the server will spit out over the wire. */
482
- c->reader->fn->freeObject(reply);
483
- }
484
- }
485
-
486
- /* Disconnect when there was an error reading the reply */
487
- if (status != REDIS_OK)
488
- __redisAsyncDisconnect(ac);
489
- }
490
-
491
- /* Internal helper function to detect socket status the first time a read or
492
- * write event fires. When connecting was not succesful, the connect callback
493
- * is called with a REDIS_ERR status and the context is free'd. */
494
- static int __redisAsyncHandleConnect(redisAsyncContext *ac) {
495
- redisContext *c = &(ac->c);
496
-
497
- if (redisCheckSocketError(c) == REDIS_ERR) {
498
- /* Try again later when connect(2) is still in progress. */
499
- if (errno == EINPROGRESS)
500
- return REDIS_OK;
501
-
502
- if (ac->onConnect) ac->onConnect(ac,REDIS_ERR);
503
- __redisAsyncDisconnect(ac);
504
- return REDIS_ERR;
505
- }
506
-
507
- /* Mark context as connected. */
508
- c->flags |= REDIS_CONNECTED;
509
- if (ac->onConnect) ac->onConnect(ac,REDIS_OK);
510
- return REDIS_OK;
511
- }
512
-
513
- /* This function should be called when the socket is readable.
514
- * It processes all replies that can be read and executes their callbacks.
515
- */
516
- void redisAsyncHandleRead(redisAsyncContext *ac) {
517
- redisContext *c = &(ac->c);
518
-
519
- if (!(c->flags & REDIS_CONNECTED)) {
520
- /* Abort connect was not successful. */
521
- if (__redisAsyncHandleConnect(ac) != REDIS_OK)
522
- return;
523
- /* Try again later when the context is still not connected. */
524
- if (!(c->flags & REDIS_CONNECTED))
525
- return;
526
- }
527
-
528
- if (redisBufferRead(c) == REDIS_ERR) {
529
- __redisAsyncDisconnect(ac);
530
- } else {
531
- /* Always re-schedule reads */
532
- _EL_ADD_READ(ac);
533
- redisProcessCallbacks(ac);
534
- }
535
- }
536
-
537
- void redisAsyncHandleWrite(redisAsyncContext *ac) {
538
- redisContext *c = &(ac->c);
539
- int done = 0;
540
-
541
- if (!(c->flags & REDIS_CONNECTED)) {
542
- /* Abort connect was not successful. */
543
- if (__redisAsyncHandleConnect(ac) != REDIS_OK)
544
- return;
545
- /* Try again later when the context is still not connected. */
546
- if (!(c->flags & REDIS_CONNECTED))
547
- return;
548
- }
549
-
550
- if (redisBufferWrite(c,&done) == REDIS_ERR) {
551
- __redisAsyncDisconnect(ac);
552
- } else {
553
- /* Continue writing when not done, stop writing otherwise */
554
- if (!done)
555
- _EL_ADD_WRITE(ac);
556
- else
557
- _EL_DEL_WRITE(ac);
558
-
559
- /* Always schedule reads after writes */
560
- _EL_ADD_READ(ac);
561
- }
562
- }
563
-
564
- /* Sets a pointer to the first argument and its length starting at p. Returns
565
- * the number of bytes to skip to get to the following argument. */
566
- static const char *nextArgument(const char *start, const char **str, size_t *len) {
567
- const char *p = start;
568
- if (p[0] != '$') {
569
- p = strchr(p,'$');
570
- if (p == NULL) return NULL;
571
- }
572
-
573
- *len = (int)strtol(p+1,NULL,10);
574
- p = strchr(p,'\r');
575
- assert(p);
576
- *str = p+2;
577
- return p+2+(*len)+2;
578
- }
579
-
580
- /* Helper function for the redisAsyncCommand* family of functions. Writes a
581
- * formatted command to the output buffer and registers the provided callback
582
- * function with the context. */
583
- static int __redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) {
584
- redisContext *c = &(ac->c);
585
- redisCallback cb;
586
- int pvariant, hasnext;
587
- const char *cstr, *astr;
588
- size_t clen, alen;
589
- const char *p;
590
- sds sname;
591
- int ret;
592
-
593
- /* Don't accept new commands when the connection is about to be closed. */
594
- if (c->flags & (REDIS_DISCONNECTING | REDIS_FREEING)) return REDIS_ERR;
595
-
596
- /* Setup callback */
597
- cb.fn = fn;
598
- cb.privdata = privdata;
599
-
600
- /* Find out which command will be appended. */
601
- p = nextArgument(cmd,&cstr,&clen);
602
- assert(p != NULL);
603
- hasnext = (p[0] == '$');
604
- pvariant = (tolower(cstr[0]) == 'p') ? 1 : 0;
605
- cstr += pvariant;
606
- clen -= pvariant;
607
-
608
- if (hasnext && strncasecmp(cstr,"subscribe\r\n",11) == 0) {
609
- c->flags |= REDIS_SUBSCRIBED;
610
-
611
- /* Add every channel/pattern to the list of subscription callbacks. */
612
- while ((p = nextArgument(p,&astr,&alen)) != NULL) {
613
- sname = sdsnewlen(astr,alen);
614
- if (pvariant)
615
- ret = dictReplace(ac->sub.patterns,sname,&cb);
616
- else
617
- ret = dictReplace(ac->sub.channels,sname,&cb);
618
-
619
- if (ret == 0) sdsfree(sname);
620
- }
621
- } else if (strncasecmp(cstr,"unsubscribe\r\n",13) == 0) {
622
- /* It is only useful to call (P)UNSUBSCRIBE when the context is
623
- * subscribed to one or more channels or patterns. */
624
- if (!(c->flags & REDIS_SUBSCRIBED)) return REDIS_ERR;
625
-
626
- /* (P)UNSUBSCRIBE does not have its own response: every channel or
627
- * pattern that is unsubscribed will receive a message. This means we
628
- * should not append a callback function for this command. */
629
- } else if(strncasecmp(cstr,"monitor\r\n",9) == 0) {
630
- /* Set monitor flag and push callback */
631
- c->flags |= REDIS_MONITORING;
632
- __redisPushCallback(&ac->replies,&cb);
633
- } else {
634
- if (c->flags & REDIS_SUBSCRIBED)
635
- /* This will likely result in an error reply, but it needs to be
636
- * received and passed to the callback. */
637
- __redisPushCallback(&ac->sub.invalid,&cb);
638
- else
639
- __redisPushCallback(&ac->replies,&cb);
640
- }
641
-
642
- __redisAppendCommand(c,cmd,len);
643
-
644
- /* Always schedule a write when the write buffer is non-empty */
645
- _EL_ADD_WRITE(ac);
646
-
647
- return REDIS_OK;
648
- }
649
-
650
- int redisvAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, va_list ap) {
651
- char *cmd;
652
- int len;
653
- int status;
654
- len = redisvFormatCommand(&cmd,format,ap);
655
-
656
- /* We don't want to pass -1 or -2 to future functions as a length. */
657
- if (len < 0)
658
- return REDIS_ERR;
659
-
660
- status = __redisAsyncCommand(ac,fn,privdata,cmd,len);
661
- free(cmd);
662
- return status;
663
- }
664
-
665
- int redisAsyncCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *format, ...) {
666
- va_list ap;
667
- int status;
668
- va_start(ap,format);
669
- status = redisvAsyncCommand(ac,fn,privdata,format,ap);
670
- va_end(ap);
671
- return status;
672
- }
673
-
674
- int redisAsyncCommandArgv(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, int argc, const char **argv, const size_t *argvlen) {
675
- sds cmd;
676
- int len;
677
- int status;
678
- len = redisFormatSdsCommandArgv(&cmd,argc,argv,argvlen);
679
- status = __redisAsyncCommand(ac,fn,privdata,cmd,len);
680
- sdsfree(cmd);
681
- return status;
682
- }
683
-
684
- int redisAsyncFormattedCommand(redisAsyncContext *ac, redisCallbackFn *fn, void *privdata, const char *cmd, size_t len) {
685
- int status = __redisAsyncCommand(ac,fn,privdata,cmd,len);
686
- return status;
687
- }