nutcracker 0.2.4.12 → 0.3.0.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/Rakefile +1 -1
- data/ext/nutcracker/ChangeLog +10 -0
- data/ext/nutcracker/Makefile.am +2 -0
- data/ext/nutcracker/Makefile.in +101 -14
- data/ext/nutcracker/README.md +18 -1
- data/ext/nutcracker/config.h.in +18 -0
- data/ext/nutcracker/configure +196 -25
- data/ext/nutcracker/configure.ac +64 -6
- data/ext/nutcracker/extconf.rb +1 -1
- data/ext/nutcracker/man/nutcracker.8 +76 -0
- data/ext/nutcracker/notes/debug.txt +116 -16
- data/ext/nutcracker/notes/kqueue.pdf +0 -0
- data/ext/nutcracker/notes/recommendation.md +20 -0
- data/ext/nutcracker/notes/redis.md +2 -2
- data/ext/nutcracker/scripts/nutcracker.spec +1 -1
- data/ext/nutcracker/scripts/redis-check.sh +3 -1
- data/ext/nutcracker/src/Makefile.am +15 -6
- data/ext/nutcracker/src/Makefile.in +39 -36
- data/ext/nutcracker/src/event/Makefile.am +16 -0
- data/ext/nutcracker/src/event/Makefile.in +492 -0
- data/ext/nutcracker/src/event/nc_epoll.c +344 -0
- data/ext/nutcracker/src/event/nc_event.h +88 -0
- data/ext/nutcracker/src/event/nc_evport.c +420 -0
- data/ext/nutcracker/src/event/nc_kqueue.c +412 -0
- data/ext/nutcracker/src/hashkit/nc_crc32.c +19 -1
- data/ext/nutcracker/src/hashkit/nc_hashkit.h +3 -1
- data/ext/nutcracker/src/hashkit/nc_md5.c +257 -315
- data/ext/nutcracker/src/nc.c +12 -1
- data/ext/nutcracker/src/nc_connection.c +18 -1
- data/ext/nutcracker/src/nc_connection.h +1 -0
- data/ext/nutcracker/src/nc_core.c +22 -30
- data/ext/nutcracker/src/nc_core.h +22 -7
- data/ext/nutcracker/src/nc_proxy.c +8 -9
- data/ext/nutcracker/src/nc_queue.h +2 -0
- data/ext/nutcracker/src/nc_request.c +3 -4
- data/ext/nutcracker/src/nc_response.c +25 -8
- data/ext/nutcracker/src/nc_server.c +8 -6
- data/ext/nutcracker/src/nc_stats.c +46 -43
- data/ext/nutcracker/src/nc_stats.h +37 -30
- data/ext/nutcracker/src/nc_util.c +6 -1
- data/ext/nutcracker/src/proto/nc_redis.c +19 -5
- data/lib/nutcracker/version.rb +1 -1
- data/lib/nutcracker.rb +1 -1
- metadata +10 -4
- data/ext/nutcracker/src/nc_event.c +0 -214
- data/ext/nutcracker/src/nc_event.h +0 -39
@@ -17,11 +17,7 @@
|
|
17
17
|
|
18
18
|
#include <stdlib.h>
|
19
19
|
#include <unistd.h>
|
20
|
-
|
21
|
-
#include <sys/epoll.h>
|
22
|
-
|
23
20
|
#include <nc_core.h>
|
24
|
-
#include <nc_event.h>
|
25
21
|
#include <nc_conf.h>
|
26
22
|
#include <nc_server.h>
|
27
23
|
#include <nc_proxy.h>
|
@@ -41,12 +37,10 @@ core_ctx_create(struct instance *nci)
|
|
41
37
|
ctx->id = ++ctx_id;
|
42
38
|
ctx->cf = NULL;
|
43
39
|
ctx->stats = NULL;
|
40
|
+
ctx->evb = NULL;
|
44
41
|
array_null(&ctx->pool);
|
45
|
-
ctx->ep = -1;
|
46
|
-
ctx->nevent = EVENT_SIZE_HINT;
|
47
42
|
ctx->max_timeout = nci->stats_interval;
|
48
43
|
ctx->timeout = ctx->max_timeout;
|
49
|
-
ctx->event = NULL;
|
50
44
|
|
51
45
|
/* parse and create configuration */
|
52
46
|
ctx->cf = conf_create(nci->conf_filename);
|
@@ -74,8 +68,8 @@ core_ctx_create(struct instance *nci)
|
|
74
68
|
}
|
75
69
|
|
76
70
|
/* initialize event handling for client, proxy and server */
|
77
|
-
|
78
|
-
if (
|
71
|
+
ctx->evb = event_base_create(EVENT_SIZE, &core_core);
|
72
|
+
if (ctx->evb == NULL) {
|
79
73
|
stats_destroy(ctx->stats);
|
80
74
|
server_pool_deinit(&ctx->pool);
|
81
75
|
conf_destroy(ctx->cf);
|
@@ -87,7 +81,7 @@ core_ctx_create(struct instance *nci)
|
|
87
81
|
status = server_pool_preconnect(ctx);
|
88
82
|
if (status != NC_OK) {
|
89
83
|
server_pool_disconnect(ctx);
|
90
|
-
|
84
|
+
event_base_destroy(ctx->evb);
|
91
85
|
stats_destroy(ctx->stats);
|
92
86
|
server_pool_deinit(&ctx->pool);
|
93
87
|
conf_destroy(ctx->cf);
|
@@ -99,7 +93,7 @@ core_ctx_create(struct instance *nci)
|
|
99
93
|
status = proxy_init(ctx);
|
100
94
|
if (status != NC_OK) {
|
101
95
|
server_pool_disconnect(ctx);
|
102
|
-
|
96
|
+
event_base_destroy(ctx->evb);
|
103
97
|
stats_destroy(ctx->stats);
|
104
98
|
server_pool_deinit(&ctx->pool);
|
105
99
|
conf_destroy(ctx->cf);
|
@@ -118,7 +112,7 @@ core_ctx_destroy(struct context *ctx)
|
|
118
112
|
log_debug(LOG_VVERB, "destroy ctx %p id %"PRIu32"", ctx, ctx->id);
|
119
113
|
proxy_deinit(ctx);
|
120
114
|
server_pool_disconnect(ctx);
|
121
|
-
|
115
|
+
event_base_destroy(ctx->evb);
|
122
116
|
stats_destroy(ctx->stats);
|
123
117
|
server_pool_deinit(&ctx->pool);
|
124
118
|
conf_destroy(ctx->cf);
|
@@ -206,9 +200,9 @@ core_close(struct context *ctx, struct conn *conn)
|
|
206
200
|
conn->eof, conn->done, conn->recv_bytes, conn->send_bytes,
|
207
201
|
conn->err ? ':' : ' ', conn->err ? strerror(conn->err) : "");
|
208
202
|
|
209
|
-
status = event_del_conn(ctx->
|
203
|
+
status = event_del_conn(ctx->evb, conn);
|
210
204
|
if (status < 0) {
|
211
|
-
log_warn("event del conn
|
205
|
+
log_warn("event del conn %c %d failed, ignored: %s",
|
212
206
|
type, conn->sd, strerror(errno));
|
213
207
|
}
|
214
208
|
|
@@ -276,10 +270,12 @@ core_timeout(struct context *ctx)
|
|
276
270
|
}
|
277
271
|
}
|
278
272
|
|
279
|
-
|
280
|
-
core_core(
|
273
|
+
rstatus_t
|
274
|
+
core_core(void *arg, uint32_t events)
|
281
275
|
{
|
282
276
|
rstatus_t status;
|
277
|
+
struct conn *conn = arg;
|
278
|
+
struct context *ctx = conn_to_ctx(conn);
|
283
279
|
|
284
280
|
log_debug(LOG_VVERB, "event %04"PRIX32" on %c %d", events,
|
285
281
|
conn->client ? 'c' : (conn->proxy ? 'p' : 's'), conn->sd);
|
@@ -287,45 +283,41 @@ core_core(struct context *ctx, struct conn *conn, uint32_t events)
|
|
287
283
|
conn->events = events;
|
288
284
|
|
289
285
|
/* error takes precedence over read | write */
|
290
|
-
if (events &
|
286
|
+
if (events & EVENT_ERR) {
|
291
287
|
core_error(ctx, conn);
|
292
|
-
return;
|
288
|
+
return NC_ERROR;
|
293
289
|
}
|
294
290
|
|
295
291
|
/* read takes precedence over write */
|
296
|
-
if (events &
|
292
|
+
if (events & EVENT_READ) {
|
297
293
|
status = core_recv(ctx, conn);
|
298
294
|
if (status != NC_OK || conn->done || conn->err) {
|
299
295
|
core_close(ctx, conn);
|
300
|
-
return;
|
296
|
+
return NC_ERROR;
|
301
297
|
}
|
302
298
|
}
|
303
299
|
|
304
|
-
if (events &
|
300
|
+
if (events & EVENT_WRITE) {
|
305
301
|
status = core_send(ctx, conn);
|
306
302
|
if (status != NC_OK || conn->done || conn->err) {
|
307
303
|
core_close(ctx, conn);
|
308
|
-
return;
|
304
|
+
return NC_ERROR;
|
309
305
|
}
|
310
306
|
}
|
307
|
+
|
308
|
+
return NC_OK;
|
311
309
|
}
|
312
310
|
|
313
311
|
rstatus_t
|
314
312
|
core_loop(struct context *ctx)
|
315
313
|
{
|
316
|
-
int
|
314
|
+
int nsd;
|
317
315
|
|
318
|
-
nsd = event_wait(ctx->
|
316
|
+
nsd = event_wait(ctx->evb, ctx->timeout);
|
319
317
|
if (nsd < 0) {
|
320
318
|
return nsd;
|
321
319
|
}
|
322
320
|
|
323
|
-
for (i = 0; i < nsd; i++) {
|
324
|
-
struct epoll_event *ev = &ctx->event[i];
|
325
|
-
|
326
|
-
core_core(ctx, ev->data.ptr, ev->events);
|
327
|
-
}
|
328
|
-
|
329
321
|
core_timeout(ctx);
|
330
322
|
|
331
323
|
stats_swap(ctx->stats);
|
@@ -40,10 +40,24 @@
|
|
40
40
|
# define NC_STATS 0
|
41
41
|
#endif
|
42
42
|
|
43
|
+
#ifdef HAVE_EPOLL
|
44
|
+
# define NC_HAVE_EPOLL 1
|
45
|
+
#elif HAVE_KQUEUE
|
46
|
+
# define NC_HAVE_KQUEUE 1
|
47
|
+
#elif HAVE_EVENT_PORTS
|
48
|
+
# define NC_HAVE_EVENT_PORTS 1
|
49
|
+
#else
|
50
|
+
# error missing scalable I/O event notification mechanism
|
51
|
+
#endif
|
52
|
+
|
43
53
|
#ifdef HAVE_LITTLE_ENDIAN
|
44
54
|
# define NC_LITTLE_ENDIAN 1
|
45
55
|
#endif
|
46
56
|
|
57
|
+
#ifdef HAVE_BACKTRACE
|
58
|
+
# define NC_HAVE_BACKTRACE 1
|
59
|
+
#endif
|
60
|
+
|
47
61
|
#define NC_OK 0
|
48
62
|
#define NC_ERROR -1
|
49
63
|
#define NC_EAGAIN -2
|
@@ -65,8 +79,8 @@ struct mbuf;
|
|
65
79
|
struct mhdr;
|
66
80
|
struct conf;
|
67
81
|
struct stats;
|
68
|
-
struct epoll_event;
|
69
82
|
struct instance;
|
83
|
+
struct event_base;
|
70
84
|
|
71
85
|
#include <stddef.h>
|
72
86
|
#include <stdint.h>
|
@@ -82,6 +96,7 @@ struct instance;
|
|
82
96
|
#include <sys/types.h>
|
83
97
|
#include <sys/socket.h>
|
84
98
|
#include <sys/un.h>
|
99
|
+
#include <sys/time.h>
|
85
100
|
#include <netinet/in.h>
|
86
101
|
|
87
102
|
#include <nc_array.h>
|
@@ -90,6 +105,7 @@ struct instance;
|
|
90
105
|
#include <nc_rbtree.h>
|
91
106
|
#include <nc_log.h>
|
92
107
|
#include <nc_util.h>
|
108
|
+
#include <event/nc_event.h>
|
93
109
|
#include <nc_stats.h>
|
94
110
|
#include <nc_mbuf.h>
|
95
111
|
#include <nc_message.h>
|
@@ -101,14 +117,12 @@ struct context {
|
|
101
117
|
struct stats *stats; /* stats */
|
102
118
|
|
103
119
|
struct array pool; /* server_pool[] */
|
104
|
-
|
105
|
-
int
|
106
|
-
int
|
107
|
-
int max_timeout; /* epoll wait max timeout in msec */
|
108
|
-
int timeout; /* epoll wait timeout in msec */
|
109
|
-
struct epoll_event *event; /* epoll event */
|
120
|
+
struct event_base *evb; /* event base */
|
121
|
+
int max_timeout; /* max timeout in msec */
|
122
|
+
int timeout; /* timeout in msec */
|
110
123
|
};
|
111
124
|
|
125
|
+
|
112
126
|
struct instance {
|
113
127
|
struct context *ctx; /* active context */
|
114
128
|
int log_level; /* log level */
|
@@ -126,6 +140,7 @@ struct instance {
|
|
126
140
|
|
127
141
|
struct context *core_start(struct instance *nci);
|
128
142
|
void core_stop(struct context *ctx);
|
143
|
+
rstatus_t core_core(void *arg, uint32_t events);
|
129
144
|
rstatus_t core_loop(struct context *ctx);
|
130
145
|
|
131
146
|
#endif
|
@@ -19,7 +19,6 @@
|
|
19
19
|
|
20
20
|
#include <nc_core.h>
|
21
21
|
#include <nc_server.h>
|
22
|
-
#include <nc_event.h>
|
23
22
|
#include <nc_proxy.h>
|
24
23
|
|
25
24
|
void
|
@@ -163,18 +162,18 @@ proxy_listen(struct context *ctx, struct conn *p)
|
|
163
162
|
return NC_ERROR;
|
164
163
|
}
|
165
164
|
|
166
|
-
status = event_add_conn(ctx->
|
165
|
+
status = event_add_conn(ctx->evb, p);
|
167
166
|
if (status < 0) {
|
168
|
-
log_error("event add conn
|
169
|
-
|
167
|
+
log_error("event add conn p %d on addr '%.*s' failed: %s",
|
168
|
+
p->sd, pool->addrstr.len, pool->addrstr.data,
|
170
169
|
strerror(errno));
|
171
170
|
return NC_ERROR;
|
172
171
|
}
|
173
172
|
|
174
|
-
status = event_del_out(ctx->
|
173
|
+
status = event_del_out(ctx->evb, p);
|
175
174
|
if (status < 0) {
|
176
|
-
log_error("event del out
|
177
|
-
|
175
|
+
log_error("event del out p %d on addr '%.*s' failed: %s",
|
176
|
+
p->sd, pool->addrstr.len, pool->addrstr.data,
|
178
177
|
strerror(errno));
|
179
178
|
return NC_ERROR;
|
180
179
|
}
|
@@ -325,9 +324,9 @@ proxy_accept(struct context *ctx, struct conn *p)
|
|
325
324
|
}
|
326
325
|
}
|
327
326
|
|
328
|
-
status = event_add_conn(ctx->
|
327
|
+
status = event_add_conn(ctx->evb, c);
|
329
328
|
if (status < 0) {
|
330
|
-
log_error("event add conn
|
329
|
+
log_error("event add conn from p %d failed: %s", p->sd,
|
331
330
|
strerror(errno));
|
332
331
|
c->close(ctx, c);
|
333
332
|
return status;
|
@@ -17,7 +17,6 @@
|
|
17
17
|
|
18
18
|
#include <nc_core.h>
|
19
19
|
#include <nc_server.h>
|
20
|
-
#include <nc_event.h>
|
21
20
|
|
22
21
|
struct msg *
|
23
22
|
req_get(struct conn *conn)
|
@@ -413,7 +412,7 @@ req_forward_error(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
413
412
|
}
|
414
413
|
|
415
414
|
if (req_done(conn, TAILQ_FIRST(&conn->omsg_q))) {
|
416
|
-
status = event_add_out(ctx->
|
415
|
+
status = event_add_out(ctx->evb, conn);
|
417
416
|
if (status != NC_OK) {
|
418
417
|
conn->err = errno;
|
419
418
|
}
|
@@ -482,7 +481,7 @@ req_forward(struct context *ctx, struct conn *c_conn, struct msg *msg)
|
|
482
481
|
|
483
482
|
/* enqueue the message (request) into server inq */
|
484
483
|
if (TAILQ_EMPTY(&s_conn->imsg_q)) {
|
485
|
-
status = event_add_out(ctx->
|
484
|
+
status = event_add_out(ctx->evb, s_conn);
|
486
485
|
if (status != NC_OK) {
|
487
486
|
req_forward_error(ctx, c_conn, msg);
|
488
487
|
s_conn->err = errno;
|
@@ -533,7 +532,7 @@ req_send_next(struct context *ctx, struct conn *conn)
|
|
533
532
|
nmsg = TAILQ_FIRST(&conn->imsg_q);
|
534
533
|
if (nmsg == NULL) {
|
535
534
|
/* nothing to send as the server inq is empty */
|
536
|
-
status = event_del_out(ctx->
|
535
|
+
status = event_del_out(ctx->evb, conn);
|
537
536
|
if (status != NC_OK) {
|
538
537
|
conn->err = errno;
|
539
538
|
}
|
@@ -17,7 +17,6 @@
|
|
17
17
|
|
18
18
|
#include <nc_core.h>
|
19
19
|
#include <nc_server.h>
|
20
|
-
#include <nc_event.h>
|
21
20
|
|
22
21
|
struct msg *
|
23
22
|
rsp_get(struct conn *conn)
|
@@ -90,7 +89,6 @@ rsp_recv_next(struct context *ctx, struct conn *conn, bool alloc)
|
|
90
89
|
struct msg *msg;
|
91
90
|
|
92
91
|
ASSERT(!conn->client && !conn->proxy);
|
93
|
-
ASSERT(!conn->connecting);
|
94
92
|
|
95
93
|
if (conn->eof) {
|
96
94
|
msg = conn->rmsg;
|
@@ -157,11 +155,30 @@ rsp_filter(struct context *ctx, struct conn *conn, struct msg *msg)
|
|
157
155
|
|
158
156
|
pmsg = TAILQ_FIRST(&conn->omsg_q);
|
159
157
|
if (pmsg == NULL) {
|
160
|
-
|
161
|
-
msg->mlen, conn->sd);
|
158
|
+
log_debug(LOG_ERR, "filter stray rsp %"PRIu64" len %"PRIu32" on s %d",
|
159
|
+
msg->id, msg->mlen, conn->sd);
|
162
160
|
rsp_put(msg);
|
163
|
-
|
164
|
-
|
161
|
+
|
162
|
+
/*
|
163
|
+
* Memcached server can respond with an error response before it has
|
164
|
+
* received the entire request. This is most commonly seen for set
|
165
|
+
* requests that exceed item_size_max. IMO, this behavior of memcached
|
166
|
+
* is incorrect. The right behavior for update requests that are over
|
167
|
+
* item_size_max would be to either:
|
168
|
+
* - close the connection Or,
|
169
|
+
* - read the entire item_size_max data and then send CLIENT_ERROR
|
170
|
+
*
|
171
|
+
* We handle this stray packet scenario in nutcracker by closing the
|
172
|
+
* server connection which would end up sending SERVER_ERROR to all
|
173
|
+
* clients that have requests pending on this server connection. The
|
174
|
+
* fix is aggresive, but not doing so would lead to clients getting
|
175
|
+
* out of sync with the server and as a result clients end up getting
|
176
|
+
* responses that don't correspond to the right request.
|
177
|
+
*
|
178
|
+
* See: https://github.com/twitter/twemproxy/issues/149
|
179
|
+
*/
|
180
|
+
conn->err = EINVAL;
|
181
|
+
conn->done = 1;
|
165
182
|
return true;
|
166
183
|
}
|
167
184
|
ASSERT(pmsg->peer == NULL);
|
@@ -222,7 +239,7 @@ rsp_forward(struct context *ctx, struct conn *s_conn, struct msg *msg)
|
|
222
239
|
ASSERT(c_conn->client && !c_conn->proxy);
|
223
240
|
|
224
241
|
if (req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) {
|
225
|
-
status = event_add_out(ctx->
|
242
|
+
status = event_add_out(ctx->evb, c_conn);
|
226
243
|
if (status != NC_OK) {
|
227
244
|
c_conn->err = errno;
|
228
245
|
}
|
@@ -267,7 +284,7 @@ rsp_send_next(struct context *ctx, struct conn *conn)
|
|
267
284
|
log_debug(LOG_INFO, "c %d is done", conn->sd);
|
268
285
|
}
|
269
286
|
|
270
|
-
status = event_del_out(ctx->
|
287
|
+
status = event_del_out(ctx->evb, conn);
|
271
288
|
if (status != NC_OK) {
|
272
289
|
conn->err = errno;
|
273
290
|
}
|
@@ -19,7 +19,6 @@
|
|
19
19
|
#include <unistd.h>
|
20
20
|
|
21
21
|
#include <nc_core.h>
|
22
|
-
#include <nc_event.h>
|
23
22
|
#include <nc_server.h>
|
24
23
|
#include <nc_conf.h>
|
25
24
|
|
@@ -273,6 +272,9 @@ server_failure(struct context *ctx, struct server *server)
|
|
273
272
|
if (now < 0) {
|
274
273
|
return;
|
275
274
|
}
|
275
|
+
|
276
|
+
stats_server_set_ts(ctx, server, server_ejected_at, now);
|
277
|
+
|
276
278
|
next = now + pool->server_retry_timeout;
|
277
279
|
|
278
280
|
log_debug(LOG_INFO, "update pool %"PRIu32" '%.*s' to delete server '%.*s' "
|
@@ -367,7 +369,7 @@ server_close(struct context *ctx, struct conn *conn)
|
|
367
369
|
msg->err = conn->err;
|
368
370
|
|
369
371
|
if (req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) {
|
370
|
-
event_add_out(ctx->
|
372
|
+
event_add_out(ctx->evb, msg->owner);
|
371
373
|
}
|
372
374
|
|
373
375
|
log_debug(LOG_INFO, "close s %d schedule error for req %"PRIu64" "
|
@@ -397,7 +399,7 @@ server_close(struct context *ctx, struct conn *conn)
|
|
397
399
|
msg->err = conn->err;
|
398
400
|
|
399
401
|
if (req_done(c_conn, TAILQ_FIRST(&c_conn->omsg_q))) {
|
400
|
-
event_add_out(ctx->
|
402
|
+
event_add_out(ctx->evb, msg->owner);
|
401
403
|
}
|
402
404
|
|
403
405
|
log_debug(LOG_INFO, "close s %d schedule error for req %"PRIu64" "
|
@@ -476,10 +478,10 @@ server_connect(struct context *ctx, struct server *server, struct conn *conn)
|
|
476
478
|
}
|
477
479
|
}
|
478
480
|
|
479
|
-
status = event_add_conn(ctx->
|
481
|
+
status = event_add_conn(ctx->evb, conn);
|
480
482
|
if (status != NC_OK) {
|
481
|
-
log_error("event add conn
|
482
|
-
|
483
|
+
log_error("event add conn s %d for server '%.*s' failed: %s",
|
484
|
+
conn->sd, server->pname.len, server->pname.data,
|
483
485
|
strerror(errno));
|
484
486
|
goto error;
|
485
487
|
}
|
@@ -21,7 +21,6 @@
|
|
21
21
|
|
22
22
|
#include <sys/types.h>
|
23
23
|
#include <sys/socket.h>
|
24
|
-
#include <sys/epoll.h>
|
25
24
|
#include <netinet/in.h>
|
26
25
|
|
27
26
|
#include <nc_core.h>
|
@@ -770,34 +769,27 @@ stats_send_rsp(struct stats *st)
|
|
770
769
|
return NC_OK;
|
771
770
|
}
|
772
771
|
|
773
|
-
static void
|
774
|
-
|
772
|
+
static void
|
773
|
+
stats_loop_callback(void *arg1, void *arg2)
|
775
774
|
{
|
776
|
-
struct stats *st =
|
777
|
-
int n;
|
775
|
+
struct stats *st = arg1;
|
776
|
+
int n = *((int *)arg2);
|
778
777
|
|
779
|
-
|
780
|
-
|
781
|
-
if (n < 0) {
|
782
|
-
if (errno == EINTR) {
|
783
|
-
continue;
|
784
|
-
}
|
785
|
-
log_error("epoll wait on e %d with event m %d failed: %s",
|
786
|
-
st->ep, st->sd, strerror(errno));
|
787
|
-
break;
|
788
|
-
}
|
789
|
-
|
790
|
-
/* aggregate stats from shadow (b) -> sum (c) */
|
791
|
-
stats_aggregate(st);
|
778
|
+
/* aggregate stats from shadow (b) -> sum (c) */
|
779
|
+
stats_aggregate(st);
|
792
780
|
|
793
|
-
|
794
|
-
|
795
|
-
}
|
796
|
-
|
797
|
-
/* send aggregate stats sum (c) to collector */
|
798
|
-
stats_send_rsp(st);
|
781
|
+
if (n == 0) {
|
782
|
+
return;
|
799
783
|
}
|
800
784
|
|
785
|
+
/* send aggregate stats sum (c) to collector */
|
786
|
+
stats_send_rsp(st);
|
787
|
+
}
|
788
|
+
|
789
|
+
static void *
|
790
|
+
stats_loop(void *arg)
|
791
|
+
{
|
792
|
+
event_loop_stats(stats_loop_callback, arg);
|
801
793
|
return NULL;
|
802
794
|
}
|
803
795
|
|
@@ -847,7 +839,6 @@ static rstatus_t
|
|
847
839
|
stats_start_aggregator(struct stats *st)
|
848
840
|
{
|
849
841
|
rstatus_t status;
|
850
|
-
struct epoll_event ev;
|
851
842
|
|
852
843
|
if (!stats_enabled) {
|
853
844
|
return NC_OK;
|
@@ -858,22 +849,6 @@ stats_start_aggregator(struct stats *st)
|
|
858
849
|
return status;
|
859
850
|
}
|
860
851
|
|
861
|
-
st->ep = epoll_create(10);
|
862
|
-
if (st->ep < 0) {
|
863
|
-
log_error("epoll create failed: %s", strerror(errno));
|
864
|
-
return NC_ERROR;
|
865
|
-
}
|
866
|
-
|
867
|
-
ev.data.fd = st->sd;
|
868
|
-
ev.events = EPOLLIN;
|
869
|
-
|
870
|
-
status = epoll_ctl(st->ep, EPOLL_CTL_ADD, st->sd, &ev);
|
871
|
-
if (status < 0) {
|
872
|
-
log_error("epoll ctl on e %d sd %d failed: %s", st->ep, st->sd,
|
873
|
-
strerror(errno));
|
874
|
-
return NC_ERROR;
|
875
|
-
}
|
876
|
-
|
877
852
|
status = pthread_create(&st->tid, NULL, stats_loop, st);
|
878
853
|
if (status < 0) {
|
879
854
|
log_error("stats aggregator create failed: %s", strerror(status));
|
@@ -891,7 +866,6 @@ stats_stop_aggregator(struct stats *st)
|
|
891
866
|
}
|
892
867
|
|
893
868
|
close(st->sd);
|
894
|
-
close(st->ep);
|
895
869
|
}
|
896
870
|
|
897
871
|
struct stats *
|
@@ -921,7 +895,6 @@ stats_create(uint16_t stats_port, char *stats_ip, int stats_interval,
|
|
921
895
|
array_null(&st->sum);
|
922
896
|
|
923
897
|
st->tid = (pthread_t) -1;
|
924
|
-
st->ep = -1;
|
925
898
|
st->sd = -1;
|
926
899
|
|
927
900
|
string_set_text(&st->service_str, "service");
|
@@ -1101,6 +1074,21 @@ _stats_pool_decr_by(struct context *ctx, struct server_pool *pool,
|
|
1101
1074
|
stm->name.data, stm->value.counter);
|
1102
1075
|
}
|
1103
1076
|
|
1077
|
+
void
|
1078
|
+
_stats_pool_set_ts(struct context *ctx, struct server_pool *pool,
|
1079
|
+
stats_pool_field_t fidx, int64_t val)
|
1080
|
+
{
|
1081
|
+
struct stats_metric *stm;
|
1082
|
+
|
1083
|
+
stm = stats_pool_to_metric(ctx, pool, fidx);
|
1084
|
+
|
1085
|
+
ASSERT(stm->type == STATS_TIMESTAMP);
|
1086
|
+
stm->value.timestamp = val;
|
1087
|
+
|
1088
|
+
log_debug(LOG_VVVERB, "set ts field '%.*s' to %"PRId64"", stm->name.len,
|
1089
|
+
stm->name.data, stm->value.timestamp);
|
1090
|
+
}
|
1091
|
+
|
1104
1092
|
static struct stats_metric *
|
1105
1093
|
stats_server_to_metric(struct context *ctx, struct server *server,
|
1106
1094
|
stats_server_field_t fidx)
|
@@ -1186,3 +1174,18 @@ _stats_server_decr_by(struct context *ctx, struct server *server,
|
|
1186
1174
|
log_debug(LOG_VVVERB, "decr by field '%.*s' to %"PRId64"", stm->name.len,
|
1187
1175
|
stm->name.data, stm->value.counter);
|
1188
1176
|
}
|
1177
|
+
|
1178
|
+
void
|
1179
|
+
_stats_server_set_ts(struct context *ctx, struct server *server,
|
1180
|
+
stats_server_field_t fidx, int64_t val)
|
1181
|
+
{
|
1182
|
+
struct stats_metric *stm;
|
1183
|
+
|
1184
|
+
stm = stats_server_to_metric(ctx, server, fidx);
|
1185
|
+
|
1186
|
+
ASSERT(stm->type == STATS_TIMESTAMP);
|
1187
|
+
stm->value.timestamp = val;
|
1188
|
+
|
1189
|
+
log_debug(LOG_VVVERB, "set ts field '%.*s' to %"PRId64"", stm->name.len,
|
1190
|
+
stm->name.data, stm->value.timestamp);
|
1191
|
+
}
|