nutcracker 0.2.4.12 → 0.3.0.12
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 +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
|
+
}
|