Merge lp:~jan-kneschke/mysql-proxy/threaded-io into lp:mysql-proxy
- threaded-io
- Merge into trunk
Proposed by
Jan Kneschke
Status: | Merged |
---|---|
Merged at revision: | 662 |
Proposed branch: | lp:~jan-kneschke/mysql-proxy/threaded-io |
Merge into: | lp:mysql-proxy |
Diff against target: | None lines |
To merge this branch: | bzr merge lp:~jan-kneschke/mysql-proxy/threaded-io |
Related bugs: | |
Related blueprints: |
Threading the network-io
(Essential)
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jan Kneschke (community) | Approve | ||
Review via email: mp+6773@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
Jan Kneschke (jan-kneschke) wrote : | # |
Revision history for this message
Jan Kneschke (jan-kneschke) wrote : | # |
* rebased to the 0.7.1 changes
* make check passes
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/Makefile.am' | |||
2 | --- src/Makefile.am 2009-05-12 19:20:06 +0000 | |||
3 | +++ src/Makefile.am 2009-05-25 08:57:34 +0000 | |||
4 | @@ -67,14 +67,15 @@ | |||
5 | 67 | chassis-plugin.c \ | 67 | chassis-plugin.c \ |
6 | 68 | chassis-log.c \ | 68 | chassis-log.c \ |
7 | 69 | chassis-mainloop.c \ | 69 | chassis-mainloop.c \ |
8 | 70 | chassis-event-thread.c \ | ||
9 | 70 | chassis-keyfile.c \ | 71 | chassis-keyfile.c \ |
10 | 71 | chassis-path.c \ | 72 | chassis-path.c \ |
11 | 72 | chassis-stats.c | 73 | chassis-stats.c |
12 | 73 | 74 | ||
13 | 74 | 75 | ||
14 | 75 | libmysql_chassis_la_LDFLAGS = -export-dynamic -no-undefined -dynamic | 76 | libmysql_chassis_la_LDFLAGS = -export-dynamic -no-undefined -dynamic |
17 | 76 | libmysql_chassis_la_CPPFLAGS = $(MYSQL_CFLAGS) $(EVENT_CFLAGS) $(GLIB_CFLAGS) $(LUA_CFLAGS) $(GMODULE_CFLAGS) | 77 | libmysql_chassis_la_CPPFLAGS = $(MYSQL_CFLAGS) $(EVENT_CFLAGS) $(GLIB_CFLAGS) $(LUA_CFLAGS) $(GMODULE_CFLAGS) $(GTHREAD_CFLAGS) |
18 | 77 | libmysql_chassis_la_LIBADD = $(EVENT_LIBS) $(GLIB_LIBS) $(LUA_LIBS) $(GMODULE_LIBS) | 78 | libmysql_chassis_la_LIBADD = $(EVENT_LIBS) $(GLIB_LIBS) $(LUA_LIBS) $(GMODULE_LIBS) $(GTHREAD_LIBS) |
19 | 78 | 79 | ||
20 | 79 | 80 | ||
21 | 80 | noinst_HEADERS=\ | 81 | noinst_HEADERS=\ |
22 | @@ -96,6 +97,7 @@ | |||
23 | 96 | chassis-keyfile.h \ | 97 | chassis-keyfile.h \ |
24 | 97 | chassis-mainloop.h \ | 98 | chassis-mainloop.h \ |
25 | 98 | chassis-path.h \ | 99 | chassis-path.h \ |
26 | 100 | chassis-event-thread.h \ | ||
27 | 99 | glib-ext.h \ | 101 | glib-ext.h \ |
28 | 100 | lua-load-factory.h \ | 102 | lua-load-factory.h \ |
29 | 101 | lua-scope.h \ | 103 | lua-scope.h \ |
30 | 102 | 104 | ||
31 | === added file 'src/chassis-event-thread.c' | |||
32 | --- src/chassis-event-thread.c 1970-01-01 00:00:00 +0000 | |||
33 | +++ src/chassis-event-thread.c 2009-05-25 08:57:34 +0000 | |||
34 | @@ -0,0 +1,287 @@ | |||
35 | 1 | /* $%BEGINLICENSE%$ | ||
36 | 2 | Copyright (C) 2007-2008 MySQL AB, 2008 Sun Microsystems, Inc | ||
37 | 3 | |||
38 | 4 | This program is free software; you can redistribute it and/or modify | ||
39 | 5 | it under the terms of the GNU General Public License as published by | ||
40 | 6 | the Free Software Foundation; version 2 of the License. | ||
41 | 7 | |||
42 | 8 | This program is distributed in the hope that it will be useful, | ||
43 | 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
44 | 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
45 | 11 | GNU General Public License for more details. | ||
46 | 12 | |||
47 | 13 | You should have received a copy of the GNU General Public License | ||
48 | 14 | along with this program; if not, write to the Free Software | ||
49 | 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
50 | 16 | |||
51 | 17 | $%ENDLICENSE%$ */ | ||
52 | 18 | |||
53 | 19 | #include <glib.h> | ||
54 | 20 | #include <errno.h> | ||
55 | 21 | |||
56 | 22 | #ifdef HAVE_CONFIG_H | ||
57 | 23 | #include "config.h" | ||
58 | 24 | #endif | ||
59 | 25 | |||
60 | 26 | #ifdef HAVE_UNISTD_H | ||
61 | 27 | #include <unistd.h> /* for write() */ | ||
62 | 28 | #endif | ||
63 | 29 | |||
64 | 30 | #include "chassis-event-thread.h" | ||
65 | 31 | |||
66 | 32 | #define C(x) x, sizeof(x) - 1 | ||
67 | 33 | |||
68 | 34 | chassis_event_op_t *chassis_event_op_new() { | ||
69 | 35 | chassis_event_op_t *e; | ||
70 | 36 | |||
71 | 37 | e = g_new0(chassis_event_op_t, 1); | ||
72 | 38 | |||
73 | 39 | return e; | ||
74 | 40 | } | ||
75 | 41 | |||
76 | 42 | void chassis_event_op_free(chassis_event_op_t *e) { | ||
77 | 43 | if (!e) return; | ||
78 | 44 | |||
79 | 45 | g_free(e); | ||
80 | 46 | } | ||
81 | 47 | |||
82 | 48 | /** | ||
83 | 49 | * execute a event-op on a event-base | ||
84 | 50 | * | ||
85 | 51 | * @see: chassis_event_add_local(), chassis_threaded_event_op() | ||
86 | 52 | */ | ||
87 | 53 | void chassis_event_op_apply(chassis_event_op_t *op, struct event_base *event_base) { | ||
88 | 54 | switch (op->type) { | ||
89 | 55 | case CHASSIS_EVENT_OP_ADD: | ||
90 | 56 | event_base_set(event_base, op->ev); | ||
91 | 57 | event_add(op->ev, NULL); | ||
92 | 58 | break; | ||
93 | 59 | case CHASSIS_EVENT_OP_UNSET: | ||
94 | 60 | g_assert_not_reached(); | ||
95 | 61 | break; | ||
96 | 62 | } | ||
97 | 63 | } | ||
98 | 64 | |||
99 | 65 | /** | ||
100 | 66 | * add a event asynchronously | ||
101 | 67 | * | ||
102 | 68 | * the event is added to the global event-queue and a fd-notification is sent allowing any | ||
103 | 69 | * of the event-threads to handle it | ||
104 | 70 | * | ||
105 | 71 | * @see network_mysqld_con_handle() | ||
106 | 72 | */ | ||
107 | 73 | void chassis_event_add(chassis *chas, struct event *ev) { | ||
108 | 74 | chassis_event_op_t *op = chassis_event_op_new(); | ||
109 | 75 | |||
110 | 76 | op->type = CHASSIS_EVENT_OP_ADD; | ||
111 | 77 | op->ev = ev; | ||
112 | 78 | g_async_queue_push(chas->threads->event_queue, op); | ||
113 | 79 | |||
114 | 80 | write(chas->threads->event_notify_fds[1], C(".")); /* ping the event handler */ | ||
115 | 81 | } | ||
116 | 82 | |||
117 | 83 | GPrivate *tls_event_base_key = NULL; | ||
118 | 84 | |||
119 | 85 | /** | ||
120 | 86 | * add a event to the current thread | ||
121 | 87 | * | ||
122 | 88 | * needs event-base stored in the thread local storage | ||
123 | 89 | * | ||
124 | 90 | * @see network_connection_pool_lua_add_connection() | ||
125 | 91 | */ | ||
126 | 92 | void chassis_event_add_local(chassis G_GNUC_UNUSED *chas, struct event *ev) { | ||
127 | 93 | struct event_base *event_base = ev->ev_base; | ||
128 | 94 | chassis_event_op_t *op; | ||
129 | 95 | |||
130 | 96 | if (!event_base) event_base = g_private_get(tls_event_base_key); | ||
131 | 97 | |||
132 | 98 | g_assert(event_base); /* the thread-local event-base has to be initialized */ | ||
133 | 99 | |||
134 | 100 | op = chassis_event_op_new(); | ||
135 | 101 | |||
136 | 102 | op->type = CHASSIS_EVENT_OP_ADD; | ||
137 | 103 | op->ev = ev; | ||
138 | 104 | |||
139 | 105 | chassis_event_op_apply(op, event_base); | ||
140 | 106 | |||
141 | 107 | chassis_event_op_free(op); | ||
142 | 108 | } | ||
143 | 109 | |||
144 | 110 | /** | ||
145 | 111 | * handled events sent through the global event-queue | ||
146 | 112 | * | ||
147 | 113 | * each event-thread has its own listener on the event-queue and | ||
148 | 114 | * calls chassis_event_handle() with its own event-base | ||
149 | 115 | * | ||
150 | 116 | * @see chassis_event_add() | ||
151 | 117 | */ | ||
152 | 118 | void chassis_event_handle(int G_GNUC_UNUSED event_fd, short G_GNUC_UNUSED events, void *user_data) { | ||
153 | 119 | chassis_event_thread_t *event_thread = user_data; | ||
154 | 120 | struct event_base *event_base = event_thread->event_base; | ||
155 | 121 | chassis *chas = event_thread->chas; | ||
156 | 122 | chassis_event_op_t *op; | ||
157 | 123 | char ping[1024]; | ||
158 | 124 | |||
159 | 125 | /* flush the pipe */ | ||
160 | 126 | while (read(event_thread->notify_fd, ping, sizeof(ping)) > 0); | ||
161 | 127 | |||
162 | 128 | while ((op = g_async_queue_try_pop(chas->threads->event_queue))) { | ||
163 | 129 | chassis_event_op_apply(op, event_base); | ||
164 | 130 | |||
165 | 131 | chassis_event_op_free(op); | ||
166 | 132 | } | ||
167 | 133 | } | ||
168 | 134 | |||
169 | 135 | chassis_event_thread_t *chassis_event_thread_new() { | ||
170 | 136 | chassis_event_thread_t *event_thread; | ||
171 | 137 | |||
172 | 138 | event_thread = g_new0(chassis_event_thread_t, 1); | ||
173 | 139 | |||
174 | 140 | return event_thread; | ||
175 | 141 | } | ||
176 | 142 | |||
177 | 143 | void chassis_event_thread_free(chassis_event_thread_t *event_thread) { | ||
178 | 144 | gboolean is_thread = (event_thread->thr != NULL); | ||
179 | 145 | |||
180 | 146 | if (!event_thread) return; | ||
181 | 147 | |||
182 | 148 | if (event_thread->thr) g_thread_join(event_thread->thr); | ||
183 | 149 | |||
184 | 150 | if (event_thread->notify_fd != -1) { | ||
185 | 151 | event_del(&(event_thread->notify_fd_event)); | ||
186 | 152 | close(event_thread->notify_fd); | ||
187 | 153 | } | ||
188 | 154 | |||
189 | 155 | /* we don't want to free the global event-base */ | ||
190 | 156 | if (is_thread && event_thread->event_base) event_base_free(event_thread->event_base); | ||
191 | 157 | |||
192 | 158 | g_free(event_thread); | ||
193 | 159 | } | ||
194 | 160 | |||
195 | 161 | /** | ||
196 | 162 | * set the event-based for the current event-thread | ||
197 | 163 | * | ||
198 | 164 | * @see chassis_event_add_local() | ||
199 | 165 | */ | ||
200 | 166 | void chassis_event_thread_set_event_base(chassis_event_thread_t G_GNUC_UNUSED *e, struct event_base *event_base) { | ||
201 | 167 | tls_event_base_key = g_private_new(NULL); | ||
202 | 168 | |||
203 | 169 | g_private_set(tls_event_base_key, event_base); | ||
204 | 170 | } | ||
205 | 171 | |||
206 | 172 | chassis_event_threads_t *chassis_event_threads_new() { | ||
207 | 173 | chassis_event_threads_t *threads; | ||
208 | 174 | |||
209 | 175 | threads = g_new0(chassis_event_threads_t, 1); | ||
210 | 176 | |||
211 | 177 | /* create the ping-fds | ||
212 | 178 | * | ||
213 | 179 | * the event-thread write a byte to the ping-pipe to trigger a fd-event when | ||
214 | 180 | * something is available in the event-async-queues | ||
215 | 181 | */ | ||
216 | 182 | if (0 != pipe(threads->event_notify_fds)) { | ||
217 | 183 | g_error("%s: pipe() failed: %s (%d)", | ||
218 | 184 | G_STRLOC, | ||
219 | 185 | g_strerror(errno), | ||
220 | 186 | errno); | ||
221 | 187 | } | ||
222 | 188 | |||
223 | 189 | threads->event_threads = g_ptr_array_new(); | ||
224 | 190 | threads->event_queue = g_async_queue_new(); | ||
225 | 191 | |||
226 | 192 | return threads; | ||
227 | 193 | } | ||
228 | 194 | |||
229 | 195 | void chassis_event_threads_free(chassis_event_threads_t *threads) { | ||
230 | 196 | guint i; | ||
231 | 197 | |||
232 | 198 | if (!threads) return; | ||
233 | 199 | |||
234 | 200 | /* all threads are running, now wait until they are down again */ | ||
235 | 201 | for (i = 0; i < threads->event_threads->len; i++) { | ||
236 | 202 | chassis_event_thread_t *event_thread = threads->event_threads->pdata[i]; | ||
237 | 203 | |||
238 | 204 | chassis_event_thread_free(event_thread); | ||
239 | 205 | } | ||
240 | 206 | |||
241 | 207 | g_ptr_array_free(threads->event_threads, TRUE); | ||
242 | 208 | g_async_queue_unref(threads->event_queue); | ||
243 | 209 | |||
244 | 210 | g_free(threads); | ||
245 | 211 | } | ||
246 | 212 | |||
247 | 213 | void chassis_event_threads_add(chassis_event_threads_t *threads, chassis_event_thread_t *thread) { | ||
248 | 214 | g_ptr_array_add(threads->event_threads, thread); | ||
249 | 215 | } | ||
250 | 216 | |||
251 | 217 | |||
252 | 218 | /** | ||
253 | 219 | * setup the notification-fd of a event-thread | ||
254 | 220 | * | ||
255 | 221 | * all event-threads listen on the same notification pipe | ||
256 | 222 | * | ||
257 | 223 | * @see chassis_event_handle() | ||
258 | 224 | */ | ||
259 | 225 | int chassis_event_threads_init_thread(chassis_event_threads_t *threads, chassis_event_thread_t *event_thread, chassis *chas) { | ||
260 | 226 | event_thread->event_base = event_base_new(); | ||
261 | 227 | event_thread->chas = chas; | ||
262 | 228 | |||
263 | 229 | event_thread->notify_fd = dup(threads->event_notify_fds[0]); | ||
264 | 230 | |||
265 | 231 | evutil_make_socket_nonblocking(event_thread->notify_fd); | ||
266 | 232 | |||
267 | 233 | event_set(&(event_thread->notify_fd_event), event_thread->notify_fd, EV_READ | EV_PERSIST, chassis_event_handle, event_thread); | ||
268 | 234 | event_base_set(event_thread->event_base, &(event_thread->notify_fd_event)); | ||
269 | 235 | event_add(&(event_thread->notify_fd_event), NULL); | ||
270 | 236 | |||
271 | 237 | return 0; | ||
272 | 238 | } | ||
273 | 239 | |||
274 | 240 | /** | ||
275 | 241 | * event-handler thread | ||
276 | 242 | * | ||
277 | 243 | */ | ||
278 | 244 | void *chassis_event_thread_loop(chassis_event_thread_t *event_thread) { | ||
279 | 245 | chassis_event_thread_set_event_base(event_thread, event_thread->event_base); | ||
280 | 246 | |||
281 | 247 | /** | ||
282 | 248 | * check once a second if we shall shutdown the proxy | ||
283 | 249 | */ | ||
284 | 250 | while (!chassis_is_shutdown()) { | ||
285 | 251 | struct timeval timeout; | ||
286 | 252 | int r; | ||
287 | 253 | |||
288 | 254 | timeout.tv_sec = 1; | ||
289 | 255 | timeout.tv_usec = 0; | ||
290 | 256 | |||
291 | 257 | g_assert(event_base_loopexit(event_thread->event_base, &timeout) == 0); | ||
292 | 258 | |||
293 | 259 | r = event_base_dispatch(event_thread->event_base); | ||
294 | 260 | |||
295 | 261 | if (r == -1) { | ||
296 | 262 | if (errno == EINTR) continue; | ||
297 | 263 | |||
298 | 264 | break; | ||
299 | 265 | } | ||
300 | 266 | } | ||
301 | 267 | |||
302 | 268 | return NULL; | ||
303 | 269 | } | ||
304 | 270 | |||
305 | 271 | void chassis_event_threads_start(chassis_event_threads_t *threads) { | ||
306 | 272 | guint i; | ||
307 | 273 | |||
308 | 274 | for (i = 1; i < threads->event_threads->len; i++) { /* the 1st is the main-thread and already set up */ | ||
309 | 275 | chassis_event_thread_t *event_thread = threads->event_threads->pdata[i]; | ||
310 | 276 | GError *gerr = NULL; | ||
311 | 277 | |||
312 | 278 | event_thread->thr = g_thread_create((GThreadFunc)chassis_event_thread_loop, event_thread, TRUE, &gerr); | ||
313 | 279 | |||
314 | 280 | if (gerr) { | ||
315 | 281 | g_error_free(gerr); | ||
316 | 282 | gerr = NULL; | ||
317 | 283 | } | ||
318 | 284 | } | ||
319 | 285 | } | ||
320 | 286 | |||
321 | 287 | |||
322 | 0 | 288 | ||
323 | === added file 'src/chassis-event-thread.h' | |||
324 | --- src/chassis-event-thread.h 1970-01-01 00:00:00 +0000 | |||
325 | +++ src/chassis-event-thread.h 2009-05-25 08:57:34 +0000 | |||
326 | @@ -0,0 +1,81 @@ | |||
327 | 1 | /* $%BEGINLICENSE%$ | ||
328 | 2 | Copyright (C) 2007-2008 MySQL AB, 2008 Sun Microsystems, Inc | ||
329 | 3 | |||
330 | 4 | This program is free software; you can redistribute it and/or modify | ||
331 | 5 | it under the terms of the GNU General Public License as published by | ||
332 | 6 | the Free Software Foundation; version 2 of the License. | ||
333 | 7 | |||
334 | 8 | This program is distributed in the hope that it will be useful, | ||
335 | 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
336 | 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
337 | 11 | GNU General Public License for more details. | ||
338 | 12 | |||
339 | 13 | You should have received a copy of the GNU General Public License | ||
340 | 14 | along with this program; if not, write to the Free Software | ||
341 | 15 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
342 | 16 | |||
343 | 17 | $%ENDLICENSE%$ */ | ||
344 | 18 | |||
345 | 19 | |||
346 | 20 | #ifndef _CHASSIS_EVENT_THREAD_H_ | ||
347 | 21 | #define _CHASSIS_EVENT_THREAD_H_ | ||
348 | 22 | |||
349 | 23 | #include <glib.h> /* GPtrArray */ | ||
350 | 24 | |||
351 | 25 | #include "chassis-exports.h" | ||
352 | 26 | #include "chassis-mainloop.h" | ||
353 | 27 | |||
354 | 28 | /** | ||
355 | 29 | * event operations | ||
356 | 30 | * | ||
357 | 31 | * event-ops are sent through the async-queues | ||
358 | 32 | */ | ||
359 | 33 | |||
360 | 34 | typedef struct { | ||
361 | 35 | enum { | ||
362 | 36 | CHASSIS_EVENT_OP_UNSET, | ||
363 | 37 | CHASSIS_EVENT_OP_ADD | ||
364 | 38 | } type; | ||
365 | 39 | |||
366 | 40 | struct event *ev; | ||
367 | 41 | } chassis_event_op_t; | ||
368 | 42 | |||
369 | 43 | CHASSIS_API chassis_event_op_t *chassis_event_op_new(); | ||
370 | 44 | CHASSIS_API void chassis_event_op_free(chassis_event_op_t *e); | ||
371 | 45 | CHASSIS_API void chassis_event_add(chassis *chas, struct event *ev); | ||
372 | 46 | CHASSIS_API void chassis_event_add_local(chassis *chas, struct event *ev); | ||
373 | 47 | |||
374 | 48 | /** | ||
375 | 49 | * a event-thread | ||
376 | 50 | */ | ||
377 | 51 | typedef struct { | ||
378 | 52 | chassis *chas; | ||
379 | 53 | |||
380 | 54 | int notify_fd; | ||
381 | 55 | struct event notify_fd_event; | ||
382 | 56 | |||
383 | 57 | GThread *thr; | ||
384 | 58 | |||
385 | 59 | struct event_base *event_base; | ||
386 | 60 | } chassis_event_thread_t; | ||
387 | 61 | |||
388 | 62 | CHASSIS_API chassis_event_thread_t *chassis_event_thread_new(); | ||
389 | 63 | CHASSIS_API void chassis_event_thread_free(chassis_event_thread_t *e); | ||
390 | 64 | CHASSIS_API void chassis_event_handle(int event_fd, short events, void *user_data); | ||
391 | 65 | CHASSIS_API void chassis_event_thread_set_event_base(chassis_event_thread_t *e, struct event_base *event_base); | ||
392 | 66 | CHASSIS_API void *chassis_event_thread_loop(chassis_event_thread_t *); | ||
393 | 67 | |||
394 | 68 | struct chassis_event_threads_t { | ||
395 | 69 | GPtrArray *event_threads; | ||
396 | 70 | |||
397 | 71 | GAsyncQueue *event_queue; | ||
398 | 72 | int event_notify_fds[2]; | ||
399 | 73 | }; | ||
400 | 74 | |||
401 | 75 | CHASSIS_API chassis_event_threads_t *chassis_event_threads_new(); | ||
402 | 76 | CHASSIS_API void chassis_event_threads_free(chassis_event_threads_t *threads); | ||
403 | 77 | CHASSIS_API int chassis_event_threads_init_thread(chassis_event_threads_t *threads, chassis_event_thread_t *event_thread, chassis *chas); | ||
404 | 78 | CHASSIS_API void chassis_event_threads_add(chassis_event_threads_t *threads, chassis_event_thread_t *thread); | ||
405 | 79 | CHASSIS_API void chassis_event_threads_start(chassis_event_threads_t *threads); | ||
406 | 80 | |||
407 | 81 | #endif | ||
408 | 0 | 82 | ||
409 | === modified file 'src/chassis-mainloop.c' | |||
410 | --- src/chassis-mainloop.c 2009-02-23 23:13:09 +0000 | |||
411 | +++ src/chassis-mainloop.c 2009-05-25 08:57:34 +0000 | |||
412 | @@ -42,6 +42,7 @@ | |||
413 | 42 | #include <glib.h> | 42 | #include <glib.h> |
414 | 43 | #include "chassis-plugin.h" | 43 | #include "chassis-plugin.h" |
415 | 44 | #include "chassis-mainloop.h" | 44 | #include "chassis-mainloop.h" |
416 | 45 | #include "chassis-event-thread.h" | ||
417 | 45 | #include "chassis-log.h" | 46 | #include "chassis-log.h" |
418 | 46 | #include "chassis-stats.h" | 47 | #include "chassis-stats.h" |
419 | 47 | 48 | ||
420 | @@ -68,6 +69,8 @@ | |||
421 | 68 | 69 | ||
422 | 69 | chas->stats = chassis_stats_new(); | 70 | chas->stats = chassis_stats_new(); |
423 | 70 | 71 | ||
424 | 72 | chas->threads = chassis_event_threads_new(); | ||
425 | 73 | |||
426 | 71 | return chas; | 74 | return chas; |
427 | 72 | } | 75 | } |
428 | 73 | 76 | ||
429 | @@ -120,6 +123,8 @@ | |||
430 | 120 | 123 | ||
431 | 121 | if (chas->stats) chassis_stats_free(chas->stats); | 124 | if (chas->stats) chassis_stats_free(chas->stats); |
432 | 122 | 125 | ||
433 | 126 | if (chas->threads) chassis_event_threads_free(chas->threads); | ||
434 | 127 | |||
435 | 123 | g_free(chas); | 128 | g_free(chas); |
436 | 124 | } | 129 | } |
437 | 125 | 130 | ||
438 | @@ -192,23 +197,12 @@ | |||
439 | 192 | g_log(G_LOG_DOMAIN, glib_log_level, "(libevent) %s", msg); | 197 | g_log(G_LOG_DOMAIN, glib_log_level, "(libevent) %s", msg); |
440 | 193 | } | 198 | } |
441 | 194 | 199 | ||
442 | 195 | /** | ||
443 | 196 | * init libevent | ||
444 | 197 | * | ||
445 | 198 | * kqueue has to be called after the fork() of daemonize | ||
446 | 199 | * | ||
447 | 200 | * @param m global context | ||
448 | 201 | */ | ||
449 | 202 | static void chassis_init_libevent(chassis *chas) { | ||
450 | 203 | chas->event_base = event_init(); | ||
451 | 204 | |||
452 | 205 | event_set_log_callback(event_log_use_glib); | ||
453 | 206 | } | ||
454 | 207 | 200 | ||
455 | 208 | int chassis_mainloop(void *_chas) { | 201 | int chassis_mainloop(void *_chas) { |
456 | 209 | chassis *chas = _chas; | 202 | chassis *chas = _chas; |
457 | 210 | guint i; | 203 | guint i; |
458 | 211 | struct event ev_sigterm, ev_sigint, ev_sighup; | 204 | struct event ev_sigterm, ev_sigint, ev_sighup; |
459 | 205 | chassis_event_thread_t *mainloop_thread; | ||
460 | 212 | 206 | ||
461 | 213 | #ifdef _WIN32 | 207 | #ifdef _WIN32 |
462 | 214 | WORD wVersionRequested; | 208 | WORD wVersionRequested; |
463 | @@ -224,8 +218,19 @@ | |||
464 | 224 | return err; /* err is positive */ | 218 | return err; /* err is positive */ |
465 | 225 | } | 219 | } |
466 | 226 | #endif | 220 | #endif |
469 | 227 | /* init the event-handlers */ | 221 | /* redirect logging from libevent to glib */ |
470 | 228 | chassis_init_libevent(chas); | 222 | event_set_log_callback(event_log_use_glib); |
471 | 223 | |||
472 | 224 | |||
473 | 225 | /* add a event-handler for the "main" events */ | ||
474 | 226 | mainloop_thread = chassis_event_thread_new(); | ||
475 | 227 | chassis_event_threads_init_thread(chas->threads, mainloop_thread, chas); | ||
476 | 228 | chassis_event_threads_add(chas->threads, mainloop_thread); | ||
477 | 229 | |||
478 | 230 | chas->event_base = mainloop_thread->event_base; /* all global events go to the 1st thread */ | ||
479 | 231 | |||
480 | 232 | g_assert(chas->event_base); | ||
481 | 233 | |||
482 | 229 | 234 | ||
483 | 230 | /* setup all plugins all plugins */ | 235 | /* setup all plugins all plugins */ |
484 | 231 | for (i = 0; i < chas->modules->len; i++) { | 236 | for (i = 0; i < chas->modules->len; i++) { |
485 | @@ -293,28 +298,32 @@ | |||
486 | 293 | } | 298 | } |
487 | 294 | #endif | 299 | #endif |
488 | 295 | 300 | ||
489 | 301 | if (chas->event_thread_count < 1) chas->event_thread_count = 0; | ||
490 | 302 | |||
491 | 303 | /* create the event-threads | ||
492 | 304 | * | ||
493 | 305 | * - dup the async-queue-ping-fds | ||
494 | 306 | * - setup the events notification | ||
495 | 307 | * */ | ||
496 | 308 | for (i = 0; i < chas->event_thread_count; i++) { | ||
497 | 309 | chassis_event_thread_t *event_thread; | ||
498 | 310 | |||
499 | 311 | event_thread = chassis_event_thread_new(); | ||
500 | 312 | chassis_event_threads_init_thread(chas->threads, event_thread, chas); | ||
501 | 313 | chassis_event_threads_add(chas->threads, event_thread); | ||
502 | 314 | } | ||
503 | 315 | |||
504 | 316 | /* start the event threads */ | ||
505 | 317 | if (chas->event_thread_count > 0) { | ||
506 | 318 | chassis_event_threads_start(chas->threads); | ||
507 | 319 | } | ||
508 | 320 | |||
509 | 296 | /** | 321 | /** |
511 | 297 | * check once a second if we shall shutdown the proxy | 322 | * handle signals and all basic events into the main-thread |
512 | 323 | * | ||
513 | 324 | * block until we are asked to shutdown | ||
514 | 298 | */ | 325 | */ |
534 | 299 | while (!chassis_is_shutdown()) { | 326 | chassis_event_thread_loop(mainloop_thread); |
516 | 300 | struct timeval timeout; | ||
517 | 301 | int r; | ||
518 | 302 | |||
519 | 303 | timeout.tv_sec = 1; | ||
520 | 304 | timeout.tv_usec = 0; | ||
521 | 305 | |||
522 | 306 | g_assert(event_base_loopexit(chas->event_base, &timeout) == 0); | ||
523 | 307 | |||
524 | 308 | r = event_base_dispatch(chas->event_base); | ||
525 | 309 | |||
526 | 310 | if (r == -1) { | ||
527 | 311 | if (errno == EINTR) continue; | ||
528 | 312 | |||
529 | 313 | g_critical("%s: event_base_dispatch() failed: %s (%d)", | ||
530 | 314 | G_STRLOC, g_strerror(errno), errno); | ||
531 | 315 | break; | ||
532 | 316 | } | ||
533 | 317 | } | ||
535 | 318 | 327 | ||
536 | 319 | signal_del(&ev_sigterm); | 328 | signal_del(&ev_sigterm); |
537 | 320 | signal_del(&ev_sigint); | 329 | signal_del(&ev_sigint); |
538 | 321 | 330 | ||
539 | === modified file 'src/chassis-mainloop.h' | |||
540 | --- src/chassis-mainloop.h 2009-02-23 23:13:09 +0000 | |||
541 | +++ src/chassis-mainloop.h 2009-05-25 08:57:34 +0000 | |||
542 | @@ -43,6 +43,7 @@ | |||
543 | 43 | 43 | ||
544 | 44 | typedef struct chassis_private chassis_private; | 44 | typedef struct chassis_private chassis_private; |
545 | 45 | typedef struct chassis chassis; | 45 | typedef struct chassis chassis; |
546 | 46 | typedef struct chassis_event_threads_t chassis_event_threads_t; | ||
547 | 46 | 47 | ||
548 | 47 | struct chassis { | 48 | struct chassis { |
549 | 48 | struct event_base *event_base; | 49 | struct event_base *event_base; |
550 | @@ -59,6 +60,11 @@ | |||
551 | 59 | chassis_log *log; | 60 | chassis_log *log; |
552 | 60 | 61 | ||
553 | 61 | chassis_stats_t *stats; /**< the overall chassis stats, includes lua and glib allocation stats */ | 62 | chassis_stats_t *stats; /**< the overall chassis stats, includes lua and glib allocation stats */ |
554 | 63 | |||
555 | 64 | /* network-io threads */ | ||
556 | 65 | gint event_thread_count; | ||
557 | 66 | |||
558 | 67 | chassis_event_threads_t *threads; | ||
559 | 62 | }; | 68 | }; |
560 | 63 | 69 | ||
561 | 64 | CHASSIS_API chassis *chassis_init(void) G_GNUC_DEPRECATED; | 70 | CHASSIS_API chassis *chassis_init(void) G_GNUC_DEPRECATED; |
562 | 65 | 71 | ||
563 | === modified file 'src/chassis.c' | |||
564 | --- src/chassis.c 2009-05-15 14:23:58 +0000 | |||
565 | +++ src/chassis.c 2009-05-25 08:57:34 +0000 | |||
566 | @@ -395,6 +395,7 @@ | |||
567 | 395 | guint invoke_dbg_on_crash = 0; | 395 | guint invoke_dbg_on_crash = 0; |
568 | 396 | guint auto_restart = 0; | 396 | guint auto_restart = 0; |
569 | 397 | guint max_files_number = 8192; | 397 | guint max_files_number = 8192; |
570 | 398 | gint event_thread_count = 0; | ||
571 | 398 | #ifndef _WIN32 | 399 | #ifndef _WIN32 |
572 | 399 | struct rlimit max_files_rlimit; | 400 | struct rlimit max_files_rlimit; |
573 | 400 | #endif | 401 | #endif |
574 | @@ -431,6 +432,7 @@ | |||
575 | 431 | { "log-backtrace-on-crash", 0, 0, G_OPTION_ARG_NONE, NULL, "try to invoke debugger on crash", NULL }, | 432 | { "log-backtrace-on-crash", 0, 0, G_OPTION_ARG_NONE, NULL, "try to invoke debugger on crash", NULL }, |
576 | 432 | { "keepalive", 0, 0, G_OPTION_ARG_NONE, NULL, "try to restart the proxy if it crashed", NULL }, | 433 | { "keepalive", 0, 0, G_OPTION_ARG_NONE, NULL, "try to restart the proxy if it crashed", NULL }, |
577 | 433 | { "max-open-files", 0, 0, G_OPTION_ARG_INT, NULL, "maximum number of open files (ulimit -n)", NULL}, | 434 | { "max-open-files", 0, 0, G_OPTION_ARG_INT, NULL, "maximum number of open files (ulimit -n)", NULL}, |
578 | 435 | { "event-threads", 0, 0, G_OPTION_ARG_INT, NULL, "number of event-handling threads", NULL}, | ||
579 | 434 | 436 | ||
580 | 435 | { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } | 437 | { NULL, 0, 0, G_OPTION_ARG_NONE, NULL, NULL, NULL } |
581 | 436 | }; | 438 | }; |
582 | @@ -501,6 +503,7 @@ | |||
583 | 501 | main_entries[i++].arg_data = &(invoke_dbg_on_crash); | 503 | main_entries[i++].arg_data = &(invoke_dbg_on_crash); |
584 | 502 | main_entries[i++].arg_data = &(auto_restart); | 504 | main_entries[i++].arg_data = &(auto_restart); |
585 | 503 | main_entries[i++].arg_data = &(max_files_number); | 505 | main_entries[i++].arg_data = &(max_files_number); |
586 | 506 | main_entries[i++].arg_data = &(srv->event_thread_count); | ||
587 | 504 | 507 | ||
588 | 505 | option_ctx = g_option_context_new("- MySQL App Shell"); | 508 | option_ctx = g_option_context_new("- MySQL App Shell"); |
589 | 506 | g_option_context_add_main_entries(option_ctx, base_main_entries, GETTEXT_PACKAGE); | 509 | g_option_context_add_main_entries(option_ctx, base_main_entries, GETTEXT_PACKAGE); |
590 | @@ -888,6 +891,16 @@ | |||
591 | 888 | exit_code = EXIT_FAILURE; | 891 | exit_code = EXIT_FAILURE; |
592 | 889 | goto exit_nicely; | 892 | goto exit_nicely; |
593 | 890 | } | 893 | } |
594 | 894 | |||
595 | 895 | /* make sure that he max-thread-count isn't negative */ | ||
596 | 896 | if (event_thread_count < 0) { | ||
597 | 897 | g_critical("unknown option: %s", argv[1]); | ||
598 | 898 | |||
599 | 899 | exit_code = EXIT_FAILURE; | ||
600 | 900 | goto exit_nicely; | ||
601 | 901 | } | ||
602 | 902 | |||
603 | 903 | srv->event_thread_count = event_thread_count; | ||
604 | 891 | 904 | ||
605 | 892 | #ifndef _WIN32 | 905 | #ifndef _WIN32 |
606 | 893 | signal(SIGPIPE, SIG_IGN); | 906 | signal(SIGPIPE, SIG_IGN); |
607 | @@ -988,7 +1001,6 @@ | |||
608 | 988 | } | 1001 | } |
609 | 989 | } | 1002 | } |
610 | 990 | #endif | 1003 | #endif |
611 | 991 | |||
612 | 992 | if (chassis_mainloop(srv)) { | 1004 | if (chassis_mainloop(srv)) { |
613 | 993 | /* looks like we failed */ | 1005 | /* looks like we failed */ |
614 | 994 | 1006 | ||
615 | 995 | 1007 | ||
616 | === modified file 'src/network-conn-pool-lua.c' | |||
617 | --- src/network-conn-pool-lua.c 2009-02-24 00:20:29 +0000 | |||
618 | +++ src/network-conn-pool-lua.c 2009-05-25 08:57:34 +0000 | |||
619 | @@ -43,6 +43,7 @@ | |||
620 | 43 | 43 | ||
621 | 44 | #include "network-mysqld.h" | 44 | #include "network-mysqld.h" |
622 | 45 | #include "network-mysqld-packet.h" | 45 | #include "network-mysqld-packet.h" |
623 | 46 | #include "chassis-event-thread.h" | ||
624 | 46 | #include "network-mysqld-lua.h" | 47 | #include "network-mysqld-lua.h" |
625 | 47 | 48 | ||
626 | 48 | #include "network-conn-pool.h" | 49 | #include "network-conn-pool.h" |
627 | @@ -201,7 +202,6 @@ | |||
628 | 201 | * proxy from its backend | 202 | * proxy from its backend |
629 | 202 | */ | 203 | */ |
630 | 203 | int network_connection_pool_lua_add_connection(network_mysqld_con *con) { | 204 | int network_connection_pool_lua_add_connection(network_mysqld_con *con) { |
631 | 204 | chassis *srv = con->srv; | ||
632 | 205 | network_connection_pool_entry *pool_entry = NULL; | 205 | network_connection_pool_entry *pool_entry = NULL; |
633 | 206 | network_mysqld_con_lua_t *st = con->plugin_con_state; | 206 | network_mysqld_con_lua_t *st = con->plugin_con_state; |
634 | 207 | 207 | ||
635 | @@ -215,8 +215,7 @@ | |||
636 | 215 | pool_entry = network_connection_pool_add(st->backend->pool, con->server); | 215 | pool_entry = network_connection_pool_add(st->backend->pool, con->server); |
637 | 216 | 216 | ||
638 | 217 | event_set(&(con->server->event), con->server->fd, EV_READ, network_mysqld_con_idle_handle, pool_entry); | 217 | event_set(&(con->server->event), con->server->fd, EV_READ, network_mysqld_con_idle_handle, pool_entry); |
641 | 218 | event_base_set(srv->event_base, &(con->server->event)); | 218 | chassis_event_add_local(con->srv, &(con->server->event)); /* add a event, but stay in the same thread */ |
640 | 219 | event_add(&(con->server->event), NULL); | ||
642 | 220 | 219 | ||
643 | 221 | st->backend->connected_clients--; | 220 | st->backend->connected_clients--; |
644 | 222 | st->backend = NULL; | 221 | st->backend = NULL; |
645 | 223 | 222 | ||
646 | === modified file 'src/network-mysqld.c' | |||
647 | --- src/network-mysqld.c 2009-02-21 14:09:48 +0000 | |||
648 | +++ src/network-mysqld.c 2009-05-25 08:57:34 +0000 | |||
649 | @@ -179,6 +179,7 @@ | |||
650 | 179 | #include "network-mysqld-packet.h" | 179 | #include "network-mysqld-packet.h" |
651 | 180 | #include "network-conn-pool.h" | 180 | #include "network-conn-pool.h" |
652 | 181 | #include "chassis-mainloop.h" | 181 | #include "chassis-mainloop.h" |
653 | 182 | #include "chassis-event-thread.h" | ||
654 | 182 | #include "lua-scope.h" | 183 | #include "lua-scope.h" |
655 | 183 | #include "glib-ext.h" | 184 | #include "glib-ext.h" |
656 | 184 | 185 | ||
657 | @@ -761,8 +762,7 @@ | |||
658 | 761 | 762 | ||
659 | 762 | #define WAIT_FOR_EVENT(ev_struct, ev_type, timeout) \ | 763 | #define WAIT_FOR_EVENT(ev_struct, ev_type, timeout) \ |
660 | 763 | event_set(&(ev_struct->event), ev_struct->fd, ev_type, network_mysqld_con_handle, user_data); \ | 764 | event_set(&(ev_struct->event), ev_struct->fd, ev_type, network_mysqld_con_handle, user_data); \ |
663 | 764 | event_base_set(srv->event_base, &(ev_struct->event));\ | 765 | chassis_event_add(srv, &(ev_struct->event)); |
662 | 765 | event_add(&(ev_struct->event), timeout); | ||
664 | 766 | 766 | ||
665 | 767 | /** | 767 | /** |
666 | 768 | * loop on the same connection as long as we don't end up in a stable state | 768 | * loop on the same connection as long as we don't end up in a stable state |
667 | 769 | 769 | ||
668 | === modified file 'tests/unit/Makefile.am' | |||
669 | --- tests/unit/Makefile.am 2009-04-02 22:10:21 +0000 | |||
670 | +++ tests/unit/Makefile.am 2009-05-25 08:57:34 +0000 | |||
671 | @@ -74,10 +74,11 @@ | |||
672 | 74 | check_chassis_path.c \ | 74 | check_chassis_path.c \ |
673 | 75 | $(top_srcdir)/src/chassis-log.c \ | 75 | $(top_srcdir)/src/chassis-log.c \ |
674 | 76 | $(top_srcdir)/src/chassis-mainloop.c \ | 76 | $(top_srcdir)/src/chassis-mainloop.c \ |
675 | 77 | $(top_srcdir)/src/chassis-event-thread.c \ | ||
676 | 77 | $(top_srcdir)/src/chassis-plugin.c \ | 78 | $(top_srcdir)/src/chassis-plugin.c \ |
677 | 78 | $(top_srcdir)/src/chassis-stats.c | 79 | $(top_srcdir)/src/chassis-stats.c |
678 | 79 | check_chassis_path_CPPFLAGS = -I$(top_srcdir)/src $(GLIB_CFLAGS) $(MYSQL_CFLAGS) $(GMODULE_CFLAGS) | 80 | check_chassis_path_CPPFLAGS = -I$(top_srcdir)/src $(GLIB_CFLAGS) $(MYSQL_CFLAGS) $(GMODULE_CFLAGS) |
680 | 80 | check_chassis_path_LDADD = $(GLIB_LIBS) $(GMODULE_LIBS) $(EVENT_LIBS) | 81 | check_chassis_path_LDADD = $(GLIB_LIBS) $(GMODULE_LIBS) $(EVENT_LIBS) $(GTHREAD_LIBS) |
681 | 81 | 82 | ||
682 | 82 | t_network_backend_SOURCES = \ | 83 | t_network_backend_SOURCES = \ |
683 | 83 | t_network_backend.c \ | 84 | t_network_backend.c \ |
684 | 84 | 85 | ||
685 | === modified file 'tests/unit/check_chassis_path.c' | |||
686 | --- tests/unit/check_chassis_path.c 2009-02-23 23:13:09 +0000 | |||
687 | +++ tests/unit/check_chassis_path.c 2009-05-25 08:57:34 +0000 | |||
688 | @@ -95,6 +95,8 @@ | |||
689 | 95 | /*@}*/ | 95 | /*@}*/ |
690 | 96 | 96 | ||
691 | 97 | int main(int argc, char **argv) { | 97 | int main(int argc, char **argv) { |
692 | 98 | g_thread_init(NULL); | ||
693 | 99 | |||
694 | 98 | g_test_init(&argc, &argv, NULL); | 100 | g_test_init(&argc, &argv, NULL); |
695 | 99 | g_test_bug_base("http://bugs.mysql.com/"); | 101 | g_test_bug_base("http://bugs.mysql.com/"); |
696 | 100 | 102 |
merge the initial threaded-io code into trunk for the 0.8 work