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.
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 *