durable_rules 0.34.57 → 2.00.001

Sign up to get free protection for your applications and to get access to all the features.
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
- }