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