nutcracker 0.3.0.12 → 0.4.0.13
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|