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.
Files changed (107) hide show
  1. checksums.yaml +5 -13
  2. data/README.md +3 -3
  3. data/Rakefile +12 -10
  4. data/ext/nutcracker/Makefile.in +215 -162
  5. data/ext/nutcracker/README.md +16 -4
  6. data/ext/nutcracker/aclocal.m4 +432 -254
  7. data/ext/nutcracker/{contrib/yaml-0.1.4/configure → autom4te.cache/output.0} +11367 -4545
  8. data/ext/nutcracker/autom4te.cache/output.1 +19907 -0
  9. data/ext/nutcracker/autom4te.cache/output.2 +19907 -0
  10. data/ext/nutcracker/autom4te.cache/requests +518 -0
  11. data/ext/nutcracker/autom4te.cache/traces.0 +2715 -0
  12. data/ext/nutcracker/autom4te.cache/traces.1 +967 -0
  13. data/ext/nutcracker/autom4te.cache/traces.2 +2715 -0
  14. data/ext/nutcracker/config/compile +347 -0
  15. data/ext/nutcracker/config/config.guess +116 -78
  16. data/ext/nutcracker/config/config.sub +65 -45
  17. data/ext/nutcracker/config/depcomp +295 -192
  18. data/ext/nutcracker/config/install-sh +7 -7
  19. data/ext/nutcracker/config/ltmain.sh +15 -20
  20. data/ext/nutcracker/config/missing +149 -265
  21. data/ext/nutcracker/configure +493 -367
  22. data/ext/nutcracker/contrib/Makefile.in +158 -116
  23. data/ext/nutcracker/extconf.rb +0 -1
  24. data/ext/nutcracker/m4/libtool.m4 +4 -23
  25. data/ext/nutcracker/m4/ltoptions.m4 +0 -0
  26. data/ext/nutcracker/m4/ltsugar.m4 +0 -0
  27. data/ext/nutcracker/m4/ltversion.m4 +0 -0
  28. data/ext/nutcracker/m4/lt~obsolete.m4 +0 -0
  29. data/ext/nutcracker/notes/recommendation.md +1 -1
  30. data/ext/nutcracker/notes/redis.md +35 -3
  31. data/ext/nutcracker/scripts/benchmark-mget.py +43 -0
  32. data/ext/nutcracker/scripts/nutcracker.spec +61 -3
  33. data/ext/nutcracker/scripts/redis-check.sh +43 -0
  34. data/ext/nutcracker/src/Makefile.in +205 -142
  35. data/ext/nutcracker/src/event/Makefile.in +164 -66
  36. data/ext/nutcracker/src/hashkit/Makefile.in +164 -66
  37. data/ext/nutcracker/src/nc_conf.c +2 -0
  38. data/ext/nutcracker/src/nc_connection.c +31 -0
  39. data/ext/nutcracker/src/nc_connection.h +3 -0
  40. data/ext/nutcracker/src/nc_core.c +38 -2
  41. data/ext/nutcracker/src/nc_core.h +11 -0
  42. data/ext/nutcracker/src/nc_log.c +90 -12
  43. data/ext/nutcracker/src/nc_log.h +11 -0
  44. data/ext/nutcracker/src/nc_mbuf.h +1 -1
  45. data/ext/nutcracker/src/nc_message.c +162 -116
  46. data/ext/nutcracker/src/nc_message.h +161 -129
  47. data/ext/nutcracker/src/nc_proxy.c +34 -4
  48. data/ext/nutcracker/src/nc_request.c +158 -32
  49. data/ext/nutcracker/src/nc_server.c +59 -5
  50. data/ext/nutcracker/src/nc_server.h +1 -0
  51. data/ext/nutcracker/src/nc_signal.c +2 -2
  52. data/ext/nutcracker/src/nc_stats.c +21 -0
  53. data/ext/nutcracker/src/nc_stats.h +28 -26
  54. data/ext/nutcracker/src/nc_string.c +176 -1
  55. data/ext/nutcracker/src/nc_string.h +26 -0
  56. data/ext/nutcracker/src/nc_util.c +12 -0
  57. data/ext/nutcracker/src/nc_util.h +1 -0
  58. data/ext/nutcracker/src/proto/Makefile.in +164 -66
  59. data/ext/nutcracker/src/proto/nc_memcache.c +279 -88
  60. data/ext/nutcracker/src/proto/nc_proto.h +3 -4
  61. data/ext/nutcracker/src/proto/nc_redis.c +561 -134
  62. data/lib/nutcracker/version.rb +1 -1
  63. metadata +31 -67
  64. data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +0 -19
  65. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +0 -20
  66. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +0 -736
  67. data/ext/nutcracker/contrib/yaml-0.1.4/README +0 -27
  68. data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +0 -956
  69. data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +0 -80
  70. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +0 -1561
  71. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +0 -1686
  72. data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +0 -630
  73. data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +0 -520
  74. data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +0 -8406
  75. data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +0 -376
  76. data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +0 -75
  77. data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +0 -222
  78. data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +0 -1971
  79. data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +0 -7357
  80. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +0 -368
  81. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +0 -123
  82. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +0 -23
  83. data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +0 -92
  84. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +0 -4
  85. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +0 -484
  86. data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +0 -1392
  87. data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +0 -394
  88. data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +0 -2329
  89. data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +0 -432
  90. data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +0 -1374
  91. data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +0 -465
  92. data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +0 -3570
  93. data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +0 -141
  94. data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +0 -640
  95. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +0 -8
  96. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +0 -675
  97. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +0 -800
  98. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +0 -1130
  99. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +0 -217
  100. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +0 -202
  101. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +0 -311
  102. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +0 -327
  103. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +0 -63
  104. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +0 -63
  105. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +0 -63
  106. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +0 -354
  107. 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 (*msg_post_splitcopy_t)(struct msg *);
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
- MSG_UNKNOWN,
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
- mbuf_copy_t pre_splitcopy; /* message pre-split copy */
180
- msg_post_splitcopy_t post_splitcopy; /* message post-split copy */
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
- uint8_t *key_start; /* key start */
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
- * FIXME: On EMFILE or ENFILE mask out IN event on the proxy; mask
287
- * it back in when some existing connection gets closed
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 = 1;
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
- * If hash_tag: is configured for this server pool, we use the part of
453
- * the key within the hash tag as an input to the distributor. Otherwise
454
- * we use the full key
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
- req_forward(ctx, conn, msg);
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 *