1 #ifndef REDIS_CLUSTER_H
2 #define REDIS_CLUSTER_H
3 
4 #include "cluster_library.h"
5 #include <php.h>
6 #include <stddef.h>
7 
8 /* Get attached object context */
9 #define GET_CONTEXT() PHPREDIS_ZVAL_GET_OBJECT(redisCluster, getThis())
10 
11 /* Command building/processing is identical for every command */
12 #define CLUSTER_BUILD_CMD(name, c, cmd, cmd_len, slot) \
13     redis_##name##_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags, &cmd, \
14                        &cmd_len, &slot)
15 
16 /* Append information required to handle MULTI commands to the tail of our MULTI
17  * linked list. */
18 #define CLUSTER_ENQUEUE_RESPONSE(c, slot, cb, ctx) \
19     clusterFoldItem *_item; \
20     _item = emalloc(sizeof(clusterFoldItem)); \
21     _item->callback = cb; \
22     _item->slot = slot; \
23     _item->ctx = ctx; \
24     _item->next = NULL; \
25     if(c->multi_head == NULL) { \
26         c->multi_head = _item; \
27         c->multi_curr = _item; \
28     } else { \
29         c->multi_curr->next = _item; \
30         c->multi_curr = _item; \
31     } \
32 
33 /* Simple macro to free our enqueued callbacks after we EXEC */
34 #define CLUSTER_FREE_QUEUE(c) \
35     clusterFoldItem *_item = c->multi_head, *_tmp; \
36     while(_item) { \
37         _tmp = _item->next; \
38         efree(_item); \
39         _item = _tmp; \
40     } \
41     c->multi_head = c->multi_curr = NULL; \
42 
43 /* Reset anything flagged as MULTI */
44 #define CLUSTER_RESET_MULTI(c) \
45     redisClusterNode *_node; \
46     ZEND_HASH_FOREACH_PTR(c->nodes, _node) { \
47         if (_node == NULL) break; \
48         _node->sock->watching = 0; \
49         _node->sock->mode = ATOMIC; \
50     } ZEND_HASH_FOREACH_END(); \
51     c->flags->watching = 0; \
52     c->flags->mode     = ATOMIC; \
53 
54 /* Simple 1-1 command -> response macro */
55 #define CLUSTER_PROCESS_CMD(cmdname, resp_func, readcmd) \
56     redisCluster *c = GET_CONTEXT(); \
57     c->readonly = CLUSTER_IS_ATOMIC(c) && readcmd; \
58     char *cmd; int cmd_len; short slot; void *ctx=NULL; \
59     if(redis_##cmdname##_cmd(INTERNAL_FUNCTION_PARAM_PASSTHRU,c->flags, &cmd, \
60                              &cmd_len, &slot, &ctx)==FAILURE) { \
61         RETURN_FALSE; \
62     } \
63     if(cluster_send_command(c,slot,cmd,cmd_len)<0 || c->err!=NULL) {\
64         efree(cmd); \
65         RETURN_FALSE; \
66     } \
67     efree(cmd); \
68     if(c->flags->mode == MULTI) { \
69         CLUSTER_ENQUEUE_RESPONSE(c, slot, resp_func, ctx); \
70         RETURN_ZVAL(getThis(), 1, 0); \
71     } \
72     resp_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
73 
74 /* More generic processing, where only the keyword differs */
75 #define CLUSTER_PROCESS_KW_CMD(kw, cmdfunc, resp_func, readcmd) \
76     redisCluster *c = GET_CONTEXT(); \
77     c->readonly = CLUSTER_IS_ATOMIC(c) && readcmd; \
78     char *cmd; int cmd_len; short slot; void *ctx=NULL; \
79     if(cmdfunc(INTERNAL_FUNCTION_PARAM_PASSTHRU, c->flags, kw, &cmd, &cmd_len,\
80                &slot,&ctx)==FAILURE) { \
81         RETURN_FALSE; \
82     } \
83     if(cluster_send_command(c,slot,cmd,cmd_len)<0 || c->err!=NULL) { \
84         efree(cmd); \
85         RETURN_FALSE; \
86     } \
87     efree(cmd); \
88     if(c->flags->mode == MULTI) { \
89         CLUSTER_ENQUEUE_RESPONSE(c, slot, resp_func, ctx); \
90         RETURN_ZVAL(getThis(), 1, 0); \
91     } \
92     resp_func(INTERNAL_FUNCTION_PARAM_PASSTHRU, c, ctx);
93 
94 /* Create cluster context */
95 zend_object *create_cluster_context(zend_class_entry *class_type);
96 
97 /* Free cluster context struct */
98 void free_cluster_context(zend_object *object);
99 
100 /* RedisCluster method implementation */
101 PHP_METHOD(RedisCluster, __construct);
102 PHP_METHOD(RedisCluster, acl);
103 PHP_METHOD(RedisCluster, close);
104 PHP_METHOD(RedisCluster, get);
105 PHP_METHOD(RedisCluster, set);
106 PHP_METHOD(RedisCluster, mget);
107 PHP_METHOD(RedisCluster, mset);
108 PHP_METHOD(RedisCluster, msetnx);
109 PHP_METHOD(RedisCluster, mset);
110 PHP_METHOD(RedisCluster, del);
111 PHP_METHOD(RedisCluster, unlink);
112 PHP_METHOD(RedisCluster, dump);
113 PHP_METHOD(RedisCluster, setex);
114 PHP_METHOD(RedisCluster, psetex);
115 PHP_METHOD(RedisCluster, setnx);
116 PHP_METHOD(RedisCluster, getset);
117 PHP_METHOD(RedisCluster, exists);
118 PHP_METHOD(RedisCluster, keys);
119 PHP_METHOD(RedisCluster, type);
120 PHP_METHOD(RedisCluster, persist);
121 PHP_METHOD(RedisCluster, lpop);
122 PHP_METHOD(RedisCluster, rpop);
123 PHP_METHOD(RedisCluster, spop);
124 PHP_METHOD(RedisCluster, rpush);
125 PHP_METHOD(RedisCluster, lpush);
126 PHP_METHOD(RedisCluster, blpop);
127 PHP_METHOD(RedisCluster, brpop);
128 PHP_METHOD(RedisCluster, rpushx);
129 PHP_METHOD(RedisCluster, lpushx);
130 PHP_METHOD(RedisCluster, linsert);
131 PHP_METHOD(RedisCluster, lindex);
132 PHP_METHOD(RedisCluster, lrem);
133 PHP_METHOD(RedisCluster, brpoplpush);
134 PHP_METHOD(RedisCluster, rpoplpush);
135 PHP_METHOD(RedisCluster, llen);
136 PHP_METHOD(RedisCluster, scard);
137 PHP_METHOD(RedisCluster, smembers);
138 PHP_METHOD(RedisCluster, sismember);
139 PHP_METHOD(RedisCluster, sadd);
140 PHP_METHOD(RedisCluster, saddarray);
141 PHP_METHOD(RedisCluster, srem);
142 PHP_METHOD(RedisCluster, sunion);
143 PHP_METHOD(RedisCluster, sunionstore);
144 PHP_METHOD(RedisCluster, sinter);
145 PHP_METHOD(RedisCluster, sinterstore);
146 PHP_METHOD(RedisCluster, sdiff);
147 PHP_METHOD(RedisCluster, sdiffstore);
148 PHP_METHOD(RedisCluster, strlen);
149 PHP_METHOD(RedisCluster, ttl);
150 PHP_METHOD(RedisCluster, pttl);
151 PHP_METHOD(RedisCluster, zcard);
152 PHP_METHOD(RedisCluster, zscore);
153 PHP_METHOD(RedisCluster, zcount);
154 PHP_METHOD(RedisCluster, zrem);
155 PHP_METHOD(RedisCluster, zremrangebyscore);
156 PHP_METHOD(RedisCluster, zrank);
157 PHP_METHOD(RedisCluster, zrevrank);
158 PHP_METHOD(RedisCluster, zadd);
159 PHP_METHOD(RedisCluster, zincrby);
160 PHP_METHOD(RedisCluster, hlen);
161 PHP_METHOD(RedisCluster, hget);
162 PHP_METHOD(RedisCluster, hkeys);
163 PHP_METHOD(RedisCluster, hvals);
164 PHP_METHOD(RedisCluster, hmget);
165 PHP_METHOD(RedisCluster, hmset);
166 PHP_METHOD(RedisCluster, hdel);
167 PHP_METHOD(RedisCluster, hgetall);
168 PHP_METHOD(RedisCluster, hexists);
169 PHP_METHOD(RedisCluster, hincrby);
170 PHP_METHOD(RedisCluster, hincrbyfloat);
171 PHP_METHOD(RedisCluster, hset);
172 PHP_METHOD(RedisCluster, hsetnx);
173 PHP_METHOD(RedisCluster, hstrlen);
174 PHP_METHOD(RedisCluster, incr);
175 PHP_METHOD(RedisCluster, decr);
176 PHP_METHOD(RedisCluster, incrby);
177 PHP_METHOD(RedisCluster, decrby);
178 PHP_METHOD(RedisCluster, incrbyfloat);
179 PHP_METHOD(RedisCluster, expire);
180 PHP_METHOD(RedisCluster, expireat);
181 PHP_METHOD(RedisCluster, pexpire);
182 PHP_METHOD(RedisCluster, pexpireat);
183 PHP_METHOD(RedisCluster, append);
184 PHP_METHOD(RedisCluster, getbit);
185 PHP_METHOD(RedisCluster, setbit);
186 PHP_METHOD(RedisCluster, bitop);
187 PHP_METHOD(RedisCluster, bitpos);
188 PHP_METHOD(RedisCluster, bitcount);
189 PHP_METHOD(RedisCluster, lget);
190 PHP_METHOD(RedisCluster, getrange);
191 PHP_METHOD(RedisCluster, ltrim);
192 PHP_METHOD(RedisCluster, lrange);
193 PHP_METHOD(RedisCluster, zremrangebyrank);
194 PHP_METHOD(RedisCluster, publish);
195 PHP_METHOD(RedisCluster, lset);
196 PHP_METHOD(RedisCluster, rename);
197 PHP_METHOD(RedisCluster, renamenx);
198 PHP_METHOD(RedisCluster, pfcount);
199 PHP_METHOD(RedisCluster, pfadd);
200 PHP_METHOD(RedisCluster, pfmerge);
201 PHP_METHOD(RedisCluster, restore);
202 PHP_METHOD(RedisCluster, setrange);
203 PHP_METHOD(RedisCluster, smove);
204 PHP_METHOD(RedisCluster, srandmember);
205 PHP_METHOD(RedisCluster, zpopmin);
206 PHP_METHOD(RedisCluster, zpopmax);
207 PHP_METHOD(RedisCluster, bzpopmax);
208 PHP_METHOD(RedisCluster, bzpopmin);
209 PHP_METHOD(RedisCluster, zrange);
210 PHP_METHOD(RedisCluster, zrevrange);
211 PHP_METHOD(RedisCluster, zrangebyscore);
212 PHP_METHOD(RedisCluster, zrevrangebyscore);
213 PHP_METHOD(RedisCluster, zrangebylex);
214 PHP_METHOD(RedisCluster, zrevrangebylex);
215 PHP_METHOD(RedisCluster, zlexcount);
216 PHP_METHOD(RedisCluster, zremrangebylex);
217 PHP_METHOD(RedisCluster, zunionstore);
218 PHP_METHOD(RedisCluster, zinterstore);
219 PHP_METHOD(RedisCluster, sort);
220 PHP_METHOD(RedisCluster, object);
221 PHP_METHOD(RedisCluster, subscribe);
222 PHP_METHOD(RedisCluster, psubscribe);
223 PHP_METHOD(RedisCluster, unsubscribe);
224 PHP_METHOD(RedisCluster, punsubscribe);
225 PHP_METHOD(RedisCluster, eval);
226 PHP_METHOD(RedisCluster, evalsha);
227 PHP_METHOD(RedisCluster, info);
228 PHP_METHOD(RedisCluster, cluster);
229 PHP_METHOD(RedisCluster, client);
230 PHP_METHOD(RedisCluster, config);
231 PHP_METHOD(RedisCluster, pubsub);
232 PHP_METHOD(RedisCluster, script);
233 PHP_METHOD(RedisCluster, slowlog);
234 PHP_METHOD(RedisCluster, command);
235 PHP_METHOD(RedisCluster, geoadd);
236 PHP_METHOD(RedisCluster, geohash);
237 PHP_METHOD(RedisCluster, geopos);
238 PHP_METHOD(RedisCluster, geodist);
239 PHP_METHOD(RedisCluster, georadius);
240 PHP_METHOD(RedisCluster, georadius_ro);
241 PHP_METHOD(RedisCluster, georadiusbymember);
242 PHP_METHOD(RedisCluster, georadiusbymember_ro);
243 
244 /* SCAN and friends */
245 PHP_METHOD(RedisCluster, scan);
246 PHP_METHOD(RedisCluster, zscan);
247 PHP_METHOD(RedisCluster, hscan);
248 PHP_METHOD(RedisCluster, sscan);
249 
250 /* STREAMS */
251 PHP_METHOD(RedisCluster, xack);
252 PHP_METHOD(RedisCluster, xadd);
253 PHP_METHOD(RedisCluster, xclaim);
254 PHP_METHOD(RedisCluster, xdel);
255 PHP_METHOD(RedisCluster, xgroup);
256 PHP_METHOD(RedisCluster, xinfo);
257 PHP_METHOD(RedisCluster, xlen);
258 PHP_METHOD(RedisCluster, xpending);
259 PHP_METHOD(RedisCluster, xrange);
260 PHP_METHOD(RedisCluster, xread);
261 PHP_METHOD(RedisCluster, xreadgroup);
262 PHP_METHOD(RedisCluster, xrevrange);
263 PHP_METHOD(RedisCluster, xtrim);
264 
265 /* Transactions */
266 PHP_METHOD(RedisCluster, multi);
267 PHP_METHOD(RedisCluster, exec);
268 PHP_METHOD(RedisCluster, discard);
269 PHP_METHOD(RedisCluster, watch);
270 PHP_METHOD(RedisCluster, unwatch);
271 
272 /* Commands we direct to a node */
273 PHP_METHOD(RedisCluster, save);
274 PHP_METHOD(RedisCluster, bgsave);
275 PHP_METHOD(RedisCluster, flushdb);
276 PHP_METHOD(RedisCluster, flushall);
277 PHP_METHOD(RedisCluster, dbsize);
278 PHP_METHOD(RedisCluster, bgrewriteaof);
279 PHP_METHOD(RedisCluster, lastsave);
280 PHP_METHOD(RedisCluster, role);
281 PHP_METHOD(RedisCluster, time);
282 PHP_METHOD(RedisCluster, randomkey);
283 PHP_METHOD(RedisCluster, ping);
284 PHP_METHOD(RedisCluster, echo);
285 PHP_METHOD(RedisCluster, rawcommand);
286 
287 /* Introspection */
288 PHP_METHOD(RedisCluster, getmode);
289 PHP_METHOD(RedisCluster, getlasterror);
290 PHP_METHOD(RedisCluster, clearlasterror);
291 PHP_METHOD(RedisCluster, getoption);
292 PHP_METHOD(RedisCluster, setoption);
293 PHP_METHOD(RedisCluster, _prefix);
294 PHP_METHOD(RedisCluster, _serialize);
295 PHP_METHOD(RedisCluster, _unserialize);
296 PHP_METHOD(RedisCluster, _compress);
297 PHP_METHOD(RedisCluster, _uncompress);
298 PHP_METHOD(RedisCluster, _pack);
299 PHP_METHOD(RedisCluster, _unpack);
300 PHP_METHOD(RedisCluster, _masters);
301 PHP_METHOD(RedisCluster, _redir);
302 
303 #endif
304