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.
- checksums.yaml +5 -13
- data/README.md +3 -3
- data/Rakefile +12 -10
- data/ext/nutcracker/Makefile.in +215 -162
- data/ext/nutcracker/README.md +16 -4
- data/ext/nutcracker/aclocal.m4 +432 -254
- data/ext/nutcracker/{contrib/yaml-0.1.4/configure → autom4te.cache/output.0} +11367 -4545
- data/ext/nutcracker/autom4te.cache/output.1 +19907 -0
- data/ext/nutcracker/autom4te.cache/output.2 +19907 -0
- data/ext/nutcracker/autom4te.cache/requests +518 -0
- data/ext/nutcracker/autom4te.cache/traces.0 +2715 -0
- data/ext/nutcracker/autom4te.cache/traces.1 +967 -0
- data/ext/nutcracker/autom4te.cache/traces.2 +2715 -0
- data/ext/nutcracker/config/compile +347 -0
- data/ext/nutcracker/config/config.guess +116 -78
- data/ext/nutcracker/config/config.sub +65 -45
- data/ext/nutcracker/config/depcomp +295 -192
- data/ext/nutcracker/config/install-sh +7 -7
- data/ext/nutcracker/config/ltmain.sh +15 -20
- data/ext/nutcracker/config/missing +149 -265
- data/ext/nutcracker/configure +493 -367
- data/ext/nutcracker/contrib/Makefile.in +158 -116
- data/ext/nutcracker/extconf.rb +0 -1
- data/ext/nutcracker/m4/libtool.m4 +4 -23
- data/ext/nutcracker/m4/ltoptions.m4 +0 -0
- data/ext/nutcracker/m4/ltsugar.m4 +0 -0
- data/ext/nutcracker/m4/ltversion.m4 +0 -0
- data/ext/nutcracker/m4/lt~obsolete.m4 +0 -0
- data/ext/nutcracker/notes/recommendation.md +1 -1
- data/ext/nutcracker/notes/redis.md +35 -3
- data/ext/nutcracker/scripts/benchmark-mget.py +43 -0
- data/ext/nutcracker/scripts/nutcracker.spec +61 -3
- data/ext/nutcracker/scripts/redis-check.sh +43 -0
- data/ext/nutcracker/src/Makefile.in +205 -142
- data/ext/nutcracker/src/event/Makefile.in +164 -66
- data/ext/nutcracker/src/hashkit/Makefile.in +164 -66
- data/ext/nutcracker/src/nc_conf.c +2 -0
- data/ext/nutcracker/src/nc_connection.c +31 -0
- data/ext/nutcracker/src/nc_connection.h +3 -0
- data/ext/nutcracker/src/nc_core.c +38 -2
- data/ext/nutcracker/src/nc_core.h +11 -0
- data/ext/nutcracker/src/nc_log.c +90 -12
- data/ext/nutcracker/src/nc_log.h +11 -0
- data/ext/nutcracker/src/nc_mbuf.h +1 -1
- data/ext/nutcracker/src/nc_message.c +162 -116
- data/ext/nutcracker/src/nc_message.h +161 -129
- data/ext/nutcracker/src/nc_proxy.c +34 -4
- data/ext/nutcracker/src/nc_request.c +158 -32
- data/ext/nutcracker/src/nc_server.c +59 -5
- data/ext/nutcracker/src/nc_server.h +1 -0
- data/ext/nutcracker/src/nc_signal.c +2 -2
- data/ext/nutcracker/src/nc_stats.c +21 -0
- data/ext/nutcracker/src/nc_stats.h +28 -26
- data/ext/nutcracker/src/nc_string.c +176 -1
- data/ext/nutcracker/src/nc_string.h +26 -0
- data/ext/nutcracker/src/nc_util.c +12 -0
- data/ext/nutcracker/src/nc_util.h +1 -0
- data/ext/nutcracker/src/proto/Makefile.in +164 -66
- data/ext/nutcracker/src/proto/nc_memcache.c +279 -88
- data/ext/nutcracker/src/proto/nc_proto.h +3 -4
- data/ext/nutcracker/src/proto/nc_redis.c +561 -134
- data/lib/nutcracker/version.rb +1 -1
- metadata +31 -67
- data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +0 -19
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +0 -20
- data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +0 -736
- data/ext/nutcracker/contrib/yaml-0.1.4/README +0 -27
- data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +0 -956
- data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +0 -80
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +0 -1561
- data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +0 -1686
- data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +0 -630
- data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +0 -520
- data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +0 -8406
- data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +0 -376
- data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +0 -75
- data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +0 -222
- data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +0 -1971
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +0 -7357
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +0 -368
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +0 -123
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +0 -23
- data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +0 -92
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +0 -4
- data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +0 -484
- data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +0 -1392
- data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +0 -394
- data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +0 -2329
- data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +0 -432
- data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +0 -1374
- data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +0 -465
- data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +0 -3570
- data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +0 -141
- data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +0 -640
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +0 -8
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +0 -675
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +0 -800
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +0 -1130
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +0 -217
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +0 -202
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +0 -311
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +0 -327
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +0 -63
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +0 -63
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +0 -63
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +0 -354
- data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +0 -29
|
@@ -1557,6 +1557,8 @@ conf_add_server(struct conf *cf, struct command *cmd, void *conf)
|
|
|
1557
1557
|
field->weight = nc_atoi(weight, weightlen);
|
|
1558
1558
|
if (field->weight < 0) {
|
|
1559
1559
|
return "has an invalid weight in \"hostname:port:weight [name]\" format string";
|
|
1560
|
+
} else if (field->weight == 0) {
|
|
1561
|
+
return "has a zero weight in \"hostname:port:weight [name]\" format string";
|
|
1560
1562
|
}
|
|
1561
1563
|
|
|
1562
1564
|
if (value->data[0] != '/') {
|
|
@@ -83,6 +83,9 @@
|
|
|
83
83
|
|
|
84
84
|
static uint32_t nfree_connq; /* # free conn q */
|
|
85
85
|
static struct conn_tqh free_connq; /* free conn q */
|
|
86
|
+
static uint64_t ntotal_conn; /* total # connections counter from start */
|
|
87
|
+
static uint32_t ncurr_conn; /* current # connections */
|
|
88
|
+
static uint32_t ncurr_cconn; /* current # client connections */
|
|
86
89
|
|
|
87
90
|
/*
|
|
88
91
|
* Return the context associated with this connection.
|
|
@@ -154,6 +157,9 @@ _conn_get(void)
|
|
|
154
157
|
conn->done = 0;
|
|
155
158
|
conn->redis = 0;
|
|
156
159
|
|
|
160
|
+
ntotal_conn++;
|
|
161
|
+
ncurr_conn++;
|
|
162
|
+
|
|
157
163
|
return conn;
|
|
158
164
|
}
|
|
159
165
|
|
|
@@ -195,6 +201,8 @@ conn_get(void *owner, bool client, bool redis)
|
|
|
195
201
|
conn->dequeue_inq = NULL;
|
|
196
202
|
conn->enqueue_outq = req_client_enqueue_omsgq;
|
|
197
203
|
conn->dequeue_outq = req_client_dequeue_omsgq;
|
|
204
|
+
|
|
205
|
+
ncurr_cconn++;
|
|
198
206
|
} else {
|
|
199
207
|
/*
|
|
200
208
|
* server receives a response, possibly parsing it, and sends a
|
|
@@ -285,6 +293,11 @@ conn_put(struct conn *conn)
|
|
|
285
293
|
|
|
286
294
|
nfree_connq++;
|
|
287
295
|
TAILQ_INSERT_HEAD(&free_connq, conn, conn_tqe);
|
|
296
|
+
|
|
297
|
+
if (conn->client) {
|
|
298
|
+
ncurr_cconn--;
|
|
299
|
+
}
|
|
300
|
+
ncurr_conn--;
|
|
288
301
|
}
|
|
289
302
|
|
|
290
303
|
void
|
|
@@ -407,3 +420,21 @@ conn_sendv(struct conn *conn, struct array *sendv, size_t nsend)
|
|
|
407
420
|
|
|
408
421
|
return NC_ERROR;
|
|
409
422
|
}
|
|
423
|
+
|
|
424
|
+
uint32_t
|
|
425
|
+
conn_ncurr_conn(void)
|
|
426
|
+
{
|
|
427
|
+
return ncurr_conn;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
uint64_t
|
|
431
|
+
conn_ntotal_conn(void)
|
|
432
|
+
{
|
|
433
|
+
return ntotal_conn;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
uint32_t
|
|
437
|
+
conn_ncurr_cconn(void)
|
|
438
|
+
{
|
|
439
|
+
return ncurr_cconn;
|
|
440
|
+
}
|
|
@@ -96,5 +96,8 @@ ssize_t conn_recv(struct conn *conn, void *buf, size_t size);
|
|
|
96
96
|
ssize_t conn_sendv(struct conn *conn, struct array *sendv, size_t nsend);
|
|
97
97
|
void conn_init(void);
|
|
98
98
|
void conn_deinit(void);
|
|
99
|
+
uint32_t conn_ncurr_conn(void);
|
|
100
|
+
uint64_t conn_ntotal_conn(void);
|
|
101
|
+
uint32_t conn_ncurr_cconn(void);
|
|
99
102
|
|
|
100
103
|
#endif
|
|
@@ -24,6 +24,27 @@
|
|
|
24
24
|
|
|
25
25
|
static uint32_t ctx_id; /* context generation */
|
|
26
26
|
|
|
27
|
+
static rstatus_t
|
|
28
|
+
core_calc_connections(struct context *ctx)
|
|
29
|
+
{
|
|
30
|
+
int status;
|
|
31
|
+
struct rlimit limit;
|
|
32
|
+
|
|
33
|
+
status = getrlimit(RLIMIT_NOFILE, &limit);
|
|
34
|
+
if (status < 0) {
|
|
35
|
+
log_error("getrlimit failed: %s", strerror(errno));
|
|
36
|
+
return NC_ERROR;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
ctx->max_nfd = (uint32_t)limit.rlim_cur;
|
|
40
|
+
ctx->max_ncconn = ctx->max_nfd - ctx->max_nsconn - RESERVED_FDS;
|
|
41
|
+
log_debug(LOG_NOTICE, "max fds %"PRIu32" max client conns %"PRIu32" "
|
|
42
|
+
"max server conns %"PRIu32"", ctx->max_nfd, ctx->max_ncconn,
|
|
43
|
+
ctx->max_nsconn);
|
|
44
|
+
|
|
45
|
+
return NC_OK;
|
|
46
|
+
}
|
|
47
|
+
|
|
27
48
|
static struct context *
|
|
28
49
|
core_ctx_create(struct instance *nci)
|
|
29
50
|
{
|
|
@@ -41,6 +62,9 @@ core_ctx_create(struct instance *nci)
|
|
|
41
62
|
array_null(&ctx->pool);
|
|
42
63
|
ctx->max_timeout = nci->stats_interval;
|
|
43
64
|
ctx->timeout = ctx->max_timeout;
|
|
65
|
+
ctx->max_nfd = 0;
|
|
66
|
+
ctx->max_ncconn = 0;
|
|
67
|
+
ctx->max_nsconn = 0;
|
|
44
68
|
|
|
45
69
|
/* parse and create configuration */
|
|
46
70
|
ctx->cf = conf_create(nci->conf_filename);
|
|
@@ -57,6 +81,18 @@ core_ctx_create(struct instance *nci)
|
|
|
57
81
|
return NULL;
|
|
58
82
|
}
|
|
59
83
|
|
|
84
|
+
/*
|
|
85
|
+
* Get rlimit and calculate max client connections after we have
|
|
86
|
+
* calculated max server connections
|
|
87
|
+
*/
|
|
88
|
+
status = core_calc_connections(ctx);
|
|
89
|
+
if (status != NC_OK) {
|
|
90
|
+
server_pool_deinit(&ctx->pool);
|
|
91
|
+
conf_destroy(ctx->cf);
|
|
92
|
+
nc_free(ctx);
|
|
93
|
+
return NULL;
|
|
94
|
+
}
|
|
95
|
+
|
|
60
96
|
/* create stats per server pool */
|
|
61
97
|
ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval,
|
|
62
98
|
nci->hostname, &ctx->pool);
|
|
@@ -172,9 +208,9 @@ core_send(struct context *ctx, struct conn *conn)
|
|
|
172
208
|
|
|
173
209
|
status = conn->send(ctx, conn);
|
|
174
210
|
if (status != NC_OK) {
|
|
175
|
-
log_debug(LOG_INFO, "send on %c %d failed: %s",
|
|
211
|
+
log_debug(LOG_INFO, "send on %c %d failed: status: %d errno: %d %s",
|
|
176
212
|
conn->client ? 'c' : (conn->proxy ? 'p' : 's'), conn->sd,
|
|
177
|
-
strerror(errno));
|
|
213
|
+
status, errno, strerror(errno));
|
|
178
214
|
}
|
|
179
215
|
|
|
180
216
|
return status;
|
|
@@ -63,6 +63,9 @@
|
|
|
63
63
|
#define NC_EAGAIN -2
|
|
64
64
|
#define NC_ENOMEM -3
|
|
65
65
|
|
|
66
|
+
/* reserved fds for std streams, log, stats fd, epoll etc. */
|
|
67
|
+
#define RESERVED_FDS 32
|
|
68
|
+
|
|
66
69
|
typedef int rstatus_t; /* return type */
|
|
67
70
|
typedef int err_t; /* error type */
|
|
68
71
|
|
|
@@ -87,6 +90,8 @@ struct event_base;
|
|
|
87
90
|
#include <stdbool.h>
|
|
88
91
|
#include <inttypes.h>
|
|
89
92
|
#include <string.h>
|
|
93
|
+
#include <stdio.h>
|
|
94
|
+
#include <ctype.h>
|
|
90
95
|
#include <errno.h>
|
|
91
96
|
#include <limits.h>
|
|
92
97
|
#include <time.h>
|
|
@@ -97,6 +102,7 @@ struct event_base;
|
|
|
97
102
|
#include <sys/socket.h>
|
|
98
103
|
#include <sys/un.h>
|
|
99
104
|
#include <sys/time.h>
|
|
105
|
+
#include <sys/resource.h>
|
|
100
106
|
#include <netinet/in.h>
|
|
101
107
|
|
|
102
108
|
#include <nc_array.h>
|
|
@@ -110,6 +116,7 @@ struct event_base;
|
|
|
110
116
|
#include <nc_mbuf.h>
|
|
111
117
|
#include <nc_message.h>
|
|
112
118
|
#include <nc_connection.h>
|
|
119
|
+
#include <nc_server.h>
|
|
113
120
|
|
|
114
121
|
struct context {
|
|
115
122
|
uint32_t id; /* unique context id */
|
|
@@ -120,6 +127,10 @@ struct context {
|
|
|
120
127
|
struct event_base *evb; /* event base */
|
|
121
128
|
int max_timeout; /* max timeout in msec */
|
|
122
129
|
int timeout; /* timeout in msec */
|
|
130
|
+
|
|
131
|
+
uint32_t max_nfd; /* max # files */
|
|
132
|
+
uint32_t max_ncconn; /* max # client connections */
|
|
133
|
+
uint32_t max_nsconn; /* max # server connections */
|
|
123
134
|
};
|
|
124
135
|
|
|
125
136
|
|
data/ext/nutcracker/src/nc_log.c
CHANGED
|
@@ -68,7 +68,7 @@ log_reopen(void)
|
|
|
68
68
|
close(l->fd);
|
|
69
69
|
l->fd = open(l->name, O_WRONLY | O_APPEND | O_CREAT, 0644);
|
|
70
70
|
if (l->fd < 0) {
|
|
71
|
-
|
|
71
|
+
log_stderr_safe("reopening log file '%s' failed, ignored: %s", l->name,
|
|
72
72
|
strerror(errno));
|
|
73
73
|
}
|
|
74
74
|
}
|
|
@@ -81,7 +81,7 @@ log_level_up(void)
|
|
|
81
81
|
|
|
82
82
|
if (l->level < LOG_PVERB) {
|
|
83
83
|
l->level++;
|
|
84
|
-
|
|
84
|
+
log_safe("up log level to %d", l->level);
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -92,7 +92,7 @@ log_level_down(void)
|
|
|
92
92
|
|
|
93
93
|
if (l->level > LOG_EMERG) {
|
|
94
94
|
l->level--;
|
|
95
|
-
|
|
95
|
+
log_safe("down log level to %d", l->level);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -105,6 +105,17 @@ log_level_set(int level)
|
|
|
105
105
|
loga("set log level to %d", l->level);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
+
void
|
|
109
|
+
log_stacktrace(void)
|
|
110
|
+
{
|
|
111
|
+
struct logger *l = &logger;
|
|
112
|
+
|
|
113
|
+
if (l->fd < 0) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
nc_stacktrace_fd(l->fd);
|
|
117
|
+
}
|
|
118
|
+
|
|
108
119
|
int
|
|
109
120
|
log_loggable(int level)
|
|
110
121
|
{
|
|
@@ -122,11 +133,10 @@ _log(const char *file, int line, int panic, const char *fmt, ...)
|
|
|
122
133
|
{
|
|
123
134
|
struct logger *l = &logger;
|
|
124
135
|
int len, size, errno_save;
|
|
125
|
-
char buf[LOG_MAX_LEN]
|
|
136
|
+
char buf[LOG_MAX_LEN];
|
|
126
137
|
va_list args;
|
|
127
|
-
struct tm *local;
|
|
128
|
-
time_t t;
|
|
129
138
|
ssize_t n;
|
|
139
|
+
struct timeval tv;
|
|
130
140
|
|
|
131
141
|
if (l->fd < 0) {
|
|
132
142
|
return;
|
|
@@ -136,12 +146,11 @@ _log(const char *file, int line, int panic, const char *fmt, ...)
|
|
|
136
146
|
len = 0; /* length of output buffer */
|
|
137
147
|
size = LOG_MAX_LEN; /* size of output buffer */
|
|
138
148
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
len += nc_scnprintf(buf + len, size - len, "
|
|
144
|
-
strlen(timestr) - 1, timestr, file, line);
|
|
149
|
+
gettimeofday(&tv, NULL);
|
|
150
|
+
buf[len++] = '[';
|
|
151
|
+
len += nc_strftime(buf + len, size - len, "%Y-%m-%d %H:%M:%S.", localtime(&tv.tv_sec));
|
|
152
|
+
len += nc_scnprintf(buf + len, size - len, "%03ld", tv.tv_usec/1000);
|
|
153
|
+
len += nc_scnprintf(buf + len, size - len, "] %s:%d ", file, line);
|
|
145
154
|
|
|
146
155
|
va_start(args, fmt);
|
|
147
156
|
len += nc_vscnprintf(buf + len, size - len, fmt, args);
|
|
@@ -250,5 +259,74 @@ _log_hexdump(const char *file, int line, char *data, int datalen,
|
|
|
250
259
|
l->nerror++;
|
|
251
260
|
}
|
|
252
261
|
|
|
262
|
+
if (len >= size - 1) {
|
|
263
|
+
n = nc_write(l->fd, "\n", 1);
|
|
264
|
+
if (n < 0) {
|
|
265
|
+
l->nerror++;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
errno = errno_save;
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
void
|
|
273
|
+
_log_safe(const char *fmt, ...)
|
|
274
|
+
{
|
|
275
|
+
struct logger *l = &logger;
|
|
276
|
+
int len, size, errno_save;
|
|
277
|
+
char buf[LOG_MAX_LEN];
|
|
278
|
+
va_list args;
|
|
279
|
+
ssize_t n;
|
|
280
|
+
|
|
281
|
+
if (l->fd < 0) {
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
errno_save = errno;
|
|
286
|
+
len = 0; /* length of output buffer */
|
|
287
|
+
size = LOG_MAX_LEN; /* size of output buffer */
|
|
288
|
+
|
|
289
|
+
len += nc_safe_snprintf(buf + len, size - len, "[.......................] ");
|
|
290
|
+
|
|
291
|
+
va_start(args, fmt);
|
|
292
|
+
len += nc_safe_vsnprintf(buf + len, size - len, fmt, args);
|
|
293
|
+
va_end(args);
|
|
294
|
+
|
|
295
|
+
buf[len++] = '\n';
|
|
296
|
+
|
|
297
|
+
n = nc_write(l->fd, buf, len);
|
|
298
|
+
if (n < 0) {
|
|
299
|
+
l->nerror++;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
errno = errno_save;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
void
|
|
306
|
+
_log_stderr_safe(const char *fmt, ...)
|
|
307
|
+
{
|
|
308
|
+
struct logger *l = &logger;
|
|
309
|
+
int len, size, errno_save;
|
|
310
|
+
char buf[LOG_MAX_LEN];
|
|
311
|
+
va_list args;
|
|
312
|
+
ssize_t n;
|
|
313
|
+
|
|
314
|
+
errno_save = errno;
|
|
315
|
+
len = 0; /* length of output buffer */
|
|
316
|
+
size = LOG_MAX_LEN; /* size of output buffer */
|
|
317
|
+
|
|
318
|
+
len += nc_safe_snprintf(buf + len, size - len, "[.......................] ");
|
|
319
|
+
|
|
320
|
+
va_start(args, fmt);
|
|
321
|
+
len += nc_safe_vsnprintf(buf + len, size - len, fmt, args);
|
|
322
|
+
va_end(args);
|
|
323
|
+
|
|
324
|
+
buf[len++] = '\n';
|
|
325
|
+
|
|
326
|
+
n = nc_write(STDERR_FILENO, buf, len);
|
|
327
|
+
if (n < 0) {
|
|
328
|
+
l->nerror++;
|
|
329
|
+
}
|
|
330
|
+
|
|
253
331
|
errno = errno_save;
|
|
254
332
|
}
|
data/ext/nutcracker/src/nc_log.h
CHANGED
|
@@ -78,6 +78,14 @@ struct logger {
|
|
|
78
78
|
_log_stderr(__VA_ARGS__); \
|
|
79
79
|
} while (0)
|
|
80
80
|
|
|
81
|
+
#define log_safe(...) do { \
|
|
82
|
+
_log_safe(__VA_ARGS__); \
|
|
83
|
+
} while (0)
|
|
84
|
+
|
|
85
|
+
#define log_stderr_safe(...) do { \
|
|
86
|
+
_log_stderr_safe(__VA_ARGS__); \
|
|
87
|
+
} while (0)
|
|
88
|
+
|
|
81
89
|
#define loga(...) do { \
|
|
82
90
|
_log(__FILE__, __LINE__, 0, __VA_ARGS__); \
|
|
83
91
|
} while (0)
|
|
@@ -111,10 +119,13 @@ void log_deinit(void);
|
|
|
111
119
|
void log_level_up(void);
|
|
112
120
|
void log_level_down(void);
|
|
113
121
|
void log_level_set(int level);
|
|
122
|
+
void log_stacktrace(void);
|
|
114
123
|
void log_reopen(void);
|
|
115
124
|
int log_loggable(int level);
|
|
116
125
|
void _log(const char *file, int line, int panic, const char *fmt, ...);
|
|
117
126
|
void _log_stderr(const char *fmt, ...);
|
|
127
|
+
void _log_safe(const char *fmt, ...);
|
|
128
|
+
void _log_stderr_safe(const char *fmt, ...);
|
|
118
129
|
void _log_hexdump(const char *file, int line, char *data, int datalen, const char *fmt, ...);
|
|
119
130
|
|
|
120
131
|
#endif
|
|
@@ -116,6 +116,13 @@ static struct msg_tqh free_msgq; /* free msg q */
|
|
|
116
116
|
static struct rbtree tmo_rbt; /* timeout rbtree */
|
|
117
117
|
static struct rbnode tmo_rbs; /* timeout rbtree sentinel */
|
|
118
118
|
|
|
119
|
+
#define DEFINE_ACTION(_name) string(#_name),
|
|
120
|
+
static struct string msg_type_strings[] = {
|
|
121
|
+
MSG_TYPE_CODEC( DEFINE_ACTION )
|
|
122
|
+
null_string
|
|
123
|
+
};
|
|
124
|
+
#undef DEFINE_ACTION
|
|
125
|
+
|
|
119
126
|
static struct msg *
|
|
120
127
|
msg_from_rbe(struct rbnode *node)
|
|
121
128
|
{
|
|
@@ -212,6 +219,7 @@ done:
|
|
|
212
219
|
|
|
213
220
|
STAILQ_INIT(&msg->mhdr);
|
|
214
221
|
msg->mlen = 0;
|
|
222
|
+
msg->start_ts = 0;
|
|
215
223
|
|
|
216
224
|
msg->state = 0;
|
|
217
225
|
msg->pos = NULL;
|
|
@@ -220,21 +228,26 @@ done:
|
|
|
220
228
|
msg->parser = NULL;
|
|
221
229
|
msg->result = MSG_PARSE_OK;
|
|
222
230
|
|
|
223
|
-
msg->
|
|
224
|
-
msg->
|
|
231
|
+
msg->fragment = NULL;
|
|
232
|
+
msg->reply = NULL;
|
|
225
233
|
msg->pre_coalesce = NULL;
|
|
226
234
|
msg->post_coalesce = NULL;
|
|
227
235
|
|
|
228
236
|
msg->type = MSG_UNKNOWN;
|
|
229
237
|
|
|
230
|
-
msg->
|
|
231
|
-
msg->
|
|
238
|
+
msg->keys = array_create(1, sizeof(struct keypos));
|
|
239
|
+
if (msg->keys == NULL) {
|
|
240
|
+
nc_free(msg);
|
|
241
|
+
return NULL;
|
|
242
|
+
}
|
|
232
243
|
|
|
233
244
|
msg->vlen = 0;
|
|
234
245
|
msg->end = NULL;
|
|
235
246
|
|
|
236
247
|
msg->frag_owner = NULL;
|
|
248
|
+
msg->frag_seq = NULL;
|
|
237
249
|
msg->nfrag = 0;
|
|
250
|
+
msg->nfrag_done = 0;
|
|
238
251
|
msg->frag_id = 0;
|
|
239
252
|
|
|
240
253
|
msg->narg_start = NULL;
|
|
@@ -250,10 +263,9 @@ done:
|
|
|
250
263
|
msg->request = 0;
|
|
251
264
|
msg->quit = 0;
|
|
252
265
|
msg->noreply = 0;
|
|
266
|
+
msg->noforward = 0;
|
|
253
267
|
msg->done = 0;
|
|
254
268
|
msg->fdone = 0;
|
|
255
|
-
msg->first_fragment = 0;
|
|
256
|
-
msg->last_fragment = 0;
|
|
257
269
|
msg->swallow = 0;
|
|
258
270
|
msg->redis = 0;
|
|
259
271
|
|
|
@@ -280,8 +292,8 @@ msg_get(struct conn *conn, bool request, bool redis)
|
|
|
280
292
|
} else {
|
|
281
293
|
msg->parser = redis_parse_rsp;
|
|
282
294
|
}
|
|
283
|
-
msg->
|
|
284
|
-
msg->
|
|
295
|
+
msg->fragment = redis_fragment;
|
|
296
|
+
msg->reply = redis_reply;
|
|
285
297
|
msg->pre_coalesce = redis_pre_coalesce;
|
|
286
298
|
msg->post_coalesce = redis_post_coalesce;
|
|
287
299
|
} else {
|
|
@@ -290,12 +302,15 @@ msg_get(struct conn *conn, bool request, bool redis)
|
|
|
290
302
|
} else {
|
|
291
303
|
msg->parser = memcache_parse_rsp;
|
|
292
304
|
}
|
|
293
|
-
msg->
|
|
294
|
-
msg->post_splitcopy = memcache_post_splitcopy;
|
|
305
|
+
msg->fragment = memcache_fragment;
|
|
295
306
|
msg->pre_coalesce = memcache_pre_coalesce;
|
|
296
307
|
msg->post_coalesce = memcache_post_coalesce;
|
|
297
308
|
}
|
|
298
309
|
|
|
310
|
+
if (log_loggable(LOG_NOTICE) != 0) {
|
|
311
|
+
msg->start_ts = nc_usec_now();
|
|
312
|
+
}
|
|
313
|
+
|
|
299
314
|
log_debug(LOG_VVERB, "get msg %p id %"PRIu64" request %d owner sd %d",
|
|
300
315
|
msg, msg->id, msg->request, conn->sd);
|
|
301
316
|
|
|
@@ -356,15 +371,30 @@ msg_put(struct msg *msg)
|
|
|
356
371
|
mbuf_put(mbuf);
|
|
357
372
|
}
|
|
358
373
|
|
|
374
|
+
if (msg->frag_seq) {
|
|
375
|
+
nc_free(msg->frag_seq);
|
|
376
|
+
msg->frag_seq = NULL;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if (msg->keys) {
|
|
380
|
+
msg->keys->nelem = 0; /* a hack here */
|
|
381
|
+
array_destroy(msg->keys);
|
|
382
|
+
msg->keys = NULL;
|
|
383
|
+
}
|
|
384
|
+
|
|
359
385
|
nfree_msgq++;
|
|
360
386
|
TAILQ_INSERT_HEAD(&free_msgq, msg, m_tqe);
|
|
361
387
|
}
|
|
362
388
|
|
|
363
389
|
void
|
|
364
|
-
msg_dump(struct msg *msg)
|
|
390
|
+
msg_dump(struct msg *msg, int level)
|
|
365
391
|
{
|
|
366
392
|
struct mbuf *mbuf;
|
|
367
393
|
|
|
394
|
+
if (log_loggable(level) == 0) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
|
|
368
398
|
loga("msg dump id %"PRIu64" request %d len %"PRIu32" type %d done %d "
|
|
369
399
|
"error %d (err %d)", msg->id, msg->request, msg->mlen, msg->type,
|
|
370
400
|
msg->done, msg->error, msg->err);
|
|
@@ -377,7 +407,7 @@ msg_dump(struct msg *msg)
|
|
|
377
407
|
q = mbuf->last;
|
|
378
408
|
len = q - p;
|
|
379
409
|
|
|
380
|
-
loga_hexdump(p, len, "mbuf with %ld bytes of data", len);
|
|
410
|
+
loga_hexdump(p, len, "mbuf [%p] with %ld bytes of data", p, len);
|
|
381
411
|
}
|
|
382
412
|
}
|
|
383
413
|
|
|
@@ -406,12 +436,122 @@ msg_deinit(void)
|
|
|
406
436
|
ASSERT(nfree_msgq == 0);
|
|
407
437
|
}
|
|
408
438
|
|
|
439
|
+
struct string *
|
|
440
|
+
msg_type_string(msg_type_t type)
|
|
441
|
+
{
|
|
442
|
+
return &msg_type_strings[type];
|
|
443
|
+
}
|
|
444
|
+
|
|
409
445
|
bool
|
|
410
446
|
msg_empty(struct msg *msg)
|
|
411
447
|
{
|
|
412
448
|
return msg->mlen == 0 ? true : false;
|
|
413
449
|
}
|
|
414
450
|
|
|
451
|
+
uint32_t
|
|
452
|
+
msg_backend_idx(struct msg *msg, uint8_t *key, uint32_t keylen)
|
|
453
|
+
{
|
|
454
|
+
struct conn *conn = msg->owner;
|
|
455
|
+
struct server_pool *pool = conn->owner;
|
|
456
|
+
|
|
457
|
+
return server_pool_idx(pool, key, keylen);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
struct mbuf *
|
|
461
|
+
msg_ensure_mbuf(struct msg *msg, size_t len)
|
|
462
|
+
{
|
|
463
|
+
struct mbuf *mbuf;
|
|
464
|
+
|
|
465
|
+
if (STAILQ_EMPTY(&msg->mhdr) ||
|
|
466
|
+
mbuf_size(STAILQ_LAST(&msg->mhdr, mbuf, next)) < len) {
|
|
467
|
+
mbuf = mbuf_get();
|
|
468
|
+
if (mbuf == NULL) {
|
|
469
|
+
return NULL;
|
|
470
|
+
}
|
|
471
|
+
mbuf_insert(&msg->mhdr, mbuf);
|
|
472
|
+
} else {
|
|
473
|
+
mbuf = STAILQ_LAST(&msg->mhdr, mbuf, next);
|
|
474
|
+
}
|
|
475
|
+
return mbuf;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/*
|
|
479
|
+
* append small(small than a mbuf) content into msg
|
|
480
|
+
*/
|
|
481
|
+
rstatus_t
|
|
482
|
+
msg_append(struct msg *msg, uint8_t *pos, size_t n)
|
|
483
|
+
{
|
|
484
|
+
struct mbuf *mbuf;
|
|
485
|
+
|
|
486
|
+
ASSERT(n <= mbuf_data_size());
|
|
487
|
+
|
|
488
|
+
mbuf = msg_ensure_mbuf(msg, n);
|
|
489
|
+
if (mbuf == NULL) {
|
|
490
|
+
return NC_ENOMEM;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
ASSERT(n <= mbuf_size(mbuf));
|
|
494
|
+
|
|
495
|
+
mbuf_copy(mbuf, pos, n);
|
|
496
|
+
msg->mlen += (uint32_t)n;
|
|
497
|
+
return NC_OK;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/*
|
|
501
|
+
* prepend small(small than a mbuf) content into msg
|
|
502
|
+
*/
|
|
503
|
+
rstatus_t
|
|
504
|
+
msg_prepend(struct msg *msg, uint8_t *pos, size_t n)
|
|
505
|
+
{
|
|
506
|
+
struct mbuf *mbuf;
|
|
507
|
+
|
|
508
|
+
mbuf = mbuf_get();
|
|
509
|
+
if (mbuf == NULL) {
|
|
510
|
+
return NC_ENOMEM;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
ASSERT(n <= mbuf_size(mbuf));
|
|
514
|
+
|
|
515
|
+
mbuf_copy(mbuf, pos, n);
|
|
516
|
+
msg->mlen += (uint32_t)n;
|
|
517
|
+
|
|
518
|
+
STAILQ_INSERT_HEAD(&msg->mhdr, mbuf, next);
|
|
519
|
+
return NC_OK;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
/*
|
|
523
|
+
* prepend small(small than a mbuf) content into msg
|
|
524
|
+
*/
|
|
525
|
+
rstatus_t
|
|
526
|
+
msg_prepend_format(struct msg *msg, const char *fmt, ...)
|
|
527
|
+
{
|
|
528
|
+
struct mbuf *mbuf;
|
|
529
|
+
int32_t n;
|
|
530
|
+
va_list args;
|
|
531
|
+
|
|
532
|
+
mbuf = mbuf_get();
|
|
533
|
+
if (mbuf == NULL) {
|
|
534
|
+
return NC_ENOMEM;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
va_start(args, fmt);
|
|
538
|
+
n = nc_vscnprintf(mbuf->last, mbuf_size(mbuf), fmt, args);
|
|
539
|
+
va_end(args);
|
|
540
|
+
|
|
541
|
+
mbuf->last += n;
|
|
542
|
+
msg->mlen += (uint32_t)n;
|
|
543
|
+
|
|
544
|
+
ASSERT(mbuf_size(mbuf) >= 0);
|
|
545
|
+
STAILQ_INSERT_HEAD(&msg->mhdr, mbuf, next);
|
|
546
|
+
return NC_OK;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
inline uint64_t
|
|
550
|
+
msg_gen_frag_id(void)
|
|
551
|
+
{
|
|
552
|
+
return ++frag_id;
|
|
553
|
+
}
|
|
554
|
+
|
|
415
555
|
static rstatus_t
|
|
416
556
|
msg_parsed(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
417
557
|
{
|
|
@@ -453,101 +593,6 @@ msg_parsed(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
|
453
593
|
return NC_OK;
|
|
454
594
|
}
|
|
455
595
|
|
|
456
|
-
static rstatus_t
|
|
457
|
-
msg_fragment(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
458
|
-
{
|
|
459
|
-
rstatus_t status; /* return status */
|
|
460
|
-
struct msg *nmsg; /* new message */
|
|
461
|
-
struct mbuf *nbuf; /* new mbuf */
|
|
462
|
-
|
|
463
|
-
ASSERT(conn->client && !conn->proxy);
|
|
464
|
-
ASSERT(msg->request);
|
|
465
|
-
|
|
466
|
-
nbuf = mbuf_split(&msg->mhdr, msg->pos, msg->pre_splitcopy, msg);
|
|
467
|
-
if (nbuf == NULL) {
|
|
468
|
-
return NC_ENOMEM;
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
status = msg->post_splitcopy(msg);
|
|
472
|
-
if (status != NC_OK) {
|
|
473
|
-
mbuf_put(nbuf);
|
|
474
|
-
return status;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
nmsg = msg_get(msg->owner, msg->request, msg->redis);
|
|
478
|
-
if (nmsg == NULL) {
|
|
479
|
-
mbuf_put(nbuf);
|
|
480
|
-
return NC_ENOMEM;
|
|
481
|
-
}
|
|
482
|
-
mbuf_insert(&nmsg->mhdr, nbuf);
|
|
483
|
-
nmsg->pos = nbuf->pos;
|
|
484
|
-
|
|
485
|
-
/* update length of current (msg) and new message (nmsg) */
|
|
486
|
-
nmsg->mlen = mbuf_length(nbuf);
|
|
487
|
-
msg->mlen -= nmsg->mlen;
|
|
488
|
-
|
|
489
|
-
/*
|
|
490
|
-
* Attach unique fragment id to all fragments of the message vector. All
|
|
491
|
-
* fragments of the message, including the first fragment point to the
|
|
492
|
-
* first fragment through the frag_owner pointer. The first_fragment and
|
|
493
|
-
* last_fragment identify first and last fragment respectively.
|
|
494
|
-
*
|
|
495
|
-
* For example, a message vector given below is split into 3 fragments:
|
|
496
|
-
* 'get key1 key2 key3\r\n'
|
|
497
|
-
* Or,
|
|
498
|
-
* '*4\r\n$4\r\nmget\r\n$4\r\nkey1\r\n$4\r\nkey2\r\n$4\r\nkey3\r\n'
|
|
499
|
-
*
|
|
500
|
-
* +--------------+
|
|
501
|
-
* | msg vector |
|
|
502
|
-
* |(original msg)|
|
|
503
|
-
* +--------------+
|
|
504
|
-
*
|
|
505
|
-
* frag_owner frag_owner
|
|
506
|
-
* /-----------+ /------------+
|
|
507
|
-
* | | | |
|
|
508
|
-
* | v v |
|
|
509
|
-
* +--------------------+ +---------------------+
|
|
510
|
-
* | frag_id = 10 | | frag_id = 10 |
|
|
511
|
-
* | first_fragment = 1 | | first_fragment = 0 |
|
|
512
|
-
* | last_fragment = 0 | | last_fragment = 0 |
|
|
513
|
-
* | nfrag = 3 | | nfrag = 0 |
|
|
514
|
-
* +--------------------+ +---------------------+
|
|
515
|
-
* ^
|
|
516
|
-
* | frag_owner
|
|
517
|
-
* \-------------+
|
|
518
|
-
* |
|
|
519
|
-
* |
|
|
520
|
-
* +---------------------+
|
|
521
|
-
* | frag_id = 10 |
|
|
522
|
-
* | first_fragment = 0 |
|
|
523
|
-
* | last_fragment = 1 |
|
|
524
|
-
* | nfrag = 0 |
|
|
525
|
-
* +---------------------+
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
*/
|
|
529
|
-
if (msg->frag_id == 0) {
|
|
530
|
-
msg->frag_id = ++frag_id;
|
|
531
|
-
msg->first_fragment = 1;
|
|
532
|
-
msg->nfrag = 1;
|
|
533
|
-
msg->frag_owner = msg;
|
|
534
|
-
}
|
|
535
|
-
nmsg->frag_id = msg->frag_id;
|
|
536
|
-
msg->last_fragment = 0;
|
|
537
|
-
nmsg->last_fragment = 1;
|
|
538
|
-
nmsg->frag_owner = msg->frag_owner;
|
|
539
|
-
msg->frag_owner->nfrag++;
|
|
540
|
-
|
|
541
|
-
stats_pool_incr(ctx, conn->owner, fragments);
|
|
542
|
-
|
|
543
|
-
log_debug(LOG_VERB, "fragment msg into %"PRIu64" and %"PRIu64" frag id "
|
|
544
|
-
"%"PRIu64"", msg->id, nmsg->id, msg->frag_id);
|
|
545
|
-
|
|
546
|
-
conn->recv_done(ctx, conn, msg, nmsg);
|
|
547
|
-
|
|
548
|
-
return NC_OK;
|
|
549
|
-
}
|
|
550
|
-
|
|
551
596
|
static rstatus_t
|
|
552
597
|
msg_repair(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
553
598
|
{
|
|
@@ -581,10 +626,6 @@ msg_parse(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
|
581
626
|
status = msg_parsed(ctx, conn, msg);
|
|
582
627
|
break;
|
|
583
628
|
|
|
584
|
-
case MSG_PARSE_FRAGMENT:
|
|
585
|
-
status = msg_fragment(ctx, conn, msg);
|
|
586
|
-
break;
|
|
587
|
-
|
|
588
629
|
case MSG_PARSE_REPAIR:
|
|
589
630
|
status = msg_repair(ctx, conn, msg);
|
|
590
631
|
break;
|
|
@@ -742,11 +783,16 @@ msg_send_chain(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
|
742
783
|
}
|
|
743
784
|
}
|
|
744
785
|
|
|
745
|
-
|
|
746
|
-
|
|
786
|
+
/*
|
|
787
|
+
* (nsend == 0) is possible in redis multi-del
|
|
788
|
+
* see PR: https://github.com/twitter/twemproxy/pull/225
|
|
789
|
+
*/
|
|
747
790
|
conn->smsg = NULL;
|
|
748
|
-
|
|
749
|
-
|
|
791
|
+
if (!TAILQ_EMPTY(&send_msgq) && nsend != 0) {
|
|
792
|
+
n = conn_sendv(conn, &sendv, nsend);
|
|
793
|
+
} else {
|
|
794
|
+
n = 0;
|
|
795
|
+
}
|
|
750
796
|
|
|
751
797
|
nsent = n > 0 ? (size_t)n : 0;
|
|
752
798
|
|
|
@@ -794,7 +840,7 @@ msg_send_chain(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
|
794
840
|
|
|
795
841
|
ASSERT(TAILQ_EMPTY(&send_msgq));
|
|
796
842
|
|
|
797
|
-
if (n
|
|
843
|
+
if (n >= 0) {
|
|
798
844
|
return NC_OK;
|
|
799
845
|
}
|
|
800
846
|
|