hirlite 0.0.2.2 → 0.1.0
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 +13 -5
- data/ext/hirlite_ext/hirlite_ext.h +1 -1
- data/ext/hirlite_ext/rlite.c +3 -23
- data/lib/hirlite/connection.rb +4 -0
- data/lib/hirlite/version.rb +1 -1
- data/vendor/rlite/deps/lua/src/lua_cjson.c +1 -1
- data/vendor/rlite/src/Makefile +12 -25
- data/vendor/rlite/src/dump.c +3 -3
- data/vendor/rlite/src/flock_posix.c +79 -0
- data/vendor/rlite/src/flock_win.c +6 -0
- data/vendor/rlite/src/hirlite.c +265 -25
- data/vendor/rlite/src/hyperloglog.c +1 -1
- data/vendor/rlite/src/lzf_c.c +1 -1
- data/vendor/rlite/src/lzf_d.c +1 -1
- data/vendor/rlite/src/page_btree.c +3 -3
- data/vendor/rlite/src/page_key.c +12 -13
- data/vendor/rlite/src/page_list.c +4 -4
- data/vendor/rlite/src/page_long.c +2 -2
- data/vendor/rlite/src/page_multi_string.c +5 -5
- data/vendor/rlite/src/page_skiplist.c +3 -3
- data/vendor/rlite/src/page_string.c +2 -2
- data/vendor/rlite/src/pubsub.c +448 -0
- data/vendor/rlite/src/restore.c +5 -5
- data/vendor/rlite/src/rlite.c +141 -146
- data/vendor/rlite/src/rlite.h +40 -12
- data/vendor/rlite/src/{constants.h → rlite/constants.h} +0 -0
- data/vendor/rlite/src/{crc64.h → rlite/crc64.h} +0 -0
- data/vendor/rlite/src/{dump.h → rlite/dump.h} +0 -0
- data/vendor/rlite/src/{endianconv.h → rlite/endianconv.h} +0 -0
- data/vendor/rlite/src/rlite/flock.h +8 -0
- data/vendor/rlite/src/{hirlite.h → rlite/hirlite.h} +1 -0
- data/vendor/rlite/src/{hyperloglog.h → rlite/hyperloglog.h} +0 -0
- data/vendor/rlite/src/{lzf.h → rlite/lzf.h} +0 -0
- data/vendor/rlite/src/{lzfP.h → rlite/lzfP.h} +0 -0
- data/vendor/rlite/src/{page_btree.h → rlite/page_btree.h} +0 -0
- data/vendor/rlite/src/{page_key.h → rlite/page_key.h} +0 -0
- data/vendor/rlite/src/{page_list.h → rlite/page_list.h} +0 -0
- data/vendor/rlite/src/{page_long.h → rlite/page_long.h} +0 -0
- data/vendor/rlite/src/{page_multi_string.h → rlite/page_multi_string.h} +0 -0
- data/vendor/rlite/src/{page_skiplist.h → rlite/page_skiplist.h} +0 -0
- data/vendor/rlite/src/{page_string.h → rlite/page_string.h} +0 -0
- data/vendor/rlite/src/{pqsort.h → rlite/pqsort.h} +0 -0
- data/vendor/rlite/src/rlite/pubsub.h +25 -0
- data/vendor/rlite/src/{rand.h → rlite/rand.h} +0 -0
- data/vendor/rlite/src/{restore.h → rlite/restore.h} +0 -0
- data/vendor/rlite/src/{scripting.h → rlite/scripting.h} +0 -0
- data/vendor/rlite/src/{sha1.h → rlite/sha1.h} +0 -0
- data/vendor/rlite/src/rlite/signal.h +11 -0
- data/vendor/rlite/src/{solarisfixes.h → rlite/solarisfixes.h} +0 -0
- data/vendor/rlite/src/{sort.h → rlite/sort.h} +0 -0
- data/vendor/rlite/src/{status.h → rlite/status.h} +1 -0
- data/vendor/rlite/src/{type_hash.h → rlite/type_hash.h} +0 -0
- data/vendor/rlite/src/{type_list.h → rlite/type_list.h} +0 -0
- data/vendor/rlite/src/{type_set.h → rlite/type_set.h} +0 -0
- data/vendor/rlite/src/{type_string.h → rlite/type_string.h} +0 -0
- data/vendor/rlite/src/{type_zset.h → rlite/type_zset.h} +0 -0
- data/vendor/rlite/src/{util.h → rlite/util.h} +2 -1
- data/vendor/rlite/src/{utilfromredis.h → rlite/utilfromredis.h} +0 -0
- data/vendor/rlite/src/rlite/wal.h +8 -0
- data/vendor/rlite/src/scripting.c +8 -10
- data/vendor/rlite/src/sha1.c +2 -2
- data/vendor/rlite/src/signal_posix.c +118 -0
- data/vendor/rlite/src/signal_win.c +17 -0
- data/vendor/rlite/src/sort.c +2 -2
- data/vendor/rlite/src/type_hash.c +4 -4
- data/vendor/rlite/src/type_list.c +4 -4
- data/vendor/rlite/src/type_set.c +4 -4
- data/vendor/rlite/src/type_string.c +4 -4
- data/vendor/rlite/src/type_zset.c +7 -7
- data/vendor/rlite/src/util.c +28 -5
- data/vendor/rlite/src/utilfromredis.c +1 -1
- data/vendor/rlite/src/wal.c +309 -0
- metadata +59 -35
checksums.yaml
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
|
|
2
|
+
!binary "U0hBMQ==":
|
|
3
|
+
metadata.gz: !binary |-
|
|
4
|
+
YjUxZDMzOWRkZTFmMzM5MzczYWM4ODMwMDNhNjdiNzQ0N2M5ZDBkOQ==
|
|
5
|
+
data.tar.gz: !binary |-
|
|
6
|
+
ZTVlOGRiYjkyZGIzZGFlOGFlNTg0YzBhZWJhMWZjYjE2ZmM0Y2U2OA==
|
|
5
7
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
|
|
8
|
+
metadata.gz: !binary |-
|
|
9
|
+
NjBjNDIxZjdiYTUwM2FlOWQ1ODFjOGI0Yjg3ZTllMmE3ZmU0NGYzZWYyNDMy
|
|
10
|
+
YzNkYzliYThhMjlhYWQ5NTBiNmJiOGY3YjhjYjAyOWZjNmE3MzFiZTY4YTBj
|
|
11
|
+
MmU0YzBlYWM3NDlhNGNkMTY2ZmM2Yzk3ZjUzMzI1MjEyMDliNjA=
|
|
12
|
+
data.tar.gz: !binary |-
|
|
13
|
+
NDYwOWQ5YWE5OWI0MWFmNGQ4ZDk1YzIxZDU1MDliN2QyMDk0NTkzYWM0YTI1
|
|
14
|
+
NjgxNDY1MTZlZmM0YWE3MzI5NWRiYzZlNzI4MjhmMjg2MTVhMjVjOTJlZmFj
|
|
15
|
+
MTM0NWQzNTQ2NDYzNzZmNmQ2ZjNlOTAxMzhmMDY3OTVlYWVkODc=
|
data/ext/hirlite_ext/rlite.c
CHANGED
|
@@ -95,7 +95,7 @@ static VALUE rlite_parent_context_alloc(VALUE klass) {
|
|
|
95
95
|
return Data_Wrap_Struct(klass, parent_context_mark, parent_context_free, pc);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
static VALUE rlite_generic_connect(VALUE self, rliteContext *c
|
|
98
|
+
static VALUE rlite_generic_connect(VALUE self, rliteContext *c) {
|
|
99
99
|
rliteParentContext *pc;
|
|
100
100
|
|
|
101
101
|
Data_Get_Struct(self,rliteParentContext,pc);
|
|
@@ -127,50 +127,30 @@ static VALUE rlite_connect(int argc, VALUE *argv, VALUE self) {
|
|
|
127
127
|
rliteContext *c;
|
|
128
128
|
VALUE arg_host = Qnil;
|
|
129
129
|
VALUE arg_port = Qnil;
|
|
130
|
-
VALUE arg_timeout = Qnil;
|
|
131
130
|
|
|
132
131
|
if (argc == 2 || argc == 3) {
|
|
133
132
|
arg_host = argv[0];
|
|
134
133
|
arg_port = argv[1];
|
|
135
|
-
|
|
136
|
-
if (argc == 3) {
|
|
137
|
-
arg_timeout = argv[2];
|
|
138
|
-
|
|
139
|
-
/* Sanity check */
|
|
140
|
-
if (NUM2INT(arg_timeout) <= 0) {
|
|
141
|
-
rb_raise(rb_eArgError, "timeout should be positive");
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
134
|
} else {
|
|
145
135
|
rb_raise(rb_eArgError, "invalid number of arguments");
|
|
146
136
|
}
|
|
147
137
|
|
|
148
138
|
c = rliteConnectNonBlock(StringValuePtr(arg_host), NUM2INT(arg_port));
|
|
149
|
-
return rlite_generic_connect(self,c
|
|
139
|
+
return rlite_generic_connect(self,c);
|
|
150
140
|
}
|
|
151
141
|
|
|
152
142
|
static VALUE rlite_connect_unix(int argc, VALUE *argv, VALUE self) {
|
|
153
143
|
rliteContext *c;
|
|
154
144
|
VALUE arg_path = Qnil;
|
|
155
|
-
VALUE arg_timeout = Qnil;
|
|
156
145
|
|
|
157
146
|
if (argc == 1 || argc == 2) {
|
|
158
147
|
arg_path = argv[0];
|
|
159
|
-
|
|
160
|
-
if (argc == 2) {
|
|
161
|
-
arg_timeout = argv[1];
|
|
162
|
-
|
|
163
|
-
/* Sanity check */
|
|
164
|
-
if (NUM2INT(arg_timeout) <= 0) {
|
|
165
|
-
rb_raise(rb_eArgError, "timeout should be positive");
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
148
|
} else {
|
|
169
149
|
rb_raise(rb_eArgError, "invalid number of arguments");
|
|
170
150
|
}
|
|
171
151
|
|
|
172
152
|
c = rliteConnectUnixNonBlock(StringValuePtr(arg_path));
|
|
173
|
-
return rlite_generic_connect(self,c
|
|
153
|
+
return rlite_generic_connect(self,c);
|
|
174
154
|
}
|
|
175
155
|
|
|
176
156
|
static VALUE rlite_is_connected(VALUE self) {
|
data/lib/hirlite/connection.rb
CHANGED
data/lib/hirlite/version.rb
CHANGED
data/vendor/rlite/src/Makefile
CHANGED
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
uname_S:= $(shell sh -c 'uname -s 2>/dev/null || echo not')
|
|
10
10
|
|
|
11
|
-
OBJ=rlite.o page_skiplist.o page_string.o page_list.o page_btree.o page_key.o page_multi_string.o page_long.o type_string.o type_list.o type_set.o type_zset.o type_hash.o util.o restore.o dump.o sort.o pqsort.o utilfromredis.o hyperloglog.o sha1.o crc64.o lzf_c.o lzf_d.o scripting.o rand.o hirlite.o
|
|
11
|
+
OBJ=rlite.o page_skiplist.o page_string.o page_list.o page_btree.o page_key.o page_multi_string.o page_long.o type_string.o type_list.o type_set.o type_zset.o type_hash.o util.o restore.o dump.o sort.o pqsort.o utilfromredis.o hyperloglog.o sha1.o crc64.o lzf_c.o lzf_d.o scripting.o rand.o flock_posix.o signal_posix.o pubsub.o wal.o hirlite.o
|
|
12
|
+
LUA_OBJ=../deps/lua/src/lapi.o ../deps/lua/src/lcode.o ../deps/lua/src/ldebug.o ../deps/lua/src/ldo.o ../deps/lua/src/ldump.o ../deps/lua/src/lfunc.o ../deps/lua/src/lgc.o ../deps/lua/src/llex.o ../deps/lua/src/lmem.o ../deps/lua/src/lobject.o ../deps/lua/src/lopcodes.o ../deps/lua/src/lparser.o ../deps/lua/src/lstate.o ../deps/lua/src/lstring.o ../deps/lua/src/ltable.o ../deps/lua/src/ltm.o ../deps/lua/src/lundump.o ../deps/lua/src/lvm.o ../deps/lua/src/lzio.o ../deps/lua/src/strbuf.o ../deps/lua/src/fpconv.o ../deps/lua/src/lauxlib.o ../deps/lua/src/lbaselib.o ../deps/lua/src/ldblib.o ../deps/lua/src/liolib.o ../deps/lua/src/lmathlib.o ../deps/lua/src/loslib.o ../deps/lua/src/ltablib.o ../deps/lua/src/lstrlib.o ../deps/lua/src/loadlib.o ../deps/lua/src/linit.o ../deps/lua/src/lua_cjson.o ../deps/lua/src/lua_struct.o ../deps/lua/src/lua_cmsgpack.o ../deps/lua/src/lua_bit.o
|
|
12
13
|
LIBNAME=libhirlite
|
|
13
14
|
PKGCONFNAME=hirlite.pc
|
|
14
15
|
|
|
@@ -27,7 +28,6 @@ endif
|
|
|
27
28
|
|
|
28
29
|
CFLAGS += -I./ -I../deps/lua/src/
|
|
29
30
|
|
|
30
|
-
DEBUG.gcc += -rdynamic
|
|
31
31
|
CFLAGS.gcc += -std=c99
|
|
32
32
|
|
|
33
33
|
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
|
@@ -38,7 +38,7 @@ DEBUG += ${DEBUG.gcc}
|
|
|
38
38
|
CFLAGS += ${CFLAGS.gcc}
|
|
39
39
|
endif
|
|
40
40
|
|
|
41
|
-
LIBS=-lm
|
|
41
|
+
LIBS=-lm -lpthread
|
|
42
42
|
|
|
43
43
|
INSTALL?= cp -a
|
|
44
44
|
# Installation related variables and target
|
|
@@ -70,19 +70,11 @@ STLIBNAME=$(LIBNAME).$(STLIBSUFFIX)
|
|
|
70
70
|
|
|
71
71
|
all: $(DYLIBNAME) $(STLIBNAME)
|
|
72
72
|
|
|
73
|
-
gcov: CFLAGS += -fprofile-arcs -ftest-coverage
|
|
74
|
-
gcov: clean test
|
|
75
|
-
|
|
76
|
-
builddebug: CFLAGS += -DDEBUG=1
|
|
77
|
-
builddebug: clean buildtest
|
|
78
|
-
|
|
79
|
-
debug: builddebug vtest
|
|
80
|
-
|
|
81
73
|
ifeq ($(uname_S),SunOS)
|
|
82
74
|
# Make isinf() available
|
|
83
75
|
LUA_CFLAGS= -D__C99FEATURES__=1
|
|
84
76
|
endif
|
|
85
|
-
LUA_CFLAGS+= -O2 -Wall -DENABLE_CJSON_GLOBAL $(CFLAGS)
|
|
77
|
+
LUA_CFLAGS+= -O2 -Wall -DENABLE_CJSON_GLOBAL -fPIC $(CFLAGS)
|
|
86
78
|
LUA_LDFLAGS+= $(LDFLAGS)
|
|
87
79
|
LUA_STLIB=../deps/lua/src/liblua.a
|
|
88
80
|
AR=ar
|
|
@@ -96,9 +88,6 @@ lcov: gcov
|
|
|
96
88
|
lcov --directory . --capture --output-file lcov/app.info
|
|
97
89
|
genhtml lcov/app.info -o lcov/html
|
|
98
90
|
|
|
99
|
-
full-lcov: CFLAGS += -fprofile-arcs -ftest-coverage -DDEBUG=1
|
|
100
|
-
full-lcov: clean buildtest
|
|
101
|
-
|
|
102
91
|
clang-analyzer:
|
|
103
92
|
rm -rf analyzer
|
|
104
93
|
scan-build -o analyzer $(MAKE)
|
|
@@ -107,22 +96,19 @@ clang-analyzer:
|
|
|
107
96
|
$(CC) $(ARCH) $(DEBUG) $(CFLAGS) -c $<
|
|
108
97
|
|
|
109
98
|
$(DYLIBNAME): $(OBJ) lua
|
|
110
|
-
$(DYLIB_MAKE_CMD) $(
|
|
99
|
+
$(DYLIB_MAKE_CMD) $(LUA_OBJ) $(OBJ)
|
|
111
100
|
|
|
112
101
|
$(STLIBNAME): $(OBJ)
|
|
113
102
|
ar -cq libhirlite.a $(OBJ)
|
|
114
103
|
|
|
115
|
-
buildtest: $(STLIBNAME)
|
|
116
|
-
|
|
117
|
-
$(CC) $(DEBUG) $(CFLAGS) -o hirlite-test echo.o hash.o list.o parser.o set.o string.o test_hirlite.o zset.o db.o multi.o hsort.o scripting-test.o $(STLIBNAME) $(LUA_STLIB) $(LIBS)
|
|
104
|
+
buildtest: $(STLIBNAME)
|
|
105
|
+
cd ../tests/ && $(MAKE) buildtest
|
|
118
106
|
|
|
119
|
-
test:
|
|
120
|
-
|
|
121
|
-
./hirlite-test
|
|
107
|
+
test: $(STLIBNAME)
|
|
108
|
+
cd ../tests/ && $(MAKE) test
|
|
122
109
|
|
|
123
|
-
vtest:
|
|
124
|
-
|
|
125
|
-
valgrind --track-origins=yes --leak-check=full --show-reachable=yes ./hirlite-test
|
|
110
|
+
vtest: $(STLIBNAME)
|
|
111
|
+
cd ../tests/ && $(MAKE) vtest
|
|
126
112
|
|
|
127
113
|
$(PKGCONFNAME): hirlite.h
|
|
128
114
|
@echo "Generating $@ for pkgconfig..."
|
|
@@ -149,3 +135,4 @@ install: $(DYLIBNAME) $(STLIBNAME) $(PKGCONFNAME)
|
|
|
149
135
|
|
|
150
136
|
clean:
|
|
151
137
|
rm -rf *-test *.o *.a *.dSYM *.gcda *.gcno lcov *.dylib ./deps/lua/src/*.a
|
|
138
|
+
cd ../tests && $(MAKE) clean
|
data/vendor/rlite/src/dump.c
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#include <arpa/inet.h>
|
|
2
2
|
#include "rlite.h"
|
|
3
|
-
#include "util.h"
|
|
4
|
-
#include "crc64.h"
|
|
5
|
-
#include "endianconv.h"
|
|
3
|
+
#include "rlite/util.h"
|
|
4
|
+
#include "rlite/crc64.h"
|
|
5
|
+
#include "rlite/endianconv.h"
|
|
6
6
|
|
|
7
7
|
int rl_dump(struct rlite *db, const unsigned char *key, long keylen, unsigned char **data, long *datalen)
|
|
8
8
|
{
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#include <sys/fcntl.h>
|
|
2
|
+
#include <sys/file.h>
|
|
3
|
+
#include <sys/time.h>
|
|
4
|
+
#include <unistd.h>
|
|
5
|
+
#include <errno.h>
|
|
6
|
+
|
|
7
|
+
#include "rlite.h"
|
|
8
|
+
|
|
9
|
+
int rl_flock(FILE *fp, int type)
|
|
10
|
+
{
|
|
11
|
+
int fd = fileno(fp);
|
|
12
|
+
int locktype;
|
|
13
|
+
if (type == RLITE_FLOCK_SH) {
|
|
14
|
+
locktype = LOCK_SH;
|
|
15
|
+
} else if (type == RLITE_FLOCK_EX) {
|
|
16
|
+
locktype = LOCK_EX;
|
|
17
|
+
} else if (type == RLITE_FLOCK_UN) {
|
|
18
|
+
locktype = LOCK_UN;
|
|
19
|
+
} else {
|
|
20
|
+
return RL_UNEXPECTED;
|
|
21
|
+
}
|
|
22
|
+
flock(fd, locktype);
|
|
23
|
+
return RL_OK;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
int rl_is_flocked(const char *path, int type)
|
|
27
|
+
{
|
|
28
|
+
int retval, oflags = O_NONBLOCK;
|
|
29
|
+
int locktype;
|
|
30
|
+
|
|
31
|
+
if (type == RLITE_FLOCK_SH) {
|
|
32
|
+
oflags |= O_RDONLY;
|
|
33
|
+
// we want to know if someone has a shared lock
|
|
34
|
+
// if we can get an exclusive, we know they do not
|
|
35
|
+
// if we cannot, we will try to get a shared to discard someone
|
|
36
|
+
// having an exclusive one
|
|
37
|
+
locktype = LOCK_EX;
|
|
38
|
+
} else if (type == RLITE_FLOCK_EX) {
|
|
39
|
+
oflags |= O_WRONLY;
|
|
40
|
+
// we'll get a shared lock iff nobody has an exclusive lock
|
|
41
|
+
locktype = LOCK_SH;
|
|
42
|
+
} else {
|
|
43
|
+
return RL_UNEXPECTED;
|
|
44
|
+
}
|
|
45
|
+
int fd = open(path, oflags);
|
|
46
|
+
if (fd == -1) {
|
|
47
|
+
// if the file does not exist, the lock is not found
|
|
48
|
+
if (errno == ENOENT || errno == EACCES) {
|
|
49
|
+
return RL_NOT_FOUND;
|
|
50
|
+
}
|
|
51
|
+
return RL_UNEXPECTED;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
retval = flock(fd, locktype | LOCK_NB);
|
|
55
|
+
if (retval == 0) {
|
|
56
|
+
retval = RL_NOT_FOUND;
|
|
57
|
+
goto cleanup;
|
|
58
|
+
}
|
|
59
|
+
if (errno == EWOULDBLOCK) {
|
|
60
|
+
if (type == RLITE_FLOCK_SH) {
|
|
61
|
+
retval = flock(fd, LOCK_SH | LOCK_NB);
|
|
62
|
+
if (retval == 0) {
|
|
63
|
+
// can get a shared lock but not an exclusive
|
|
64
|
+
// thus someone has a shared lock
|
|
65
|
+
retval = RL_FOUND;
|
|
66
|
+
goto cleanup;
|
|
67
|
+
} else {
|
|
68
|
+
retval = RL_NOT_FOUND;
|
|
69
|
+
goto cleanup;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
retval = RL_FOUND;
|
|
73
|
+
goto cleanup;
|
|
74
|
+
}
|
|
75
|
+
retval = RL_UNEXPECTED;
|
|
76
|
+
cleanup:
|
|
77
|
+
close(fd);
|
|
78
|
+
return retval;
|
|
79
|
+
}
|
data/vendor/rlite/src/hirlite.c
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#include <stdio.h>
|
|
2
|
-
#include "constants.h"
|
|
2
|
+
#include "rlite/constants.h"
|
|
3
3
|
#include <assert.h>
|
|
4
4
|
#include <errno.h>
|
|
5
5
|
#include <ctype.h>
|
|
@@ -11,10 +11,11 @@
|
|
|
11
11
|
#include <time.h>
|
|
12
12
|
#include <unistd.h>
|
|
13
13
|
|
|
14
|
-
#include "hyperloglog.h"
|
|
15
|
-
#include "hirlite.h"
|
|
16
|
-
#include "scripting.h"
|
|
17
|
-
#include "util.h"
|
|
14
|
+
#include "rlite/hyperloglog.h"
|
|
15
|
+
#include "rlite/hirlite.h"
|
|
16
|
+
#include "rlite/scripting.h"
|
|
17
|
+
#include "rlite/util.h"
|
|
18
|
+
#include "rlite/pubsub.h"
|
|
18
19
|
|
|
19
20
|
#define UNSIGN(val) ((unsigned char *)val)
|
|
20
21
|
|
|
@@ -23,9 +24,13 @@
|
|
|
23
24
|
c->reply = createErrorObject(RLITE_WRONGTYPEERR);\
|
|
24
25
|
goto cleanup;\
|
|
25
26
|
}\
|
|
27
|
+
if (retval == RL_UNEXPECTED) {\
|
|
28
|
+
c->reply = createErrorObject("ERR unexpected");\
|
|
29
|
+
goto cleanup;\
|
|
30
|
+
}\
|
|
26
31
|
if (retval == RL_OVERFLOW) {\
|
|
27
32
|
c->reply = createErrorObject("ERR increment would produce NaN or Infinity");\
|
|
28
|
-
|
|
33
|
+
goto cleanup;\
|
|
29
34
|
}\
|
|
30
35
|
if (retval == RL_NAN) {\
|
|
31
36
|
c->reply = createErrorObject("ERR resulting score is not a number (NaN)");\
|
|
@@ -188,8 +193,7 @@ static int addReply(rliteContext* c, rliteReply *reply) {
|
|
|
188
193
|
c->replies = tmp;
|
|
189
194
|
}
|
|
190
195
|
|
|
191
|
-
c->replies[c->
|
|
192
|
-
c->replyLength++;
|
|
196
|
+
c->replies[c->replyLength++] = reply;
|
|
193
197
|
return RLITE_OK;
|
|
194
198
|
}
|
|
195
199
|
|
|
@@ -605,6 +609,10 @@ int rliteFormatCommandArgv(rliteClient *client, int argc, char **argv, size_t *a
|
|
|
605
609
|
return RLITE_OK;
|
|
606
610
|
}
|
|
607
611
|
|
|
612
|
+
static int refresh_rlite_fp(rliteContext* context) {
|
|
613
|
+
return rl_refresh(context->db);
|
|
614
|
+
}
|
|
615
|
+
|
|
608
616
|
#define DEFAULT_REPLIES_SIZE 16
|
|
609
617
|
static rliteContext *_rliteConnect(const char *path) {
|
|
610
618
|
rliteContext *context = malloc(sizeof(*context));
|
|
@@ -617,6 +625,15 @@ static rliteContext *_rliteConnect(const char *path) {
|
|
|
617
625
|
context = NULL;
|
|
618
626
|
goto cleanup;
|
|
619
627
|
}
|
|
628
|
+
size_t pathlen = 1 + strlen(path);
|
|
629
|
+
context->path = malloc(sizeof(char) * pathlen);
|
|
630
|
+
if (!context->path) {
|
|
631
|
+
free(context->replies);
|
|
632
|
+
free(context);
|
|
633
|
+
context = NULL;
|
|
634
|
+
goto cleanup;
|
|
635
|
+
}
|
|
636
|
+
memcpy(context->path, path, pathlen);
|
|
620
637
|
context->err = 0;
|
|
621
638
|
context->writeCommand = NULL;
|
|
622
639
|
context->replyPosition = 0;
|
|
@@ -627,18 +644,31 @@ static rliteContext *_rliteConnect(const char *path) {
|
|
|
627
644
|
context->cluster_enabled = 0;
|
|
628
645
|
context->hashtableLimitValue = 0;
|
|
629
646
|
context->inLuaScript = 0;
|
|
630
|
-
int retval = rl_open(path, &context->db, RLITE_OPEN_READWRITE | RLITE_OPEN_CREATE);
|
|
631
|
-
if (retval != RL_OK) {
|
|
632
|
-
free(context);
|
|
633
|
-
context = NULL;
|
|
634
|
-
goto cleanup;
|
|
635
|
-
}
|
|
636
647
|
context->inTransaction = 0;
|
|
637
648
|
context->transactionFailed = 0;
|
|
638
649
|
context->watchedKeysLength = context->enqueuedCommandsLength = 0;
|
|
639
650
|
context->watchedKeysAlloc = context->enqueuedCommandsAlloc = 0;
|
|
640
651
|
context->watchedKeys = NULL;
|
|
641
652
|
context->enqueuedCommands = NULL;
|
|
653
|
+
context->db = NULL;
|
|
654
|
+
int retval = rl_open(context->path, &context->db, RLITE_OPEN_READWRITE | RLITE_OPEN_CREATE);;
|
|
655
|
+
if (retval != RL_OK) {
|
|
656
|
+
free(context->path);
|
|
657
|
+
free(context->replies);
|
|
658
|
+
free(context);
|
|
659
|
+
context = NULL;
|
|
660
|
+
goto cleanup;
|
|
661
|
+
}
|
|
662
|
+
// if created, need to release locks
|
|
663
|
+
retval = rl_commit(context->db);
|
|
664
|
+
if (retval != RL_OK) {
|
|
665
|
+
rl_close(context->db);
|
|
666
|
+
free(context->path);
|
|
667
|
+
free(context->replies);
|
|
668
|
+
free(context);
|
|
669
|
+
context = NULL;
|
|
670
|
+
goto cleanup;
|
|
671
|
+
}
|
|
642
672
|
cleanup:
|
|
643
673
|
return context;
|
|
644
674
|
}
|
|
@@ -682,12 +712,15 @@ int rliteEnableKeepAlive(rliteContext *UNUSED(c)) {
|
|
|
682
712
|
return 0;
|
|
683
713
|
}
|
|
684
714
|
void rliteFree(rliteContext *c) {
|
|
685
|
-
|
|
715
|
+
if (c->db) {
|
|
716
|
+
rl_close(c->db);
|
|
717
|
+
}
|
|
686
718
|
int i;
|
|
687
719
|
for (i = c->replyPosition; i < c->replyLength; i++) {
|
|
688
720
|
rliteFreeReplyObject(c->replies[i]);
|
|
689
721
|
}
|
|
690
722
|
free(c->replies);
|
|
723
|
+
free(c->path);
|
|
691
724
|
free(c);
|
|
692
725
|
}
|
|
693
726
|
|
|
@@ -759,6 +792,7 @@ static void execCommand(rliteClient *c) {
|
|
|
759
792
|
c->reply = createErrorObject("EXECABORT Transaction discarded because of previous errors.");
|
|
760
793
|
goto cleanup;
|
|
761
794
|
}
|
|
795
|
+
RL_CALL(refresh_rlite_fp, RL_OK, c->context);
|
|
762
796
|
retval = rl_check_watched_keys(c->context->db, c->context->watchedKeysLength, c->context->watchedKeys);
|
|
763
797
|
RLITE_SERVER_ERR(c, retval);
|
|
764
798
|
if (retval != RL_OK) {
|
|
@@ -797,7 +831,7 @@ static void execCommand(rliteClient *c) {
|
|
|
797
831
|
if (command->sflags[i] == 'w') {
|
|
798
832
|
char *argv[] = {"multi"};
|
|
799
833
|
size_t argvlen[] = {5};
|
|
800
|
-
c->context->writeCommand(c->context->db
|
|
834
|
+
c->context->writeCommand(rl_get_selected_db(c->context->db), 1, argv, argvlen);
|
|
801
835
|
written = 1;
|
|
802
836
|
break;
|
|
803
837
|
}
|
|
@@ -805,7 +839,7 @@ static void execCommand(rliteClient *c) {
|
|
|
805
839
|
}
|
|
806
840
|
RL_CALL(rl_dirty_hash, RL_OK, client->context->db, &newhash);
|
|
807
841
|
if (newhash && (!oldhash || memcmp(newhash, oldhash, 20) != 0)) {
|
|
808
|
-
client->context->writeCommand(client->context->db
|
|
842
|
+
client->context->writeCommand(rl_get_selected_db(client->context->db), client->argc, client->argv, client->argvlen);
|
|
809
843
|
}
|
|
810
844
|
}
|
|
811
845
|
rl_free(oldhash);
|
|
@@ -817,7 +851,7 @@ static void execCommand(rliteClient *c) {
|
|
|
817
851
|
if (written) {
|
|
818
852
|
char *argv[] = {"exec"};
|
|
819
853
|
size_t argvlen[] = {4};
|
|
820
|
-
c->context->writeCommand(c->context->db
|
|
854
|
+
c->context->writeCommand(rl_get_selected_db(c->context->db), 1, argv, argvlen);
|
|
821
855
|
}
|
|
822
856
|
|
|
823
857
|
retval = rl_commit(c->context->db);
|
|
@@ -888,6 +922,18 @@ static void unwatchCommand(rliteClient *c) {
|
|
|
888
922
|
c->reply = createStatusObject(RLITE_STR_OK);
|
|
889
923
|
}
|
|
890
924
|
|
|
925
|
+
static rliteReply *pollToReply(long elementc, unsigned char **elements, long *elementslen) {
|
|
926
|
+
long i;
|
|
927
|
+
rliteReply *reply = createArrayObject(elementc);
|
|
928
|
+
for (i = 0; i < elementc; i++) {
|
|
929
|
+
reply->element[i] = createStringObject((char *)elements[i], elementslen[i]);
|
|
930
|
+
rl_free(elements[i]);
|
|
931
|
+
}
|
|
932
|
+
rl_free(elements);
|
|
933
|
+
rl_free(elementslen);
|
|
934
|
+
return reply;
|
|
935
|
+
}
|
|
936
|
+
|
|
891
937
|
static void *_popReply(rliteContext *c) {
|
|
892
938
|
if (c->replyPosition < c->replyLength) {
|
|
893
939
|
void *ret;
|
|
@@ -897,6 +943,18 @@ static void *_popReply(rliteContext *c) {
|
|
|
897
943
|
c->replyPosition = c->replyLength = 0;
|
|
898
944
|
}
|
|
899
945
|
return ret;
|
|
946
|
+
} else if (c->replyPosition == c->replyLength && c->db->subscriber_id) {
|
|
947
|
+
int elementc;
|
|
948
|
+
unsigned char **elements;
|
|
949
|
+
long *elementslen;
|
|
950
|
+
int retval = rl_poll_wait(c->db, &elementc, &elements, &elementslen, NULL);
|
|
951
|
+
if (retval == RL_NOT_FOUND) {
|
|
952
|
+
return createReplyObject(RLITE_REPLY_NIL);
|
|
953
|
+
} else if (retval == RL_OK) {
|
|
954
|
+
return pollToReply(elementc, elements, elementslen);
|
|
955
|
+
} else {
|
|
956
|
+
return createErrorObject("unknown retval");
|
|
957
|
+
}
|
|
900
958
|
} else {
|
|
901
959
|
return NULL;
|
|
902
960
|
}
|
|
@@ -931,6 +989,8 @@ int rliteAppendCommandClient(rliteClient *client) {
|
|
|
931
989
|
retval = addReplyErrorFormat(client->context, "wrong number of arguments for '%s' command", command->name);
|
|
932
990
|
flagTransactions(client);
|
|
933
991
|
} else {
|
|
992
|
+
RL_CALL(refresh_rlite_fp, RL_OK, client->context);
|
|
993
|
+
|
|
934
994
|
if (client->context->inTransaction && (command->proc != execCommand && command->proc != discardCommand &&
|
|
935
995
|
command->proc != multiCommand && command->proc != watchCommand)) {
|
|
936
996
|
if (client->context->enqueuedCommandsLength == client->context->enqueuedCommandsAlloc) {
|
|
@@ -984,7 +1044,7 @@ int rliteAppendCommandClient(rliteClient *client) {
|
|
|
984
1044
|
if (client->context->writeCommand) {
|
|
985
1045
|
RL_CALL(rl_dirty_hash, RL_OK, client->context->db, &newhash);
|
|
986
1046
|
if (newhash && (!oldhash || memcmp(newhash, oldhash, 20) != 0)) {
|
|
987
|
-
client->context->writeCommand(client->context->db
|
|
1047
|
+
client->context->writeCommand(rl_get_selected_db(client->context->db), client->argc, client->argv, client->argvlen);
|
|
988
1048
|
}
|
|
989
1049
|
}
|
|
990
1050
|
RL_CALL(rl_commit, RL_OK, client->context->db);
|
|
@@ -3819,6 +3879,185 @@ cleanup:
|
|
|
3819
3879
|
free(getvlen);
|
|
3820
3880
|
}
|
|
3821
3881
|
|
|
3882
|
+
static void pubsubVarargCommandProcessed(rliteClient *c, const char *type, int argc, unsigned char **args, long *argslen, int func(rlite *db, int argc, unsigned char **argv, long *argvlen)) {
|
|
3883
|
+
int i, retval;
|
|
3884
|
+
retval = func(c->context->db, argc, args, argslen);
|
|
3885
|
+
RLITE_SERVER_ERR(c, retval);
|
|
3886
|
+
|
|
3887
|
+
long count = 0;
|
|
3888
|
+
int subscribing = !strcasecmp(type, "subscribe") || !strcasecmp(type, "psubscribe");
|
|
3889
|
+
rl_pubsub_count_subscriptions(c->context->db, &count);
|
|
3890
|
+
for (i = 0; i < argc; i++) {
|
|
3891
|
+
rliteReply *reply = createArrayObject(3);;
|
|
3892
|
+
if (reply) {
|
|
3893
|
+
reply->element[0] = createCStringObject(type);
|
|
3894
|
+
reply->element[1] = createStringObject((char *)args[i], argslen[i]);
|
|
3895
|
+
// TODO: count might be off if a clients connects to the same channel multiple times
|
|
3896
|
+
reply->element[2] = createLongLongObject(subscribing ? (count - argc + i + 1) : (count + argc - i - 1));
|
|
3897
|
+
addReply(c->context, reply);
|
|
3898
|
+
}
|
|
3899
|
+
}
|
|
3900
|
+
retval = RL_OK;
|
|
3901
|
+
cleanup:
|
|
3902
|
+
return;
|
|
3903
|
+
}
|
|
3904
|
+
|
|
3905
|
+
static void pubsubVarargCommand(rliteClient *c, const char *type, int func(rlite *db, int argc, unsigned char **argv, long *argvlen)) {
|
|
3906
|
+
int i = 0, argc = c->argc - 1;
|
|
3907
|
+
unsigned char **args = NULL;
|
|
3908
|
+
long *argslen = NULL;
|
|
3909
|
+
|
|
3910
|
+
args = malloc(sizeof(unsigned char *) * argc);
|
|
3911
|
+
if (!args) {
|
|
3912
|
+
__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
|
|
3913
|
+
goto cleanup;
|
|
3914
|
+
}
|
|
3915
|
+
argslen = malloc(sizeof(long) * argc);
|
|
3916
|
+
if (!argslen) {
|
|
3917
|
+
__rliteSetError(c->context, RLITE_ERR_OOM, "Out of memory");
|
|
3918
|
+
goto cleanup;
|
|
3919
|
+
}
|
|
3920
|
+
for (i = 0; i < argc; i++) {
|
|
3921
|
+
args[i] = (unsigned char *)c->argv[1 + i];
|
|
3922
|
+
argslen[i] = (long)c->argvlen[1 + i];
|
|
3923
|
+
}
|
|
3924
|
+
pubsubVarargCommandProcessed(c, type, argc, args, argslen, func);
|
|
3925
|
+
cleanup:
|
|
3926
|
+
rl_free(args);
|
|
3927
|
+
rl_free(argslen);
|
|
3928
|
+
}
|
|
3929
|
+
|
|
3930
|
+
static void subscribeCommand(rliteClient *c) {
|
|
3931
|
+
pubsubVarargCommand(c, "subscribe", rl_subscribe);
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3934
|
+
static void unsubscribeCommand(rliteClient *c) {
|
|
3935
|
+
long i, channelc = 0;
|
|
3936
|
+
unsigned char **channelv = NULL;
|
|
3937
|
+
long *channelvlen = NULL;
|
|
3938
|
+
if (c->argc == 1) {
|
|
3939
|
+
int retval = rl_pubsub_channels(c->context->db, NULL, 0, &channelc, &channelv, &channelvlen);
|
|
3940
|
+
RLITE_SERVER_ERR(c, retval);
|
|
3941
|
+
pubsubVarargCommandProcessed(c, "unsubscribe", channelc, channelv, channelvlen, rl_unsubscribe);
|
|
3942
|
+
} else {
|
|
3943
|
+
pubsubVarargCommand(c, "unsubscribe", rl_unsubscribe);
|
|
3944
|
+
}
|
|
3945
|
+
|
|
3946
|
+
cleanup:
|
|
3947
|
+
for (i = 0; i < channelc; i++) {
|
|
3948
|
+
rl_free(channelv[i]);
|
|
3949
|
+
}
|
|
3950
|
+
rl_free(channelv);
|
|
3951
|
+
rl_free(channelvlen);
|
|
3952
|
+
}
|
|
3953
|
+
|
|
3954
|
+
static void psubscribeCommand(rliteClient *c) {
|
|
3955
|
+
pubsubVarargCommand(c, "psubscribe", rl_psubscribe);
|
|
3956
|
+
}
|
|
3957
|
+
|
|
3958
|
+
static void punsubscribeCommand(rliteClient *c) {
|
|
3959
|
+
long i, patternc = 0;
|
|
3960
|
+
unsigned char **patternv = NULL;
|
|
3961
|
+
long *patternvlen = NULL;
|
|
3962
|
+
if (c->argc == 1) {
|
|
3963
|
+
int retval = rl_pubsub_patterns(c->context->db, &patternc, &patternv, &patternvlen);
|
|
3964
|
+
RLITE_SERVER_ERR(c, retval);
|
|
3965
|
+
pubsubVarargCommandProcessed(c, "punsubscribe", patternc, patternv, patternvlen, rl_punsubscribe);
|
|
3966
|
+
} else {
|
|
3967
|
+
pubsubVarargCommand(c, "punsubscribe", rl_punsubscribe);
|
|
3968
|
+
}
|
|
3969
|
+
|
|
3970
|
+
cleanup:
|
|
3971
|
+
for (i = 0; i < patternc; i++) {
|
|
3972
|
+
rl_free(patternv[i]);
|
|
3973
|
+
}
|
|
3974
|
+
rl_free(patternv);
|
|
3975
|
+
rl_free(patternvlen);
|
|
3976
|
+
}
|
|
3977
|
+
|
|
3978
|
+
static void publishCommand(rliteClient *c) {
|
|
3979
|
+
unsigned char *channel = (unsigned char *)c->argv[1];
|
|
3980
|
+
size_t channellen = c->argvlen[1];
|
|
3981
|
+
char *data = c->argv[2];
|
|
3982
|
+
size_t datalen = c->argvlen[2];
|
|
3983
|
+
long recipients = 0;
|
|
3984
|
+
int retval = rl_publish(c->context->db, channel, channellen, data, datalen, &recipients);
|
|
3985
|
+
RLITE_SERVER_ERR(c, retval);
|
|
3986
|
+
c->reply = createLongLongObject(recipients);
|
|
3987
|
+
cleanup:
|
|
3988
|
+
return;
|
|
3989
|
+
}
|
|
3990
|
+
|
|
3991
|
+
static void pubsubCommand(rliteClient *c) {
|
|
3992
|
+
long i, channelc = 0;
|
|
3993
|
+
unsigned char **channelv = NULL;
|
|
3994
|
+
long *channelvlen = NULL;
|
|
3995
|
+
int retval;
|
|
3996
|
+
if (!strcasecmp(c->argv[1],"channels")) {
|
|
3997
|
+
unsigned char *pattern = NULL;
|
|
3998
|
+
long patternlen = 0;
|
|
3999
|
+
if (c->argc >= 3) {
|
|
4000
|
+
pattern = (unsigned char *)c->argv[2];
|
|
4001
|
+
patternlen = c->argvlen[2];
|
|
4002
|
+
}
|
|
4003
|
+
retval = rl_pubsub_channels(c->context->db, pattern, patternlen, &channelc, &channelv, &channelvlen);
|
|
4004
|
+
RLITE_SERVER_ERR(c, retval);
|
|
4005
|
+
c->reply = createArrayObject(channelc);
|
|
4006
|
+
if (c->reply == NULL) {
|
|
4007
|
+
goto cleanup;
|
|
4008
|
+
}
|
|
4009
|
+
for (i = 0; i < channelc; i++) {
|
|
4010
|
+
c->reply->element[i] = createStringObject((char *)channelv[i], channelvlen[i]);
|
|
4011
|
+
}
|
|
4012
|
+
} else if (!strcasecmp(c->argv[1],"numsub")) {
|
|
4013
|
+
long numsub;
|
|
4014
|
+
retval = rl_pubsub_numsub(c->context->db, c->argc - 2, (unsigned char **)&c->argv[2], (long *)&c->argvlen[2], &numsub);
|
|
4015
|
+
c->reply = createLongLongObject(numsub);
|
|
4016
|
+
} else if (!strcasecmp(c->argv[1],"numpat")) {
|
|
4017
|
+
long numpat;
|
|
4018
|
+
retval = rl_pubsub_numpat(c->context->db, &numpat);
|
|
4019
|
+
c->reply = createLongLongObject(numpat);
|
|
4020
|
+
}
|
|
4021
|
+
cleanup:
|
|
4022
|
+
for (i = 0; i < channelc; i++) {
|
|
4023
|
+
rl_free(channelv[i]);
|
|
4024
|
+
}
|
|
4025
|
+
rl_free(channelv);
|
|
4026
|
+
rl_free(channelvlen);
|
|
4027
|
+
return;
|
|
4028
|
+
}
|
|
4029
|
+
|
|
4030
|
+
void pubsubPollCommand(rliteClient *c) {
|
|
4031
|
+
int retval;
|
|
4032
|
+
int elementc;
|
|
4033
|
+
unsigned char **elements;
|
|
4034
|
+
long *elementslen;
|
|
4035
|
+
if (c->argc >= 2) {
|
|
4036
|
+
long timeout_param;
|
|
4037
|
+
struct timeval timeout;
|
|
4038
|
+
if ((getLongFromObjectOrReply(c, c->argv[1], c->argvlen[1], &timeout_param, NULL) != RLITE_OK)) {
|
|
4039
|
+
return;
|
|
4040
|
+
}
|
|
4041
|
+
if (timeout_param != 0) {
|
|
4042
|
+
timeout.tv_sec = 0;
|
|
4043
|
+
timeout.tv_usec = timeout_param;
|
|
4044
|
+
}
|
|
4045
|
+
retval = rl_poll_wait(c->context->db, &elementc, &elements, &elementslen, timeout_param == 0 ? NULL : &timeout);
|
|
4046
|
+
} else {
|
|
4047
|
+
retval = rl_poll(c->context->db, &elementc, &elements, &elementslen);
|
|
4048
|
+
}
|
|
4049
|
+
RLITE_SERVER_ERR(c, retval);
|
|
4050
|
+
if (retval == RL_NOT_FOUND) {
|
|
4051
|
+
c->reply = createReplyObject(RLITE_REPLY_NIL);
|
|
4052
|
+
} else if (retval == RL_OK) {
|
|
4053
|
+
c->reply = pollToReply(elementc, elements, elementslen);
|
|
4054
|
+
} else {
|
|
4055
|
+
addReplyErrorFormat(c->context, "unknown retval %d", retval);
|
|
4056
|
+
}
|
|
4057
|
+
cleanup:
|
|
4058
|
+
return;
|
|
4059
|
+
}
|
|
4060
|
+
|
|
3822
4061
|
static struct rliteCommand rliteCommandTable[] = {
|
|
3823
4062
|
{"get",getCommand,2,"rF",0,1,1,1,0,0},
|
|
3824
4063
|
{"set",setCommand,-3,"wm",0,1,1,1,0,0},
|
|
@@ -3949,12 +4188,13 @@ static struct rliteCommand rliteCommandTable[] = {
|
|
|
3949
4188
|
// {"role",roleCommand,1,"last",0,NULL,0,0,0,0,0},
|
|
3950
4189
|
{"debug",debugCommand,-2,"as",0,0,0,0,0,0},
|
|
3951
4190
|
// {"config",configCommand,-2,"art",0,NULL,0,0,0,0,0},
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
|
|
4191
|
+
{"subscribe",subscribeCommand,-2,"rpslt",0,0,0,0,0,0},
|
|
4192
|
+
{"unsubscribe",unsubscribeCommand,-1,"rpslt",0,0,0,0,0,0},
|
|
4193
|
+
{"psubscribe",psubscribeCommand,-2,"rpslt",0,0,0,0,0,0},
|
|
4194
|
+
{"punsubscribe",punsubscribeCommand,-1,"rpslt",0,0,0,0,0,0},
|
|
4195
|
+
{"publish",publishCommand,3,"pltrF",0,0,0,0,0,0},
|
|
4196
|
+
{"pubsub",pubsubCommand,-2,"pltrR",0,0,0,0,0,0},
|
|
4197
|
+
{"__rlite_poll",pubsubPollCommand,-1,"pltrR",0,0,0,0,0,0},
|
|
3958
4198
|
{"watch",watchCommand,-2,"rsF",0,1,-1,1,0,0},
|
|
3959
4199
|
{"unwatch",unwatchCommand,1,"rsF",0,0,0,0,0,0},
|
|
3960
4200
|
// {"cluster",clusterCommand,-2,"ar",0,NULL,0,0,0,0,0},
|