nutcracker 0.4.0.16 → 0.4.1.18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +3 -3
- data/ext/nutcracker/ChangeLog +33 -8
- data/ext/nutcracker/Makefile.in +34 -21
- data/ext/nutcracker/README.md +61 -26
- data/ext/nutcracker/aclocal.m4 +34 -31
- data/ext/nutcracker/autom4te.cache/output.0 +1875 -1330
- data/ext/nutcracker/autom4te.cache/output.1 +1875 -1330
- data/ext/nutcracker/autom4te.cache/requests +232 -451
- data/ext/nutcracker/autom4te.cache/traces.0 +2256 -2129
- data/ext/nutcracker/autom4te.cache/traces.1 +73 -59
- data/ext/nutcracker/config.h.in +1 -2
- data/ext/nutcracker/config.h.in~ +333 -0
- data/ext/nutcracker/config/compile +1 -1
- data/ext/nutcracker/config/config.guess +13 -160
- data/ext/nutcracker/config/config.sub +25 -11
- data/ext/nutcracker/config/depcomp +1 -1
- data/ext/nutcracker/config/install-sh +170 -196
- data/ext/nutcracker/config/ltmain.sh +3509 -2018
- data/ext/nutcracker/config/missing +1 -1
- data/ext/nutcracker/configure +1874 -1329
- data/ext/nutcracker/configure.ac +3 -2
- data/ext/nutcracker/contrib/Makefile.in +18 -5
- 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 +832 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/README +27 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +1157 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/autom4te.cache/output.0 +13342 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/autom4te.cache/output.1 +14611 -0
- data/ext/nutcracker/{autom4te.cache → contrib/yaml-0.1.4/autom4te.cache}/output.2 +3465 -8761
- data/ext/nutcracker/contrib/yaml-0.1.4/autom4te.cache/requests +516 -0
- data/ext/nutcracker/{autom4te.cache/traces.2 → contrib/yaml-0.1.4/autom4te.cache/traces.0} +662 -698
- data/ext/nutcracker/contrib/yaml-0.1.4/autom4te.cache/traces.1 +577 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/autom4te.cache/traces.2 +2721 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +79 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in~ +80 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/compile +347 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +1421 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +1807 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +791 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +501 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +11147 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +215 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/config/test-driver +148 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/configure +14611 -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 +8369 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +437 -0
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +124 -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 +99 -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 +600 -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 +1083 -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/m4/libtool.m4 +1474 -1087
- data/ext/nutcracker/m4/ltoptions.m4 +90 -37
- data/ext/nutcracker/m4/ltsugar.m4 +4 -3
- data/ext/nutcracker/m4/ltversion.m4 +6 -6
- data/ext/nutcracker/m4/lt~obsolete.m4 +4 -3
- data/ext/nutcracker/man/nutcracker.8 +1 -1
- data/ext/nutcracker/notes/memcache.md +162 -0
- data/ext/nutcracker/notes/recommendation.md +10 -5
- data/ext/nutcracker/notes/redis.md +23 -9
- data/ext/nutcracker/scripts/nutcracker.init +10 -0
- data/ext/nutcracker/scripts/nutcracker.init.debian +83 -0
- data/ext/nutcracker/scripts/nutcracker.spec +36 -2
- data/ext/nutcracker/scripts/redis-check.sh +4 -0
- data/ext/nutcracker/src/Makefile.am +6 -1
- data/ext/nutcracker/src/Makefile.in +26 -12
- data/ext/nutcracker/src/event/Makefile.in +19 -6
- data/ext/nutcracker/src/hashkit/Makefile.in +19 -6
- data/ext/nutcracker/src/hashkit/nc_jenkins.c +1 -1
- data/ext/nutcracker/src/hashkit/nc_ketama.c +3 -3
- data/ext/nutcracker/src/nc.c +1 -1
- data/ext/nutcracker/src/nc_conf.c +67 -19
- data/ext/nutcracker/src/nc_conf.h +9 -4
- data/ext/nutcracker/src/nc_connection.c +35 -2
- data/ext/nutcracker/src/nc_connection.h +53 -47
- data/ext/nutcracker/src/nc_core.c +8 -1
- data/ext/nutcracker/src/nc_message.c +23 -7
- data/ext/nutcracker/src/nc_message.h +24 -1
- data/ext/nutcracker/src/nc_proxy.c +14 -3
- data/ext/nutcracker/src/nc_rbtree.c +1 -5
- data/ext/nutcracker/src/nc_request.c +58 -10
- data/ext/nutcracker/src/nc_response.c +27 -4
- data/ext/nutcracker/src/nc_server.c +33 -5
- data/ext/nutcracker/src/nc_server.h +10 -9
- data/ext/nutcracker/src/nc_string.h +17 -0
- data/ext/nutcracker/src/nc_util.c +5 -1
- data/ext/nutcracker/src/proto/Makefile.in +19 -6
- data/ext/nutcracker/src/proto/nc_memcache.c +76 -12
- data/ext/nutcracker/src/proto/nc_proto.h +9 -0
- data/ext/nutcracker/src/proto/nc_redis.c +400 -18
- data/lib/nutcracker.rb +1 -1
- data/lib/nutcracker/version.rb +1 -1
- metadata +61 -6
- data/ext/nutcracker/notes/memcache.txt +0 -123
@@ -311,7 +311,14 @@ core_core(void *arg, uint32_t events)
|
|
311
311
|
{
|
312
312
|
rstatus_t status;
|
313
313
|
struct conn *conn = arg;
|
314
|
-
struct context *ctx
|
314
|
+
struct context *ctx;
|
315
|
+
|
316
|
+
if (conn->owner == NULL) {
|
317
|
+
log_warn("conn is already unrefed!");
|
318
|
+
return NC_OK;
|
319
|
+
}
|
320
|
+
|
321
|
+
ctx = conn_to_ctx(conn);
|
315
322
|
|
316
323
|
log_debug(LOG_VVERB, "event %04"PRIX32" on %c %d", events,
|
317
324
|
conn->client ? 'c' : (conn->proxy ? 'p' : 's'), conn->sd);
|
@@ -226,6 +226,7 @@ done:
|
|
226
226
|
msg->token = NULL;
|
227
227
|
|
228
228
|
msg->parser = NULL;
|
229
|
+
msg->add_auth = NULL;
|
229
230
|
msg->result = MSG_PARSE_OK;
|
230
231
|
|
231
232
|
msg->fragment = NULL;
|
@@ -292,8 +293,10 @@ msg_get(struct conn *conn, bool request, bool redis)
|
|
292
293
|
} else {
|
293
294
|
msg->parser = redis_parse_rsp;
|
294
295
|
}
|
296
|
+
msg->add_auth = redis_add_auth;
|
295
297
|
msg->fragment = redis_fragment;
|
296
298
|
msg->reply = redis_reply;
|
299
|
+
msg->failure = redis_failure;
|
297
300
|
msg->pre_coalesce = redis_pre_coalesce;
|
298
301
|
msg->post_coalesce = redis_post_coalesce;
|
299
302
|
} else {
|
@@ -302,7 +305,9 @@ msg_get(struct conn *conn, bool request, bool redis)
|
|
302
305
|
} else {
|
303
306
|
msg->parser = memcache_parse_rsp;
|
304
307
|
}
|
308
|
+
msg->add_auth = memcache_add_auth;
|
305
309
|
msg->fragment = memcache_fragment;
|
310
|
+
msg->failure = memcache_failure;
|
306
311
|
msg->pre_coalesce = memcache_pre_coalesce;
|
307
312
|
msg->post_coalesce = memcache_post_coalesce;
|
308
313
|
}
|
@@ -472,11 +477,13 @@ msg_ensure_mbuf(struct msg *msg, size_t len)
|
|
472
477
|
} else {
|
473
478
|
mbuf = STAILQ_LAST(&msg->mhdr, mbuf, next);
|
474
479
|
}
|
480
|
+
|
475
481
|
return mbuf;
|
476
482
|
}
|
477
483
|
|
478
484
|
/*
|
479
|
-
*
|
485
|
+
* Append n bytes of data, with n <= mbuf_size(mbuf)
|
486
|
+
* into mbuf
|
480
487
|
*/
|
481
488
|
rstatus_t
|
482
489
|
msg_append(struct msg *msg, uint8_t *pos, size_t n)
|
@@ -494,11 +501,13 @@ msg_append(struct msg *msg, uint8_t *pos, size_t n)
|
|
494
501
|
|
495
502
|
mbuf_copy(mbuf, pos, n);
|
496
503
|
msg->mlen += (uint32_t)n;
|
504
|
+
|
497
505
|
return NC_OK;
|
498
506
|
}
|
499
507
|
|
500
508
|
/*
|
501
|
-
*
|
509
|
+
* Prepend n bytes of data, with n <= mbuf_size(mbuf)
|
510
|
+
* into mbuf
|
502
511
|
*/
|
503
512
|
rstatus_t
|
504
513
|
msg_prepend(struct msg *msg, uint8_t *pos, size_t n)
|
@@ -516,17 +525,20 @@ msg_prepend(struct msg *msg, uint8_t *pos, size_t n)
|
|
516
525
|
msg->mlen += (uint32_t)n;
|
517
526
|
|
518
527
|
STAILQ_INSERT_HEAD(&msg->mhdr, mbuf, next);
|
528
|
+
|
519
529
|
return NC_OK;
|
520
530
|
}
|
521
531
|
|
522
532
|
/*
|
523
|
-
*
|
533
|
+
* Prepend a formatted string into msg. Returns an error if the formatted
|
534
|
+
* string does not fit in a single mbuf.
|
524
535
|
*/
|
525
536
|
rstatus_t
|
526
537
|
msg_prepend_format(struct msg *msg, const char *fmt, ...)
|
527
538
|
{
|
528
539
|
struct mbuf *mbuf;
|
529
|
-
|
540
|
+
int n;
|
541
|
+
uint32_t size;
|
530
542
|
va_list args;
|
531
543
|
|
532
544
|
mbuf = mbuf_get();
|
@@ -534,15 +546,19 @@ msg_prepend_format(struct msg *msg, const char *fmt, ...)
|
|
534
546
|
return NC_ENOMEM;
|
535
547
|
}
|
536
548
|
|
549
|
+
size = mbuf_size(mbuf);
|
550
|
+
|
537
551
|
va_start(args, fmt);
|
538
|
-
n =
|
552
|
+
n = nc_vsnprintf(mbuf->last, size, fmt, args);
|
539
553
|
va_end(args);
|
554
|
+
if (n <= 0 || n >= (int)size) {
|
555
|
+
return NC_ERROR;
|
556
|
+
}
|
540
557
|
|
541
558
|
mbuf->last += n;
|
542
559
|
msg->mlen += (uint32_t)n;
|
543
|
-
|
544
|
-
ASSERT(mbuf_size(mbuf) >= 0);
|
545
560
|
STAILQ_INSERT_HEAD(&msg->mhdr, mbuf, next);
|
561
|
+
|
546
562
|
return NC_OK;
|
547
563
|
}
|
548
564
|
|
@@ -21,9 +21,11 @@
|
|
21
21
|
#include <nc_core.h>
|
22
22
|
|
23
23
|
typedef void (*msg_parse_t)(struct msg *);
|
24
|
+
typedef rstatus_t (*msg_add_auth_t)(struct context *ctx, struct conn *c_conn, struct conn *s_conn);
|
24
25
|
typedef rstatus_t (*msg_fragment_t)(struct msg *, uint32_t, struct msg_tqh *);
|
25
26
|
typedef void (*msg_coalesce_t)(struct msg *r);
|
26
27
|
typedef rstatus_t (*msg_reply_t)(struct msg *r);
|
28
|
+
typedef bool (*msg_failure_t)(struct msg *r);
|
27
29
|
|
28
30
|
typedef enum msg_parse_result {
|
29
31
|
MSG_PARSE_OK, /* parsing ok */
|
@@ -45,6 +47,7 @@ typedef enum msg_parse_result {
|
|
45
47
|
ACTION( REQ_MC_PREPEND ) \
|
46
48
|
ACTION( REQ_MC_INCR ) /* memcache arithmetic request */ \
|
47
49
|
ACTION( REQ_MC_DECR ) \
|
50
|
+
ACTION( REQ_MC_TOUCH ) /* memcache touch request */ \
|
48
51
|
ACTION( REQ_MC_QUIT ) /* memcache quit request */ \
|
49
52
|
ACTION( RSP_MC_NUM ) /* memcache arithmetic response */ \
|
50
53
|
ACTION( RSP_MC_STORED ) /* memcache cas and storage response */ \
|
@@ -54,6 +57,7 @@ typedef enum msg_parse_result {
|
|
54
57
|
ACTION( RSP_MC_END ) \
|
55
58
|
ACTION( RSP_MC_VALUE ) \
|
56
59
|
ACTION( RSP_MC_DELETED ) /* memcache delete response */ \
|
60
|
+
ACTION( RSP_MC_TOUCHED ) /* memcache touch response */ \
|
57
61
|
ACTION( RSP_MC_ERROR ) /* memcache error responses */ \
|
58
62
|
ACTION( RSP_MC_CLIENT_ERROR ) \
|
59
63
|
ACTION( RSP_MC_SERVER_ERROR ) \
|
@@ -160,8 +164,23 @@ typedef enum msg_parse_result {
|
|
160
164
|
ACTION( REQ_REDIS_EVALSHA ) \
|
161
165
|
ACTION( REQ_REDIS_PING ) /* redis requests - ping/quit */ \
|
162
166
|
ACTION( REQ_REDIS_QUIT) \
|
167
|
+
ACTION( REQ_REDIS_AUTH) \
|
168
|
+
ACTION( REQ_REDIS_SELECT) /* only during init */ \
|
163
169
|
ACTION( RSP_REDIS_STATUS ) /* redis response */ \
|
164
170
|
ACTION( RSP_REDIS_ERROR ) \
|
171
|
+
ACTION( RSP_REDIS_ERROR_ERR ) \
|
172
|
+
ACTION( RSP_REDIS_ERROR_OOM ) \
|
173
|
+
ACTION( RSP_REDIS_ERROR_BUSY ) \
|
174
|
+
ACTION( RSP_REDIS_ERROR_NOAUTH ) \
|
175
|
+
ACTION( RSP_REDIS_ERROR_LOADING ) \
|
176
|
+
ACTION( RSP_REDIS_ERROR_BUSYKEY ) \
|
177
|
+
ACTION( RSP_REDIS_ERROR_MISCONF ) \
|
178
|
+
ACTION( RSP_REDIS_ERROR_NOSCRIPT ) \
|
179
|
+
ACTION( RSP_REDIS_ERROR_READONLY ) \
|
180
|
+
ACTION( RSP_REDIS_ERROR_WRONGTYPE ) \
|
181
|
+
ACTION( RSP_REDIS_ERROR_EXECABORT ) \
|
182
|
+
ACTION( RSP_REDIS_ERROR_MASTERDOWN ) \
|
183
|
+
ACTION( RSP_REDIS_ERROR_NOREPLICAS ) \
|
165
184
|
ACTION( RSP_REDIS_INTEGER ) \
|
166
185
|
ACTION( RSP_REDIS_BULK ) \
|
167
186
|
ACTION( RSP_REDIS_MULTIBULK ) \
|
@@ -202,7 +221,10 @@ struct msg {
|
|
202
221
|
msg_parse_result_t result; /* message parsing result */
|
203
222
|
|
204
223
|
msg_fragment_t fragment; /* message fragment */
|
205
|
-
msg_reply_t reply; /*
|
224
|
+
msg_reply_t reply; /* generate message reply (example: ping) */
|
225
|
+
msg_add_auth_t add_auth; /* add auth message when we forward msg */
|
226
|
+
msg_failure_t failure; /* transient failure response? */
|
227
|
+
|
206
228
|
msg_coalesce_t pre_coalesce; /* message pre-coalesce */
|
207
229
|
msg_coalesce_t post_coalesce; /* message post-coalesce */
|
208
230
|
|
@@ -267,6 +289,7 @@ void req_put(struct msg *msg);
|
|
267
289
|
bool req_done(struct conn *conn, struct msg *msg);
|
268
290
|
bool req_error(struct conn *conn, struct msg *msg);
|
269
291
|
void req_server_enqueue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
292
|
+
void req_server_enqueue_imsgq_head(struct context *ctx, struct conn *conn, struct msg *msg);
|
270
293
|
void req_server_dequeue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
271
294
|
void req_client_enqueue_omsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
272
295
|
void req_server_enqueue_omsgq(struct context *ctx, struct conn *conn, struct msg *msg);
|
@@ -15,6 +15,7 @@
|
|
15
15
|
* limitations under the License.
|
16
16
|
*/
|
17
17
|
|
18
|
+
#include <sys/stat.h>
|
18
19
|
#include <sys/un.h>
|
19
20
|
|
20
21
|
#include <nc_core.h>
|
@@ -29,9 +30,9 @@ proxy_ref(struct conn *conn, void *owner)
|
|
29
30
|
ASSERT(!conn->client && conn->proxy);
|
30
31
|
ASSERT(conn->owner == NULL);
|
31
32
|
|
32
|
-
conn->family = pool->family;
|
33
|
-
conn->addrlen = pool->addrlen;
|
34
|
-
conn->addr = pool->addr;
|
33
|
+
conn->family = pool->info.family;
|
34
|
+
conn->addrlen = pool->info.addrlen;
|
35
|
+
conn->addr = (struct sockaddr *)&pool->info.addr;
|
35
36
|
|
36
37
|
pool->p_conn = conn;
|
37
38
|
|
@@ -148,6 +149,16 @@ proxy_listen(struct context *ctx, struct conn *p)
|
|
148
149
|
return NC_ERROR;
|
149
150
|
}
|
150
151
|
|
152
|
+
if (p->family == AF_UNIX && pool->perm) {
|
153
|
+
struct sockaddr_un *un = (struct sockaddr_un *)p->addr;
|
154
|
+
status = chmod(un->sun_path, pool->perm);
|
155
|
+
if (status < 0) {
|
156
|
+
log_error("chmod on p %d on addr '%.*s' failed: %s", p->sd,
|
157
|
+
pool->addrstr.len, pool->addrstr.data, strerror(errno));
|
158
|
+
return NC_ERROR;
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
151
162
|
status = listen(p->sd, pool->backlog);
|
152
163
|
if (status < 0) {
|
153
164
|
log_error("listen on p %d on addr '%.*s' failed: %s", p->sd,
|
@@ -218,11 +218,7 @@ rbtree_delete(struct rbtree *tree, struct rbnode *node)
|
|
218
218
|
subst = node;
|
219
219
|
} else {
|
220
220
|
subst = rbtree_node_min(node->right, sentinel);
|
221
|
-
|
222
|
-
temp = subst->left;
|
223
|
-
} else {
|
224
|
-
temp = subst->right;
|
225
|
-
}
|
221
|
+
temp = subst->right;
|
226
222
|
}
|
227
223
|
|
228
224
|
if (subst == *root) {
|
@@ -303,7 +303,7 @@ req_server_enqueue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg
|
|
303
303
|
* or the message is dequeued from the server out_q
|
304
304
|
*
|
305
305
|
* noreply request are free from timeouts because client is not intrested
|
306
|
-
* in the
|
306
|
+
* in the response anyway!
|
307
307
|
*/
|
308
308
|
if (!msg->noreply) {
|
309
309
|
msg_tmo_insert(msg, conn);
|
@@ -315,6 +315,30 @@ req_server_enqueue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg
|
|
315
315
|
stats_server_incr_by(ctx, conn->owner, in_queue_bytes, msg->mlen);
|
316
316
|
}
|
317
317
|
|
318
|
+
void
|
319
|
+
req_server_enqueue_imsgq_head(struct context *ctx, struct conn *conn, struct msg *msg)
|
320
|
+
{
|
321
|
+
ASSERT(msg->request);
|
322
|
+
ASSERT(!conn->client && !conn->proxy);
|
323
|
+
|
324
|
+
/*
|
325
|
+
* timeout clock starts ticking the instant the message is enqueued into
|
326
|
+
* the server in_q; the clock continues to tick until it either expires
|
327
|
+
* or the message is dequeued from the server out_q
|
328
|
+
*
|
329
|
+
* noreply request are free from timeouts because client is not intrested
|
330
|
+
* in the reponse anyway!
|
331
|
+
*/
|
332
|
+
if (!msg->noreply) {
|
333
|
+
msg_tmo_insert(msg, conn);
|
334
|
+
}
|
335
|
+
|
336
|
+
TAILQ_INSERT_HEAD(&conn->imsg_q, msg, s_tqe);
|
337
|
+
|
338
|
+
stats_server_incr(ctx, conn->owner, in_queue);
|
339
|
+
stats_server_incr_by(ctx, conn->owner, in_queue_bytes, msg->mlen);
|
340
|
+
}
|
341
|
+
|
318
342
|
void
|
319
343
|
req_server_dequeue_imsgq(struct context *ctx, struct conn *conn, struct msg *msg)
|
320
344
|
{
|
@@ -429,20 +453,21 @@ req_recv_next(struct context *ctx, struct conn *conn, bool alloc)
|
|
429
453
|
static rstatus_t
|
430
454
|
req_make_reply(struct context *ctx, struct conn *conn, struct msg *req)
|
431
455
|
{
|
432
|
-
struct msg *
|
456
|
+
struct msg *rsp;
|
433
457
|
|
434
|
-
|
435
|
-
if (
|
458
|
+
rsp = msg_get(conn, false, conn->redis); /* replay */
|
459
|
+
if (rsp == NULL) {
|
436
460
|
conn->err = errno;
|
437
461
|
return NC_ENOMEM;
|
438
462
|
}
|
439
463
|
|
440
|
-
req->peer =
|
441
|
-
|
442
|
-
|
464
|
+
req->peer = rsp;
|
465
|
+
rsp->peer = req;
|
466
|
+
rsp->request = 0;
|
443
467
|
|
444
468
|
req->done = 1;
|
445
469
|
conn->enqueue_outq(ctx, conn, req);
|
470
|
+
|
446
471
|
return NC_OK;
|
447
472
|
}
|
448
473
|
|
@@ -460,19 +485,32 @@ req_filter(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
460
485
|
}
|
461
486
|
|
462
487
|
/*
|
463
|
-
* Handle "quit\r\n"
|
464
|
-
* passive close
|
488
|
+
* Handle "quit\r\n" (memcache) or "*1\r\n$4\r\nquit\r\n" (redis), which
|
489
|
+
* is the protocol way of doing a passive close. The connection is closed
|
490
|
+
* as soon as all pending replies have been written to the client.
|
465
491
|
*/
|
466
492
|
if (msg->quit) {
|
467
|
-
ASSERT(conn->rmsg == NULL);
|
468
493
|
log_debug(LOG_INFO, "filter quit req %"PRIu64" from c %d", msg->id,
|
469
494
|
conn->sd);
|
495
|
+
if (conn->rmsg != NULL) {
|
496
|
+
log_debug(LOG_INFO, "discard invalid req %"PRIu64" len %"PRIu32" "
|
497
|
+
"from c %d sent after quit req", conn->rmsg->id,
|
498
|
+
conn->rmsg->mlen, conn->sd);
|
499
|
+
}
|
470
500
|
conn->eof = 1;
|
471
501
|
conn->recv_ready = 0;
|
472
502
|
req_put(msg);
|
473
503
|
return true;
|
474
504
|
}
|
475
505
|
|
506
|
+
/*
|
507
|
+
* If this conn is not authenticated, we will mark it as noforward,
|
508
|
+
* and handle it in the redis_reply handler.
|
509
|
+
*/
|
510
|
+
if (!conn_authenticated(conn)) {
|
511
|
+
msg->noforward = 1;
|
512
|
+
}
|
513
|
+
|
476
514
|
return false;
|
477
515
|
}
|
478
516
|
|
@@ -554,6 +592,16 @@ req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg)
|
|
554
592
|
return;
|
555
593
|
}
|
556
594
|
}
|
595
|
+
|
596
|
+
if (!conn_authenticated(s_conn)) {
|
597
|
+
status = msg->add_auth(ctx, c_conn, s_conn);
|
598
|
+
if (status != NC_OK) {
|
599
|
+
req_forward_error(ctx, c_conn, msg);
|
600
|
+
s_conn->err = errno;
|
601
|
+
return;
|
602
|
+
}
|
603
|
+
}
|
604
|
+
|
557
605
|
s_conn->enqueue_inq(ctx, s_conn, msg);
|
558
606
|
|
559
607
|
req_forward_stats(ctx, s_conn->owner, msg);
|
@@ -171,7 +171,7 @@ rsp_filter(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
171
171
|
* We handle this stray packet scenario in nutcracker by closing the
|
172
172
|
* server connection which would end up sending SERVER_ERROR to all
|
173
173
|
* clients that have requests pending on this server connection. The
|
174
|
-
* fix is
|
174
|
+
* fix is aggressive, but not doing so would lead to clients getting
|
175
175
|
* out of sync with the server and as a result clients end up getting
|
176
176
|
* responses that don't correspond to the right request.
|
177
177
|
*
|
@@ -184,7 +184,28 @@ rsp_filter(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
184
184
|
ASSERT(pmsg->peer == NULL);
|
185
185
|
ASSERT(pmsg->request && !pmsg->done);
|
186
186
|
|
187
|
+
/*
|
188
|
+
* If the response from a server suggests a protocol level transient
|
189
|
+
* failure, close the server connection and send back a generic error
|
190
|
+
* response to the client.
|
191
|
+
*
|
192
|
+
* If auto_eject_host is enabled, this will also update the failure_count
|
193
|
+
* and eject the server if it exceeds the failure_limit
|
194
|
+
*/
|
195
|
+
if (msg->failure(msg)) {
|
196
|
+
log_debug(LOG_INFO, "server failure rsp %"PRIu64" len %"PRIu32" "
|
197
|
+
"type %d on s %d", msg->id, msg->mlen, msg->type, conn->sd);
|
198
|
+
rsp_put(msg);
|
199
|
+
|
200
|
+
conn->err = EINVAL;
|
201
|
+
conn->done = 1;
|
202
|
+
|
203
|
+
return true;
|
204
|
+
}
|
205
|
+
|
187
206
|
if (pmsg->swallow) {
|
207
|
+
conn->swallow_msg(conn, pmsg, msg);
|
208
|
+
|
188
209
|
conn->dequeue_outq(ctx, conn, pmsg);
|
189
210
|
pmsg->done = 1;
|
190
211
|
|
@@ -201,12 +222,12 @@ rsp_filter(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
201
222
|
}
|
202
223
|
|
203
224
|
static void
|
204
|
-
rsp_forward_stats(struct context *ctx, struct server *server, struct msg *msg)
|
225
|
+
rsp_forward_stats(struct context *ctx, struct server *server, struct msg *msg, uint32_t msgsize)
|
205
226
|
{
|
206
227
|
ASSERT(!msg->request);
|
207
228
|
|
208
229
|
stats_server_incr(ctx, server, responses);
|
209
|
-
stats_server_incr_by(ctx, server, response_bytes,
|
230
|
+
stats_server_incr_by(ctx, server, response_bytes, msgsize);
|
210
231
|
}
|
211
232
|
|
212
233
|
static void
|
@@ -215,8 +236,10 @@ rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *msg)
|
|
215
236
|
rstatus_t status;
|
216
237
|
struct msg *pmsg;
|
217
238
|
struct conn *c_conn;
|
239
|
+
uint32_t msgsize;
|
218
240
|
|
219
241
|
ASSERT(!s_conn->client && !s_conn->proxy);
|
242
|
+
msgsize = msg->mlen;
|
220
243
|
|
221
244
|
/* response from server implies that server is ok and heartbeating */
|
222
245
|
server_ok(ctx, s_conn);
|
@@ -245,7 +268,7 @@ rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *msg)
|
|
245
268
|
}
|
246
269
|
}
|
247
270
|
|
248
|
-
rsp_forward_stats(ctx, s_conn->owner, msg);
|
271
|
+
rsp_forward_stats(ctx, s_conn->owner, msg, msgsize);
|
249
272
|
}
|
250
273
|
|
251
274
|
void
|
@@ -22,6 +22,23 @@
|
|
22
22
|
#include <nc_server.h>
|
23
23
|
#include <nc_conf.h>
|
24
24
|
|
25
|
+
static void
|
26
|
+
server_resolve(struct server *server, struct conn *conn)
|
27
|
+
{
|
28
|
+
rstatus_t status;
|
29
|
+
|
30
|
+
status = nc_resolve(&server->addrstr, server->port, &server->info);
|
31
|
+
if (status != NC_OK) {
|
32
|
+
conn->err = EHOSTDOWN;
|
33
|
+
conn->done = 1;
|
34
|
+
return;
|
35
|
+
}
|
36
|
+
|
37
|
+
conn->family = server->info.family;
|
38
|
+
conn->addrlen = server->info.addrlen;
|
39
|
+
conn->addr = (struct sockaddr *)&server->info.addr;
|
40
|
+
}
|
41
|
+
|
25
42
|
void
|
26
43
|
server_ref(struct conn *conn, void *owner)
|
27
44
|
{
|
@@ -30,9 +47,7 @@ server_ref(struct conn *conn, void *owner)
|
|
30
47
|
ASSERT(!conn->client && !conn->proxy);
|
31
48
|
ASSERT(conn->owner == NULL);
|
32
49
|
|
33
|
-
conn
|
34
|
-
conn->addrlen = server->addrlen;
|
35
|
-
conn->addr = server->addr;
|
50
|
+
server_resolve(server, conn);
|
36
51
|
|
37
52
|
server->ns_conn_q++;
|
38
53
|
TAILQ_INSERT_TAIL(&server->s_conn_q, conn, conn_tqe);
|
@@ -338,6 +353,8 @@ server_close(struct context *ctx, struct conn *conn)
|
|
338
353
|
server_close_stats(ctx, conn->owner, conn->err, conn->eof,
|
339
354
|
conn->connected);
|
340
355
|
|
356
|
+
conn->connected = false;
|
357
|
+
|
341
358
|
if (conn->sd < 0) {
|
342
359
|
server_failure(ctx, conn->owner);
|
343
360
|
conn->unref(conn);
|
@@ -452,6 +469,12 @@ server_connect(struct context *ctx, struct server *server, struct conn *conn)
|
|
452
469
|
|
453
470
|
ASSERT(!conn->client && !conn->proxy);
|
454
471
|
|
472
|
+
if (conn->err) {
|
473
|
+
ASSERT(conn->done && conn->sd < 0);
|
474
|
+
errno = conn->err;
|
475
|
+
return NC_ERROR;
|
476
|
+
}
|
477
|
+
|
455
478
|
if (conn->sd > 0) {
|
456
479
|
/* already connected on server connection */
|
457
480
|
return NC_OK;
|
@@ -535,6 +558,8 @@ server_connected(struct context *ctx, struct conn *conn)
|
|
535
558
|
conn->connecting = 0;
|
536
559
|
conn->connected = 1;
|
537
560
|
|
561
|
+
conn->post_connect(ctx, conn, server);
|
562
|
+
|
538
563
|
log_debug(LOG_INFO, "connected on s %d to server '%.*s'", conn->sd,
|
539
564
|
server->pname.len, server->pname.data);
|
540
565
|
}
|
@@ -605,12 +630,15 @@ static uint32_t
|
|
605
630
|
server_pool_hash(struct server_pool *pool, uint8_t *key, uint32_t keylen)
|
606
631
|
{
|
607
632
|
ASSERT(array_n(&pool->server) != 0);
|
633
|
+
ASSERT(key != NULL);
|
608
634
|
|
609
635
|
if (array_n(&pool->server) == 1) {
|
610
636
|
return 0;
|
611
637
|
}
|
612
638
|
|
613
|
-
|
639
|
+
if (keylen == 0) {
|
640
|
+
return 0;
|
641
|
+
}
|
614
642
|
|
615
643
|
return pool->key_hash((char *)key, keylen);
|
616
644
|
}
|
@@ -621,7 +649,7 @@ server_pool_idx(struct server_pool *pool, uint8_t *key, uint32_t keylen)
|
|
621
649
|
uint32_t hash, idx;
|
622
650
|
|
623
651
|
ASSERT(array_n(&pool->server) != 0);
|
624
|
-
ASSERT(key != NULL
|
652
|
+
ASSERT(key != NULL);
|
625
653
|
|
626
654
|
/*
|
627
655
|
* If hash_tag: is configured for this server pool, we use the part of
|