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.
Files changed (47) hide show
  1. checksums.yaml +8 -8
  2. data/Rakefile +1 -1
  3. data/ext/nutcracker/ChangeLog +10 -0
  4. data/ext/nutcracker/Makefile.am +2 -0
  5. data/ext/nutcracker/Makefile.in +101 -14
  6. data/ext/nutcracker/README.md +18 -1
  7. data/ext/nutcracker/config.h.in +18 -0
  8. data/ext/nutcracker/configure +196 -25
  9. data/ext/nutcracker/configure.ac +64 -6
  10. data/ext/nutcracker/extconf.rb +1 -1
  11. data/ext/nutcracker/man/nutcracker.8 +76 -0
  12. data/ext/nutcracker/notes/debug.txt +116 -16
  13. data/ext/nutcracker/notes/kqueue.pdf +0 -0
  14. data/ext/nutcracker/notes/recommendation.md +20 -0
  15. data/ext/nutcracker/notes/redis.md +2 -2
  16. data/ext/nutcracker/scripts/nutcracker.spec +1 -1
  17. data/ext/nutcracker/scripts/redis-check.sh +3 -1
  18. data/ext/nutcracker/src/Makefile.am +15 -6
  19. data/ext/nutcracker/src/Makefile.in +39 -36
  20. data/ext/nutcracker/src/event/Makefile.am +16 -0
  21. data/ext/nutcracker/src/event/Makefile.in +492 -0
  22. data/ext/nutcracker/src/event/nc_epoll.c +344 -0
  23. data/ext/nutcracker/src/event/nc_event.h +88 -0
  24. data/ext/nutcracker/src/event/nc_evport.c +420 -0
  25. data/ext/nutcracker/src/event/nc_kqueue.c +412 -0
  26. data/ext/nutcracker/src/hashkit/nc_crc32.c +19 -1
  27. data/ext/nutcracker/src/hashkit/nc_hashkit.h +3 -1
  28. data/ext/nutcracker/src/hashkit/nc_md5.c +257 -315
  29. data/ext/nutcracker/src/nc.c +12 -1
  30. data/ext/nutcracker/src/nc_connection.c +18 -1
  31. data/ext/nutcracker/src/nc_connection.h +1 -0
  32. data/ext/nutcracker/src/nc_core.c +22 -30
  33. data/ext/nutcracker/src/nc_core.h +22 -7
  34. data/ext/nutcracker/src/nc_proxy.c +8 -9
  35. data/ext/nutcracker/src/nc_queue.h +2 -0
  36. data/ext/nutcracker/src/nc_request.c +3 -4
  37. data/ext/nutcracker/src/nc_response.c +25 -8
  38. data/ext/nutcracker/src/nc_server.c +8 -6
  39. data/ext/nutcracker/src/nc_stats.c +46 -43
  40. data/ext/nutcracker/src/nc_stats.h +37 -30
  41. data/ext/nutcracker/src/nc_util.c +6 -1
  42. data/ext/nutcracker/src/proto/nc_redis.c +19 -5
  43. data/lib/nutcracker/version.rb +1 -1
  44. data/lib/nutcracker.rb +1 -1
  45. metadata +10 -4
  46. data/ext/nutcracker/src/nc_event.c +0 -214
  47. data/ext/nutcracker/src/nc_event.h +0 -39
@@ -88,6 +88,7 @@ struct conn {
88
88
 
89
89
  TAILQ_HEAD(conn_tqh, conn);
90
90
 
91
+ struct context *conn_to_ctx(struct conn *conn);
91
92
  struct conn *conn_get(void *owner, bool client, bool redis);
92
93
  struct conn *conn_get_proxy(void *owner);
93
94
  void conn_put(struct conn *conn);
@@ -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
- status = event_init(ctx, EVENT_SIZE_HINT);
78
- if (status != NC_OK) {
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
- event_deinit(ctx);
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
- event_deinit(ctx);
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
- event_deinit(ctx);
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->ep, conn);
203
+ status = event_del_conn(ctx->evb, conn);
210
204
  if (status < 0) {
211
- log_warn("event del conn e %d %c %d failed, ignored: %s", ctx->ep,
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
- static void
280
- core_core(struct context *ctx, struct conn *conn, uint32_t events)
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 & EPOLLERR) {
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 & (EPOLLIN | EPOLLHUP)) {
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 & EPOLLOUT) {
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 i, nsd;
314
+ int nsd;
317
315
 
318
- nsd = event_wait(ctx->ep, ctx->event, ctx->nevent, ctx->timeout);
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 ep; /* epoll device */
106
- int nevent; /* # epoll event */
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->ep, p);
165
+ status = event_add_conn(ctx->evb, p);
167
166
  if (status < 0) {
168
- log_error("event add conn e %d p %d on addr '%.*s' failed: %s",
169
- ctx->ep, p->sd, pool->addrstr.len, pool->addrstr.data,
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->ep, p);
173
+ status = event_del_out(ctx->evb, p);
175
174
  if (status < 0) {
176
- log_error("event del out e %d p %d on addr '%.*s' failed: %s",
177
- ctx->ep, p->sd, pool->addrstr.len, pool->addrstr.data,
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->ep, c);
327
+ status = event_add_conn(ctx->evb, c);
329
328
  if (status < 0) {
330
- log_error("event add conn of c %d from p %d failed: %s", c->sd, p->sd,
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;
@@ -52,7 +52,9 @@
52
52
 
53
53
  #include <nc_log.h>
54
54
 
55
+ #ifndef __offsetof
55
56
  #define __offsetof(type, field) ((size_t)(&((type *)NULL)->field))
57
+ #endif
56
58
 
57
59
  /*
58
60
  * This file defines five types of data structures: singly-linked lists,
@@ -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->ep, conn);
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->ep, s_conn);
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->ep, conn);
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
- log_error("filter stray rsp %"PRIu64" len %"PRIu32" on s %d", msg->id,
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
- errno = EINVAL;
164
- conn->err = errno;
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->ep, c_conn);
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->ep, conn);
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->ep, msg->owner);
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->ep, msg->owner);
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->ep, conn);
481
+ status = event_add_conn(ctx->evb, conn);
480
482
  if (status != NC_OK) {
481
- log_error("event add conn e %d s %d for server '%.*s' failed: %s",
482
- ctx->ep, conn->sd, server->pname.len, server->pname.data,
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
- stats_loop(void *arg)
772
+ static void
773
+ stats_loop_callback(void *arg1, void *arg2)
775
774
  {
776
- struct stats *st = arg;
777
- int n;
775
+ struct stats *st = arg1;
776
+ int n = *((int *)arg2);
778
777
 
779
- for (;;) {
780
- n = epoll_wait(st->ep, &st->event, 1, st->interval);
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
- if (n == 0) {
794
- continue;
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
+ }