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.
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
@@ -0,0 +1,344 @@
1
+ /*
2
+ * twemproxy - A fast and lightweight proxy for memcached protocol.
3
+ * Copyright (C) 2011 Twitter, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #include <nc_core.h>
19
+
20
+ #ifdef NC_HAVE_EPOLL
21
+
22
+ #include <sys/epoll.h>
23
+
24
+ struct event_base *
25
+ event_base_create(int nevent, event_cb_t cb)
26
+ {
27
+ struct event_base *evb;
28
+ int status, ep;
29
+ struct epoll_event *event;
30
+
31
+ ASSERT(nevent > 0);
32
+
33
+ ep = epoll_create(nevent);
34
+ if (ep < 0) {
35
+ log_error("epoll create of size %d failed: %s", nevent, strerror(errno));
36
+ return NULL;
37
+ }
38
+
39
+ event = nc_calloc(nevent, sizeof(*event));
40
+ if (event == NULL) {
41
+ status = close(ep);
42
+ if (status < 0) {
43
+ log_error("close e %d failed, ignored: %s", ep, strerror(errno));
44
+ }
45
+ return NULL;
46
+ }
47
+
48
+ evb = nc_alloc(sizeof(*evb));
49
+ if (evb == NULL) {
50
+ nc_free(event);
51
+ status = close(ep);
52
+ if (status < 0) {
53
+ log_error("close e %d failed, ignored: %s", ep, strerror(errno));
54
+ }
55
+ return NULL;
56
+ }
57
+
58
+ evb->ep = ep;
59
+ evb->event = event;
60
+ evb->nevent = nevent;
61
+ evb->cb = cb;
62
+
63
+ log_debug(LOG_INFO, "e %d with nevent %d", evb->ep, evb->nevent);
64
+
65
+ return evb;
66
+ }
67
+
68
+ void
69
+ event_base_destroy(struct event_base *evb)
70
+ {
71
+ int status;
72
+
73
+ if (evb == NULL) {
74
+ return;
75
+ }
76
+
77
+ ASSERT(evb->ep > 0);
78
+
79
+ nc_free(evb->event);
80
+
81
+ status = close(evb->ep);
82
+ if (status < 0) {
83
+ log_error("close e %d failed, ignored: %s", evb->ep, strerror(errno));
84
+ }
85
+ evb->ep = -1;
86
+
87
+ nc_free(evb);
88
+ }
89
+
90
+ int
91
+ event_add_in(struct event_base *evb, struct conn *c)
92
+ {
93
+ int status;
94
+ struct epoll_event event;
95
+ int ep = evb->ep;
96
+
97
+ ASSERT(ep > 0);
98
+ ASSERT(c != NULL);
99
+ ASSERT(c->sd > 0);
100
+
101
+ if (c->recv_active) {
102
+ return 0;
103
+ }
104
+
105
+ event.events = (uint32_t)(EPOLLIN | EPOLLET);
106
+ event.data.ptr = c;
107
+
108
+ status = epoll_ctl(ep, EPOLL_CTL_MOD, c->sd, &event);
109
+ if (status < 0) {
110
+ log_error("epoll ctl on e %d sd %d failed: %s", ep, c->sd,
111
+ strerror(errno));
112
+ } else {
113
+ c->recv_active = 1;
114
+ }
115
+
116
+ return status;
117
+ }
118
+
119
+ int
120
+ event_del_in(struct event_base *evb, struct conn *c)
121
+ {
122
+ return 0;
123
+ }
124
+
125
+ int
126
+ event_add_out(struct event_base *evb, struct conn *c)
127
+ {
128
+ int status;
129
+ struct epoll_event event;
130
+ int ep = evb->ep;
131
+
132
+ ASSERT(ep > 0);
133
+ ASSERT(c != NULL);
134
+ ASSERT(c->sd > 0);
135
+ ASSERT(c->recv_active);
136
+
137
+ if (c->send_active) {
138
+ return 0;
139
+ }
140
+
141
+ event.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET);
142
+ event.data.ptr = c;
143
+
144
+ status = epoll_ctl(ep, EPOLL_CTL_MOD, c->sd, &event);
145
+ if (status < 0) {
146
+ log_error("epoll ctl on e %d sd %d failed: %s", ep, c->sd,
147
+ strerror(errno));
148
+ } else {
149
+ c->send_active = 1;
150
+ }
151
+
152
+ return status;
153
+ }
154
+
155
+ int
156
+ event_del_out(struct event_base *evb, struct conn *c)
157
+ {
158
+ int status;
159
+ struct epoll_event event;
160
+ int ep = evb->ep;
161
+
162
+ ASSERT(ep > 0);
163
+ ASSERT(c != NULL);
164
+ ASSERT(c->sd > 0);
165
+ ASSERT(c->recv_active);
166
+
167
+ if (!c->send_active) {
168
+ return 0;
169
+ }
170
+
171
+ event.events = (uint32_t)(EPOLLIN | EPOLLET);
172
+ event.data.ptr = c;
173
+
174
+ status = epoll_ctl(ep, EPOLL_CTL_MOD, c->sd, &event);
175
+ if (status < 0) {
176
+ log_error("epoll ctl on e %d sd %d failed: %s", ep, c->sd,
177
+ strerror(errno));
178
+ } else {
179
+ c->send_active = 0;
180
+ }
181
+
182
+ return status;
183
+ }
184
+
185
+ int
186
+ event_add_conn(struct event_base *evb, struct conn *c)
187
+ {
188
+ int status;
189
+ struct epoll_event event;
190
+ int ep = evb->ep;
191
+
192
+ ASSERT(ep > 0);
193
+ ASSERT(c != NULL);
194
+ ASSERT(c->sd > 0);
195
+
196
+ event.events = (uint32_t)(EPOLLIN | EPOLLOUT | EPOLLET);
197
+ event.data.ptr = c;
198
+
199
+ status = epoll_ctl(ep, EPOLL_CTL_ADD, c->sd, &event);
200
+ if (status < 0) {
201
+ log_error("epoll ctl on e %d sd %d failed: %s", ep, c->sd,
202
+ strerror(errno));
203
+ } else {
204
+ c->send_active = 1;
205
+ c->recv_active = 1;
206
+ }
207
+
208
+ return status;
209
+ }
210
+
211
+ int
212
+ event_del_conn(struct event_base *evb, struct conn *c)
213
+ {
214
+ int status;
215
+ int ep = evb->ep;
216
+
217
+ ASSERT(ep > 0);
218
+ ASSERT(c != NULL);
219
+ ASSERT(c->sd > 0);
220
+
221
+ status = epoll_ctl(ep, EPOLL_CTL_DEL, c->sd, NULL);
222
+ if (status < 0) {
223
+ log_error("epoll ctl on e %d sd %d failed: %s", ep, c->sd,
224
+ strerror(errno));
225
+ } else {
226
+ c->recv_active = 0;
227
+ c->send_active = 0;
228
+ }
229
+
230
+ return status;
231
+ }
232
+
233
+ int
234
+ event_wait(struct event_base *evb, int timeout)
235
+ {
236
+ int ep = evb->ep;
237
+ struct epoll_event *event = evb->event;
238
+ int nevent = evb->nevent;
239
+
240
+ ASSERT(ep > 0);
241
+ ASSERT(event != NULL);
242
+ ASSERT(nevent > 0);
243
+
244
+ for (;;) {
245
+ int i, nsd;
246
+
247
+ nsd = epoll_wait(ep, event, nevent, timeout);
248
+ if (nsd > 0) {
249
+ for (i = 0; i < nsd; i++) {
250
+ struct epoll_event *ev = &evb->event[i];
251
+ uint32_t events = 0;
252
+
253
+ log_debug(LOG_VVERB, "epoll %04"PRIX32" triggered on conn %p",
254
+ ev->events, ev->data.ptr);
255
+
256
+ if (ev->events & EPOLLERR) {
257
+ events |= EVENT_ERR;
258
+ }
259
+
260
+ if (ev->events & (EPOLLIN | EPOLLHUP)) {
261
+ events |= EVENT_READ;
262
+ }
263
+
264
+ if (ev->events & EPOLLOUT) {
265
+ events |= EVENT_WRITE;
266
+ }
267
+
268
+ if (evb->cb != NULL) {
269
+ evb->cb(ev->data.ptr, events);
270
+ }
271
+ }
272
+ return nsd;
273
+ }
274
+
275
+ if (nsd == 0) {
276
+ if (timeout == -1) {
277
+ log_error("epoll wait on e %d with %d events and %d timeout "
278
+ "returned no events", ep, nevent, timeout);
279
+ return -1;
280
+ }
281
+
282
+ return 0;
283
+ }
284
+
285
+ if (errno == EINTR) {
286
+ continue;
287
+ }
288
+
289
+ log_error("epoll wait on e %d with %d events failed: %s", ep, nevent,
290
+ strerror(errno));
291
+ return -1;
292
+ }
293
+
294
+ NOT_REACHED();
295
+ }
296
+
297
+ void
298
+ event_loop_stats(event_stats_cb_t cb, void *arg)
299
+ {
300
+ struct stats *st = arg;
301
+ int status, ep;
302
+ struct epoll_event ev;
303
+
304
+ ep = epoll_create(1);
305
+ if (ep < 0) {
306
+ log_error("epoll create failed: %s", strerror(errno));
307
+ return;
308
+ }
309
+
310
+ ev.data.fd = st->sd;
311
+ ev.events = EPOLLIN;
312
+
313
+ status = epoll_ctl(ep, EPOLL_CTL_ADD, st->sd, &ev);
314
+ if (status < 0) {
315
+ log_error("epoll ctl on e %d sd %d failed: %s", ep, st->sd,
316
+ strerror(errno));
317
+ goto error;
318
+ }
319
+
320
+ for (;;) {
321
+ int n;
322
+
323
+ n = epoll_wait(ep, &ev, 1, st->interval);
324
+ if (n < 0) {
325
+ if (errno == EINTR) {
326
+ continue;
327
+ }
328
+ log_error("epoll wait on e %d with m %d failed: %s", ep,
329
+ st->sd, strerror(errno));
330
+ break;
331
+ }
332
+
333
+ cb(st, &n);
334
+ }
335
+
336
+ error:
337
+ status = close(ep);
338
+ if (status < 0) {
339
+ log_error("close e %d failed, ignored: %s", ep, strerror(errno));
340
+ }
341
+ ep = -1;
342
+ }
343
+
344
+ #endif /* NC_HAVE_EPOLL */
@@ -0,0 +1,88 @@
1
+ /*
2
+ * twemproxy - A fast and lightweight proxy for memcached protocol.
3
+ * Copyright (C) 2011 Twitter, Inc.
4
+ *
5
+ * Licensed under the Apache License, Version 2.0 (the "License");
6
+ * you may not use this file except in compliance with the License.
7
+ * You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ #ifndef _NC_EVENT_H_
19
+ #define _NC_EVENT_H_
20
+
21
+ #include <nc_core.h>
22
+
23
+ #define EVENT_SIZE 1024
24
+
25
+ #define EVENT_READ 0x0000ff
26
+ #define EVENT_WRITE 0x00ff00
27
+ #define EVENT_ERR 0xff0000
28
+
29
+ typedef int (*event_cb_t)(void *, uint32_t);
30
+ typedef void (*event_stats_cb_t)(void *, void *);
31
+
32
+ #ifdef NC_HAVE_KQUEUE
33
+
34
+ struct event_base {
35
+ int kq; /* kernel event queue descriptor */
36
+
37
+ struct kevent *change; /* change[] - events we want to monitor */
38
+ int nchange; /* # change */
39
+
40
+ struct kevent *event; /* event[] - events that were triggered */
41
+ int nevent; /* # event */
42
+ int nreturned; /* # event placed in event[] */
43
+ int nprocessed; /* # event processed from event[] */
44
+
45
+ event_cb_t cb; /* event callback */
46
+ };
47
+
48
+ #elif NC_HAVE_EPOLL
49
+
50
+ struct event_base {
51
+ int ep; /* epoll descriptor */
52
+
53
+ struct epoll_event *event; /* event[] - events that were triggered */
54
+ int nevent; /* # event */
55
+
56
+ event_cb_t cb; /* event callback */
57
+ };
58
+
59
+ #elif NC_HAVE_EVENT_PORTS
60
+
61
+ #include <port.h>
62
+
63
+ struct event_base {
64
+ int evp; /* event port descriptor */
65
+
66
+ port_event_t *event; /* event[] - events that were triggered */
67
+ int nevent; /* # event */
68
+
69
+ event_cb_t cb; /* event callback */
70
+ };
71
+
72
+ #else
73
+ # error missing scalable I/O event notification mechanism
74
+ #endif
75
+
76
+ struct event_base *event_base_create(int size, event_cb_t cb);
77
+ void event_base_destroy(struct event_base *evb);
78
+
79
+ int event_add_in(struct event_base *evb, struct conn *c);
80
+ int event_del_in(struct event_base *evb, struct conn *c);
81
+ int event_add_out(struct event_base *evb, struct conn *c);
82
+ int event_del_out(struct event_base *evb, struct conn *c);
83
+ int event_add_conn(struct event_base *evb, struct conn *c);
84
+ int event_del_conn(struct event_base *evb, struct conn *c);
85
+ int event_wait(struct event_base *evb, int timeout);
86
+ void event_loop_stats(event_stats_cb_t cb, void *arg);
87
+
88
+ #endif /* _NC_EVENT_H */