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
|
@@ -21,139 +21,163 @@
|
|
|
21
21
|
#include <nc_core.h>
|
|
22
22
|
|
|
23
23
|
typedef void (*msg_parse_t)(struct msg *);
|
|
24
|
-
typedef rstatus_t (*
|
|
24
|
+
typedef rstatus_t (*msg_fragment_t)(struct msg *, uint32_t, struct msg_tqh *);
|
|
25
25
|
typedef void (*msg_coalesce_t)(struct msg *r);
|
|
26
|
+
typedef rstatus_t (*msg_reply_t)(struct msg *r);
|
|
26
27
|
|
|
27
28
|
typedef enum msg_parse_result {
|
|
28
29
|
MSG_PARSE_OK, /* parsing ok */
|
|
29
30
|
MSG_PARSE_ERROR, /* parsing error */
|
|
30
31
|
MSG_PARSE_REPAIR, /* more to parse -> repair parsed & unparsed data */
|
|
31
|
-
MSG_PARSE_FRAGMENT, /* multi-vector request -> fragment */
|
|
32
32
|
MSG_PARSE_AGAIN, /* incomplete -> parse again */
|
|
33
33
|
} msg_parse_result_t;
|
|
34
34
|
|
|
35
|
+
#define MSG_TYPE_CODEC(ACTION) \
|
|
36
|
+
ACTION( UNKNOWN ) \
|
|
37
|
+
ACTION( REQ_MC_GET ) /* memcache retrieval requests */ \
|
|
38
|
+
ACTION( REQ_MC_GETS ) \
|
|
39
|
+
ACTION( REQ_MC_DELETE ) /* memcache delete request */ \
|
|
40
|
+
ACTION( REQ_MC_CAS ) /* memcache cas request and storage request */ \
|
|
41
|
+
ACTION( REQ_MC_SET ) /* memcache storage request */ \
|
|
42
|
+
ACTION( REQ_MC_ADD ) \
|
|
43
|
+
ACTION( REQ_MC_REPLACE ) \
|
|
44
|
+
ACTION( REQ_MC_APPEND ) \
|
|
45
|
+
ACTION( REQ_MC_PREPEND ) \
|
|
46
|
+
ACTION( REQ_MC_INCR ) /* memcache arithmetic request */ \
|
|
47
|
+
ACTION( REQ_MC_DECR ) \
|
|
48
|
+
ACTION( REQ_MC_QUIT ) /* memcache quit request */ \
|
|
49
|
+
ACTION( RSP_MC_NUM ) /* memcache arithmetic response */ \
|
|
50
|
+
ACTION( RSP_MC_STORED ) /* memcache cas and storage response */ \
|
|
51
|
+
ACTION( RSP_MC_NOT_STORED ) \
|
|
52
|
+
ACTION( RSP_MC_EXISTS ) \
|
|
53
|
+
ACTION( RSP_MC_NOT_FOUND ) \
|
|
54
|
+
ACTION( RSP_MC_END ) \
|
|
55
|
+
ACTION( RSP_MC_VALUE ) \
|
|
56
|
+
ACTION( RSP_MC_DELETED ) /* memcache delete response */ \
|
|
57
|
+
ACTION( RSP_MC_ERROR ) /* memcache error responses */ \
|
|
58
|
+
ACTION( RSP_MC_CLIENT_ERROR ) \
|
|
59
|
+
ACTION( RSP_MC_SERVER_ERROR ) \
|
|
60
|
+
ACTION( REQ_REDIS_DEL ) /* redis commands - keys */ \
|
|
61
|
+
ACTION( REQ_REDIS_EXISTS ) \
|
|
62
|
+
ACTION( REQ_REDIS_EXPIRE ) \
|
|
63
|
+
ACTION( REQ_REDIS_EXPIREAT ) \
|
|
64
|
+
ACTION( REQ_REDIS_PEXPIRE ) \
|
|
65
|
+
ACTION( REQ_REDIS_PEXPIREAT ) \
|
|
66
|
+
ACTION( REQ_REDIS_PERSIST ) \
|
|
67
|
+
ACTION( REQ_REDIS_PTTL ) \
|
|
68
|
+
ACTION( REQ_REDIS_SORT ) \
|
|
69
|
+
ACTION( REQ_REDIS_TTL ) \
|
|
70
|
+
ACTION( REQ_REDIS_TYPE ) \
|
|
71
|
+
ACTION( REQ_REDIS_APPEND ) /* redis requests - string */ \
|
|
72
|
+
ACTION( REQ_REDIS_BITCOUNT ) \
|
|
73
|
+
ACTION( REQ_REDIS_DECR ) \
|
|
74
|
+
ACTION( REQ_REDIS_DECRBY ) \
|
|
75
|
+
ACTION( REQ_REDIS_DUMP ) \
|
|
76
|
+
ACTION( REQ_REDIS_GET ) \
|
|
77
|
+
ACTION( REQ_REDIS_GETBIT ) \
|
|
78
|
+
ACTION( REQ_REDIS_GETRANGE ) \
|
|
79
|
+
ACTION( REQ_REDIS_GETSET ) \
|
|
80
|
+
ACTION( REQ_REDIS_INCR ) \
|
|
81
|
+
ACTION( REQ_REDIS_INCRBY ) \
|
|
82
|
+
ACTION( REQ_REDIS_INCRBYFLOAT ) \
|
|
83
|
+
ACTION( REQ_REDIS_MGET ) \
|
|
84
|
+
ACTION( REQ_REDIS_MSET ) \
|
|
85
|
+
ACTION( REQ_REDIS_PSETEX ) \
|
|
86
|
+
ACTION( REQ_REDIS_RESTORE ) \
|
|
87
|
+
ACTION( REQ_REDIS_SET ) \
|
|
88
|
+
ACTION( REQ_REDIS_SETBIT ) \
|
|
89
|
+
ACTION( REQ_REDIS_SETEX ) \
|
|
90
|
+
ACTION( REQ_REDIS_SETNX ) \
|
|
91
|
+
ACTION( REQ_REDIS_SETRANGE ) \
|
|
92
|
+
ACTION( REQ_REDIS_STRLEN ) \
|
|
93
|
+
ACTION( REQ_REDIS_HDEL ) /* redis requests - hashes */ \
|
|
94
|
+
ACTION( REQ_REDIS_HEXISTS ) \
|
|
95
|
+
ACTION( REQ_REDIS_HGET ) \
|
|
96
|
+
ACTION( REQ_REDIS_HGETALL ) \
|
|
97
|
+
ACTION( REQ_REDIS_HINCRBY ) \
|
|
98
|
+
ACTION( REQ_REDIS_HINCRBYFLOAT ) \
|
|
99
|
+
ACTION( REQ_REDIS_HKEYS ) \
|
|
100
|
+
ACTION( REQ_REDIS_HLEN ) \
|
|
101
|
+
ACTION( REQ_REDIS_HMGET ) \
|
|
102
|
+
ACTION( REQ_REDIS_HMSET ) \
|
|
103
|
+
ACTION( REQ_REDIS_HSET ) \
|
|
104
|
+
ACTION( REQ_REDIS_HSETNX ) \
|
|
105
|
+
ACTION( REQ_REDIS_HSCAN) \
|
|
106
|
+
ACTION( REQ_REDIS_HVALS ) \
|
|
107
|
+
ACTION( REQ_REDIS_LINDEX ) /* redis requests - lists */ \
|
|
108
|
+
ACTION( REQ_REDIS_LINSERT ) \
|
|
109
|
+
ACTION( REQ_REDIS_LLEN ) \
|
|
110
|
+
ACTION( REQ_REDIS_LPOP ) \
|
|
111
|
+
ACTION( REQ_REDIS_LPUSH ) \
|
|
112
|
+
ACTION( REQ_REDIS_LPUSHX ) \
|
|
113
|
+
ACTION( REQ_REDIS_LRANGE ) \
|
|
114
|
+
ACTION( REQ_REDIS_LREM ) \
|
|
115
|
+
ACTION( REQ_REDIS_LSET ) \
|
|
116
|
+
ACTION( REQ_REDIS_LTRIM ) \
|
|
117
|
+
ACTION( REQ_REDIS_PFADD ) /* redis requests - hyperloglog */ \
|
|
118
|
+
ACTION( REQ_REDIS_PFCOUNT ) \
|
|
119
|
+
ACTION( REQ_REDIS_PFMERGE ) \
|
|
120
|
+
ACTION( REQ_REDIS_RPOP ) \
|
|
121
|
+
ACTION( REQ_REDIS_RPOPLPUSH ) \
|
|
122
|
+
ACTION( REQ_REDIS_RPUSH ) \
|
|
123
|
+
ACTION( REQ_REDIS_RPUSHX ) \
|
|
124
|
+
ACTION( REQ_REDIS_SADD ) /* redis requests - sets */ \
|
|
125
|
+
ACTION( REQ_REDIS_SCARD ) \
|
|
126
|
+
ACTION( REQ_REDIS_SDIFF ) \
|
|
127
|
+
ACTION( REQ_REDIS_SDIFFSTORE ) \
|
|
128
|
+
ACTION( REQ_REDIS_SINTER ) \
|
|
129
|
+
ACTION( REQ_REDIS_SINTERSTORE ) \
|
|
130
|
+
ACTION( REQ_REDIS_SISMEMBER ) \
|
|
131
|
+
ACTION( REQ_REDIS_SMEMBERS ) \
|
|
132
|
+
ACTION( REQ_REDIS_SMOVE ) \
|
|
133
|
+
ACTION( REQ_REDIS_SPOP ) \
|
|
134
|
+
ACTION( REQ_REDIS_SRANDMEMBER ) \
|
|
135
|
+
ACTION( REQ_REDIS_SREM ) \
|
|
136
|
+
ACTION( REQ_REDIS_SUNION ) \
|
|
137
|
+
ACTION( REQ_REDIS_SUNIONSTORE ) \
|
|
138
|
+
ACTION( REQ_REDIS_SSCAN) \
|
|
139
|
+
ACTION( REQ_REDIS_ZADD ) /* redis requests - sorted sets */ \
|
|
140
|
+
ACTION( REQ_REDIS_ZCARD ) \
|
|
141
|
+
ACTION( REQ_REDIS_ZCOUNT ) \
|
|
142
|
+
ACTION( REQ_REDIS_ZINCRBY ) \
|
|
143
|
+
ACTION( REQ_REDIS_ZINTERSTORE ) \
|
|
144
|
+
ACTION( REQ_REDIS_ZLEXCOUNT ) \
|
|
145
|
+
ACTION( REQ_REDIS_ZRANGE ) \
|
|
146
|
+
ACTION( REQ_REDIS_ZRANGEBYLEX ) \
|
|
147
|
+
ACTION( REQ_REDIS_ZRANGEBYSCORE ) \
|
|
148
|
+
ACTION( REQ_REDIS_ZRANK ) \
|
|
149
|
+
ACTION( REQ_REDIS_ZREM ) \
|
|
150
|
+
ACTION( REQ_REDIS_ZREMRANGEBYRANK ) \
|
|
151
|
+
ACTION( REQ_REDIS_ZREMRANGEBYLEX ) \
|
|
152
|
+
ACTION( REQ_REDIS_ZREMRANGEBYSCORE ) \
|
|
153
|
+
ACTION( REQ_REDIS_ZREVRANGE ) \
|
|
154
|
+
ACTION( REQ_REDIS_ZREVRANGEBYSCORE ) \
|
|
155
|
+
ACTION( REQ_REDIS_ZREVRANK ) \
|
|
156
|
+
ACTION( REQ_REDIS_ZSCORE ) \
|
|
157
|
+
ACTION( REQ_REDIS_ZUNIONSTORE ) \
|
|
158
|
+
ACTION( REQ_REDIS_ZSCAN) \
|
|
159
|
+
ACTION( REQ_REDIS_EVAL ) /* redis requests - eval */ \
|
|
160
|
+
ACTION( REQ_REDIS_EVALSHA ) \
|
|
161
|
+
ACTION( REQ_REDIS_PING ) /* redis requests - ping/quit */ \
|
|
162
|
+
ACTION( REQ_REDIS_QUIT) \
|
|
163
|
+
ACTION( RSP_REDIS_STATUS ) /* redis response */ \
|
|
164
|
+
ACTION( RSP_REDIS_ERROR ) \
|
|
165
|
+
ACTION( RSP_REDIS_INTEGER ) \
|
|
166
|
+
ACTION( RSP_REDIS_BULK ) \
|
|
167
|
+
ACTION( RSP_REDIS_MULTIBULK ) \
|
|
168
|
+
ACTION( SENTINEL ) \
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
#define DEFINE_ACTION(_name) MSG_##_name,
|
|
35
172
|
typedef enum msg_type {
|
|
36
|
-
|
|
37
|
-
MSG_REQ_MC_GET, /* memcache retrieval requests */
|
|
38
|
-
MSG_REQ_MC_GETS,
|
|
39
|
-
MSG_REQ_MC_DELETE, /* memcache delete request */
|
|
40
|
-
MSG_REQ_MC_CAS, /* memcache cas request and storage request */
|
|
41
|
-
MSG_REQ_MC_SET, /* memcache storage request */
|
|
42
|
-
MSG_REQ_MC_ADD,
|
|
43
|
-
MSG_REQ_MC_REPLACE,
|
|
44
|
-
MSG_REQ_MC_APPEND,
|
|
45
|
-
MSG_REQ_MC_PREPEND,
|
|
46
|
-
MSG_REQ_MC_INCR, /* memcache arithmetic request */
|
|
47
|
-
MSG_REQ_MC_DECR,
|
|
48
|
-
MSG_REQ_MC_QUIT, /* memcache quit request */
|
|
49
|
-
MSG_RSP_MC_NUM, /* memcache arithmetic response */
|
|
50
|
-
MSG_RSP_MC_STORED, /* memcache cas and storage response */
|
|
51
|
-
MSG_RSP_MC_NOT_STORED,
|
|
52
|
-
MSG_RSP_MC_EXISTS,
|
|
53
|
-
MSG_RSP_MC_NOT_FOUND,
|
|
54
|
-
MSG_RSP_MC_END,
|
|
55
|
-
MSG_RSP_MC_VALUE,
|
|
56
|
-
MSG_RSP_MC_DELETED, /* memcache delete response */
|
|
57
|
-
MSG_RSP_MC_ERROR, /* memcache error responses */
|
|
58
|
-
MSG_RSP_MC_CLIENT_ERROR,
|
|
59
|
-
MSG_RSP_MC_SERVER_ERROR,
|
|
60
|
-
MSG_REQ_REDIS_DEL, /* redis commands - keys */
|
|
61
|
-
MSG_REQ_REDIS_EXISTS,
|
|
62
|
-
MSG_REQ_REDIS_EXPIRE,
|
|
63
|
-
MSG_REQ_REDIS_EXPIREAT,
|
|
64
|
-
MSG_REQ_REDIS_PEXPIRE,
|
|
65
|
-
MSG_REQ_REDIS_PEXPIREAT,
|
|
66
|
-
MSG_REQ_REDIS_PERSIST,
|
|
67
|
-
MSG_REQ_REDIS_PTTL,
|
|
68
|
-
MSG_REQ_REDIS_TTL,
|
|
69
|
-
MSG_REQ_REDIS_TYPE,
|
|
70
|
-
MSG_REQ_REDIS_APPEND, /* redis requests - string */
|
|
71
|
-
MSG_REQ_REDIS_BITCOUNT,
|
|
72
|
-
MSG_REQ_REDIS_DECR,
|
|
73
|
-
MSG_REQ_REDIS_DECRBY,
|
|
74
|
-
MSG_REQ_REDIS_DUMP,
|
|
75
|
-
MSG_REQ_REDIS_GET,
|
|
76
|
-
MSG_REQ_REDIS_GETBIT,
|
|
77
|
-
MSG_REQ_REDIS_GETRANGE,
|
|
78
|
-
MSG_REQ_REDIS_GETSET,
|
|
79
|
-
MSG_REQ_REDIS_INCR,
|
|
80
|
-
MSG_REQ_REDIS_INCRBY,
|
|
81
|
-
MSG_REQ_REDIS_INCRBYFLOAT,
|
|
82
|
-
MSG_REQ_REDIS_MGET,
|
|
83
|
-
MSG_REQ_REDIS_PSETEX,
|
|
84
|
-
MSG_REQ_REDIS_RESTORE,
|
|
85
|
-
MSG_REQ_REDIS_SET,
|
|
86
|
-
MSG_REQ_REDIS_SETBIT,
|
|
87
|
-
MSG_REQ_REDIS_SETEX,
|
|
88
|
-
MSG_REQ_REDIS_SETNX,
|
|
89
|
-
MSG_REQ_REDIS_SETRANGE,
|
|
90
|
-
MSG_REQ_REDIS_STRLEN,
|
|
91
|
-
MSG_REQ_REDIS_HDEL, /* redis requests - hashes */
|
|
92
|
-
MSG_REQ_REDIS_HEXISTS,
|
|
93
|
-
MSG_REQ_REDIS_HGET,
|
|
94
|
-
MSG_REQ_REDIS_HGETALL,
|
|
95
|
-
MSG_REQ_REDIS_HINCRBY,
|
|
96
|
-
MSG_REQ_REDIS_HINCRBYFLOAT,
|
|
97
|
-
MSG_REQ_REDIS_HKEYS,
|
|
98
|
-
MSG_REQ_REDIS_HLEN,
|
|
99
|
-
MSG_REQ_REDIS_HMGET,
|
|
100
|
-
MSG_REQ_REDIS_HMSET,
|
|
101
|
-
MSG_REQ_REDIS_HSET,
|
|
102
|
-
MSG_REQ_REDIS_HSETNX,
|
|
103
|
-
MSG_REQ_REDIS_HVALS,
|
|
104
|
-
MSG_REQ_REDIS_LINDEX, /* redis requests - lists */
|
|
105
|
-
MSG_REQ_REDIS_LINSERT,
|
|
106
|
-
MSG_REQ_REDIS_LLEN,
|
|
107
|
-
MSG_REQ_REDIS_LPOP,
|
|
108
|
-
MSG_REQ_REDIS_LPUSH,
|
|
109
|
-
MSG_REQ_REDIS_LPUSHX,
|
|
110
|
-
MSG_REQ_REDIS_LRANGE,
|
|
111
|
-
MSG_REQ_REDIS_LREM,
|
|
112
|
-
MSG_REQ_REDIS_LSET,
|
|
113
|
-
MSG_REQ_REDIS_LTRIM,
|
|
114
|
-
MSG_REQ_REDIS_RPOP,
|
|
115
|
-
MSG_REQ_REDIS_RPOPLPUSH,
|
|
116
|
-
MSG_REQ_REDIS_RPUSH,
|
|
117
|
-
MSG_REQ_REDIS_RPUSHX,
|
|
118
|
-
MSG_REQ_REDIS_SADD, /* redis requests - sets */
|
|
119
|
-
MSG_REQ_REDIS_SCARD,
|
|
120
|
-
MSG_REQ_REDIS_SDIFF,
|
|
121
|
-
MSG_REQ_REDIS_SDIFFSTORE,
|
|
122
|
-
MSG_REQ_REDIS_SINTER,
|
|
123
|
-
MSG_REQ_REDIS_SINTERSTORE,
|
|
124
|
-
MSG_REQ_REDIS_SISMEMBER,
|
|
125
|
-
MSG_REQ_REDIS_SMEMBERS,
|
|
126
|
-
MSG_REQ_REDIS_SMOVE,
|
|
127
|
-
MSG_REQ_REDIS_SPOP,
|
|
128
|
-
MSG_REQ_REDIS_SRANDMEMBER,
|
|
129
|
-
MSG_REQ_REDIS_SREM,
|
|
130
|
-
MSG_REQ_REDIS_SUNION,
|
|
131
|
-
MSG_REQ_REDIS_SUNIONSTORE,
|
|
132
|
-
MSG_REQ_REDIS_ZADD, /* redis requests - sorted sets */
|
|
133
|
-
MSG_REQ_REDIS_ZCARD,
|
|
134
|
-
MSG_REQ_REDIS_ZCOUNT,
|
|
135
|
-
MSG_REQ_REDIS_ZINCRBY,
|
|
136
|
-
MSG_REQ_REDIS_ZINTERSTORE,
|
|
137
|
-
MSG_REQ_REDIS_ZRANGE,
|
|
138
|
-
MSG_REQ_REDIS_ZRANGEBYSCORE,
|
|
139
|
-
MSG_REQ_REDIS_ZRANK,
|
|
140
|
-
MSG_REQ_REDIS_ZREM,
|
|
141
|
-
MSG_REQ_REDIS_ZREMRANGEBYRANK,
|
|
142
|
-
MSG_REQ_REDIS_ZREMRANGEBYSCORE,
|
|
143
|
-
MSG_REQ_REDIS_ZREVRANGE,
|
|
144
|
-
MSG_REQ_REDIS_ZREVRANGEBYSCORE,
|
|
145
|
-
MSG_REQ_REDIS_ZREVRANK,
|
|
146
|
-
MSG_REQ_REDIS_ZSCORE,
|
|
147
|
-
MSG_REQ_REDIS_ZUNIONSTORE,
|
|
148
|
-
MSG_REQ_REDIS_EVAL, /* redis requests - eval */
|
|
149
|
-
MSG_REQ_REDIS_EVALSHA,
|
|
150
|
-
MSG_RSP_REDIS_STATUS, /* redis response */
|
|
151
|
-
MSG_RSP_REDIS_ERROR,
|
|
152
|
-
MSG_RSP_REDIS_INTEGER,
|
|
153
|
-
MSG_RSP_REDIS_BULK,
|
|
154
|
-
MSG_RSP_REDIS_MULTIBULK,
|
|
155
|
-
MSG_SENTINEL
|
|
173
|
+
MSG_TYPE_CODEC(DEFINE_ACTION)
|
|
156
174
|
} msg_type_t;
|
|
175
|
+
#undef DEFINE_ACTION
|
|
176
|
+
|
|
177
|
+
struct keypos {
|
|
178
|
+
uint8_t *start; /* key start pos */
|
|
179
|
+
uint8_t *end; /* key end pos */
|
|
180
|
+
};
|
|
157
181
|
|
|
158
182
|
struct msg {
|
|
159
183
|
TAILQ_ENTRY(msg) c_tqe; /* link in client q */
|
|
@@ -168,6 +192,7 @@ struct msg {
|
|
|
168
192
|
|
|
169
193
|
struct mhdr mhdr; /* message mbuf header */
|
|
170
194
|
uint32_t mlen; /* message length */
|
|
195
|
+
int64_t start_ts; /* request start timestamp in usec */
|
|
171
196
|
|
|
172
197
|
int state; /* current parser state */
|
|
173
198
|
uint8_t *pos; /* parser position marker */
|
|
@@ -176,15 +201,14 @@ struct msg {
|
|
|
176
201
|
msg_parse_t parser; /* message parser */
|
|
177
202
|
msg_parse_result_t result; /* message parsing result */
|
|
178
203
|
|
|
179
|
-
|
|
180
|
-
|
|
204
|
+
msg_fragment_t fragment; /* message fragment */
|
|
205
|
+
msg_reply_t reply; /* gen message reply (example: ping) */
|
|
181
206
|
msg_coalesce_t pre_coalesce; /* message pre-coalesce */
|
|
182
207
|
msg_coalesce_t post_coalesce; /* message post-coalesce */
|
|
183
208
|
|
|
184
209
|
msg_type_t type; /* message type */
|
|
185
210
|
|
|
186
|
-
|
|
187
|
-
uint8_t *key_end; /* key end */
|
|
211
|
+
struct array *keys; /* array of keypos, for req */
|
|
188
212
|
|
|
189
213
|
uint32_t vlen; /* value length (memcache) */
|
|
190
214
|
uint8_t *end; /* end marker (memcache) */
|
|
@@ -198,7 +222,9 @@ struct msg {
|
|
|
198
222
|
|
|
199
223
|
struct msg *frag_owner; /* owner of fragment message */
|
|
200
224
|
uint32_t nfrag; /* # fragment */
|
|
225
|
+
uint32_t nfrag_done; /* # fragment done */
|
|
201
226
|
uint64_t frag_id; /* id of fragmented message */
|
|
227
|
+
struct msg **frag_seq; /* sequence of fragment message, map from keys to fragments*/
|
|
202
228
|
|
|
203
229
|
err_t err; /* errno on error? */
|
|
204
230
|
unsigned error:1; /* error? */
|
|
@@ -206,10 +232,9 @@ struct msg {
|
|
|
206
232
|
unsigned request:1; /* request? or response? */
|
|
207
233
|
unsigned quit:1; /* quit request? */
|
|
208
234
|
unsigned noreply:1; /* noreply? */
|
|
235
|
+
unsigned noforward:1; /* not need forward (example: ping) */
|
|
209
236
|
unsigned done:1; /* done? */
|
|
210
237
|
unsigned fdone:1; /* all fragments are done? */
|
|
211
|
-
unsigned first_fragment:1;/* first fragment? */
|
|
212
|
-
unsigned last_fragment:1; /* last fragment? */
|
|
213
238
|
unsigned swallow:1; /* swallow response? */
|
|
214
239
|
unsigned redis:1; /* redis? */
|
|
215
240
|
};
|
|
@@ -222,13 +247,20 @@ void msg_tmo_delete(struct msg *msg);
|
|
|
222
247
|
|
|
223
248
|
void msg_init(void);
|
|
224
249
|
void msg_deinit(void);
|
|
250
|
+
struct string *msg_type_string(msg_type_t type);
|
|
225
251
|
struct msg *msg_get(struct conn *conn, bool request, bool redis);
|
|
226
252
|
void msg_put(struct msg *msg);
|
|
227
253
|
struct msg *msg_get_error(bool redis, err_t err);
|
|
228
|
-
void msg_dump(struct msg *msg);
|
|
254
|
+
void msg_dump(struct msg *msg, int level);
|
|
229
255
|
bool msg_empty(struct msg *msg);
|
|
230
256
|
rstatus_t msg_recv(struct context *ctx, struct conn *conn);
|
|
231
257
|
rstatus_t msg_send(struct context *ctx, struct conn *conn);
|
|
258
|
+
uint64_t msg_gen_frag_id(void);
|
|
259
|
+
uint32_t msg_backend_idx(struct msg *msg, uint8_t *key, uint32_t keylen);
|
|
260
|
+
struct mbuf *msg_ensure_mbuf(struct msg *msg, size_t len);
|
|
261
|
+
rstatus_t msg_append(struct msg *msg, uint8_t *pos, size_t n);
|
|
262
|
+
rstatus_t msg_prepend(struct msg *msg, uint8_t *pos, size_t n);
|
|
263
|
+
rstatus_t msg_prepend_format(struct msg *msg, const char *fmt, ...);
|
|
232
264
|
|
|
233
265
|
struct msg *req_get(struct conn *conn);
|
|
234
266
|
void req_put(struct msg *msg);
|
|
@@ -276,24 +276,54 @@ proxy_accept(struct context *ctx, struct conn *p)
|
|
|
276
276
|
continue;
|
|
277
277
|
}
|
|
278
278
|
|
|
279
|
-
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
279
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ECONNABORTED) {
|
|
280
280
|
log_debug(LOG_VERB, "accept on p %d not ready - eagain", p->sd);
|
|
281
281
|
p->recv_ready = 0;
|
|
282
282
|
return NC_OK;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
-
/*
|
|
286
|
-
*
|
|
287
|
-
*
|
|
285
|
+
/*
|
|
286
|
+
* Workaround of https://github.com/twitter/twemproxy/issues/97
|
|
287
|
+
*
|
|
288
|
+
* We should never reach here because the check for conn_ncurr_cconn()
|
|
289
|
+
* against ctx->max_ncconn should catch this earlier in the cycle.
|
|
290
|
+
* If we reach here ignore EMFILE/ENFILE, return NC_OK will enable
|
|
291
|
+
* the server continue to run instead of close the server socket
|
|
292
|
+
*
|
|
293
|
+
* The right solution however, is on EMFILE/ENFILE to mask out IN
|
|
294
|
+
* event on the proxy and mask it back in when some existing
|
|
295
|
+
* connections gets closed
|
|
288
296
|
*/
|
|
297
|
+
if (errno == EMFILE || errno == ENFILE) {
|
|
298
|
+
log_debug(LOG_CRIT, "accept on p %d with max fds %"PRIu32" "
|
|
299
|
+
"used connections %"PRIu32" max client connections %"PRIu32" "
|
|
300
|
+
"curr client connections %"PRIu32" failed: %s",
|
|
301
|
+
p->sd, ctx->max_nfd, conn_ncurr_conn(),
|
|
302
|
+
ctx->max_ncconn, conn_ncurr_cconn(), strerror(errno));
|
|
303
|
+
|
|
304
|
+
p->recv_ready = 0;
|
|
305
|
+
|
|
306
|
+
return NC_OK;
|
|
307
|
+
}
|
|
289
308
|
|
|
290
309
|
log_error("accept on p %d failed: %s", p->sd, strerror(errno));
|
|
310
|
+
|
|
291
311
|
return NC_ERROR;
|
|
292
312
|
}
|
|
293
313
|
|
|
294
314
|
break;
|
|
295
315
|
}
|
|
296
316
|
|
|
317
|
+
if (conn_ncurr_cconn() >= ctx->max_ncconn) {
|
|
318
|
+
log_debug(LOG_CRIT, "client connections %"PRIu32" exceed limit %"PRIu32,
|
|
319
|
+
conn_ncurr_cconn(), ctx->max_ncconn);
|
|
320
|
+
status = close(sd);
|
|
321
|
+
if (status < 0) {
|
|
322
|
+
log_error("close c %d failed, ignored: %s", sd, strerror(errno));
|
|
323
|
+
}
|
|
324
|
+
return NC_OK;
|
|
325
|
+
}
|
|
326
|
+
|
|
297
327
|
c = conn_get(p->owner, true, p->redis);
|
|
298
328
|
if (c == NULL) {
|
|
299
329
|
log_error("get conn for c %d from p %d failed: %s", sd, p->sd,
|
|
@@ -29,10 +29,73 @@ req_get(struct conn *conn)
|
|
|
29
29
|
if (msg == NULL) {
|
|
30
30
|
conn->err = errno;
|
|
31
31
|
}
|
|
32
|
-
|
|
33
32
|
return msg;
|
|
34
33
|
}
|
|
35
34
|
|
|
35
|
+
static void
|
|
36
|
+
req_log(struct msg *req)
|
|
37
|
+
{
|
|
38
|
+
struct msg *rsp; /* peer message (response) */
|
|
39
|
+
int64_t req_time; /* time cost for this request */
|
|
40
|
+
char *peer_str; /* peer client ip:port */
|
|
41
|
+
uint32_t req_len, rsp_len; /* request and response length */
|
|
42
|
+
struct string *req_type; /* request type string */
|
|
43
|
+
struct keypos *kpos;
|
|
44
|
+
|
|
45
|
+
if (log_loggable(LOG_NOTICE) == 0) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/* a fragment? */
|
|
50
|
+
if (req->frag_id != 0 && req->frag_owner != req) {
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* conn close normally? */
|
|
55
|
+
if (req->mlen == 0) {
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
/*
|
|
59
|
+
* there is a race scenario where a requests comes in, the log level is not LOG_NOTICE,
|
|
60
|
+
* and before the response arrives you modify the log level to LOG_NOTICE
|
|
61
|
+
* using SIGTTIN OR SIGTTOU, then req_log() wouldn't have msg->start_ts set
|
|
62
|
+
*/
|
|
63
|
+
if (req->start_ts == 0) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
req_time = nc_usec_now() - req->start_ts;
|
|
68
|
+
|
|
69
|
+
rsp = req->peer;
|
|
70
|
+
req_len = req->mlen;
|
|
71
|
+
rsp_len = (rsp != NULL) ? rsp->mlen : 0;
|
|
72
|
+
|
|
73
|
+
if (array_n(req->keys) < 1) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
kpos = array_get(req->keys, 0);
|
|
78
|
+
if (kpos->end != NULL) {
|
|
79
|
+
*(kpos->end) = '\0';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* FIXME: add backend addr here
|
|
84
|
+
* Maybe we can store addrstr just like server_pool in conn struct
|
|
85
|
+
* when connections are resolved
|
|
86
|
+
*/
|
|
87
|
+
peer_str = nc_unresolve_peer_desc(req->owner->sd);
|
|
88
|
+
|
|
89
|
+
req_type = msg_type_string(req->type);
|
|
90
|
+
|
|
91
|
+
log_debug(LOG_NOTICE, "req %"PRIu64" done on c %d req_time %"PRIi64".%03"PRIi64
|
|
92
|
+
" msec type %.*s narg %"PRIu32" req_len %"PRIu32" rsp_len %"PRIu32
|
|
93
|
+
" key0 '%s' peer '%s' done %d error %d",
|
|
94
|
+
req->id, req->owner->sd, req_time / 1000, req_time % 1000,
|
|
95
|
+
req_type->len, req_type->data, req->narg, req_len, rsp_len,
|
|
96
|
+
kpos->start, peer_str, req->done, req->error);
|
|
97
|
+
}
|
|
98
|
+
|
|
36
99
|
void
|
|
37
100
|
req_put(struct msg *msg)
|
|
38
101
|
{
|
|
@@ -40,6 +103,8 @@ req_put(struct msg *msg)
|
|
|
40
103
|
|
|
41
104
|
ASSERT(msg->request);
|
|
42
105
|
|
|
106
|
+
req_log(msg);
|
|
107
|
+
|
|
43
108
|
pmsg = msg->peer;
|
|
44
109
|
if (pmsg != NULL) {
|
|
45
110
|
ASSERT(!pmsg->request && pmsg->peer == msg);
|
|
@@ -84,6 +149,10 @@ req_done(struct conn *conn, struct msg *msg)
|
|
|
84
149
|
return true;
|
|
85
150
|
}
|
|
86
151
|
|
|
152
|
+
if (msg->nfrag_done < msg->nfrag) {
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
|
|
87
156
|
/* check all fragments of the given request vector are done */
|
|
88
157
|
|
|
89
158
|
for (pmsg = msg, cmsg = TAILQ_PREV(msg, msg_tqh, c_tqe);
|
|
@@ -104,10 +173,6 @@ req_done(struct conn *conn, struct msg *msg)
|
|
|
104
173
|
}
|
|
105
174
|
}
|
|
106
175
|
|
|
107
|
-
if (!pmsg->last_fragment) {
|
|
108
|
-
return false;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
176
|
/*
|
|
112
177
|
* At this point, all the fragments including the last fragment have
|
|
113
178
|
* been received.
|
|
@@ -117,7 +182,7 @@ req_done(struct conn *conn, struct msg *msg)
|
|
|
117
182
|
*/
|
|
118
183
|
|
|
119
184
|
msg->fdone = 1;
|
|
120
|
-
nfragment =
|
|
185
|
+
nfragment = 0;
|
|
121
186
|
|
|
122
187
|
for (pmsg = msg, cmsg = TAILQ_PREV(msg, msg_tqh, c_tqe);
|
|
123
188
|
cmsg != NULL && cmsg->frag_id == id;
|
|
@@ -143,6 +208,7 @@ req_done(struct conn *conn, struct msg *msg)
|
|
|
143
208
|
return true;
|
|
144
209
|
}
|
|
145
210
|
|
|
211
|
+
|
|
146
212
|
/*
|
|
147
213
|
* Return true if request is in error, false otherwise
|
|
148
214
|
*
|
|
@@ -360,6 +426,26 @@ req_recv_next(struct context *ctx, struct conn *conn, bool alloc)
|
|
|
360
426
|
return msg;
|
|
361
427
|
}
|
|
362
428
|
|
|
429
|
+
static rstatus_t
|
|
430
|
+
req_make_reply(struct context *ctx, struct conn *conn, struct msg *req)
|
|
431
|
+
{
|
|
432
|
+
struct msg *msg;
|
|
433
|
+
|
|
434
|
+
msg = msg_get(conn, true, conn->redis); /* replay */
|
|
435
|
+
if (msg == NULL) {
|
|
436
|
+
conn->err = errno;
|
|
437
|
+
return NC_ENOMEM;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
req->peer = msg;
|
|
441
|
+
msg->peer = req;
|
|
442
|
+
msg->request = 0;
|
|
443
|
+
|
|
444
|
+
req->done = 1;
|
|
445
|
+
conn->enqueue_outq(ctx, conn, req);
|
|
446
|
+
return NC_OK;
|
|
447
|
+
}
|
|
448
|
+
|
|
363
449
|
static bool
|
|
364
450
|
req_filter(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
365
451
|
{
|
|
@@ -436,6 +522,7 @@ req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg)
|
|
|
436
522
|
struct server_pool *pool;
|
|
437
523
|
uint8_t *key;
|
|
438
524
|
uint32_t keylen;
|
|
525
|
+
struct keypos *kpos;
|
|
439
526
|
|
|
440
527
|
ASSERT(c_conn->client && !c_conn->proxy);
|
|
441
528
|
|
|
@@ -445,32 +532,11 @@ req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg)
|
|
|
445
532
|
}
|
|
446
533
|
|
|
447
534
|
pool = c_conn->owner;
|
|
448
|
-
key = NULL;
|
|
449
|
-
keylen = 0;
|
|
450
535
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
*/
|
|
456
|
-
if (!string_empty(&pool->hash_tag)) {
|
|
457
|
-
struct string *tag = &pool->hash_tag;
|
|
458
|
-
uint8_t *tag_start, *tag_end;
|
|
459
|
-
|
|
460
|
-
tag_start = nc_strchr(msg->key_start, msg->key_end, tag->data[0]);
|
|
461
|
-
if (tag_start != NULL) {
|
|
462
|
-
tag_end = nc_strchr(tag_start + 1, msg->key_end, tag->data[1]);
|
|
463
|
-
if (tag_end != NULL) {
|
|
464
|
-
key = tag_start + 1;
|
|
465
|
-
keylen = (uint32_t)(tag_end - key);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
}
|
|
469
|
-
|
|
470
|
-
if (keylen == 0) {
|
|
471
|
-
key = msg->key_start;
|
|
472
|
-
keylen = (uint32_t)(msg->key_end - msg->key_start);
|
|
473
|
-
}
|
|
536
|
+
ASSERT(array_n(msg->keys) > 0);
|
|
537
|
+
kpos = array_get(msg->keys, 0);
|
|
538
|
+
key = kpos->start;
|
|
539
|
+
keylen = (uint32_t)(kpos->end - kpos->start);
|
|
474
540
|
|
|
475
541
|
s_conn = server_pool_conn(ctx, c_conn->owner, key, keylen);
|
|
476
542
|
if (s_conn == NULL) {
|
|
@@ -501,6 +567,12 @@ void
|
|
|
501
567
|
req_recv_done(struct context *ctx, struct conn *conn, struct msg *msg,
|
|
502
568
|
struct msg *nmsg)
|
|
503
569
|
{
|
|
570
|
+
rstatus_t status;
|
|
571
|
+
struct server_pool *pool;
|
|
572
|
+
struct msg_tqh frag_msgq;
|
|
573
|
+
struct msg *sub_msg;
|
|
574
|
+
struct msg *tmsg; /* tmp next message */
|
|
575
|
+
|
|
504
576
|
ASSERT(conn->client && !conn->proxy);
|
|
505
577
|
ASSERT(msg->request);
|
|
506
578
|
ASSERT(msg->owner == conn);
|
|
@@ -514,7 +586,61 @@ req_recv_done(struct context *ctx, struct conn *conn, struct msg *msg,
|
|
|
514
586
|
return;
|
|
515
587
|
}
|
|
516
588
|
|
|
517
|
-
|
|
589
|
+
if (msg->noforward) {
|
|
590
|
+
status = req_make_reply(ctx, conn, msg);
|
|
591
|
+
if (status != NC_OK) {
|
|
592
|
+
conn->err = errno;
|
|
593
|
+
return;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
status = msg->reply(msg);
|
|
597
|
+
if (status != NC_OK) {
|
|
598
|
+
conn->err = errno;
|
|
599
|
+
return;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
status = event_add_out(ctx->evb, conn);
|
|
603
|
+
if (status != NC_OK) {
|
|
604
|
+
conn->err = errno;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
/* do fragment */
|
|
611
|
+
pool = conn->owner;
|
|
612
|
+
TAILQ_INIT(&frag_msgq);
|
|
613
|
+
status = msg->fragment(msg, pool->ncontinuum, &frag_msgq);
|
|
614
|
+
if (status != NC_OK) {
|
|
615
|
+
if (!msg->noreply) {
|
|
616
|
+
conn->enqueue_outq(ctx, conn, msg);
|
|
617
|
+
}
|
|
618
|
+
req_forward_error(ctx, conn, msg);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
/* if no fragment happened */
|
|
622
|
+
if (TAILQ_EMPTY(&frag_msgq)) {
|
|
623
|
+
req_forward(ctx, conn, msg);
|
|
624
|
+
return;
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
status = req_make_reply(ctx, conn, msg);
|
|
628
|
+
if (status != NC_OK) {
|
|
629
|
+
if (!msg->noreply) {
|
|
630
|
+
conn->enqueue_outq(ctx, conn, msg);
|
|
631
|
+
}
|
|
632
|
+
req_forward_error(ctx, conn, msg);
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
for (sub_msg = TAILQ_FIRST(&frag_msgq); sub_msg != NULL; sub_msg = tmsg) {
|
|
636
|
+
tmsg = TAILQ_NEXT(sub_msg, m_tqe);
|
|
637
|
+
|
|
638
|
+
TAILQ_REMOVE(&frag_msgq, sub_msg, m_tqe);
|
|
639
|
+
req_forward(ctx, conn, sub_msg);
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
ASSERT(TAILQ_EMPTY(&frag_msgq));
|
|
643
|
+
return;
|
|
518
644
|
}
|
|
519
645
|
|
|
520
646
|
struct msg *
|