nutcracker 0.2.3
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.
- data/README.md +22 -0
- data/Rakefile +55 -0
- data/bin/nutcracker +2 -0
- data/ext/nutcracker/ChangeLog +66 -0
- data/ext/nutcracker/LICENSE +177 -0
- data/ext/nutcracker/Makefile.am +7 -0
- data/ext/nutcracker/Makefile.in +726 -0
- data/ext/nutcracker/NOTICE +124 -0
- data/ext/nutcracker/README.md +240 -0
- data/ext/nutcracker/aclocal.m4 +956 -0
- data/ext/nutcracker/conf/nutcracker.leaf.yml +10 -0
- data/ext/nutcracker/conf/nutcracker.root.yml +8 -0
- data/ext/nutcracker/conf/nutcracker.yml +67 -0
- data/ext/nutcracker/config.h.in +316 -0
- data/ext/nutcracker/config/config.guess +1561 -0
- data/ext/nutcracker/config/config.sub +1686 -0
- data/ext/nutcracker/config/depcomp +630 -0
- data/ext/nutcracker/config/install-sh +520 -0
- data/ext/nutcracker/config/ltmain.sh +8413 -0
- data/ext/nutcracker/config/missing +376 -0
- data/ext/nutcracker/configure +18862 -0
- data/ext/nutcracker/configure.ac +155 -0
- data/ext/nutcracker/contrib/Makefile.am +3 -0
- data/ext/nutcracker/contrib/Makefile.in +560 -0
- data/ext/nutcracker/contrib/yaml-0.1.4.tar.gz +0 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +19 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +20 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +736 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/README +27 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +956 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +80 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +1561 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +1686 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +630 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +520 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +8406 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +376 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/configure +13085 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +75 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +222 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +1971 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +7357 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +368 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +123 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +23 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +92 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +4 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +484 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +1392 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +394 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +2329 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +432 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +1374 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +465 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +3570 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +141 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +640 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +8 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +675 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +800 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +1130 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +217 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +202 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +311 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +327 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +63 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +63 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +63 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +354 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +29 -0
- data/ext/nutcracker/extconf.rb +5 -0
- data/ext/nutcracker/m4/libtool.m4 +7376 -0
- data/ext/nutcracker/m4/ltoptions.m4 +368 -0
- data/ext/nutcracker/m4/ltsugar.m4 +123 -0
- data/ext/nutcracker/m4/ltversion.m4 +23 -0
- data/ext/nutcracker/m4/lt~obsolete.m4 +92 -0
- data/ext/nutcracker/notes/c-styleguide.txt +425 -0
- data/ext/nutcracker/notes/debug.txt +96 -0
- data/ext/nutcracker/notes/memcache.txt +123 -0
- data/ext/nutcracker/notes/recommendation.md +118 -0
- data/ext/nutcracker/notes/redis.md +415 -0
- data/ext/nutcracker/notes/socket.txt +131 -0
- data/ext/nutcracker/scripts/multi_get.sh +26 -0
- data/ext/nutcracker/scripts/nutcracker.init +73 -0
- data/ext/nutcracker/scripts/nutcracker.spec +52 -0
- data/ext/nutcracker/scripts/pipelined_read.sh +23 -0
- data/ext/nutcracker/scripts/pipelined_write.sh +29 -0
- data/ext/nutcracker/scripts/populate_memcached.sh +24 -0
- data/ext/nutcracker/scripts/redis-check.py +23 -0
- data/ext/nutcracker/scripts/redis-check.sh +564 -0
- data/ext/nutcracker/src/Makefile.am +46 -0
- data/ext/nutcracker/src/Makefile.in +726 -0
- data/ext/nutcracker/src/hashkit/Makefile.am +22 -0
- data/ext/nutcracker/src/hashkit/Makefile.in +501 -0
- data/ext/nutcracker/src/hashkit/nc_crc32.c +105 -0
- data/ext/nutcracker/src/hashkit/nc_fnv.c +82 -0
- data/ext/nutcracker/src/hashkit/nc_hashkit.h +74 -0
- data/ext/nutcracker/src/hashkit/nc_hsieh.c +93 -0
- data/ext/nutcracker/src/hashkit/nc_jenkins.c +230 -0
- data/ext/nutcracker/src/hashkit/nc_ketama.c +240 -0
- data/ext/nutcracker/src/hashkit/nc_md5.c +379 -0
- data/ext/nutcracker/src/hashkit/nc_modula.c +144 -0
- data/ext/nutcracker/src/hashkit/nc_murmur.c +99 -0
- data/ext/nutcracker/src/hashkit/nc_one_at_a_time.c +51 -0
- data/ext/nutcracker/src/hashkit/nc_random.c +146 -0
- data/ext/nutcracker/src/nc.c +573 -0
- data/ext/nutcracker/src/nc_array.c +204 -0
- data/ext/nutcracker/src/nc_array.h +73 -0
- data/ext/nutcracker/src/nc_client.c +189 -0
- data/ext/nutcracker/src/nc_client.h +28 -0
- data/ext/nutcracker/src/nc_conf.c +1766 -0
- data/ext/nutcracker/src/nc_conf.h +134 -0
- data/ext/nutcracker/src/nc_connection.c +392 -0
- data/ext/nutcracker/src/nc_connection.h +99 -0
- data/ext/nutcracker/src/nc_core.c +334 -0
- data/ext/nutcracker/src/nc_core.h +131 -0
- data/ext/nutcracker/src/nc_event.c +214 -0
- data/ext/nutcracker/src/nc_event.h +39 -0
- data/ext/nutcracker/src/nc_log.c +254 -0
- data/ext/nutcracker/src/nc_log.h +120 -0
- data/ext/nutcracker/src/nc_mbuf.c +285 -0
- data/ext/nutcracker/src/nc_mbuf.h +67 -0
- data/ext/nutcracker/src/nc_message.c +828 -0
- data/ext/nutcracker/src/nc_message.h +253 -0
- data/ext/nutcracker/src/nc_proxy.c +359 -0
- data/ext/nutcracker/src/nc_proxy.h +34 -0
- data/ext/nutcracker/src/nc_queue.h +788 -0
- data/ext/nutcracker/src/nc_rbtree.c +348 -0
- data/ext/nutcracker/src/nc_rbtree.h +47 -0
- data/ext/nutcracker/src/nc_request.c +588 -0
- data/ext/nutcracker/src/nc_response.c +332 -0
- data/ext/nutcracker/src/nc_server.c +841 -0
- data/ext/nutcracker/src/nc_server.h +143 -0
- data/ext/nutcracker/src/nc_signal.c +131 -0
- data/ext/nutcracker/src/nc_signal.h +34 -0
- data/ext/nutcracker/src/nc_stats.c +1188 -0
- data/ext/nutcracker/src/nc_stats.h +206 -0
- data/ext/nutcracker/src/nc_string.c +109 -0
- data/ext/nutcracker/src/nc_string.h +112 -0
- data/ext/nutcracker/src/nc_util.c +619 -0
- data/ext/nutcracker/src/nc_util.h +214 -0
- data/ext/nutcracker/src/proto/Makefile.am +14 -0
- data/ext/nutcracker/src/proto/Makefile.in +482 -0
- data/ext/nutcracker/src/proto/nc_memcache.c +1306 -0
- data/ext/nutcracker/src/proto/nc_proto.h +155 -0
- data/ext/nutcracker/src/proto/nc_redis.c +2102 -0
- data/lib/nutcracker.rb +7 -0
- data/lib/nutcracker/version.rb +3 -0
- metadata +194 -0
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* twemproxy - A fast and lightweight proxy for memcached protocol.
|
|
3
|
+
* Copyright (C) 2011 Twitter, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#ifndef _NC_MESSAGE_H_
|
|
19
|
+
#define _NC_MESSAGE_H_
|
|
20
|
+
|
|
21
|
+
#include <nc_core.h>
|
|
22
|
+
|
|
23
|
+
typedef void (*msg_parse_t)(struct msg *);
|
|
24
|
+
typedef rstatus_t (*msg_post_splitcopy_t)(struct msg *);
|
|
25
|
+
typedef void (*msg_coalesce_t)(struct msg *r);
|
|
26
|
+
|
|
27
|
+
typedef enum msg_parse_result {
|
|
28
|
+
MSG_PARSE_OK, /* parsing ok */
|
|
29
|
+
MSG_PARSE_ERROR, /* parsing error */
|
|
30
|
+
MSG_PARSE_REPAIR, /* more to parse -> repair parsed & unparsed data */
|
|
31
|
+
MSG_PARSE_FRAGMENT, /* multi-vector request -> fragment */
|
|
32
|
+
MSG_PARSE_AGAIN, /* incomplete -> parse again */
|
|
33
|
+
} msg_parse_result_t;
|
|
34
|
+
|
|
35
|
+
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_GET,
|
|
75
|
+
MSG_REQ_REDIS_GETBIT,
|
|
76
|
+
MSG_REQ_REDIS_GETRANGE,
|
|
77
|
+
MSG_REQ_REDIS_GETSET,
|
|
78
|
+
MSG_REQ_REDIS_INCR,
|
|
79
|
+
MSG_REQ_REDIS_INCRBY,
|
|
80
|
+
MSG_REQ_REDIS_INCRBYFLOAT,
|
|
81
|
+
MSG_REQ_REDIS_MGET,
|
|
82
|
+
MSG_REQ_REDIS_PSETEX,
|
|
83
|
+
MSG_REQ_REDIS_SET,
|
|
84
|
+
MSG_REQ_REDIS_SETBIT,
|
|
85
|
+
MSG_REQ_REDIS_SETEX,
|
|
86
|
+
MSG_REQ_REDIS_SETNX,
|
|
87
|
+
MSG_REQ_REDIS_SETRANGE,
|
|
88
|
+
MSG_REQ_REDIS_STRLEN,
|
|
89
|
+
MSG_REQ_REDIS_HDEL, /* redis requests - hashes */
|
|
90
|
+
MSG_REQ_REDIS_HEXISTS,
|
|
91
|
+
MSG_REQ_REDIS_HGET,
|
|
92
|
+
MSG_REQ_REDIS_HGETALL,
|
|
93
|
+
MSG_REQ_REDIS_HINCRBY,
|
|
94
|
+
MSG_REQ_REDIS_HINCRBYFLOAT,
|
|
95
|
+
MSG_REQ_REDIS_HKEYS,
|
|
96
|
+
MSG_REQ_REDIS_HLEN,
|
|
97
|
+
MSG_REQ_REDIS_HMGET,
|
|
98
|
+
MSG_REQ_REDIS_HMSET,
|
|
99
|
+
MSG_REQ_REDIS_HSET,
|
|
100
|
+
MSG_REQ_REDIS_HSETNX,
|
|
101
|
+
MSG_REQ_REDIS_HVALS,
|
|
102
|
+
MSG_REQ_REDIS_LINDEX, /* redis requests - lists */
|
|
103
|
+
MSG_REQ_REDIS_LINSERT,
|
|
104
|
+
MSG_REQ_REDIS_LLEN,
|
|
105
|
+
MSG_REQ_REDIS_LPOP,
|
|
106
|
+
MSG_REQ_REDIS_LPUSH,
|
|
107
|
+
MSG_REQ_REDIS_LPUSHX,
|
|
108
|
+
MSG_REQ_REDIS_LRANGE,
|
|
109
|
+
MSG_REQ_REDIS_LREM,
|
|
110
|
+
MSG_REQ_REDIS_LSET,
|
|
111
|
+
MSG_REQ_REDIS_LTRIM,
|
|
112
|
+
MSG_REQ_REDIS_RPOP,
|
|
113
|
+
MSG_REQ_REDIS_RPOPLPUSH,
|
|
114
|
+
MSG_REQ_REDIS_RPUSH,
|
|
115
|
+
MSG_REQ_REDIS_RPUSHX,
|
|
116
|
+
MSG_REQ_REDIS_SADD, /* redis requests - sets */
|
|
117
|
+
MSG_REQ_REDIS_SCARD,
|
|
118
|
+
MSG_REQ_REDIS_SDIFF,
|
|
119
|
+
MSG_REQ_REDIS_SDIFFSTORE,
|
|
120
|
+
MSG_REQ_REDIS_SINTER,
|
|
121
|
+
MSG_REQ_REDIS_SINTERSTORE,
|
|
122
|
+
MSG_REQ_REDIS_SISMEMBER,
|
|
123
|
+
MSG_REQ_REDIS_SMEMBERS,
|
|
124
|
+
MSG_REQ_REDIS_SMOVE,
|
|
125
|
+
MSG_REQ_REDIS_SPOP,
|
|
126
|
+
MSG_REQ_REDIS_SRANDMEMBER,
|
|
127
|
+
MSG_REQ_REDIS_SREM,
|
|
128
|
+
MSG_REQ_REDIS_SUNION,
|
|
129
|
+
MSG_REQ_REDIS_SUNIONSTORE,
|
|
130
|
+
MSG_REQ_REDIS_ZADD, /* redis requests - sorted sets */
|
|
131
|
+
MSG_REQ_REDIS_ZCARD,
|
|
132
|
+
MSG_REQ_REDIS_ZCOUNT,
|
|
133
|
+
MSG_REQ_REDIS_ZINCRBY,
|
|
134
|
+
MSG_REQ_REDIS_ZINTERSTORE,
|
|
135
|
+
MSG_REQ_REDIS_ZRANGE,
|
|
136
|
+
MSG_REQ_REDIS_ZRANGEBYSCORE,
|
|
137
|
+
MSG_REQ_REDIS_ZRANK,
|
|
138
|
+
MSG_REQ_REDIS_ZREM,
|
|
139
|
+
MSG_REQ_REDIS_ZREMRANGEBYRANK,
|
|
140
|
+
MSG_REQ_REDIS_ZREMRANGEBYSCORE,
|
|
141
|
+
MSG_REQ_REDIS_ZREVRANGE,
|
|
142
|
+
MSG_REQ_REDIS_ZREVRANGEBYSCORE,
|
|
143
|
+
MSG_REQ_REDIS_ZREVRANK,
|
|
144
|
+
MSG_REQ_REDIS_ZSCORE,
|
|
145
|
+
MSG_REQ_REDIS_ZUNIONSTORE,
|
|
146
|
+
MSG_REQ_REDIS_EVAL, /* redis requests - eval */
|
|
147
|
+
MSG_REQ_REDIS_EVALSHA,
|
|
148
|
+
MSG_RSP_REDIS_STATUS, /* redis response */
|
|
149
|
+
MSG_RSP_REDIS_ERROR,
|
|
150
|
+
MSG_RSP_REDIS_INTEGER,
|
|
151
|
+
MSG_RSP_REDIS_BULK,
|
|
152
|
+
MSG_RSP_REDIS_MULTIBULK,
|
|
153
|
+
MSG_SENTINEL
|
|
154
|
+
} msg_type_t;
|
|
155
|
+
|
|
156
|
+
struct msg {
|
|
157
|
+
TAILQ_ENTRY(msg) c_tqe; /* link in client q */
|
|
158
|
+
TAILQ_ENTRY(msg) s_tqe; /* link in server q */
|
|
159
|
+
TAILQ_ENTRY(msg) m_tqe; /* link in send q / free q */
|
|
160
|
+
|
|
161
|
+
uint64_t id; /* message id */
|
|
162
|
+
struct msg *peer; /* message peer */
|
|
163
|
+
struct conn *owner; /* message owner - client | server */
|
|
164
|
+
|
|
165
|
+
struct rbnode tmo_rbe; /* entry in rbtree */
|
|
166
|
+
|
|
167
|
+
struct mhdr mhdr; /* message mbuf header */
|
|
168
|
+
uint32_t mlen; /* message length */
|
|
169
|
+
|
|
170
|
+
int state; /* current parser state */
|
|
171
|
+
uint8_t *pos; /* parser position marker */
|
|
172
|
+
uint8_t *token; /* token marker */
|
|
173
|
+
|
|
174
|
+
msg_parse_t parser; /* message parser */
|
|
175
|
+
msg_parse_result_t result; /* message parsing result */
|
|
176
|
+
|
|
177
|
+
mbuf_copy_t pre_splitcopy; /* message pre-split copy */
|
|
178
|
+
msg_post_splitcopy_t post_splitcopy; /* message post-split copy */
|
|
179
|
+
msg_coalesce_t pre_coalesce; /* message pre-coalesce */
|
|
180
|
+
msg_coalesce_t post_coalesce; /* message post-coalesce */
|
|
181
|
+
|
|
182
|
+
msg_type_t type; /* message type */
|
|
183
|
+
|
|
184
|
+
uint8_t *key_start; /* key start */
|
|
185
|
+
uint8_t *key_end; /* key end */
|
|
186
|
+
|
|
187
|
+
uint32_t vlen; /* value length (memcache) */
|
|
188
|
+
uint8_t *end; /* end marker (memcache) */
|
|
189
|
+
|
|
190
|
+
uint8_t *narg_start; /* narg start (redis) */
|
|
191
|
+
uint8_t *narg_end; /* narg end (redis) */
|
|
192
|
+
uint32_t narg; /* # arguments (redis) */
|
|
193
|
+
uint32_t rnarg; /* running # arg used by parsing fsa (redis) */
|
|
194
|
+
uint32_t rlen; /* running length in parsing fsa (redis) */
|
|
195
|
+
uint32_t integer; /* integer reply value (redis) */
|
|
196
|
+
|
|
197
|
+
struct msg *frag_owner; /* owner of fragment message */
|
|
198
|
+
uint32_t nfrag; /* # fragment */
|
|
199
|
+
uint64_t frag_id; /* id of fragmented message */
|
|
200
|
+
|
|
201
|
+
err_t err; /* errno on error? */
|
|
202
|
+
unsigned error:1; /* error? */
|
|
203
|
+
unsigned ferror:1; /* one or more fragments are in error? */
|
|
204
|
+
unsigned request:1; /* request? or response? */
|
|
205
|
+
unsigned quit:1; /* quit request? */
|
|
206
|
+
unsigned noreply:1; /* noreply? */
|
|
207
|
+
unsigned done:1; /* done? */
|
|
208
|
+
unsigned fdone:1; /* all fragments are done? */
|
|
209
|
+
unsigned first_fragment:1;/* first fragment? */
|
|
210
|
+
unsigned last_fragment:1; /* last fragment? */
|
|
211
|
+
unsigned swallow:1; /* swallow response? */
|
|
212
|
+
unsigned redis:1; /* redis? */
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
TAILQ_HEAD(msg_tqh, msg);
|
|
216
|
+
|
|
217
|
+
struct msg *msg_tmo_min(void);
|
|
218
|
+
void msg_tmo_insert(struct msg *msg, struct conn *conn);
|
|
219
|
+
void msg_tmo_delete(struct msg *msg);
|
|
220
|
+
|
|
221
|
+
void msg_init(void);
|
|
222
|
+
void msg_deinit(void);
|
|
223
|
+
struct msg *msg_get(struct conn *conn, bool request, bool redis);
|
|
224
|
+
void msg_put(struct msg *msg);
|
|
225
|
+
struct msg *msg_get_error(bool redis, err_t err);
|
|
226
|
+
void msg_dump(struct msg *msg);
|
|
227
|
+
bool msg_empty(struct msg *msg);
|
|
228
|
+
rstatus_t msg_recv(struct context *ctx, struct conn *conn);
|
|
229
|
+
rstatus_t msg_send(struct context *ctx, struct conn *conn);
|
|
230
|
+
|
|
231
|
+
struct msg *req_get(struct conn *conn);
|
|
232
|
+
void req_put(struct msg *msg);
|
|
233
|
+
bool req_done(struct conn *conn, struct msg *msg);
|
|
234
|
+
bool req_error(struct conn *conn, struct msg *msg);
|
|
235
|
+
void req_server_enqueue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
236
|
+
void req_server_dequeue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
237
|
+
void req_client_enqueue_omsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
238
|
+
void req_server_enqueue_omsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
239
|
+
void req_client_dequeue_omsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
240
|
+
void req_server_dequeue_omsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
241
|
+
struct msg *req_recv_next(struct context *ctx, struct conn *conn, bool alloc);
|
|
242
|
+
void req_recv_done(struct context *ctx, struct conn *conn, struct msg *msg, struct msg *nmsg);
|
|
243
|
+
struct msg *req_send_next(struct context *ctx, struct conn *conn);
|
|
244
|
+
void req_send_done(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
245
|
+
|
|
246
|
+
struct msg *rsp_get(struct conn *conn);
|
|
247
|
+
void rsp_put(struct msg *msg);
|
|
248
|
+
struct msg *rsp_recv_next(struct context *ctx, struct conn *conn, bool alloc);
|
|
249
|
+
void rsp_recv_done(struct context *ctx, struct conn *conn, struct msg *msg, struct msg *nmsg);
|
|
250
|
+
struct msg *rsp_send_next(struct context *ctx, struct conn *conn);
|
|
251
|
+
void rsp_send_done(struct context *ctx, struct conn *conn, struct msg *msg);
|
|
252
|
+
|
|
253
|
+
#endif
|
|
@@ -0,0 +1,359 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* twemproxy - A fast and lightweight proxy for memcached protocol.
|
|
3
|
+
* Copyright (C) 2011 Twitter, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
#include <sys/un.h>
|
|
19
|
+
|
|
20
|
+
#include <nc_core.h>
|
|
21
|
+
#include <nc_server.h>
|
|
22
|
+
#include <nc_event.h>
|
|
23
|
+
#include <nc_proxy.h>
|
|
24
|
+
|
|
25
|
+
void
|
|
26
|
+
proxy_ref(struct conn *conn, void *owner)
|
|
27
|
+
{
|
|
28
|
+
struct server_pool *pool = owner;
|
|
29
|
+
|
|
30
|
+
ASSERT(!conn->client && conn->proxy);
|
|
31
|
+
ASSERT(conn->owner == NULL);
|
|
32
|
+
|
|
33
|
+
conn->family = pool->family;
|
|
34
|
+
conn->addrlen = pool->addrlen;
|
|
35
|
+
conn->addr = pool->addr;
|
|
36
|
+
|
|
37
|
+
pool->p_conn = conn;
|
|
38
|
+
|
|
39
|
+
/* owner of the proxy connection is the server pool */
|
|
40
|
+
conn->owner = owner;
|
|
41
|
+
|
|
42
|
+
log_debug(LOG_VVERB, "ref conn %p owner %p into pool %"PRIu32"", conn,
|
|
43
|
+
pool, pool->idx);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
void
|
|
47
|
+
proxy_unref(struct conn *conn)
|
|
48
|
+
{
|
|
49
|
+
struct server_pool *pool;
|
|
50
|
+
|
|
51
|
+
ASSERT(!conn->client && conn->proxy);
|
|
52
|
+
ASSERT(conn->owner != NULL);
|
|
53
|
+
|
|
54
|
+
pool = conn->owner;
|
|
55
|
+
conn->owner = NULL;
|
|
56
|
+
|
|
57
|
+
pool->p_conn = NULL;
|
|
58
|
+
|
|
59
|
+
log_debug(LOG_VVERB, "unref conn %p owner %p from pool %"PRIu32"", conn,
|
|
60
|
+
pool, pool->idx);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void
|
|
64
|
+
proxy_close(struct context *ctx, struct conn *conn)
|
|
65
|
+
{
|
|
66
|
+
rstatus_t status;
|
|
67
|
+
|
|
68
|
+
ASSERT(!conn->client && conn->proxy);
|
|
69
|
+
|
|
70
|
+
if (conn->sd < 0) {
|
|
71
|
+
conn->unref(conn);
|
|
72
|
+
conn_put(conn);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
ASSERT(conn->rmsg == NULL);
|
|
77
|
+
ASSERT(conn->smsg == NULL);
|
|
78
|
+
ASSERT(TAILQ_EMPTY(&conn->imsg_q));
|
|
79
|
+
ASSERT(TAILQ_EMPTY(&conn->omsg_q));
|
|
80
|
+
|
|
81
|
+
conn->unref(conn);
|
|
82
|
+
|
|
83
|
+
status = close(conn->sd);
|
|
84
|
+
if (status < 0) {
|
|
85
|
+
log_error("close p %d failed, ignored: %s", conn->sd, strerror(errno));
|
|
86
|
+
}
|
|
87
|
+
conn->sd = -1;
|
|
88
|
+
|
|
89
|
+
conn_put(conn);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
static rstatus_t
|
|
93
|
+
proxy_reuse(struct conn *p)
|
|
94
|
+
{
|
|
95
|
+
rstatus_t status;
|
|
96
|
+
struct sockaddr_un *un;
|
|
97
|
+
|
|
98
|
+
switch (p->family) {
|
|
99
|
+
case AF_INET:
|
|
100
|
+
case AF_INET6:
|
|
101
|
+
status = nc_set_reuseaddr(p->sd);
|
|
102
|
+
break;
|
|
103
|
+
|
|
104
|
+
case AF_UNIX:
|
|
105
|
+
/*
|
|
106
|
+
* bind() will fail if the pathname already exist. So, we call unlink()
|
|
107
|
+
* to delete the pathname, in case it already exists. If it does not
|
|
108
|
+
* exist, unlink() returns error, which we ignore
|
|
109
|
+
*/
|
|
110
|
+
un = (struct sockaddr_un *) p->addr;
|
|
111
|
+
unlink(un->sun_path);
|
|
112
|
+
status = NC_OK;
|
|
113
|
+
break;
|
|
114
|
+
|
|
115
|
+
default:
|
|
116
|
+
NOT_REACHED();
|
|
117
|
+
status = NC_ERROR;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return status;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
static rstatus_t
|
|
124
|
+
proxy_listen(struct context *ctx, struct conn *p)
|
|
125
|
+
{
|
|
126
|
+
rstatus_t status;
|
|
127
|
+
struct server_pool *pool = p->owner;
|
|
128
|
+
|
|
129
|
+
ASSERT(p->proxy);
|
|
130
|
+
|
|
131
|
+
p->sd = socket(p->family, SOCK_STREAM, 0);
|
|
132
|
+
if (p->sd < 0) {
|
|
133
|
+
log_error("socket failed: %s", strerror(errno));
|
|
134
|
+
return NC_ERROR;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
status = proxy_reuse(p);
|
|
138
|
+
if (status < 0) {
|
|
139
|
+
log_error("reuse of addr '%.*s' for listening on p %d failed: %s",
|
|
140
|
+
pool->addrstr.len, pool->addrstr.data, p->sd,
|
|
141
|
+
strerror(errno));
|
|
142
|
+
return NC_ERROR;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
status = bind(p->sd, p->addr, p->addrlen);
|
|
146
|
+
if (status < 0) {
|
|
147
|
+
log_error("bind on p %d to addr '%.*s' failed: %s", p->sd,
|
|
148
|
+
pool->addrstr.len, pool->addrstr.data, strerror(errno));
|
|
149
|
+
return NC_ERROR;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
status = listen(p->sd, pool->backlog);
|
|
153
|
+
if (status < 0) {
|
|
154
|
+
log_error("listen on p %d on addr '%.*s' failed: %s", p->sd,
|
|
155
|
+
pool->addrstr.len, pool->addrstr.data, strerror(errno));
|
|
156
|
+
return NC_ERROR;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
status = nc_set_nonblocking(p->sd);
|
|
160
|
+
if (status < 0) {
|
|
161
|
+
log_error("set nonblock on p %d on addr '%.*s' failed: %s", p->sd,
|
|
162
|
+
pool->addrstr.len, pool->addrstr.data, strerror(errno));
|
|
163
|
+
return NC_ERROR;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
status = event_add_conn(ctx->ep, p);
|
|
167
|
+
if (status < 0) {
|
|
168
|
+
log_error("event add conn e %d p %d on addr '%.*s' failed: %s",
|
|
169
|
+
ctx->ep, p->sd, pool->addrstr.len, pool->addrstr.data,
|
|
170
|
+
strerror(errno));
|
|
171
|
+
return NC_ERROR;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
status = event_del_out(ctx->ep, p);
|
|
175
|
+
if (status < 0) {
|
|
176
|
+
log_error("event del out e %d p %d on addr '%.*s' failed: %s",
|
|
177
|
+
ctx->ep, p->sd, pool->addrstr.len, pool->addrstr.data,
|
|
178
|
+
strerror(errno));
|
|
179
|
+
return NC_ERROR;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return NC_OK;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
rstatus_t
|
|
186
|
+
proxy_each_init(void *elem, void *data)
|
|
187
|
+
{
|
|
188
|
+
rstatus_t status;
|
|
189
|
+
struct server_pool *pool = elem;
|
|
190
|
+
struct conn *p;
|
|
191
|
+
|
|
192
|
+
p = conn_get_proxy(pool);
|
|
193
|
+
if (p == NULL) {
|
|
194
|
+
return NC_ENOMEM;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
status = proxy_listen(pool->ctx, p);
|
|
198
|
+
if (status != NC_OK) {
|
|
199
|
+
p->close(pool->ctx, p);
|
|
200
|
+
return status;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
log_debug(LOG_NOTICE, "p %d listening on '%.*s' in %s pool %"PRIu32" '%.*s'"
|
|
204
|
+
" with %"PRIu32" servers", p->sd, pool->addrstr.len,
|
|
205
|
+
pool->addrstr.data, pool->redis ? "redis" : "memcache",
|
|
206
|
+
pool->idx, pool->name.len, pool->name.data,
|
|
207
|
+
array_n(&pool->server));
|
|
208
|
+
|
|
209
|
+
return NC_OK;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
rstatus_t
|
|
213
|
+
proxy_init(struct context *ctx)
|
|
214
|
+
{
|
|
215
|
+
rstatus_t status;
|
|
216
|
+
|
|
217
|
+
ASSERT(array_n(&ctx->pool) != 0);
|
|
218
|
+
|
|
219
|
+
status = array_each(&ctx->pool, proxy_each_init, NULL);
|
|
220
|
+
if (status != NC_OK) {
|
|
221
|
+
proxy_deinit(ctx);
|
|
222
|
+
return status;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
log_debug(LOG_VVERB, "init proxy with %"PRIu32" pools",
|
|
226
|
+
array_n(&ctx->pool));
|
|
227
|
+
|
|
228
|
+
return NC_OK;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
rstatus_t
|
|
232
|
+
proxy_each_deinit(void *elem, void *data)
|
|
233
|
+
{
|
|
234
|
+
struct server_pool *pool = elem;
|
|
235
|
+
struct conn *p;
|
|
236
|
+
|
|
237
|
+
p = pool->p_conn;
|
|
238
|
+
if (p != NULL) {
|
|
239
|
+
p->close(pool->ctx, p);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
return NC_OK;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
void
|
|
246
|
+
proxy_deinit(struct context *ctx)
|
|
247
|
+
{
|
|
248
|
+
rstatus_t status;
|
|
249
|
+
|
|
250
|
+
ASSERT(array_n(&ctx->pool) != 0);
|
|
251
|
+
|
|
252
|
+
status = array_each(&ctx->pool, proxy_each_deinit, NULL);
|
|
253
|
+
if (status != NC_OK) {
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
log_debug(LOG_VVERB, "deinit proxy with %"PRIu32" pools",
|
|
258
|
+
array_n(&ctx->pool));
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
static rstatus_t
|
|
262
|
+
proxy_accept(struct context *ctx, struct conn *p)
|
|
263
|
+
{
|
|
264
|
+
rstatus_t status;
|
|
265
|
+
struct conn *c;
|
|
266
|
+
int sd;
|
|
267
|
+
|
|
268
|
+
ASSERT(p->proxy && !p->client);
|
|
269
|
+
ASSERT(p->sd > 0);
|
|
270
|
+
ASSERT(p->recv_active && p->recv_ready);
|
|
271
|
+
|
|
272
|
+
for (;;) {
|
|
273
|
+
sd = accept(p->sd, NULL, NULL);
|
|
274
|
+
if (sd < 0) {
|
|
275
|
+
if (errno == EINTR) {
|
|
276
|
+
log_debug(LOG_VERB, "accept on p %d not ready - eintr", p->sd);
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
|
281
|
+
log_debug(LOG_VERB, "accept on p %d not ready - eagain", p->sd);
|
|
282
|
+
p->recv_ready = 0;
|
|
283
|
+
return NC_OK;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
/*
|
|
287
|
+
* FIXME: On EMFILE or ENFILE mask out IN event on the proxy; mask
|
|
288
|
+
* it back in when some existing connection gets closed
|
|
289
|
+
*/
|
|
290
|
+
|
|
291
|
+
log_error("accept on p %d failed: %s", p->sd, strerror(errno));
|
|
292
|
+
return NC_ERROR;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
break;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
c = conn_get(p->owner, true, p->redis);
|
|
299
|
+
if (c == NULL) {
|
|
300
|
+
log_error("get conn for c %d from p %d failed: %s", sd, p->sd,
|
|
301
|
+
strerror(errno));
|
|
302
|
+
status = close(sd);
|
|
303
|
+
if (status < 0) {
|
|
304
|
+
log_error("close c %d failed, ignored: %s", sd, strerror(errno));
|
|
305
|
+
}
|
|
306
|
+
return NC_ENOMEM;
|
|
307
|
+
}
|
|
308
|
+
c->sd = sd;
|
|
309
|
+
|
|
310
|
+
stats_pool_incr(ctx, c->owner, client_connections);
|
|
311
|
+
|
|
312
|
+
status = nc_set_nonblocking(c->sd);
|
|
313
|
+
if (status < 0) {
|
|
314
|
+
log_error("set nonblock on c %d from p %d failed: %s", c->sd, p->sd,
|
|
315
|
+
strerror(errno));
|
|
316
|
+
c->close(ctx, c);
|
|
317
|
+
return status;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (p->family == AF_INET || p->family == AF_INET6) {
|
|
321
|
+
status = nc_set_tcpnodelay(c->sd);
|
|
322
|
+
if (status < 0) {
|
|
323
|
+
log_warn("set tcpnodelay on c %d from p %d failed, ignored: %s",
|
|
324
|
+
c->sd, p->sd, strerror(errno));
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
status = event_add_conn(ctx->ep, c);
|
|
329
|
+
if (status < 0) {
|
|
330
|
+
log_error("event add conn of c %d from p %d failed: %s", c->sd, p->sd,
|
|
331
|
+
strerror(errno));
|
|
332
|
+
c->close(ctx, c);
|
|
333
|
+
return status;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
log_debug(LOG_NOTICE, "accepted c %d on p %d from '%s'", c->sd, p->sd,
|
|
337
|
+
nc_unresolve_peer_desc(c->sd));
|
|
338
|
+
|
|
339
|
+
return NC_OK;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
rstatus_t
|
|
343
|
+
proxy_recv(struct context *ctx, struct conn *conn)
|
|
344
|
+
{
|
|
345
|
+
rstatus_t status;
|
|
346
|
+
|
|
347
|
+
ASSERT(conn->proxy && !conn->client);
|
|
348
|
+
ASSERT(conn->recv_active);
|
|
349
|
+
|
|
350
|
+
conn->recv_ready = 1;
|
|
351
|
+
do {
|
|
352
|
+
status = proxy_accept(ctx, conn);
|
|
353
|
+
if (status != NC_OK) {
|
|
354
|
+
return status;
|
|
355
|
+
}
|
|
356
|
+
} while (conn->recv_ready);
|
|
357
|
+
|
|
358
|
+
return NC_OK;
|
|
359
|
+
}
|