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
@@ -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 */