nutcracker 0.3.0.12 → 0.4.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/README.md +3 -3
- data/Rakefile +12 -10
- data/ext/nutcracker/Makefile.in +215 -162
- data/ext/nutcracker/README.md +16 -4
- data/ext/nutcracker/aclocal.m4 +432 -254
- data/ext/nutcracker/{contrib/yaml-0.1.4/configure → autom4te.cache/output.0} +11367 -4545
- data/ext/nutcracker/autom4te.cache/output.1 +19907 -0
- data/ext/nutcracker/autom4te.cache/output.2 +19907 -0
- data/ext/nutcracker/autom4te.cache/requests +518 -0
- data/ext/nutcracker/autom4te.cache/traces.0 +2715 -0
- data/ext/nutcracker/autom4te.cache/traces.1 +967 -0
- data/ext/nutcracker/autom4te.cache/traces.2 +2715 -0
- data/ext/nutcracker/config/compile +347 -0
- data/ext/nutcracker/config/config.guess +116 -78
- data/ext/nutcracker/config/config.sub +65 -45
- data/ext/nutcracker/config/depcomp +295 -192
- data/ext/nutcracker/config/install-sh +7 -7
- data/ext/nutcracker/config/ltmain.sh +15 -20
- data/ext/nutcracker/config/missing +149 -265
- data/ext/nutcracker/configure +493 -367
- data/ext/nutcracker/contrib/Makefile.in +158 -116
- data/ext/nutcracker/extconf.rb +0 -1
- data/ext/nutcracker/m4/libtool.m4 +4 -23
- data/ext/nutcracker/m4/ltoptions.m4 +0 -0
- data/ext/nutcracker/m4/ltsugar.m4 +0 -0
- data/ext/nutcracker/m4/ltversion.m4 +0 -0
- data/ext/nutcracker/m4/lt~obsolete.m4 +0 -0
- data/ext/nutcracker/notes/recommendation.md +1 -1
- data/ext/nutcracker/notes/redis.md +35 -3
- data/ext/nutcracker/scripts/benchmark-mget.py +43 -0
- data/ext/nutcracker/scripts/nutcracker.spec +61 -3
- data/ext/nutcracker/scripts/redis-check.sh +43 -0
- data/ext/nutcracker/src/Makefile.in +205 -142
- data/ext/nutcracker/src/event/Makefile.in +164 -66
- data/ext/nutcracker/src/hashkit/Makefile.in +164 -66
- data/ext/nutcracker/src/nc_conf.c +2 -0
- data/ext/nutcracker/src/nc_connection.c +31 -0
- data/ext/nutcracker/src/nc_connection.h +3 -0
- data/ext/nutcracker/src/nc_core.c +38 -2
- data/ext/nutcracker/src/nc_core.h +11 -0
- data/ext/nutcracker/src/nc_log.c +90 -12
- data/ext/nutcracker/src/nc_log.h +11 -0
- data/ext/nutcracker/src/nc_mbuf.h +1 -1
- data/ext/nutcracker/src/nc_message.c +162 -116
- data/ext/nutcracker/src/nc_message.h +161 -129
- data/ext/nutcracker/src/nc_proxy.c +34 -4
- data/ext/nutcracker/src/nc_request.c +158 -32
- data/ext/nutcracker/src/nc_server.c +59 -5
- data/ext/nutcracker/src/nc_server.h +1 -0
- data/ext/nutcracker/src/nc_signal.c +2 -2
- data/ext/nutcracker/src/nc_stats.c +21 -0
- data/ext/nutcracker/src/nc_stats.h +28 -26
- data/ext/nutcracker/src/nc_string.c +176 -1
- data/ext/nutcracker/src/nc_string.h +26 -0
- data/ext/nutcracker/src/nc_util.c +12 -0
- data/ext/nutcracker/src/nc_util.h +1 -0
- data/ext/nutcracker/src/proto/Makefile.in +164 -66
- data/ext/nutcracker/src/proto/nc_memcache.c +279 -88
- data/ext/nutcracker/src/proto/nc_proto.h +3 -4
- data/ext/nutcracker/src/proto/nc_redis.c +561 -134
- data/lib/nutcracker/version.rb +1 -1
- metadata +31 -67
- data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +0 -19
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +0 -20
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +0 -736
- data/ext/nutcracker/contrib/yaml-0.1.4/README +0 -27
- data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +0 -956
- data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +0 -80
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +0 -1561
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +0 -1686
- data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +0 -630
- data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +0 -520
- data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +0 -8406
- data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +0 -376
- data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +0 -75
- data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +0 -222
- data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +0 -1971
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +0 -7357
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +0 -368
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +0 -123
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +0 -23
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +0 -92
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +0 -4
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +0 -484
- data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +0 -1392
- data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +0 -394
- data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +0 -2329
- data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +0 -432
- data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +0 -1374
- data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +0 -465
- data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +0 -3570
- data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +0 -141
- data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +0 -640
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +0 -8
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +0 -675
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +0 -800
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +0 -1130
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +0 -217
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +0 -202
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +0 -311
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +0 -327
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +0 -63
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +0 -63
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +0 -63
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +0 -354
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +0 -29
@@ -140,16 +140,15 @@
|
|
140
140
|
|
141
141
|
void memcache_parse_req(struct msg *r);
|
142
142
|
void memcache_parse_rsp(struct msg *r);
|
143
|
-
void memcache_pre_splitcopy(struct mbuf *mbuf, void *arg);
|
144
|
-
rstatus_t memcache_post_splitcopy(struct msg *r);
|
145
143
|
void memcache_pre_coalesce(struct msg *r);
|
146
144
|
void memcache_post_coalesce(struct msg *r);
|
145
|
+
rstatus_t memcache_fragment(struct msg *r, uint32_t ncontinuum, struct msg_tqh *frag_msgq);
|
147
146
|
|
148
147
|
void redis_parse_req(struct msg *r);
|
149
148
|
void redis_parse_rsp(struct msg *r);
|
150
|
-
void redis_pre_splitcopy(struct mbuf *mbuf, void *arg);
|
151
|
-
rstatus_t redis_post_splitcopy(struct msg *r);
|
152
149
|
void redis_pre_coalesce(struct msg *r);
|
153
150
|
void redis_post_coalesce(struct msg *r);
|
151
|
+
rstatus_t redis_fragment(struct msg *r, uint32_t ncontinuum, struct msg_tqh *frag_msgq);
|
152
|
+
rstatus_t redis_reply(struct msg *r);
|
154
153
|
|
155
154
|
#endif
|
@@ -21,6 +21,25 @@
|
|
21
21
|
#include <nc_core.h>
|
22
22
|
#include <nc_proto.h>
|
23
23
|
|
24
|
+
/*
|
25
|
+
* Return true, if the redis command take no key, otherwise
|
26
|
+
* return false
|
27
|
+
*/
|
28
|
+
static bool
|
29
|
+
redis_argz(struct msg *r)
|
30
|
+
{
|
31
|
+
switch (r->type) {
|
32
|
+
case MSG_REQ_REDIS_PING:
|
33
|
+
case MSG_REQ_REDIS_QUIT:
|
34
|
+
return true;
|
35
|
+
|
36
|
+
default:
|
37
|
+
break;
|
38
|
+
}
|
39
|
+
|
40
|
+
return false;
|
41
|
+
}
|
42
|
+
|
24
43
|
/*
|
25
44
|
* Return true, if the redis command accepts no arguments, otherwise
|
26
45
|
* return false
|
@@ -32,6 +51,7 @@ redis_arg0(struct msg *r)
|
|
32
51
|
case MSG_REQ_REDIS_EXISTS:
|
33
52
|
case MSG_REQ_REDIS_PERSIST:
|
34
53
|
case MSG_REQ_REDIS_PTTL:
|
54
|
+
case MSG_REQ_REDIS_SORT:
|
35
55
|
case MSG_REQ_REDIS_TTL:
|
36
56
|
case MSG_REQ_REDIS_TYPE:
|
37
57
|
case MSG_REQ_REDIS_DUMP:
|
@@ -55,6 +75,8 @@ redis_arg0(struct msg *r)
|
|
55
75
|
case MSG_REQ_REDIS_SPOP:
|
56
76
|
|
57
77
|
case MSG_REQ_REDIS_ZCARD:
|
78
|
+
|
79
|
+
case MSG_REQ_REDIS_PFCOUNT:
|
58
80
|
return true;
|
59
81
|
|
60
82
|
default:
|
@@ -134,7 +156,9 @@ redis_arg2(struct msg *r)
|
|
134
156
|
case MSG_REQ_REDIS_SMOVE:
|
135
157
|
|
136
158
|
case MSG_REQ_REDIS_ZCOUNT:
|
159
|
+
case MSG_REQ_REDIS_ZLEXCOUNT:
|
137
160
|
case MSG_REQ_REDIS_ZINCRBY:
|
161
|
+
case MSG_REQ_REDIS_ZREMRANGEBYLEX:
|
138
162
|
case MSG_REQ_REDIS_ZREMRANGEBYRANK:
|
139
163
|
case MSG_REQ_REDIS_ZREMRANGEBYSCORE:
|
140
164
|
|
@@ -180,6 +204,7 @@ redis_argn(struct msg *r)
|
|
180
204
|
case MSG_REQ_REDIS_HDEL:
|
181
205
|
case MSG_REQ_REDIS_HMGET:
|
182
206
|
case MSG_REQ_REDIS_HMSET:
|
207
|
+
case MSG_REQ_REDIS_HSCAN:
|
183
208
|
|
184
209
|
case MSG_REQ_REDIS_LPUSH:
|
185
210
|
case MSG_REQ_REDIS_RPUSH:
|
@@ -193,6 +218,10 @@ redis_argn(struct msg *r)
|
|
193
218
|
case MSG_REQ_REDIS_SUNION:
|
194
219
|
case MSG_REQ_REDIS_SUNIONSTORE:
|
195
220
|
case MSG_REQ_REDIS_SRANDMEMBER:
|
221
|
+
case MSG_REQ_REDIS_SSCAN:
|
222
|
+
|
223
|
+
case MSG_REQ_REDIS_PFADD:
|
224
|
+
case MSG_REQ_REDIS_PFMERGE:
|
196
225
|
|
197
226
|
case MSG_REQ_REDIS_ZADD:
|
198
227
|
case MSG_REQ_REDIS_ZINTERSTORE:
|
@@ -200,8 +229,10 @@ redis_argn(struct msg *r)
|
|
200
229
|
case MSG_REQ_REDIS_ZRANGEBYSCORE:
|
201
230
|
case MSG_REQ_REDIS_ZREM:
|
202
231
|
case MSG_REQ_REDIS_ZREVRANGE:
|
232
|
+
case MSG_REQ_REDIS_ZRANGEBYLEX:
|
203
233
|
case MSG_REQ_REDIS_ZREVRANGEBYSCORE:
|
204
234
|
case MSG_REQ_REDIS_ZUNIONSTORE:
|
235
|
+
case MSG_REQ_REDIS_ZSCAN:
|
205
236
|
return true;
|
206
237
|
|
207
238
|
default:
|
@@ -230,6 +261,24 @@ redis_argx(struct msg *r)
|
|
230
261
|
return false;
|
231
262
|
}
|
232
263
|
|
264
|
+
/*
|
265
|
+
* Return true, if the redis command is a vector command accepting one or
|
266
|
+
* more key-value pairs, otherwise return false
|
267
|
+
*/
|
268
|
+
static bool
|
269
|
+
redis_argkvx(struct msg *r)
|
270
|
+
{
|
271
|
+
switch (r->type) {
|
272
|
+
case MSG_REQ_REDIS_MSET:
|
273
|
+
return true;
|
274
|
+
|
275
|
+
default:
|
276
|
+
break;
|
277
|
+
}
|
278
|
+
|
279
|
+
return false;
|
280
|
+
}
|
281
|
+
|
233
282
|
/*
|
234
283
|
* Return true, if the redis command is either EVAL or EVALSHA. These commands
|
235
284
|
* have a special format with exactly 2 arguments, followed by one or more keys,
|
@@ -309,7 +358,6 @@ redis_parse_req(struct msg *r)
|
|
309
358
|
SW_ARGN_LEN_LF,
|
310
359
|
SW_ARGN,
|
311
360
|
SW_ARGN_LF,
|
312
|
-
SW_FRAGMENT,
|
313
361
|
SW_SENTINEL
|
314
362
|
} state;
|
315
363
|
|
@@ -540,6 +588,10 @@ redis_parse_req(struct msg *r)
|
|
540
588
|
r->type = MSG_REQ_REDIS_MGET;
|
541
589
|
break;
|
542
590
|
}
|
591
|
+
if (str4icmp(m, 'm', 's', 'e', 't')) {
|
592
|
+
r->type = MSG_REQ_REDIS_MSET;
|
593
|
+
break;
|
594
|
+
}
|
543
595
|
|
544
596
|
if (str4icmp(m, 'z', 'a', 'd', 'd')) {
|
545
597
|
r->type = MSG_REQ_REDIS_ZADD;
|
@@ -556,6 +608,23 @@ redis_parse_req(struct msg *r)
|
|
556
608
|
break;
|
557
609
|
}
|
558
610
|
|
611
|
+
if (str4icmp(m, 's', 'o', 'r', 't')) {
|
612
|
+
r->type = MSG_REQ_REDIS_SORT;
|
613
|
+
break;
|
614
|
+
}
|
615
|
+
|
616
|
+
if (str4icmp(m, 'p', 'i', 'n', 'g')) {
|
617
|
+
r->type = MSG_REQ_REDIS_PING;
|
618
|
+
r->noforward = 1;
|
619
|
+
break;
|
620
|
+
}
|
621
|
+
|
622
|
+
if (str4icmp(m, 'q', 'u', 'i', 't')) {
|
623
|
+
r->type = MSG_REQ_REDIS_QUIT;
|
624
|
+
r->quit = 1;
|
625
|
+
break;
|
626
|
+
}
|
627
|
+
|
559
628
|
break;
|
560
629
|
|
561
630
|
case 5:
|
@@ -579,6 +648,11 @@ redis_parse_req(struct msg *r)
|
|
579
648
|
break;
|
580
649
|
}
|
581
650
|
|
651
|
+
if (str5icmp(m, 'h', 's', 'c', 'a', 'n')) {
|
652
|
+
r->type = MSG_REQ_REDIS_HSCAN;
|
653
|
+
break;
|
654
|
+
}
|
655
|
+
|
582
656
|
if (str5icmp(m, 'l', 'p', 'u', 's', 'h')) {
|
583
657
|
r->type = MSG_REQ_REDIS_LPUSH;
|
584
658
|
break;
|
@@ -619,6 +693,11 @@ redis_parse_req(struct msg *r)
|
|
619
693
|
break;
|
620
694
|
}
|
621
695
|
|
696
|
+
if (str5icmp(m, 's', 's', 'c', 'a', 'n')) {
|
697
|
+
r->type = MSG_REQ_REDIS_SSCAN;
|
698
|
+
break;
|
699
|
+
}
|
700
|
+
|
622
701
|
if (str5icmp(m, 'z', 'c', 'a', 'r', 'd')) {
|
623
702
|
r->type = MSG_REQ_REDIS_ZCARD;
|
624
703
|
break;
|
@@ -629,6 +708,16 @@ redis_parse_req(struct msg *r)
|
|
629
708
|
break;
|
630
709
|
}
|
631
710
|
|
711
|
+
if (str5icmp(m, 'z', 's', 'c', 'a', 'n')) {
|
712
|
+
r->type = MSG_REQ_REDIS_ZSCAN;
|
713
|
+
break;
|
714
|
+
}
|
715
|
+
|
716
|
+
if (str5icmp(m, 'p', 'f', 'a', 'd', 'd')) {
|
717
|
+
r->type = MSG_REQ_REDIS_PFADD;
|
718
|
+
break;
|
719
|
+
}
|
720
|
+
|
632
721
|
break;
|
633
722
|
|
634
723
|
case 6:
|
@@ -780,6 +869,16 @@ redis_parse_req(struct msg *r)
|
|
780
869
|
break;
|
781
870
|
}
|
782
871
|
|
872
|
+
if (str7icmp(m, 'p', 'f', 'c', 'o', 'u', 'n', 't')) {
|
873
|
+
r->type = MSG_REQ_REDIS_PFCOUNT;
|
874
|
+
break;
|
875
|
+
}
|
876
|
+
|
877
|
+
if (str7icmp(m, 'p', 'f', 'm', 'e', 'r', 'g', 'e')) {
|
878
|
+
r->type = MSG_REQ_REDIS_PFMERGE;
|
879
|
+
break;
|
880
|
+
}
|
881
|
+
|
783
882
|
break;
|
784
883
|
|
785
884
|
case 8:
|
@@ -836,6 +935,11 @@ redis_parse_req(struct msg *r)
|
|
836
935
|
break;
|
837
936
|
}
|
838
937
|
|
938
|
+
if (str9icmp(m, 'z', 'l', 'e', 'x', 'c', 'o', 'u', 'n', 't')) {
|
939
|
+
r->type = MSG_REQ_REDIS_ZLEXCOUNT;
|
940
|
+
break;
|
941
|
+
}
|
942
|
+
|
839
943
|
break;
|
840
944
|
|
841
945
|
case 10:
|
@@ -875,6 +979,11 @@ redis_parse_req(struct msg *r)
|
|
875
979
|
break;
|
876
980
|
}
|
877
981
|
|
982
|
+
if (str11icmp(m, 'z', 'r', 'a', 'n', 'g', 'e', 'b', 'y', 'l', 'e', 'x')) {
|
983
|
+
r->type = MSG_REQ_REDIS_ZRANGEBYLEX;
|
984
|
+
break;
|
985
|
+
}
|
986
|
+
|
878
987
|
break;
|
879
988
|
|
880
989
|
case 12:
|
@@ -894,6 +1003,14 @@ redis_parse_req(struct msg *r)
|
|
894
1003
|
|
895
1004
|
break;
|
896
1005
|
|
1006
|
+
case 14:
|
1007
|
+
if (str14icmp(m, 'z', 'r', 'e', 'm', 'r', 'a', 'n', 'g', 'e', 'b', 'y', 'l', 'e', 'x')) {
|
1008
|
+
r->type = MSG_REQ_REDIS_ZREMRANGEBYLEX;
|
1009
|
+
break;
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
break;
|
1013
|
+
|
897
1014
|
case 15:
|
898
1015
|
if (str15icmp(m, 'z', 'r', 'e', 'm', 'r', 'a', 'n', 'g', 'e', 'b', 'y', 'r', 'a', 'n', 'k')) {
|
899
1016
|
r->type = MSG_REQ_REDIS_ZREMRANGEBYRANK;
|
@@ -932,7 +1049,9 @@ redis_parse_req(struct msg *r)
|
|
932
1049
|
case SW_REQ_TYPE_LF:
|
933
1050
|
switch (ch) {
|
934
1051
|
case LF:
|
935
|
-
if (
|
1052
|
+
if (redis_argz(r)) {
|
1053
|
+
goto done;
|
1054
|
+
} else if (redis_argeval(r)) {
|
936
1055
|
state = SW_ARG1_LEN;
|
937
1056
|
} else {
|
938
1057
|
state = SW_KEY_LEN;
|
@@ -1005,17 +1124,23 @@ redis_parse_req(struct msg *r)
|
|
1005
1124
|
|
1006
1125
|
if (*m != CR) {
|
1007
1126
|
goto error;
|
1008
|
-
}
|
1127
|
+
} else { /* got a key */
|
1128
|
+
struct keypos *kpos;
|
1009
1129
|
|
1010
|
-
|
1011
|
-
|
1012
|
-
|
1013
|
-
|
1130
|
+
p = m; /* move forward by rlen bytes */
|
1131
|
+
r->rlen = 0;
|
1132
|
+
m = r->token;
|
1133
|
+
r->token = NULL;
|
1014
1134
|
|
1015
|
-
|
1016
|
-
|
1135
|
+
kpos = array_push(r->keys);
|
1136
|
+
if (kpos == NULL) {
|
1137
|
+
goto enomem;
|
1138
|
+
}
|
1139
|
+
kpos->start = m;
|
1140
|
+
kpos->end = p;
|
1017
1141
|
|
1018
|
-
|
1142
|
+
state = SW_KEY_LF;
|
1143
|
+
}
|
1019
1144
|
|
1020
1145
|
break;
|
1021
1146
|
|
@@ -1051,7 +1176,12 @@ redis_parse_req(struct msg *r)
|
|
1051
1176
|
if (r->rnarg == 0) {
|
1052
1177
|
goto done;
|
1053
1178
|
}
|
1054
|
-
state =
|
1179
|
+
state = SW_KEY_LEN;
|
1180
|
+
} else if (redis_argkvx(r)) {
|
1181
|
+
if (r->rnarg == 0) {
|
1182
|
+
goto done;
|
1183
|
+
}
|
1184
|
+
state = SW_ARG1_LEN;
|
1055
1185
|
} else if (redis_argeval(r)) {
|
1056
1186
|
if (r->rnarg == 0) {
|
1057
1187
|
goto done;
|
@@ -1069,10 +1199,6 @@ redis_parse_req(struct msg *r)
|
|
1069
1199
|
|
1070
1200
|
break;
|
1071
1201
|
|
1072
|
-
case SW_FRAGMENT:
|
1073
|
-
r->token = p;
|
1074
|
-
goto fragment;
|
1075
|
-
|
1076
1202
|
case SW_ARG1_LEN:
|
1077
1203
|
if (r->token == NULL) {
|
1078
1204
|
if (ch != '$') {
|
@@ -1155,6 +1281,11 @@ redis_parse_req(struct msg *r)
|
|
1155
1281
|
goto error;
|
1156
1282
|
}
|
1157
1283
|
state = SW_ARG2_LEN;
|
1284
|
+
} else if (redis_argkvx(r)) {
|
1285
|
+
if (r->rnarg == 0) {
|
1286
|
+
goto done;
|
1287
|
+
}
|
1288
|
+
state = SW_KEY_LEN;
|
1158
1289
|
} else {
|
1159
1290
|
goto error;
|
1160
1291
|
}
|
@@ -1387,7 +1518,7 @@ redis_parse_req(struct msg *r)
|
|
1387
1518
|
r->rnarg--;
|
1388
1519
|
r->token = NULL;
|
1389
1520
|
state = SW_ARGN_LEN_LF;
|
1390
|
-
}
|
1521
|
+
} else {
|
1391
1522
|
goto error;
|
1392
1523
|
}
|
1393
1524
|
|
@@ -1468,19 +1599,6 @@ redis_parse_req(struct msg *r)
|
|
1468
1599
|
r->state, r->pos - b->pos, b->last - b->pos);
|
1469
1600
|
return;
|
1470
1601
|
|
1471
|
-
fragment:
|
1472
|
-
ASSERT(p != b->last);
|
1473
|
-
ASSERT(r->token != NULL);
|
1474
|
-
r->pos = r->token;
|
1475
|
-
r->token = NULL;
|
1476
|
-
r->state = state;
|
1477
|
-
r->result = MSG_PARSE_FRAGMENT;
|
1478
|
-
|
1479
|
-
log_hexdump(LOG_VERB, b->pos, mbuf_length(b), "parsed req %"PRIu64" res %d "
|
1480
|
-
"type %d state %d rpos %d of %d", r->id, r->result, r->type,
|
1481
|
-
r->state, r->pos - b->pos, b->last - b->pos);
|
1482
|
-
return;
|
1483
|
-
|
1484
1602
|
done:
|
1485
1603
|
ASSERT(r->type > MSG_UNKNOWN && r->type < MSG_SENTINEL);
|
1486
1604
|
r->pos = p + 1;
|
@@ -1494,6 +1612,15 @@ done:
|
|
1494
1612
|
r->state, r->pos - b->pos, b->last - b->pos);
|
1495
1613
|
return;
|
1496
1614
|
|
1615
|
+
enomem:
|
1616
|
+
r->result = MSG_PARSE_ERROR;
|
1617
|
+
r->state = state;
|
1618
|
+
|
1619
|
+
log_hexdump(LOG_INFO, b->pos, mbuf_length(b), "out of memory on parse req %"PRIu64" "
|
1620
|
+
"res %d type %d state %d", r->id, r->result, r->type, r->state);
|
1621
|
+
|
1622
|
+
return;
|
1623
|
+
|
1497
1624
|
error:
|
1498
1625
|
r->result = MSG_PARSE_ERROR;
|
1499
1626
|
r->state = state;
|
@@ -1789,7 +1916,28 @@ redis_parse_rsp(struct msg *r)
|
|
1789
1916
|
*
|
1790
1917
|
* Here, we only handle a multi bulk reply element that
|
1791
1918
|
* are either integer reply or bulk reply.
|
1919
|
+
*
|
1920
|
+
* there is a special case for sscan/hscan/zscan, these command
|
1921
|
+
* replay a nested multi-bulk with a number and a multi bulk like this:
|
1922
|
+
*
|
1923
|
+
* - mulit-bulk
|
1924
|
+
* - cursor
|
1925
|
+
* - mulit-bulk
|
1926
|
+
* - val1
|
1927
|
+
* - val2
|
1928
|
+
* - val3
|
1929
|
+
*
|
1930
|
+
* in this case, there is only one sub-multi-bulk,
|
1931
|
+
* and it's the last element of parent,
|
1932
|
+
* we can handle it like tail-recursive.
|
1933
|
+
*
|
1792
1934
|
*/
|
1935
|
+
if (ch == '*') { /* for sscan/hscan/zscan only */
|
1936
|
+
p = p - 1; /* go back by 1 byte */
|
1937
|
+
state = SW_MULTIBULK;
|
1938
|
+
break;
|
1939
|
+
}
|
1940
|
+
|
1793
1941
|
if (ch != '$' && ch != ':') {
|
1794
1942
|
goto error;
|
1795
1943
|
}
|
@@ -1813,7 +1961,6 @@ redis_parse_rsp(struct msg *r)
|
|
1813
1961
|
}
|
1814
1962
|
r->rnarg--;
|
1815
1963
|
r->token = NULL;
|
1816
|
-
|
1817
1964
|
} else {
|
1818
1965
|
goto error;
|
1819
1966
|
}
|
@@ -1916,77 +2063,77 @@ error:
|
|
1916
2063
|
}
|
1917
2064
|
|
1918
2065
|
/*
|
1919
|
-
*
|
1920
|
-
*
|
1921
|
-
|
1922
|
-
|
1923
|
-
|
2066
|
+
* copy one bulk from src to dst
|
2067
|
+
*
|
2068
|
+
* if dst == NULL, we just eat the bulk
|
2069
|
+
*
|
2070
|
+
* */
|
2071
|
+
static rstatus_t
|
2072
|
+
redis_copy_bulk(struct msg *dst, struct msg *src)
|
1924
2073
|
{
|
1925
|
-
struct
|
1926
|
-
|
1927
|
-
|
1928
|
-
|
1929
|
-
|
1930
|
-
|
1931
|
-
|
1932
|
-
|
1933
|
-
|
1934
|
-
|
1935
|
-
|
1936
|
-
|
1937
|
-
|
1938
|
-
case MSG_REQ_REDIS_DEL:
|
1939
|
-
n = nc_snprintf(mbuf->last, mbuf_size(mbuf), "*%d\r\n$3\r\ndel\r\n",
|
1940
|
-
r->narg - 1);
|
1941
|
-
break;
|
1942
|
-
|
1943
|
-
default:
|
1944
|
-
n = 0;
|
1945
|
-
NOT_REACHED();
|
2074
|
+
struct mbuf *mbuf, *nbuf;
|
2075
|
+
uint8_t *p;
|
2076
|
+
uint32_t len = 0;
|
2077
|
+
uint32_t bytes = 0;
|
2078
|
+
rstatus_t status;
|
2079
|
+
|
2080
|
+
for (mbuf = STAILQ_FIRST(&src->mhdr);
|
2081
|
+
mbuf && mbuf_empty(mbuf);
|
2082
|
+
mbuf = STAILQ_FIRST(&src->mhdr)) {
|
2083
|
+
|
2084
|
+
mbuf_remove(&src->mhdr, mbuf);
|
2085
|
+
mbuf_put(mbuf);
|
1946
2086
|
}
|
1947
2087
|
|
1948
|
-
mbuf
|
1949
|
-
|
1950
|
-
|
1951
|
-
/*
|
1952
|
-
* Post-split copy handler invoked when the request is a multi vector -
|
1953
|
-
* 'mget' or 'del' request and has already been split into two requests
|
1954
|
-
*/
|
1955
|
-
rstatus_t
|
1956
|
-
redis_post_splitcopy(struct msg *r)
|
1957
|
-
{
|
1958
|
-
struct mbuf *hbuf, *nhbuf; /* head mbuf and new head mbuf */
|
1959
|
-
struct string hstr = string("*2"); /* header string */
|
1960
|
-
|
1961
|
-
ASSERT(r->request);
|
1962
|
-
ASSERT(r->type == MSG_REQ_REDIS_MGET || r->type == MSG_REQ_REDIS_DEL);
|
1963
|
-
ASSERT(!STAILQ_EMPTY(&r->mhdr));
|
1964
|
-
|
1965
|
-
nhbuf = mbuf_get();
|
1966
|
-
if (nhbuf == NULL) {
|
1967
|
-
return NC_ENOMEM;
|
2088
|
+
mbuf = STAILQ_FIRST(&src->mhdr);
|
2089
|
+
if (mbuf == NULL) {
|
2090
|
+
return NC_ERROR;
|
1968
2091
|
}
|
1969
2092
|
|
1970
|
-
|
1971
|
-
|
1972
|
-
|
1973
|
-
*/
|
1974
|
-
hbuf = STAILQ_FIRST(&r->mhdr);
|
1975
|
-
ASSERT(hbuf->pos == r->narg_start);
|
1976
|
-
ASSERT(hbuf->pos < r->narg_end && r->narg_end <= hbuf->last);
|
1977
|
-
hbuf->pos = r->narg_end;
|
1978
|
-
|
1979
|
-
/*
|
1980
|
-
* Add a new head mbuf in the head (A) msg that just contains '*2'
|
1981
|
-
* token
|
1982
|
-
*/
|
1983
|
-
STAILQ_INSERT_HEAD(&r->mhdr, nhbuf, next);
|
1984
|
-
mbuf_copy(nhbuf, hstr.data, hstr.len);
|
2093
|
+
p = mbuf->pos;
|
2094
|
+
ASSERT(*p == '$');
|
2095
|
+
p++;
|
1985
2096
|
|
1986
|
-
|
1987
|
-
|
1988
|
-
|
2097
|
+
if (p[0] == '-' && p[1] == '1') {
|
2098
|
+
len = 1 + 2 + CRLF_LEN; /* $-1\r\n */
|
2099
|
+
p = mbuf->pos + len;
|
2100
|
+
} else {
|
2101
|
+
len = 0;
|
2102
|
+
for (; p < mbuf->last && isdigit(*p); p++) {
|
2103
|
+
len = len * 10 + (uint32_t)(*p - '0');
|
2104
|
+
}
|
2105
|
+
len += CRLF_LEN * 2;
|
2106
|
+
len += (p - mbuf->pos);
|
2107
|
+
}
|
2108
|
+
bytes = len;
|
2109
|
+
|
2110
|
+
/* copy len bytes to dst */
|
2111
|
+
for (; mbuf;) {
|
2112
|
+
if (mbuf_length(mbuf) <= len) { /* steal this buf from src to dst */
|
2113
|
+
nbuf = STAILQ_NEXT(mbuf, next);
|
2114
|
+
mbuf_remove(&src->mhdr, mbuf);
|
2115
|
+
if (dst != NULL) {
|
2116
|
+
mbuf_insert(&dst->mhdr, mbuf);
|
2117
|
+
}
|
2118
|
+
len -= mbuf_length(mbuf);
|
2119
|
+
mbuf = nbuf;
|
2120
|
+
} else { /* split it */
|
2121
|
+
if (dst != NULL) {
|
2122
|
+
status = msg_append(dst, mbuf->pos, len);
|
2123
|
+
if (status != NC_OK) {
|
2124
|
+
return status;
|
2125
|
+
}
|
2126
|
+
}
|
2127
|
+
mbuf->pos += len;
|
2128
|
+
break;
|
2129
|
+
}
|
2130
|
+
}
|
1989
2131
|
|
2132
|
+
if (dst != NULL) {
|
2133
|
+
dst->mlen += bytes;
|
2134
|
+
}
|
2135
|
+
src->mlen -= bytes;
|
2136
|
+
log_debug(LOG_VVERB, "redis_copy_bulk copy bytes: %d", bytes);
|
1990
2137
|
return NC_OK;
|
1991
2138
|
}
|
1992
2139
|
|
@@ -2008,6 +2155,7 @@ redis_pre_coalesce(struct msg *r)
|
|
2008
2155
|
/* do nothing, if not a response to a fragmented request */
|
2009
2156
|
return;
|
2010
2157
|
}
|
2158
|
+
pr->frag_owner->nfrag_done++;
|
2011
2159
|
|
2012
2160
|
switch (r->type) {
|
2013
2161
|
case MSG_RSP_REDIS_INTEGER:
|
@@ -2049,14 +2197,13 @@ redis_pre_coalesce(struct msg *r)
|
|
2049
2197
|
r->mlen -= (uint32_t)(r->narg_end - r->narg_start);
|
2050
2198
|
mbuf->pos = r->narg_end;
|
2051
2199
|
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
|
2056
|
-
|
2057
|
-
|
2058
|
-
|
2059
|
-
STAILQ_INSERT_HEAD(&r->mhdr, mbuf, next);
|
2200
|
+
break;
|
2201
|
+
|
2202
|
+
case MSG_RSP_REDIS_STATUS:
|
2203
|
+
if (pr->type == MSG_REQ_REDIS_MSET) { /* MSET segments */
|
2204
|
+
mbuf = STAILQ_FIRST(&r->mhdr);
|
2205
|
+
r->mlen -= mbuf_length(mbuf);
|
2206
|
+
mbuf_rewind(mbuf);
|
2060
2207
|
}
|
2061
2208
|
break;
|
2062
2209
|
|
@@ -2075,6 +2222,309 @@ redis_pre_coalesce(struct msg *r)
|
|
2075
2222
|
}
|
2076
2223
|
}
|
2077
2224
|
|
2225
|
+
static rstatus_t
|
2226
|
+
redis_append_key(struct msg *r, uint8_t *key, uint32_t keylen)
|
2227
|
+
{
|
2228
|
+
uint32_t len;
|
2229
|
+
struct mbuf *mbuf;
|
2230
|
+
uint8_t printbuf[32];
|
2231
|
+
struct keypos *kpos;
|
2232
|
+
|
2233
|
+
/* 1. keylen */
|
2234
|
+
len = (uint32_t)nc_snprintf(printbuf, sizeof(printbuf), "$%d\r\n", keylen);
|
2235
|
+
mbuf = msg_ensure_mbuf(r, len);
|
2236
|
+
if (mbuf == NULL) {
|
2237
|
+
return NC_ENOMEM;
|
2238
|
+
}
|
2239
|
+
mbuf_copy(mbuf, printbuf, len);
|
2240
|
+
r->mlen += len;
|
2241
|
+
|
2242
|
+
/* 2. key */
|
2243
|
+
mbuf = msg_ensure_mbuf(r, keylen);
|
2244
|
+
if (mbuf == NULL) {
|
2245
|
+
return NC_ENOMEM;
|
2246
|
+
}
|
2247
|
+
|
2248
|
+
kpos = array_push(r->keys);
|
2249
|
+
if (kpos == NULL) {
|
2250
|
+
return NC_ENOMEM;
|
2251
|
+
}
|
2252
|
+
|
2253
|
+
kpos->start = mbuf->last;
|
2254
|
+
kpos->end = mbuf->last + keylen;
|
2255
|
+
mbuf_copy(mbuf, key, keylen);
|
2256
|
+
r->mlen += keylen;
|
2257
|
+
|
2258
|
+
/* 3. CRLF */
|
2259
|
+
mbuf = msg_ensure_mbuf(r, CRLF_LEN);
|
2260
|
+
if (mbuf == NULL) {
|
2261
|
+
return NC_ENOMEM;
|
2262
|
+
}
|
2263
|
+
mbuf_copy(mbuf, (uint8_t *)CRLF, CRLF_LEN);
|
2264
|
+
r->mlen += (uint32_t)CRLF_LEN;
|
2265
|
+
|
2266
|
+
return NC_OK;
|
2267
|
+
}
|
2268
|
+
|
2269
|
+
/*
|
2270
|
+
* input a msg, return a msg chain.
|
2271
|
+
* ncontinuum is the number of backend redis/memcache server
|
2272
|
+
*
|
2273
|
+
* the original msg will be fragment into at most ncontinuum fragments.
|
2274
|
+
* all the keys map to the same backend will group into one fragment.
|
2275
|
+
*
|
2276
|
+
* frag_id:
|
2277
|
+
* a unique fragment id for all fragments of the message vector. including the orig msg.
|
2278
|
+
*
|
2279
|
+
* frag_owner:
|
2280
|
+
* All fragments of the message use frag_owner point to the orig msg
|
2281
|
+
*
|
2282
|
+
* frag_seq:
|
2283
|
+
* the map from each key to it's fragment, (only in the orig msg)
|
2284
|
+
*
|
2285
|
+
* For example, a message vector with 3 keys:
|
2286
|
+
*
|
2287
|
+
* get key1 key2 key3
|
2288
|
+
*
|
2289
|
+
* suppose we have 2 backend server, and the map is:
|
2290
|
+
*
|
2291
|
+
* key1 => backend 0
|
2292
|
+
* key2 => backend 1
|
2293
|
+
* key3 => backend 0
|
2294
|
+
*
|
2295
|
+
* it will fragment like this:
|
2296
|
+
*
|
2297
|
+
* +-----------------+
|
2298
|
+
* | msg vector |
|
2299
|
+
* |(original msg) |
|
2300
|
+
* |key1, key2, key3 |
|
2301
|
+
* +-----------------+
|
2302
|
+
*
|
2303
|
+
* frag_owner
|
2304
|
+
* /--------------------------------------+
|
2305
|
+
* frag_owner / |
|
2306
|
+
* /-----------+ | /------------+ frag_owner |
|
2307
|
+
* | | | | | |
|
2308
|
+
* | v v v | |
|
2309
|
+
* +--------------------+ +---------------------+ +----+----------------+
|
2310
|
+
* | frag_id = 10 | | frag_id = 10 | | frag_id = 10 |
|
2311
|
+
* | nfrag = 3 | | nfrag = 0 | | nfrag = 0 |
|
2312
|
+
* | frag_seq = x x x | | key1, key3 | | key2 |
|
2313
|
+
* +------------|-|-|---+ +---------------------+ +---------------------+
|
2314
|
+
* | | | ^ ^ ^
|
2315
|
+
* | \ \ | | |
|
2316
|
+
* | \ ----------+ | |
|
2317
|
+
* +---\---------------+ |
|
2318
|
+
* ------------------------------------------+
|
2319
|
+
*
|
2320
|
+
*/
|
2321
|
+
static rstatus_t
|
2322
|
+
redis_fragment_argx(struct msg *r, uint32_t ncontinuum, struct msg_tqh *frag_msgq,
|
2323
|
+
uint32_t key_step)
|
2324
|
+
{
|
2325
|
+
struct mbuf *mbuf;
|
2326
|
+
struct msg **sub_msgs;
|
2327
|
+
uint32_t i;
|
2328
|
+
rstatus_t status;
|
2329
|
+
|
2330
|
+
ASSERT(array_n(r->keys) == (r->narg - 1) / key_step);
|
2331
|
+
|
2332
|
+
sub_msgs = nc_zalloc(ncontinuum * sizeof(*sub_msgs));
|
2333
|
+
if (sub_msgs == NULL) {
|
2334
|
+
return NC_ENOMEM;
|
2335
|
+
}
|
2336
|
+
|
2337
|
+
ASSERT(r->frag_seq == NULL);
|
2338
|
+
r->frag_seq = nc_alloc(array_n(r->keys) * sizeof(*r->frag_seq));
|
2339
|
+
if (r->frag_seq == NULL) {
|
2340
|
+
nc_free(sub_msgs);
|
2341
|
+
return NC_ENOMEM;
|
2342
|
+
}
|
2343
|
+
|
2344
|
+
mbuf = STAILQ_FIRST(&r->mhdr);
|
2345
|
+
mbuf->pos = mbuf->start;
|
2346
|
+
|
2347
|
+
/*
|
2348
|
+
* This code is based on the assumption that '*narg\r\n$4\r\nMGET\r\n' is located
|
2349
|
+
* in a contiguous location.
|
2350
|
+
* This is always true because we have capped our MBUF_MIN_SIZE at 512 and
|
2351
|
+
* whenever we have multiple messages, we copy the tail message into a new mbuf
|
2352
|
+
*/
|
2353
|
+
for (i = 0; i < 3; i++) { /* eat *narg\r\n$4\r\nMGET\r\n */
|
2354
|
+
for (; *(mbuf->pos) != '\n';) {
|
2355
|
+
mbuf->pos++;
|
2356
|
+
}
|
2357
|
+
mbuf->pos++;
|
2358
|
+
}
|
2359
|
+
|
2360
|
+
r->frag_id = msg_gen_frag_id();
|
2361
|
+
r->nfrag = 0;
|
2362
|
+
r->frag_owner = r;
|
2363
|
+
|
2364
|
+
for (i = 0; i < array_n(r->keys); i++) { /* for each key */
|
2365
|
+
struct msg *sub_msg;
|
2366
|
+
struct keypos *kpos = array_get(r->keys, i);
|
2367
|
+
uint32_t idx = msg_backend_idx(r, kpos->start, kpos->end - kpos->start);
|
2368
|
+
|
2369
|
+
if (sub_msgs[idx] == NULL) {
|
2370
|
+
sub_msgs[idx] = msg_get(r->owner, r->request, r->redis);
|
2371
|
+
if (sub_msgs[idx] == NULL) {
|
2372
|
+
nc_free(sub_msgs);
|
2373
|
+
return NC_ENOMEM;
|
2374
|
+
}
|
2375
|
+
}
|
2376
|
+
r->frag_seq[i] = sub_msg = sub_msgs[idx];
|
2377
|
+
|
2378
|
+
sub_msg->narg++;
|
2379
|
+
status = redis_append_key(sub_msg, kpos->start, kpos->end - kpos->start);
|
2380
|
+
if (status != NC_OK) {
|
2381
|
+
nc_free(sub_msgs);
|
2382
|
+
return status;
|
2383
|
+
}
|
2384
|
+
|
2385
|
+
if (key_step == 1) { /* mget,del */
|
2386
|
+
continue;
|
2387
|
+
} else { /* mset */
|
2388
|
+
status = redis_copy_bulk(NULL, r); /* eat key */
|
2389
|
+
if (status != NC_OK) {
|
2390
|
+
nc_free(sub_msgs);
|
2391
|
+
return status;
|
2392
|
+
}
|
2393
|
+
|
2394
|
+
status = redis_copy_bulk(sub_msg, r);
|
2395
|
+
if (status != NC_OK) {
|
2396
|
+
nc_free(sub_msgs);
|
2397
|
+
return status;
|
2398
|
+
}
|
2399
|
+
|
2400
|
+
sub_msg->narg++;
|
2401
|
+
}
|
2402
|
+
}
|
2403
|
+
|
2404
|
+
for (i = 0; i < ncontinuum; i++) { /* prepend mget header, and forward it */
|
2405
|
+
struct msg *sub_msg = sub_msgs[i];
|
2406
|
+
if (sub_msg == NULL) {
|
2407
|
+
continue;
|
2408
|
+
}
|
2409
|
+
|
2410
|
+
if (r->type == MSG_REQ_REDIS_MGET) {
|
2411
|
+
status = msg_prepend_format(sub_msg, "*%d\r\n$4\r\nmget\r\n",
|
2412
|
+
sub_msg->narg + 1);
|
2413
|
+
} else if (r->type == MSG_REQ_REDIS_DEL) {
|
2414
|
+
status = msg_prepend_format(sub_msg, "*%d\r\n$3\r\ndel\r\n",
|
2415
|
+
sub_msg->narg + 1);
|
2416
|
+
} else if (r->type == MSG_REQ_REDIS_MSET) {
|
2417
|
+
status = msg_prepend_format(sub_msg, "*%d\r\n$4\r\nmset\r\n",
|
2418
|
+
sub_msg->narg + 1);
|
2419
|
+
} else {
|
2420
|
+
NOT_REACHED();
|
2421
|
+
}
|
2422
|
+
if (status != NC_OK) {
|
2423
|
+
nc_free(sub_msgs);
|
2424
|
+
return status;
|
2425
|
+
}
|
2426
|
+
|
2427
|
+
sub_msg->type = r->type;
|
2428
|
+
sub_msg->frag_id = r->frag_id;
|
2429
|
+
sub_msg->frag_owner = r->frag_owner;
|
2430
|
+
|
2431
|
+
TAILQ_INSERT_TAIL(frag_msgq, sub_msg, m_tqe);
|
2432
|
+
r->nfrag++;
|
2433
|
+
}
|
2434
|
+
|
2435
|
+
nc_free(sub_msgs);
|
2436
|
+
return NC_OK;
|
2437
|
+
}
|
2438
|
+
|
2439
|
+
rstatus_t
|
2440
|
+
redis_fragment(struct msg *r, uint32_t ncontinuum, struct msg_tqh *frag_msgq)
|
2441
|
+
{
|
2442
|
+
switch (r->type) {
|
2443
|
+
case MSG_REQ_REDIS_MGET:
|
2444
|
+
case MSG_REQ_REDIS_DEL:
|
2445
|
+
return redis_fragment_argx(r, ncontinuum, frag_msgq, 1);
|
2446
|
+
case MSG_REQ_REDIS_MSET:
|
2447
|
+
return redis_fragment_argx(r, ncontinuum, frag_msgq, 2);
|
2448
|
+
default:
|
2449
|
+
return NC_OK;
|
2450
|
+
}
|
2451
|
+
}
|
2452
|
+
|
2453
|
+
rstatus_t
|
2454
|
+
redis_reply(struct msg *r)
|
2455
|
+
{
|
2456
|
+
struct msg *response = r->peer;
|
2457
|
+
|
2458
|
+
ASSERT(response != NULL);
|
2459
|
+
|
2460
|
+
switch (r->type) {
|
2461
|
+
case MSG_REQ_REDIS_PING:
|
2462
|
+
return msg_append(response, (uint8_t *)"+PONG\r\n", 7);
|
2463
|
+
|
2464
|
+
default:
|
2465
|
+
NOT_REACHED();
|
2466
|
+
return NC_ERROR;
|
2467
|
+
}
|
2468
|
+
}
|
2469
|
+
|
2470
|
+
void
|
2471
|
+
redis_post_coalesce_mset(struct msg *request)
|
2472
|
+
{
|
2473
|
+
struct msg *response = request->peer;
|
2474
|
+
rstatus_t status;
|
2475
|
+
|
2476
|
+
status = msg_append(response, (uint8_t *)"+OK\r\n", 5);
|
2477
|
+
if (status != NC_OK) {
|
2478
|
+
response->error = 1; /* mark this msg as err */
|
2479
|
+
response->err = errno;
|
2480
|
+
}
|
2481
|
+
}
|
2482
|
+
|
2483
|
+
void
|
2484
|
+
redis_post_coalesce_del(struct msg *request)
|
2485
|
+
{
|
2486
|
+
struct msg *response = request->peer;
|
2487
|
+
rstatus_t status;
|
2488
|
+
|
2489
|
+
status = msg_prepend_format(response, ":%d\r\n", request->integer);
|
2490
|
+
if (status != NC_OK) {
|
2491
|
+
response->error = 1;
|
2492
|
+
response->err = errno;
|
2493
|
+
}
|
2494
|
+
}
|
2495
|
+
|
2496
|
+
static void
|
2497
|
+
redis_post_coalesce_mget(struct msg *request)
|
2498
|
+
{
|
2499
|
+
struct msg *response = request->peer;
|
2500
|
+
struct msg *sub_msg;
|
2501
|
+
rstatus_t status;
|
2502
|
+
uint32_t i;
|
2503
|
+
|
2504
|
+
status = msg_prepend_format(response, "*%d\r\n", request->narg - 1);
|
2505
|
+
if (status != NC_OK) {
|
2506
|
+
/*
|
2507
|
+
* the fragments is still in c_conn->omsg_q, we have to discard all of them,
|
2508
|
+
* we just close the conn here
|
2509
|
+
*/
|
2510
|
+
response->owner->err = 1;
|
2511
|
+
return;
|
2512
|
+
}
|
2513
|
+
|
2514
|
+
for (i = 0; i < array_n(request->keys); i++) { /* for each key */
|
2515
|
+
sub_msg = request->frag_seq[i]->peer; /* get it's peer response */
|
2516
|
+
if (sub_msg == NULL) {
|
2517
|
+
response->owner->err = 1;
|
2518
|
+
return;
|
2519
|
+
}
|
2520
|
+
status = redis_copy_bulk(response, sub_msg);
|
2521
|
+
if (status != NC_OK) {
|
2522
|
+
response->owner->err = 1;
|
2523
|
+
return;
|
2524
|
+
}
|
2525
|
+
}
|
2526
|
+
}
|
2527
|
+
|
2078
2528
|
/*
|
2079
2529
|
* Post-coalesce handler is invoked when the message is a response to
|
2080
2530
|
* the fragmented multi vector request - 'mget' or 'del' and all the
|
@@ -2085,44 +2535,21 @@ void
|
|
2085
2535
|
redis_post_coalesce(struct msg *r)
|
2086
2536
|
{
|
2087
2537
|
struct msg *pr = r->peer; /* peer response */
|
2088
|
-
struct mbuf *mbuf;
|
2089
|
-
int n;
|
2090
2538
|
|
2091
|
-
ASSERT(
|
2539
|
+
ASSERT(!pr->request);
|
2540
|
+
ASSERT(r->request && (r->frag_owner == r));
|
2092
2541
|
if (r->error || r->ferror) {
|
2093
2542
|
/* do nothing, if msg is in error */
|
2094
2543
|
return;
|
2095
2544
|
}
|
2096
2545
|
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
case
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
2104
|
-
mbuf = STAILQ_FIRST(&pr->mhdr);
|
2105
|
-
|
2106
|
-
ASSERT(pr->mlen == 0);
|
2107
|
-
ASSERT(mbuf_empty(mbuf));
|
2108
|
-
|
2109
|
-
n = nc_scnprintf(mbuf->last, mbuf_size(mbuf), ":%d\r\n", r->integer);
|
2110
|
-
mbuf->last += n;
|
2111
|
-
pr->mlen += (uint32_t)n;
|
2112
|
-
break;
|
2113
|
-
|
2114
|
-
case MSG_RSP_REDIS_MULTIBULK:
|
2115
|
-
/* only redis 'mget' fragmented request sends back multi-bulk reply */
|
2116
|
-
ASSERT(r->type == MSG_REQ_REDIS_MGET);
|
2117
|
-
|
2118
|
-
mbuf = STAILQ_FIRST(&pr->mhdr);
|
2119
|
-
ASSERT(mbuf_empty(mbuf));
|
2120
|
-
|
2121
|
-
n = nc_scnprintf(mbuf->last, mbuf_size(mbuf), "*%d\r\n", r->nfrag);
|
2122
|
-
mbuf->last += n;
|
2123
|
-
pr->mlen += (uint32_t)n;
|
2124
|
-
break;
|
2125
|
-
|
2546
|
+
switch (r->type) {
|
2547
|
+
case MSG_REQ_REDIS_MGET:
|
2548
|
+
return redis_post_coalesce_mget(r);
|
2549
|
+
case MSG_REQ_REDIS_DEL:
|
2550
|
+
return redis_post_coalesce_del(r);
|
2551
|
+
case MSG_REQ_REDIS_MSET:
|
2552
|
+
return redis_post_coalesce_mset(r);
|
2126
2553
|
default:
|
2127
2554
|
NOT_REACHED();
|
2128
2555
|
}
|