nutcracker 0.4.0.16 → 0.4.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|