nutcracker 0.3.0.12 → 0.4.0.13
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 +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
|
}
|