nutcracker 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. data/README.md +22 -0
  2. data/Rakefile +55 -0
  3. data/bin/nutcracker +2 -0
  4. data/ext/nutcracker/ChangeLog +66 -0
  5. data/ext/nutcracker/LICENSE +177 -0
  6. data/ext/nutcracker/Makefile.am +7 -0
  7. data/ext/nutcracker/Makefile.in +726 -0
  8. data/ext/nutcracker/NOTICE +124 -0
  9. data/ext/nutcracker/README.md +240 -0
  10. data/ext/nutcracker/aclocal.m4 +956 -0
  11. data/ext/nutcracker/conf/nutcracker.leaf.yml +10 -0
  12. data/ext/nutcracker/conf/nutcracker.root.yml +8 -0
  13. data/ext/nutcracker/conf/nutcracker.yml +67 -0
  14. data/ext/nutcracker/config.h.in +316 -0
  15. data/ext/nutcracker/config/config.guess +1561 -0
  16. data/ext/nutcracker/config/config.sub +1686 -0
  17. data/ext/nutcracker/config/depcomp +630 -0
  18. data/ext/nutcracker/config/install-sh +520 -0
  19. data/ext/nutcracker/config/ltmain.sh +8413 -0
  20. data/ext/nutcracker/config/missing +376 -0
  21. data/ext/nutcracker/configure +18862 -0
  22. data/ext/nutcracker/configure.ac +155 -0
  23. data/ext/nutcracker/contrib/Makefile.am +3 -0
  24. data/ext/nutcracker/contrib/Makefile.in +560 -0
  25. data/ext/nutcracker/contrib/yaml-0.1.4.tar.gz +0 -0
  26. data/ext/nutcracker/contrib/yaml-0.1.4/LICENSE +19 -0
  27. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.am +20 -0
  28. data/ext/nutcracker/contrib/yaml-0.1.4/Makefile.in +736 -0
  29. data/ext/nutcracker/contrib/yaml-0.1.4/README +27 -0
  30. data/ext/nutcracker/contrib/yaml-0.1.4/aclocal.m4 +956 -0
  31. data/ext/nutcracker/contrib/yaml-0.1.4/config.h.in +80 -0
  32. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.guess +1561 -0
  33. data/ext/nutcracker/contrib/yaml-0.1.4/config/config.sub +1686 -0
  34. data/ext/nutcracker/contrib/yaml-0.1.4/config/depcomp +630 -0
  35. data/ext/nutcracker/contrib/yaml-0.1.4/config/install-sh +520 -0
  36. data/ext/nutcracker/contrib/yaml-0.1.4/config/ltmain.sh +8406 -0
  37. data/ext/nutcracker/contrib/yaml-0.1.4/config/missing +376 -0
  38. data/ext/nutcracker/contrib/yaml-0.1.4/configure +13085 -0
  39. data/ext/nutcracker/contrib/yaml-0.1.4/configure.ac +75 -0
  40. data/ext/nutcracker/contrib/yaml-0.1.4/doc/doxygen.cfg +222 -0
  41. data/ext/nutcracker/contrib/yaml-0.1.4/include/yaml.h +1971 -0
  42. data/ext/nutcracker/contrib/yaml-0.1.4/m4/libtool.m4 +7357 -0
  43. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltoptions.m4 +368 -0
  44. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltsugar.m4 +123 -0
  45. data/ext/nutcracker/contrib/yaml-0.1.4/m4/ltversion.m4 +23 -0
  46. data/ext/nutcracker/contrib/yaml-0.1.4/m4/lt~obsolete.m4 +92 -0
  47. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.am +4 -0
  48. data/ext/nutcracker/contrib/yaml-0.1.4/src/Makefile.in +484 -0
  49. data/ext/nutcracker/contrib/yaml-0.1.4/src/api.c +1392 -0
  50. data/ext/nutcracker/contrib/yaml-0.1.4/src/dumper.c +394 -0
  51. data/ext/nutcracker/contrib/yaml-0.1.4/src/emitter.c +2329 -0
  52. data/ext/nutcracker/contrib/yaml-0.1.4/src/loader.c +432 -0
  53. data/ext/nutcracker/contrib/yaml-0.1.4/src/parser.c +1374 -0
  54. data/ext/nutcracker/contrib/yaml-0.1.4/src/reader.c +465 -0
  55. data/ext/nutcracker/contrib/yaml-0.1.4/src/scanner.c +3570 -0
  56. data/ext/nutcracker/contrib/yaml-0.1.4/src/writer.c +141 -0
  57. data/ext/nutcracker/contrib/yaml-0.1.4/src/yaml_private.h +640 -0
  58. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.am +8 -0
  59. data/ext/nutcracker/contrib/yaml-0.1.4/tests/Makefile.in +675 -0
  60. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor-alt.c +800 -0
  61. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-deconstructor.c +1130 -0
  62. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter-alt.c +217 -0
  63. data/ext/nutcracker/contrib/yaml-0.1.4/tests/example-reformatter.c +202 -0
  64. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-dumper.c +311 -0
  65. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-emitter.c +327 -0
  66. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-loader.c +63 -0
  67. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-parser.c +63 -0
  68. data/ext/nutcracker/contrib/yaml-0.1.4/tests/run-scanner.c +63 -0
  69. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-reader.c +354 -0
  70. data/ext/nutcracker/contrib/yaml-0.1.4/tests/test-version.c +29 -0
  71. data/ext/nutcracker/extconf.rb +5 -0
  72. data/ext/nutcracker/m4/libtool.m4 +7376 -0
  73. data/ext/nutcracker/m4/ltoptions.m4 +368 -0
  74. data/ext/nutcracker/m4/ltsugar.m4 +123 -0
  75. data/ext/nutcracker/m4/ltversion.m4 +23 -0
  76. data/ext/nutcracker/m4/lt~obsolete.m4 +92 -0
  77. data/ext/nutcracker/notes/c-styleguide.txt +425 -0
  78. data/ext/nutcracker/notes/debug.txt +96 -0
  79. data/ext/nutcracker/notes/memcache.txt +123 -0
  80. data/ext/nutcracker/notes/recommendation.md +118 -0
  81. data/ext/nutcracker/notes/redis.md +415 -0
  82. data/ext/nutcracker/notes/socket.txt +131 -0
  83. data/ext/nutcracker/scripts/multi_get.sh +26 -0
  84. data/ext/nutcracker/scripts/nutcracker.init +73 -0
  85. data/ext/nutcracker/scripts/nutcracker.spec +52 -0
  86. data/ext/nutcracker/scripts/pipelined_read.sh +23 -0
  87. data/ext/nutcracker/scripts/pipelined_write.sh +29 -0
  88. data/ext/nutcracker/scripts/populate_memcached.sh +24 -0
  89. data/ext/nutcracker/scripts/redis-check.py +23 -0
  90. data/ext/nutcracker/scripts/redis-check.sh +564 -0
  91. data/ext/nutcracker/src/Makefile.am +46 -0
  92. data/ext/nutcracker/src/Makefile.in +726 -0
  93. data/ext/nutcracker/src/hashkit/Makefile.am +22 -0
  94. data/ext/nutcracker/src/hashkit/Makefile.in +501 -0
  95. data/ext/nutcracker/src/hashkit/nc_crc32.c +105 -0
  96. data/ext/nutcracker/src/hashkit/nc_fnv.c +82 -0
  97. data/ext/nutcracker/src/hashkit/nc_hashkit.h +74 -0
  98. data/ext/nutcracker/src/hashkit/nc_hsieh.c +93 -0
  99. data/ext/nutcracker/src/hashkit/nc_jenkins.c +230 -0
  100. data/ext/nutcracker/src/hashkit/nc_ketama.c +240 -0
  101. data/ext/nutcracker/src/hashkit/nc_md5.c +379 -0
  102. data/ext/nutcracker/src/hashkit/nc_modula.c +144 -0
  103. data/ext/nutcracker/src/hashkit/nc_murmur.c +99 -0
  104. data/ext/nutcracker/src/hashkit/nc_one_at_a_time.c +51 -0
  105. data/ext/nutcracker/src/hashkit/nc_random.c +146 -0
  106. data/ext/nutcracker/src/nc.c +573 -0
  107. data/ext/nutcracker/src/nc_array.c +204 -0
  108. data/ext/nutcracker/src/nc_array.h +73 -0
  109. data/ext/nutcracker/src/nc_client.c +189 -0
  110. data/ext/nutcracker/src/nc_client.h +28 -0
  111. data/ext/nutcracker/src/nc_conf.c +1766 -0
  112. data/ext/nutcracker/src/nc_conf.h +134 -0
  113. data/ext/nutcracker/src/nc_connection.c +392 -0
  114. data/ext/nutcracker/src/nc_connection.h +99 -0
  115. data/ext/nutcracker/src/nc_core.c +334 -0
  116. data/ext/nutcracker/src/nc_core.h +131 -0
  117. data/ext/nutcracker/src/nc_event.c +214 -0
  118. data/ext/nutcracker/src/nc_event.h +39 -0
  119. data/ext/nutcracker/src/nc_log.c +254 -0
  120. data/ext/nutcracker/src/nc_log.h +120 -0
  121. data/ext/nutcracker/src/nc_mbuf.c +285 -0
  122. data/ext/nutcracker/src/nc_mbuf.h +67 -0
  123. data/ext/nutcracker/src/nc_message.c +828 -0
  124. data/ext/nutcracker/src/nc_message.h +253 -0
  125. data/ext/nutcracker/src/nc_proxy.c +359 -0
  126. data/ext/nutcracker/src/nc_proxy.h +34 -0
  127. data/ext/nutcracker/src/nc_queue.h +788 -0
  128. data/ext/nutcracker/src/nc_rbtree.c +348 -0
  129. data/ext/nutcracker/src/nc_rbtree.h +47 -0
  130. data/ext/nutcracker/src/nc_request.c +588 -0
  131. data/ext/nutcracker/src/nc_response.c +332 -0
  132. data/ext/nutcracker/src/nc_server.c +841 -0
  133. data/ext/nutcracker/src/nc_server.h +143 -0
  134. data/ext/nutcracker/src/nc_signal.c +131 -0
  135. data/ext/nutcracker/src/nc_signal.h +34 -0
  136. data/ext/nutcracker/src/nc_stats.c +1188 -0
  137. data/ext/nutcracker/src/nc_stats.h +206 -0
  138. data/ext/nutcracker/src/nc_string.c +109 -0
  139. data/ext/nutcracker/src/nc_string.h +112 -0
  140. data/ext/nutcracker/src/nc_util.c +619 -0
  141. data/ext/nutcracker/src/nc_util.h +214 -0
  142. data/ext/nutcracker/src/proto/Makefile.am +14 -0
  143. data/ext/nutcracker/src/proto/Makefile.in +482 -0
  144. data/ext/nutcracker/src/proto/nc_memcache.c +1306 -0
  145. data/ext/nutcracker/src/proto/nc_proto.h +155 -0
  146. data/ext/nutcracker/src/proto/nc_redis.c +2102 -0
  147. data/lib/nutcracker.rb +7 -0
  148. data/lib/nutcracker/version.rb +3 -0
  149. metadata +194 -0
@@ -0,0 +1,99 @@
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_CONNECTION_H_
19
+ #define _NC_CONNECTION_H_
20
+
21
+ #include <nc_core.h>
22
+
23
+ typedef rstatus_t (*conn_recv_t)(struct context *, struct conn*);
24
+ typedef struct msg* (*conn_recv_next_t)(struct context *, struct conn *, bool);
25
+ typedef void (*conn_recv_done_t)(struct context *, struct conn *, struct msg *, struct msg *);
26
+
27
+ typedef rstatus_t (*conn_send_t)(struct context *, struct conn*);
28
+ typedef struct msg* (*conn_send_next_t)(struct context *, struct conn *);
29
+ typedef void (*conn_send_done_t)(struct context *, struct conn *, struct msg *);
30
+
31
+ typedef void (*conn_close_t)(struct context *, struct conn *);
32
+ typedef bool (*conn_active_t)(struct conn *);
33
+
34
+ typedef void (*conn_ref_t)(struct conn *, void *);
35
+ typedef void (*conn_unref_t)(struct conn *);
36
+
37
+ typedef void (*conn_msgq_t)(struct context *, struct conn *, struct msg *);
38
+
39
+ struct conn {
40
+ TAILQ_ENTRY(conn) conn_tqe; /* link in server_pool / server / free q */
41
+ void *owner; /* connection owner - server_pool / server */
42
+
43
+ int sd; /* socket descriptor */
44
+ int family; /* socket address family */
45
+ socklen_t addrlen; /* socket length */
46
+ struct sockaddr *addr; /* socket address (ref in server or server_pool) */
47
+
48
+ struct msg_tqh imsg_q; /* incoming request Q */
49
+ struct msg_tqh omsg_q; /* outstanding request Q */
50
+ struct msg *rmsg; /* current message being rcvd */
51
+ struct msg *smsg; /* current message being sent */
52
+
53
+ conn_recv_t recv; /* recv (read) handler */
54
+ conn_recv_next_t recv_next; /* recv next message handler */
55
+ conn_recv_done_t recv_done; /* read done handler */
56
+ conn_send_t send; /* send (write) handler */
57
+ conn_send_next_t send_next; /* write next message handler */
58
+ conn_send_done_t send_done; /* write done handler */
59
+ conn_close_t close; /* close handler */
60
+ conn_active_t active; /* active? handler */
61
+
62
+ conn_ref_t ref; /* connection reference handler */
63
+ conn_unref_t unref; /* connection unreference handler */
64
+
65
+ conn_msgq_t enqueue_inq; /* connection inq msg enqueue handler */
66
+ conn_msgq_t dequeue_inq; /* connection inq msg dequeue handler */
67
+ conn_msgq_t enqueue_outq; /* connection outq msg enqueue handler */
68
+ conn_msgq_t dequeue_outq; /* connection outq msg dequeue handler */
69
+
70
+ size_t recv_bytes; /* received (read) bytes */
71
+ size_t send_bytes; /* sent (written) bytes */
72
+
73
+ uint32_t events; /* connection io events */
74
+ err_t err; /* connection errno */
75
+ unsigned recv_active:1; /* recv active? */
76
+ unsigned recv_ready:1; /* recv ready? */
77
+ unsigned send_active:1; /* send active? */
78
+ unsigned send_ready:1; /* send ready? */
79
+
80
+ unsigned client:1; /* client? or server? */
81
+ unsigned proxy:1; /* proxy? */
82
+ unsigned connecting:1; /* connecting? */
83
+ unsigned connected:1; /* connected? */
84
+ unsigned eof:1; /* eof? aka passive close? */
85
+ unsigned done:1; /* done? aka close? */
86
+ unsigned redis:1; /* redis? */
87
+ };
88
+
89
+ TAILQ_HEAD(conn_tqh, conn);
90
+
91
+ struct conn *conn_get(void *owner, bool client, bool redis);
92
+ struct conn *conn_get_proxy(void *owner);
93
+ void conn_put(struct conn *conn);
94
+ ssize_t conn_recv(struct conn *conn, void *buf, size_t size);
95
+ ssize_t conn_sendv(struct conn *conn, struct array *sendv, size_t nsend);
96
+ void conn_init(void);
97
+ void conn_deinit(void);
98
+
99
+ #endif
@@ -0,0 +1,334 @@
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 <stdlib.h>
19
+ #include <unistd.h>
20
+
21
+ #include <sys/epoll.h>
22
+
23
+ #include <nc_core.h>
24
+ #include <nc_event.h>
25
+ #include <nc_conf.h>
26
+ #include <nc_server.h>
27
+ #include <nc_proxy.h>
28
+
29
+ static uint32_t ctx_id; /* context generation */
30
+
31
+ static struct context *
32
+ core_ctx_create(struct instance *nci)
33
+ {
34
+ rstatus_t status;
35
+ struct context *ctx;
36
+
37
+ ctx = nc_alloc(sizeof(*ctx));
38
+ if (ctx == NULL) {
39
+ return NULL;
40
+ }
41
+ ctx->id = ++ctx_id;
42
+ ctx->cf = NULL;
43
+ ctx->stats = NULL;
44
+ array_null(&ctx->pool);
45
+ ctx->ep = -1;
46
+ ctx->nevent = EVENT_SIZE_HINT;
47
+ ctx->max_timeout = nci->stats_interval;
48
+ ctx->timeout = ctx->max_timeout;
49
+ ctx->event = NULL;
50
+
51
+ /* parse and create configuration */
52
+ ctx->cf = conf_create(nci->conf_filename);
53
+ if (ctx->cf == NULL) {
54
+ nc_free(ctx);
55
+ return NULL;
56
+ }
57
+
58
+ /* initialize server pool from configuration */
59
+ status = server_pool_init(&ctx->pool, &ctx->cf->pool, ctx);
60
+ if (status != NC_OK) {
61
+ conf_destroy(ctx->cf);
62
+ nc_free(ctx);
63
+ return NULL;
64
+ }
65
+
66
+ /* create stats per server pool */
67
+ ctx->stats = stats_create(nci->stats_port, nci->stats_addr, nci->stats_interval,
68
+ nci->hostname, &ctx->pool);
69
+ if (ctx->stats == NULL) {
70
+ server_pool_deinit(&ctx->pool);
71
+ conf_destroy(ctx->cf);
72
+ nc_free(ctx);
73
+ return NULL;
74
+ }
75
+
76
+ /* initialize event handling for client, proxy and server */
77
+ status = event_init(ctx, EVENT_SIZE_HINT);
78
+ if (status != NC_OK) {
79
+ stats_destroy(ctx->stats);
80
+ server_pool_deinit(&ctx->pool);
81
+ conf_destroy(ctx->cf);
82
+ nc_free(ctx);
83
+ return NULL;
84
+ }
85
+
86
+ /* preconnect? servers in server pool */
87
+ status = server_pool_preconnect(ctx);
88
+ if (status != NC_OK) {
89
+ server_pool_disconnect(ctx);
90
+ event_deinit(ctx);
91
+ stats_destroy(ctx->stats);
92
+ server_pool_deinit(&ctx->pool);
93
+ conf_destroy(ctx->cf);
94
+ nc_free(ctx);
95
+ return NULL;
96
+ }
97
+
98
+ /* initialize proxy per server pool */
99
+ status = proxy_init(ctx);
100
+ if (status != NC_OK) {
101
+ server_pool_disconnect(ctx);
102
+ event_deinit(ctx);
103
+ stats_destroy(ctx->stats);
104
+ server_pool_deinit(&ctx->pool);
105
+ conf_destroy(ctx->cf);
106
+ nc_free(ctx);
107
+ return NULL;
108
+ }
109
+
110
+ log_debug(LOG_VVERB, "created ctx %p id %"PRIu32"", ctx, ctx->id);
111
+
112
+ return ctx;
113
+ }
114
+
115
+ static void
116
+ core_ctx_destroy(struct context *ctx)
117
+ {
118
+ log_debug(LOG_VVERB, "destroy ctx %p id %"PRIu32"", ctx, ctx->id);
119
+ proxy_deinit(ctx);
120
+ server_pool_disconnect(ctx);
121
+ event_deinit(ctx);
122
+ stats_destroy(ctx->stats);
123
+ server_pool_deinit(&ctx->pool);
124
+ conf_destroy(ctx->cf);
125
+ nc_free(ctx);
126
+ }
127
+
128
+ struct context *
129
+ core_start(struct instance *nci)
130
+ {
131
+ struct context *ctx;
132
+
133
+ mbuf_init(nci);
134
+ msg_init();
135
+ conn_init();
136
+
137
+ ctx = core_ctx_create(nci);
138
+ if (ctx != NULL) {
139
+ nci->ctx = ctx;
140
+ return ctx;
141
+ }
142
+
143
+ conn_deinit();
144
+ msg_deinit();
145
+ mbuf_deinit();
146
+
147
+ return NULL;
148
+ }
149
+
150
+ void
151
+ core_stop(struct context *ctx)
152
+ {
153
+ conn_deinit();
154
+ msg_deinit();
155
+ mbuf_deinit();
156
+ core_ctx_destroy(ctx);
157
+ }
158
+
159
+ static rstatus_t
160
+ core_recv(struct context *ctx, struct conn *conn)
161
+ {
162
+ rstatus_t status;
163
+
164
+ status = conn->recv(ctx, conn);
165
+ if (status != NC_OK) {
166
+ log_debug(LOG_INFO, "recv on %c %d failed: %s",
167
+ conn->client ? 'c' : (conn->proxy ? 'p' : 's'), conn->sd,
168
+ strerror(errno));
169
+ }
170
+
171
+ return status;
172
+ }
173
+
174
+ static rstatus_t
175
+ core_send(struct context *ctx, struct conn *conn)
176
+ {
177
+ rstatus_t status;
178
+
179
+ status = conn->send(ctx, conn);
180
+ if (status != NC_OK) {
181
+ log_debug(LOG_INFO, "send on %c %d failed: %s",
182
+ conn->client ? 'c' : (conn->proxy ? 'p' : 's'), conn->sd,
183
+ strerror(errno));
184
+ }
185
+
186
+ return status;
187
+ }
188
+
189
+ static void
190
+ core_close(struct context *ctx, struct conn *conn)
191
+ {
192
+ rstatus_t status;
193
+ char type, *addrstr;
194
+
195
+ ASSERT(conn->sd > 0);
196
+
197
+ if (conn->client) {
198
+ type = 'c';
199
+ addrstr = nc_unresolve_peer_desc(conn->sd);
200
+ } else {
201
+ type = conn->proxy ? 'p' : 's';
202
+ addrstr = nc_unresolve_addr(conn->addr, conn->addrlen);
203
+ }
204
+ log_debug(LOG_NOTICE, "close %c %d '%s' on event %04"PRIX32" eof %d done "
205
+ "%d rb %zu sb %zu%c %s", type, conn->sd, addrstr, conn->events,
206
+ conn->eof, conn->done, conn->recv_bytes, conn->send_bytes,
207
+ conn->err ? ':' : ' ', conn->err ? strerror(conn->err) : "");
208
+
209
+ status = event_del_conn(ctx->ep, conn);
210
+ if (status < 0) {
211
+ log_warn("event del conn e %d %c %d failed, ignored: %s", ctx->ep,
212
+ type, conn->sd, strerror(errno));
213
+ }
214
+
215
+ conn->close(ctx, conn);
216
+ }
217
+
218
+ static void
219
+ core_error(struct context *ctx, struct conn *conn)
220
+ {
221
+ rstatus_t status;
222
+ char type = conn->client ? 'c' : (conn->proxy ? 'p' : 's');
223
+
224
+ status = nc_get_soerror(conn->sd);
225
+ if (status < 0) {
226
+ log_warn("get soerr on %c %d failed, ignored: %s", type, conn->sd,
227
+ strerror(errno));
228
+ }
229
+ conn->err = errno;
230
+
231
+ core_close(ctx, conn);
232
+ }
233
+
234
+ static void
235
+ core_timeout(struct context *ctx)
236
+ {
237
+ for (;;) {
238
+ struct msg *msg;
239
+ struct conn *conn;
240
+ int64_t now, then;
241
+
242
+ msg = msg_tmo_min();
243
+ if (msg == NULL) {
244
+ ctx->timeout = ctx->max_timeout;
245
+ return;
246
+ }
247
+
248
+ /* skip over req that are in-error or done */
249
+
250
+ if (msg->error || msg->done) {
251
+ msg_tmo_delete(msg);
252
+ continue;
253
+ }
254
+
255
+ /*
256
+ * timeout expired req and all the outstanding req on the timing
257
+ * out server
258
+ */
259
+
260
+ conn = msg->tmo_rbe.data;
261
+ then = msg->tmo_rbe.key;
262
+
263
+ now = nc_msec_now();
264
+ if (now < then) {
265
+ int delta = (int)(then - now);
266
+ ctx->timeout = MIN(delta, ctx->max_timeout);
267
+ return;
268
+ }
269
+
270
+ log_debug(LOG_INFO, "req %"PRIu64" on s %d timedout", msg->id, conn->sd);
271
+
272
+ msg_tmo_delete(msg);
273
+ conn->err = ETIMEDOUT;
274
+
275
+ core_close(ctx, conn);
276
+ }
277
+ }
278
+
279
+ static void
280
+ core_core(struct context *ctx, struct conn *conn, uint32_t events)
281
+ {
282
+ rstatus_t status;
283
+
284
+ log_debug(LOG_VVERB, "event %04"PRIX32" on %c %d", events,
285
+ conn->client ? 'c' : (conn->proxy ? 'p' : 's'), conn->sd);
286
+
287
+ conn->events = events;
288
+
289
+ /* error takes precedence over read | write */
290
+ if (events & EPOLLERR) {
291
+ core_error(ctx, conn);
292
+ return;
293
+ }
294
+
295
+ /* read takes precedence over write */
296
+ if (events & (EPOLLIN | EPOLLHUP)) {
297
+ status = core_recv(ctx, conn);
298
+ if (status != NC_OK || conn->done || conn->err) {
299
+ core_close(ctx, conn);
300
+ return;
301
+ }
302
+ }
303
+
304
+ if (events & EPOLLOUT) {
305
+ status = core_send(ctx, conn);
306
+ if (status != NC_OK || conn->done || conn->err) {
307
+ core_close(ctx, conn);
308
+ return;
309
+ }
310
+ }
311
+ }
312
+
313
+ rstatus_t
314
+ core_loop(struct context *ctx)
315
+ {
316
+ int i, nsd;
317
+
318
+ nsd = event_wait(ctx->ep, ctx->event, ctx->nevent, ctx->timeout);
319
+ if (nsd < 0) {
320
+ return nsd;
321
+ }
322
+
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
+ core_timeout(ctx);
330
+
331
+ stats_swap(ctx->stats);
332
+
333
+ return NC_OK;
334
+ }
@@ -0,0 +1,131 @@
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_CORE_H_
19
+ #define _NC_CORE_H_
20
+
21
+ #ifdef HAVE_CONFIG_H
22
+ # include <config.h>
23
+ #endif
24
+
25
+ #ifdef HAVE_DEBUG_LOG
26
+ # define NC_DEBUG_LOG 1
27
+ #endif
28
+
29
+ #ifdef HAVE_ASSERT_PANIC
30
+ # define NC_ASSERT_PANIC 1
31
+ #endif
32
+
33
+ #ifdef HAVE_ASSERT_LOG
34
+ # define NC_ASSERT_LOG 1
35
+ #endif
36
+
37
+ #ifdef HAVE_STATS
38
+ # define NC_STATS 1
39
+ #else
40
+ # define NC_STATS 0
41
+ #endif
42
+
43
+ #ifdef HAVE_LITTLE_ENDIAN
44
+ # define NC_LITTLE_ENDIAN 1
45
+ #endif
46
+
47
+ #define NC_OK 0
48
+ #define NC_ERROR -1
49
+ #define NC_EAGAIN -2
50
+ #define NC_ENOMEM -3
51
+
52
+ typedef int rstatus_t; /* return type */
53
+ typedef int err_t; /* error type */
54
+
55
+ struct array;
56
+ struct string;
57
+ struct context;
58
+ struct conn;
59
+ struct conn_tqh;
60
+ struct msg;
61
+ struct msg_tqh;
62
+ struct server;
63
+ struct server_pool;
64
+ struct mbuf;
65
+ struct mhdr;
66
+ struct conf;
67
+ struct stats;
68
+ struct epoll_event;
69
+ struct instance;
70
+
71
+ #include <stddef.h>
72
+ #include <stdint.h>
73
+ #include <stdbool.h>
74
+ #include <inttypes.h>
75
+ #include <string.h>
76
+ #include <errno.h>
77
+ #include <limits.h>
78
+ #include <time.h>
79
+ #include <unistd.h>
80
+ #include <pthread.h>
81
+
82
+ #include <sys/types.h>
83
+ #include <sys/socket.h>
84
+ #include <sys/un.h>
85
+ #include <netinet/in.h>
86
+
87
+ #include <nc_array.h>
88
+ #include <nc_string.h>
89
+ #include <nc_queue.h>
90
+ #include <nc_rbtree.h>
91
+ #include <nc_log.h>
92
+ #include <nc_util.h>
93
+ #include <nc_stats.h>
94
+ #include <nc_mbuf.h>
95
+ #include <nc_message.h>
96
+ #include <nc_connection.h>
97
+
98
+ struct context {
99
+ uint32_t id; /* unique context id */
100
+ struct conf *cf; /* configuration */
101
+ struct stats *stats; /* stats */
102
+
103
+ 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 */
110
+ };
111
+
112
+ struct instance {
113
+ struct context *ctx; /* active context */
114
+ int log_level; /* log level */
115
+ char *log_filename; /* log filename */
116
+ char *conf_filename; /* configuration filename */
117
+ uint16_t stats_port; /* stats monitoring port */
118
+ int stats_interval; /* stats aggregation interval */
119
+ char *stats_addr; /* stats monitoring addr */
120
+ char hostname[NC_MAXHOSTNAMELEN]; /* hostname */
121
+ size_t mbuf_chunk_size; /* mbuf chunk size */
122
+ pid_t pid; /* process id */
123
+ char *pid_filename; /* pid filename */
124
+ unsigned pidfile:1; /* pid file created? */
125
+ };
126
+
127
+ struct context *core_start(struct instance *nci);
128
+ void core_stop(struct context *ctx);
129
+ rstatus_t core_loop(struct context *ctx);
130
+
131
+ #endif