Merge lp:~cbehrens/agent-smith/implement-state into lp:agent-smith
- implement-state
- Merge into trunk
Proposed by
Chris Behrens
Status: | Merged |
---|---|
Merged at revision: | 86 |
Proposed branch: | lp:~cbehrens/agent-smith/implement-state |
Merge into: | lp:agent-smith |
Diff against target: |
1361 lines (+505/-235) 14 files modified
src/agent.c (+119/-34) src/agent.h (+10/-2) src/main.c (+5/-2) src/slist.c (+23/-10) src/slist.h (+9/-2) src/spool.c (+111/-59) src/spool.h (+15/-5) src/xen.c (+109/-80) src/xen.h (+34/-10) tests/check_agent.c (+21/-8) tests/check_slist.c (+19/-4) tests/check_spool.c (+7/-6) tests/check_xen.c (+16/-13) tests/mock_xenstore.c (+7/-0) |
To merge this branch: | bzr merge lp:~cbehrens/agent-smith/implement-state |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Agent Smith devs | Pending | ||
Review via email: mp+33834@code.launchpad.net |
Commit message
Description of the change
This implements some state structures to eliminate global variables and make it easier to monitor multiple spool directories and so forth if required in the future. It also implements a single poll() on the spool and xenstore.
To post a comment you must log in.
- 83. By Chris Behrens
-
I guess xs_domain_open is not interchangable with xs_daemon_open..
- 84. By Chris Behrens
-
merge trunk
- 85. By Chris Behrens
-
merged trunk
- 86. By Chris Behrens
-
merged trunk
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/agent.c' |
2 | --- src/agent.c 2010-09-16 19:58:14 +0000 |
3 | +++ src/agent.c 2010-09-16 20:31:06 +0000 |
4 | @@ -26,14 +26,22 @@ |
5 | #include <sys/wait.h> |
6 | #include <unistd.h> |
7 | #include "log.h" |
8 | +#include "agent.h" |
9 | #include "spool.h" |
10 | #include "xen.h" |
11 | |
12 | +struct _AgentInfo |
13 | +{ |
14 | + SpoolInfo *ai_spool_info; |
15 | + XenInfo *ai_xen_info; |
16 | + struct pollfd ai_pfds[2]; |
17 | + char *ai_dispatcher; |
18 | +}; |
19 | + |
20 | /* |
21 | * Global variables |
22 | */ |
23 | |
24 | -char *dispatcher = NULL; |
25 | int agent_got_sigterm = 0; |
26 | |
27 | /* |
28 | @@ -66,7 +74,7 @@ |
29 | /* |
30 | * Public functions |
31 | */ |
32 | -void read_from_spool_and_send_to_xen(const char *msg) { |
33 | +void read_from_spool_and_send_to_xen(SpoolInfo *si, const char *msg) { |
34 | char *buf = NULL, xs_path[255]; |
35 | const char *msgid; |
36 | struct stat sb; |
37 | @@ -78,21 +86,38 @@ |
38 | else |
39 | msgid++; |
40 | |
41 | - if (stat(msg, &sb) == -1) |
42 | + if (stat(msg, &sb) == -1) { |
43 | + AGENT_LOG("Failed to stat spool file '%s': %s", msg, strerror(errno)); |
44 | return; |
45 | + } |
46 | |
47 | fd = open(msg, O_RDONLY); |
48 | + if (fd < 0) { |
49 | + AGENT_LOG("Failed to open spool file '%s': %s", msg, strerror(errno)); |
50 | + return; |
51 | + } |
52 | + |
53 | buf = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); |
54 | + if (buf == (char *)-1) { |
55 | + AGENT_LOG("Failed to mmap spool file '%s': %s", msg, strerror(errno)); |
56 | + close(fd); |
57 | + return; |
58 | + } |
59 | + |
60 | snprintf(xs_path, 255, XS_MSG_OUTGOING_BASE_PATH "/%s", msgid); |
61 | - xen_write_path(xs_path, buf, sb.st_size); |
62 | + xen_write_path(spool_to_agent_info(si)->ai_xen_info, |
63 | + xs_path, buf, sb.st_size); |
64 | munmap(buf, sb.st_size); |
65 | + |
66 | return; |
67 | } |
68 | |
69 | -int store_in_spool_and_call_dispatcher(const char *xs_path, |
70 | - const char *buf, |
71 | - const size_t buflen, |
72 | - const char *token) { |
73 | +int store_in_spool_and_call_dispatcher(XenInfo *xi, |
74 | + const char *xs_path, |
75 | + const char *buf, |
76 | + const size_t buflen, |
77 | + const char *token) { |
78 | + const char *dispatcher; |
79 | const char *msgid = strrchr(xs_path, '/'); |
80 | |
81 | if (!msgid) |
82 | @@ -102,6 +127,8 @@ |
83 | |
84 | spool_store(msgid, buf, buflen); |
85 | |
86 | + dispatcher = xen_to_agent_info(xi)->ai_dispatcher; |
87 | + |
88 | /* TODO: Set up a SIGCHLD handler */ |
89 | if (!fork()) |
90 | execl(dispatcher, dispatcher, msgid, NULL); |
91 | @@ -124,50 +151,108 @@ |
92 | return 0; |
93 | } |
94 | |
95 | -int agent_init(const char *dispatcher_cmd) { |
96 | +AgentInfo *agent_init(const char *dispatcher_cmd) { |
97 | + AgentInfo *ai; |
98 | + |
99 | AGENT_LOG0("Starting Agent Smith"); |
100 | |
101 | + ai = calloc(1, sizeof(AgentInfo)); |
102 | + if (ai == NULL) |
103 | + return NULL; |
104 | + |
105 | if (agent_setup_signals() < 0) { |
106 | AGENT_LOG0("Failed to initialise signal handlers"); |
107 | - return -1; |
108 | + agent_deinit(ai); |
109 | + return NULL; |
110 | } |
111 | |
112 | - if (xen_init() < 0) { |
113 | + if ((ai->ai_xen_info = xen_init(ai)) == NULL) { |
114 | AGENT_LOG0("Failed to initialise Xen connection"); |
115 | - return -1; |
116 | + agent_deinit(ai); |
117 | + return NULL; |
118 | } |
119 | |
120 | - if (spool_init() < 0) { |
121 | + if ((ai->ai_spool_info = spool_init(ai)) == NULL) { |
122 | AGENT_LOG0("Failed to initialise spool"); |
123 | - return -1; |
124 | + agent_deinit(ai); |
125 | + return NULL; |
126 | } |
127 | |
128 | - if (spool_watch(read_from_spool_and_send_to_xen) < 0) { |
129 | + if (spool_watch(ai->ai_spool_info, read_from_spool_and_send_to_xen) < 0) { |
130 | AGENT_LOG0("Failed to register spool watch."); |
131 | - return -1; |
132 | + agent_deinit(ai); |
133 | + return NULL; |
134 | } |
135 | |
136 | - if (xen_register_watch(XS_MSG_INCOMING_BASE_PATH, |
137 | + if (xen_register_watch(ai->ai_xen_info, XS_MSG_INCOMING_BASE_PATH, |
138 | store_in_spool_and_call_dispatcher, |
139 | "notoken") < 0) { |
140 | AGENT_LOG0("Failed to register Xen watch."); |
141 | - return -1; |
142 | + agent_deinit(ai); |
143 | + return NULL; |
144 | } |
145 | |
146 | - if ((dispatcher = strdup(dispatcher_cmd)) == NULL) { |
147 | + if ((ai->ai_dispatcher = strdup(dispatcher_cmd)) == NULL) { |
148 | AGENT_LOG("Failed to strdup: %s", strerror(errno)); |
149 | - return -1; |
150 | - } |
151 | - |
152 | - return 0; |
153 | -} |
154 | - |
155 | -int agent_loop(void) |
156 | -{ |
157 | - spool_process_pending_events(); |
158 | - xen_process_pending_events(); |
159 | - if (agent_got_sigterm) |
160 | - return 1; |
161 | - return 0; |
162 | -} |
163 | - |
164 | + agent_deinit(ai); |
165 | + return NULL; |
166 | + } |
167 | + |
168 | + if (spool_fill_pollfd(ai->ai_spool_info, &ai->ai_pfds[0]) < 0) { |
169 | + AGENT_LOG0("Failed to add spool pollfd"); |
170 | + agent_deinit(ai); |
171 | + return NULL; |
172 | + } |
173 | + |
174 | + if (xen_fill_pollfd(ai->ai_xen_info, &ai->ai_pfds[1]) < 0) { |
175 | + AGENT_LOG0("Failed to add xen pollfd"); |
176 | + agent_deinit(ai); |
177 | + return NULL; |
178 | + } |
179 | + |
180 | + return ai; |
181 | +} |
182 | + |
183 | +void agent_deinit(AgentInfo *ai) |
184 | +{ |
185 | + if (ai->ai_xen_info != NULL) |
186 | + xen_deinit(ai->ai_xen_info); |
187 | + if (ai->ai_spool_info != NULL) |
188 | + spool_deinit(ai->ai_spool_info); |
189 | + free(ai->ai_dispatcher); |
190 | + free(ai); |
191 | +} |
192 | + |
193 | +int agent_loop(AgentInfo *ai) |
194 | +{ |
195 | + int num_ready; |
196 | + |
197 | + /* we can go ahead and try to do this one without polling first */ |
198 | + spool_process_pending_events(ai->ai_spool_info); |
199 | + |
200 | + if (agent_got_sigterm) |
201 | + return 1; |
202 | + |
203 | + num_ready = poll(ai->ai_pfds, 2, -1); |
204 | + if (num_ready > 0) { |
205 | + if (ai->ai_pfds[0].revents) { |
206 | + spool_process_pending_events(ai->ai_spool_info); |
207 | + ai->ai_pfds[0].revents = 0; |
208 | + } |
209 | + if (ai->ai_pfds[1].revents) { |
210 | + xen_process_pending_events(ai->ai_xen_info); |
211 | + ai->ai_pfds[1].revents = 0; |
212 | + } |
213 | + } |
214 | + |
215 | + if (agent_got_sigterm) |
216 | + return 1; |
217 | + |
218 | + return 0; |
219 | +} |
220 | + |
221 | +/* Only useed by tests */ |
222 | +XenInfo *agent_xen_info(AgentInfo *ai) |
223 | +{ |
224 | + return ai->ai_xen_info; |
225 | +} |
226 | |
227 | === modified file 'src/agent.h' |
228 | --- src/agent.h 2010-08-19 08:36:27 +0000 |
229 | +++ src/agent.h 2010-09-16 20:31:06 +0000 |
230 | @@ -13,5 +13,13 @@ |
231 | * See the License for the specific language governing permissions and |
232 | * limitations under the License. |
233 | */ |
234 | -int agent_init(const char *dispatcher_cmd); |
235 | -int agent_loop(void); |
236 | +#ifndef __SRC_AGENT_H__ |
237 | +#define __SRC_AGENT_H__ |
238 | + |
239 | +typedef struct _AgentInfo AgentInfo; |
240 | + |
241 | +AgentInfo *agent_init(const char *dispatcher_cmd); |
242 | +void agent_deinit(AgentInfo *ai); |
243 | +int agent_loop(AgentInfo *ai); |
244 | + |
245 | +#endif /* __SRC_AGENT_H__ */ |
246 | |
247 | === modified file 'src/main.c' |
248 | --- src/main.c 2010-08-25 03:54:18 +0000 |
249 | +++ src/main.c 2010-09-16 20:31:06 +0000 |
250 | @@ -40,6 +40,7 @@ |
251 | int opt; |
252 | char *pidfile; |
253 | FILE *fp; |
254 | + AgentInfo *ai; |
255 | |
256 | while ((opt = getopt(argc, argv, "fh")) != -1) { |
257 | switch (opt) { |
258 | @@ -81,12 +82,14 @@ |
259 | fprintf(fp, "%d\n", getpid()); |
260 | fclose(fp); |
261 | |
262 | - if (agent_init(argv[optind]) < 0) { |
263 | + if ((ai = agent_init(argv[optind])) == NULL) { |
264 | syslog(LOG_DAEMON | LOG_CRIT, "Agent initialisation failed."); |
265 | return -1; |
266 | } |
267 | |
268 | - while (!agent_loop()); |
269 | + while (!agent_loop(ai)); |
270 | + |
271 | + agent_deinit(ai); |
272 | |
273 | return 0; |
274 | } |
275 | |
276 | === modified file 'src/slist.c' |
277 | --- src/slist.c 2010-08-25 06:22:40 +0000 |
278 | +++ src/slist.c 2010-09-16 20:31:06 +0000 |
279 | @@ -59,17 +59,9 @@ |
280 | if (slist != NULL) |
281 | { |
282 | SListElem *elem; |
283 | - SListElem *next; |
284 | |
285 | - for(elem = slist_first(slist); |
286 | - elem != NULL; |
287 | - elem = next) |
288 | - { |
289 | - next = slist_next(slist, elem); |
290 | - if ((elem->sle_data != NULL) && slist->sl_destroy_cb != NULL) |
291 | - slist->sl_destroy_cb(elem->sle_data); |
292 | - free(elem); |
293 | - } |
294 | + while((elem = slist_first(slist)) != NULL) |
295 | + slist_remove(slist, elem); |
296 | |
297 | free(slist); |
298 | } |
299 | @@ -102,6 +94,27 @@ |
300 | } |
301 | |
302 | /** |
303 | + * Remove an element from a list |
304 | + * |
305 | + * @param list The list to remove from |
306 | + * @param elem The element to remove |
307 | + */ |
308 | +void slist_remove(SList *list, SListElem *elem) { |
309 | + assert(list != NULL); |
310 | + assert(elem != &(list->sl_elem)); |
311 | + /* list is actually empty ? */ |
312 | + assert(list->sl_elem.sle_next != &(list->sl_elem)); |
313 | + |
314 | + elem->sle_next->sle_prev = elem->sle_prev; |
315 | + elem->sle_prev->sle_next = elem->sle_next; |
316 | + |
317 | + if (list->sl_destroy_cb != NULL) |
318 | + list->sl_destroy_cb(elem); |
319 | + |
320 | + free(elem); |
321 | +} |
322 | + |
323 | +/** |
324 | * Return the first element of a previously created list |
325 | * |
326 | * @param list The list |
327 | |
328 | === modified file 'src/slist.h' |
329 | --- src/slist.h 2010-08-25 06:50:43 +0000 |
330 | +++ src/slist.h 2010-09-16 20:31:06 +0000 |
331 | @@ -19,7 +19,7 @@ |
332 | typedef struct _SList SList; |
333 | typedef struct _SListElem SListElem; |
334 | |
335 | -typedef void (*slist_destroy_cb)(void *data); |
336 | +typedef void (*slist_destroy_cb)(SListElem *elem); |
337 | |
338 | /** |
339 | * Create a new list for storing arbitrary data |
340 | @@ -46,6 +46,14 @@ |
341 | SListElem *slist_append(SList *list, void *data); |
342 | |
343 | /** |
344 | + * Remove an element from a list |
345 | + * |
346 | + * @param list The list to remove from |
347 | + * @param elem The element to remove |
348 | + */ |
349 | +void slist_remove(SList *list, SListElem *elem); |
350 | + |
351 | +/** |
352 | * Return the first element of a previously created list |
353 | * |
354 | * @param list The list |
355 | @@ -87,5 +95,4 @@ |
356 | */ |
357 | void *slist_data(SListElem *elem); |
358 | |
359 | - |
360 | #endif /* __SRC_SLIST_H__ */ |
361 | |
362 | === modified file 'src/spool.c' |
363 | --- src/spool.c 2010-08-25 06:22:40 +0000 |
364 | +++ src/spool.c 2010-09-16 20:31:06 +0000 |
365 | @@ -23,10 +23,12 @@ |
366 | #include <stdlib.h> |
367 | #include <stdio.h> |
368 | #include <string.h> |
369 | +#include <assert.h> |
370 | #include "log.h" |
371 | #include "slist.h" |
372 | #include "spool.h" |
373 | #include "util.h" |
374 | +#include "xen.h" |
375 | |
376 | #ifndef SPOOLDIR |
377 | #define SPOOLDIR "/var/spool/agent" |
378 | @@ -35,26 +37,47 @@ |
379 | #define INCOMING_DIR "incoming" |
380 | #define OUTGOING_DIR "outgoing" |
381 | |
382 | -/* |
383 | - * Global variables |
384 | - */ |
385 | +#define INOTIFY_BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)) |
386 | |
387 | -int inotify_fd = -1; |
388 | -SList *callbacks = NULL; |
389 | +struct _SpoolInfo |
390 | +{ |
391 | + AgentInfo *si_agent_info; |
392 | + int si_inotify_fd; |
393 | + char si_buf[INOTIFY_BUFF_SIZE]; |
394 | + SList *si_callbacks; |
395 | +}; |
396 | |
397 | int spool_ensure_dir(const char *dir); |
398 | |
399 | char *spool_basedir(void); |
400 | static char *spool_queue_dir(int in); |
401 | |
402 | -int spool_init(void) { |
403 | +#if 0 |
404 | +static void _spool_callback_destroy(void *data) |
405 | +{ |
406 | + free(data); |
407 | +} |
408 | +#endif |
409 | |
410 | +SpoolInfo *spool_init(AgentInfo *ai) { |
411 | + SpoolInfo *si; |
412 | char *tmp; |
413 | |
414 | - callbacks = slist_init(NULL); |
415 | - if (callbacks == NULL) |
416 | - { |
417 | - return -1; |
418 | + si = calloc(1, sizeof(SpoolInfo)); |
419 | + if (si == NULL) |
420 | + { |
421 | + syslog(LOG_DAEMON | LOG_CRIT, "Out of memory creating spool state"); |
422 | + return NULL; |
423 | + } |
424 | + |
425 | + si->si_inotify_fd = -1; |
426 | + si->si_agent_info = ai; |
427 | + |
428 | + si->si_callbacks = slist_init(NULL); |
429 | + if (si->si_callbacks == NULL) |
430 | + { |
431 | + spool_deinit(si); |
432 | + return NULL; |
433 | } |
434 | |
435 | if (spool_ensure_dir(tmp = spool_incoming_dir()) == 0) |
436 | @@ -62,9 +85,8 @@ |
437 | else { |
438 | syslog(LOG_DAEMON | LOG_CRIT, "Failed to create incoming spool dir: %s", tmp); |
439 | free(tmp); |
440 | - slist_deinit(callbacks); |
441 | - callbacks = NULL; |
442 | - return -1; |
443 | + spool_deinit(si); |
444 | + return NULL; |
445 | } |
446 | |
447 | if (spool_ensure_dir(tmp = spool_outgoing_dir()) == 0) |
448 | @@ -72,12 +94,21 @@ |
449 | else { |
450 | syslog(LOG_DAEMON | LOG_CRIT, "Failed to create outgoing spool dir: %s", tmp); |
451 | free(tmp); |
452 | - slist_deinit(callbacks); |
453 | - callbacks = NULL; |
454 | - return -1; |
455 | - } |
456 | - |
457 | - return 0; |
458 | + spool_deinit(si); |
459 | + return NULL; |
460 | + } |
461 | + |
462 | + return si; |
463 | +} |
464 | + |
465 | +void spool_deinit(SpoolInfo *si) |
466 | +{ |
467 | + if (si != NULL) { |
468 | + if (si->si_inotify_fd >= 0) |
469 | + close(si->si_inotify_fd); |
470 | + slist_deinit(si->si_callbacks); |
471 | + free(si); |
472 | + } |
473 | } |
474 | |
475 | /** |
476 | @@ -252,36 +283,41 @@ |
477 | return 0; |
478 | } |
479 | |
480 | -int spool_watch(spool_callback cb) { |
481 | - char *incoming_dir; |
482 | - |
483 | - if (inotify_fd == -1) { |
484 | - inotify_fd = inotify_init(); |
485 | - if (inotify_fd < 0) |
486 | - return -1; |
487 | - |
488 | - if (fcntl(inotify_fd, F_SETFL, O_NONBLOCK) < 0) { |
489 | - close(inotify_fd); |
490 | - inotify_fd = -1; |
491 | - return -1; |
492 | - } |
493 | - } |
494 | - |
495 | - incoming_dir = spool_incoming_dir(); |
496 | - if (spool_ensure_dir(incoming_dir) < 0) { |
497 | - free(incoming_dir); |
498 | - return -1; |
499 | - } |
500 | - |
501 | - if (inotify_add_watch(inotify_fd, incoming_dir, IN_CLOSE_WRITE) < 0) { |
502 | - free(incoming_dir); |
503 | - perror("inotify_add_watch failed"); |
504 | - return -1; |
505 | - } |
506 | - |
507 | - free(incoming_dir); |
508 | - |
509 | - if (slist_append(callbacks, cb) == NULL) |
510 | +int spool_watch(SpoolInfo *si, spool_callback cb) { |
511 | + |
512 | + assert(si != NULL); |
513 | + |
514 | + if (si->si_inotify_fd == -1) { |
515 | + char *incoming_dir; |
516 | + |
517 | + si->si_inotify_fd = inotify_init(); |
518 | + if (si->si_inotify_fd < 0) |
519 | + { |
520 | + return -1; |
521 | + } |
522 | + |
523 | + if (fcntl(si->si_inotify_fd, F_SETFL, O_NONBLOCK) < 0) { |
524 | + close(si->si_inotify_fd); |
525 | + si->si_inotify_fd = -1; |
526 | + return -1; |
527 | + } |
528 | + |
529 | + incoming_dir = spool_incoming_dir(); |
530 | + if (spool_ensure_dir(incoming_dir) < 0) { |
531 | + free(incoming_dir); |
532 | + return -1; |
533 | + } |
534 | + |
535 | + if (inotify_add_watch(si->si_inotify_fd, incoming_dir, IN_CLOSE_WRITE) < 0) { |
536 | + free(incoming_dir); |
537 | + perror("inotify_add_watch failed"); |
538 | + return -1; |
539 | + } |
540 | + |
541 | + free(incoming_dir); |
542 | + } |
543 | + |
544 | + if (slist_append(si->si_callbacks, cb) == NULL) |
545 | { |
546 | return -1; |
547 | } |
548 | @@ -291,22 +327,24 @@ |
549 | |
550 | #define INOTIFY_BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)) |
551 | |
552 | -void spool_process_pending_events(void) { |
553 | +void spool_process_pending_events(SpoolInfo *si) { |
554 | ssize_t len, i; |
555 | - char buf[INOTIFY_BUFF_SIZE]; |
556 | + |
557 | + assert(si != NULL); |
558 | |
559 | while (1) { |
560 | - len = read(inotify_fd, buf, INOTIFY_BUFF_SIZE); |
561 | + len = read(si->si_inotify_fd, si->si_buf, INOTIFY_BUFF_SIZE); |
562 | if (len < 0) { |
563 | - /* (errno == EAGAIN && errno == EWOULDBLOCK) would mean that everything |
564 | - * fine, there just hasn't been any action, but we just return no matter |
565 | - * what */ |
566 | + /* (errno == EAGAIN && errno == EWOULDBLOCK) would mean that |
567 | + * everything is fine, there just hasn't been any action, but |
568 | + * we just return no matter what |
569 | + */ |
570 | return; |
571 | } |
572 | |
573 | i = 0; |
574 | while (len >= sizeof(struct inotify_event)) { |
575 | - struct inotify_event *ev = (struct inotify_event *) &buf[i]; |
576 | + struct inotify_event *ev = (struct inotify_event *) &si->si_buf[i]; |
577 | |
578 | len -= sizeof(struct inotify_event); |
579 | |
580 | @@ -323,11 +361,12 @@ |
581 | path = util_join_paths(incoming_dir, ev->name); |
582 | free(incoming_dir); |
583 | |
584 | - for(elem = slist_first(callbacks); |
585 | + for(elem = slist_first(si->si_callbacks); |
586 | elem != NULL; |
587 | - elem = slist_next(callbacks, elem)) { |
588 | + elem = slist_next(si->si_callbacks, elem)) |
589 | + { |
590 | spool_callback cb = (spool_callback)slist_data(elem); |
591 | - cb(path); |
592 | + cb(si, path); |
593 | } |
594 | |
595 | free(path); |
596 | @@ -339,3 +378,16 @@ |
597 | } |
598 | } |
599 | } |
600 | + |
601 | +int spool_fill_pollfd(SpoolInfo *si, struct pollfd *pfd) |
602 | +{ |
603 | + pfd->fd = si->si_inotify_fd; |
604 | + pfd->events = POLLIN; |
605 | + pfd->revents = 0; |
606 | + return 0; |
607 | +} |
608 | + |
609 | +AgentInfo *spool_to_agent_info(SpoolInfo *si) |
610 | +{ |
611 | + return si->si_agent_info; |
612 | +} |
613 | |
614 | === modified file 'src/spool.h' |
615 | --- src/spool.h 2010-08-25 03:54:18 +0000 |
616 | +++ src/spool.h 2010-09-16 20:31:06 +0000 |
617 | @@ -16,9 +16,14 @@ |
618 | #ifndef SPOOL_H |
619 | #define SPOOL_H |
620 | |
621 | -typedef void (*spool_callback)(const char *path); |
622 | - |
623 | -int spool_init(void); |
624 | +#include <poll.h> |
625 | +#include "agent.h" |
626 | + |
627 | +typedef struct _SpoolInfo SpoolInfo; |
628 | +typedef void (*spool_callback)(SpoolInfo *si, const char *path); |
629 | + |
630 | +SpoolInfo *spool_init(AgentInfo *ai); |
631 | +void spool_deinit(SpoolInfo *si); |
632 | char *spool_incoming_dir(void); |
633 | char *spool_outgoing_dir(void); |
634 | int agent_setup_signals(void); |
635 | @@ -42,7 +47,7 @@ |
636 | * @param cb Function to call when a new file is created in the spool |
637 | * @return 1 on success, 0 otherwise |
638 | */ |
639 | -int spool_watch(spool_callback cb); |
640 | +int spool_watch(SpoolInfo *si, spool_callback cb); |
641 | |
642 | /** |
643 | * Process pending watch events |
644 | @@ -50,9 +55,14 @@ |
645 | * Fires any callbacks that are pending, then returns. If no events are |
646 | * pending, returns immediately. |
647 | */ |
648 | -void spool_process_pending_events(void); |
649 | +void spool_process_pending_events(SpoolInfo *si); |
650 | |
651 | /* void *spool_retrieve(char **msgid, unsigned int *buflen); */ |
652 | int spool_delete(const char *msgid); |
653 | |
654 | +int spool_fill_pollfd(SpoolInfo *si, struct pollfd *pfd); |
655 | + |
656 | +AgentInfo *spool_to_agent_info(SpoolInfo *si); |
657 | + |
658 | + |
659 | #endif /* SPOOL_H */ |
660 | |
661 | === modified file 'src/xen.c' |
662 | --- src/xen.c 2010-09-09 19:21:25 +0000 |
663 | +++ src/xen.c 2010-09-16 20:31:06 +0000 |
664 | @@ -23,59 +23,92 @@ |
665 | #include "log.h" |
666 | #include "slist.h" |
667 | #include "xen.h" |
668 | +#include "agent.h" |
669 | |
670 | /* |
671 | * Local types |
672 | */ |
673 | -typedef int (*xen_cb)(const char *, const char *, const size_t, const char *); |
674 | - |
675 | typedef struct { |
676 | char *token; |
677 | xen_cb callback; |
678 | } token_callback_tuple; |
679 | |
680 | -/* |
681 | - * Global variables |
682 | - */ |
683 | -SList *handlers = NULL; |
684 | -struct xs_handle *xh; |
685 | +struct _XenInfo { |
686 | + AgentInfo *xi_agent_info; |
687 | + struct xs_handle *xi_handle; |
688 | + int xi_handle_fd; |
689 | + SList *xi_handlers; |
690 | +}; |
691 | + |
692 | |
693 | /* |
694 | * Static function prototypes |
695 | */ |
696 | -static void _xen_destroy_callback(void *data); |
697 | +static void _xen_destroy_callback(SListElem *elem); |
698 | |
699 | /* |
700 | * Static functions |
701 | */ |
702 | -static void _xen_destroy_callback(void *data) { |
703 | - token_callback_tuple *cb = (token_callback_tuple *)data; |
704 | +static void _xen_destroy_callback(SListElem *elem) { |
705 | + token_callback_tuple *cb = (token_callback_tuple *)slist_data(elem); |
706 | |
707 | free(cb->token); |
708 | free(cb); |
709 | } |
710 | |
711 | -void xen_fire_callback(const char *path, const char *token, void *buf, |
712 | +void xen_fire_callback(XenInfo *xi, const char *path, const char *token, void *buf, |
713 | unsigned int buflen); |
714 | -int xen_convert_network_event(char *prefix, char **buf, unsigned int *buflen); |
715 | - |
716 | -/* |
717 | - * Initialise the connection to Xen Store |
718 | - * |
719 | - * @returns 0 on success, -1 otherwise |
720 | - */ |
721 | -int xen_init(void) { |
722 | - if (!xh) { |
723 | - handlers = slist_init(_xen_destroy_callback); |
724 | - if (handlers == NULL) |
725 | - return -1; |
726 | - |
727 | - if (!(xh = xs_domain_open())) { |
728 | - AGENT_LOG("Failed to connect to Xen Store: %s", strerror(errno)); |
729 | - slist_deinit(handlers); |
730 | - } |
731 | - } |
732 | - return xh ? 0 : -1; |
733 | +int xen_convert_network_event(XenInfo *xi, char *prefix, char **buf, unsigned int *buflen); |
734 | + |
735 | +/* |
736 | + * Initialise the connection to Xen Store |
737 | + * |
738 | + * @returns a new XenInfo *, or NULL if there was a failure |
739 | + */ |
740 | +XenInfo *xen_init(AgentInfo *ai) { |
741 | + XenInfo *xi; |
742 | + |
743 | + xi = calloc(1, sizeof(XenInfo)); |
744 | + if (xi == NULL) |
745 | + return NULL; |
746 | + |
747 | + xi->xi_agent_info = ai; |
748 | + |
749 | + xi->xi_handlers = slist_init(_xen_destroy_callback); |
750 | + if (xi->xi_handlers == NULL) { |
751 | + xen_deinit(xi); |
752 | + return NULL; |
753 | + } |
754 | + |
755 | + if ((xi->xi_handle = xs_domain_open()) == NULL) { |
756 | + AGENT_LOG("Failed to connect to Xen Store: %s", strerror(errno)); |
757 | + xen_deinit(xi); |
758 | + return NULL; |
759 | + } |
760 | + |
761 | + if ((xi->xi_handle_fd = xs_fileno(xi->xi_handle)) < 0) { |
762 | + AGENT_LOG("Failed to get file descriptor for connection to " |
763 | + "Xen Store: %s", strerror(errno)); |
764 | + xen_deinit(xi); |
765 | + return NULL; |
766 | + } |
767 | + |
768 | + return xi; |
769 | +} |
770 | + |
771 | +/* |
772 | + * Initialise the connection to Xen Store |
773 | + * |
774 | + * @param xi A previously returned XenInfo * from xen_init() |
775 | + */ |
776 | +void xen_deinit(XenInfo *xi) |
777 | +{ |
778 | + if (xi != NULL) { |
779 | + if (xi->xi_handle) |
780 | + xs_daemon_close(xi->xi_handle); |
781 | + slist_deinit(xi->xi_handlers); |
782 | + free(xi); |
783 | + } |
784 | } |
785 | |
786 | /* |
787 | @@ -87,12 +120,12 @@ |
788 | * @param data: A string to pass to the callback |
789 | * @returns 0 on success, -1 otherwise. |
790 | */ |
791 | -int xen_register_watch(const char *path, |
792 | +int xen_register_watch(XenInfo *xi, const char *path, |
793 | xen_cb callback, |
794 | const char *data) { |
795 | token_callback_tuple *cb; |
796 | |
797 | - assert(xh != NULL); /* make sure xen_init() was called */ |
798 | + assert(xi != NULL); |
799 | |
800 | if (!(cb = malloc(sizeof(token_callback_tuple)))) { |
801 | AGENT_LOG("malloc: %s", strerror(errno)); |
802 | @@ -100,7 +133,7 @@ |
803 | } |
804 | |
805 | AGENT_LOG("Starting to watch %s", path); |
806 | - if (!(xs_watch(xh, path, data))) { |
807 | + if (!(xs_watch(xi->xi_handle, path, data))) { |
808 | AGENT_LOG0("Failed to register watch with Xen Store"); |
809 | free(cb); |
810 | return -1; |
811 | @@ -114,7 +147,7 @@ |
812 | |
813 | cb->callback = callback; |
814 | |
815 | - if (slist_append(handlers, cb) == NULL) { |
816 | + if (slist_append(xi->xi_handlers, cb) == NULL) { |
817 | AGENT_LOG0("Failed to append callback to handler list."); |
818 | free(cb->token); |
819 | free(cb); |
820 | @@ -134,7 +167,7 @@ |
821 | * "{\"opt\":\"opt_value\",\"value\":" |
822 | * The final '}' will be appended by this call. |
823 | */ |
824 | -int xen_convert_network_event(char *prefix, char **buf, unsigned int *buflen) |
825 | +int xen_convert_network_event(XenInfo *xi, char *prefix, char **buf, unsigned int *buflen) |
826 | { |
827 | char dir_entry_path[255]; |
828 | char **dir_list; |
829 | @@ -147,7 +180,7 @@ |
830 | unsigned int new_buf_len; |
831 | void *vptr; |
832 | |
833 | - dir_list = xen_read_dir(XENSTORE_NETWORKING_PATH, &dir_list_num); |
834 | + dir_list = xen_read_dir(xi, XENSTORE_NETWORKING_PATH, &dir_list_num); |
835 | if (dir_list == NULL) { |
836 | return -1; |
837 | } |
838 | @@ -168,7 +201,7 @@ |
839 | snprintf(dir_entry_path, sizeof(dir_entry_path), "%s/%s", |
840 | XENSTORE_NETWORKING_PATH, *d); |
841 | |
842 | - dir_entry = xen_read_path(dir_entry_path, &dir_entry_len); |
843 | + dir_entry = xen_read_path(xi, dir_entry_path, &dir_entry_len); |
844 | if (dir_entry == NULL) |
845 | { |
846 | free(new_buf); |
847 | @@ -208,43 +241,24 @@ |
848 | return 0; |
849 | } |
850 | |
851 | -int xen_process_pending_events(void) { |
852 | +int xen_process_pending_events(XenInfo *xi) { |
853 | char **vec; |
854 | unsigned int num; |
855 | char *buf; |
856 | unsigned int buflen; |
857 | - int fd; |
858 | - fd_set rfds; |
859 | - struct timeval timeout; |
860 | - int fds; |
861 | - |
862 | - if ((fd = xs_fileno(xh)) < 0) { |
863 | - AGENT_LOG("Failed to get file descriptor for connection to " |
864 | - "Xen Store: %s", strerror(errno)); |
865 | - return -1; |
866 | - } |
867 | - |
868 | - timeout.tv_sec = 0; |
869 | - timeout.tv_usec = 500000; |
870 | - |
871 | - FD_ZERO(&rfds); |
872 | - FD_SET(fd, &rfds); |
873 | - |
874 | - if ((fds = select(fd+1, &rfds, NULL, NULL, &timeout)) < 1) |
875 | - return 0; |
876 | |
877 | /* |
878 | * Documentation on how this can fail is very scarce, so we'll |
879 | * just keep our fingers crossed, hoping it'll never fail. :( |
880 | */ |
881 | - vec = xs_read_watch(xh, &num); |
882 | + vec = xs_read_watch(xi->xi_handle, &num); |
883 | if (num != 2) { |
884 | free(vec); |
885 | return -1; |
886 | } |
887 | |
888 | AGENT_LOG("vec[XS_WATCH_PATH]: %s", vec[XS_WATCH_PATH]); |
889 | - if ((buf = xen_read_path(vec[XS_WATCH_PATH], &buflen)) == NULL) { |
890 | + if ((buf = xen_read_path(xi, vec[XS_WATCH_PATH], &buflen)) == NULL) { |
891 | free(vec); |
892 | return -1; |
893 | } |
894 | @@ -257,13 +271,13 @@ |
895 | */ |
896 | |
897 | free(buf); |
898 | - if (xen_convert_network_event(NETWORKRESET_EVENT, &buf, &buflen) < 0) { |
899 | + if (xen_convert_network_event(xi, NETWORKRESET_EVENT, &buf, &buflen) < 0) { |
900 | free(vec); |
901 | return -1; |
902 | } |
903 | } |
904 | |
905 | - xen_fire_callback(vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN], buf, buflen); |
906 | + xen_fire_callback(xi, vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN], buf, buflen); |
907 | |
908 | free(vec); |
909 | free(buf); |
910 | @@ -271,18 +285,19 @@ |
911 | return 0; |
912 | } |
913 | |
914 | -int xen_write_path(const char *path, void *buf, unsigned int buflen) { |
915 | +int xen_write_path(XenInfo *xi, const char *path, void *buf, unsigned int buflen) { |
916 | xs_transaction_t t; |
917 | int retval; |
918 | int max_tries = 5; |
919 | |
920 | do { |
921 | - if (!(t = xs_transaction_start(xh))) { |
922 | + if (!(t = xs_transaction_start(xi->xi_handle))) { |
923 | AGENT_LOG0("Failed to start transaction with Xen Store."); |
924 | return -1; |
925 | } |
926 | - retval = xs_write(xh, t, path, buf, buflen) ? -1 : 0; |
927 | - if (!xs_transaction_end(xh, t, 0)) { |
928 | + |
929 | + retval = xs_write(xi->xi_handle, t, path, buf, buflen) ? -1 : 0; |
930 | + if (!xs_transaction_end(xi->xi_handle, t, 0)) { |
931 | if (errno == EAGAIN && max_tries-- > 0) |
932 | continue; |
933 | else |
934 | @@ -293,39 +308,39 @@ |
935 | return retval; |
936 | } |
937 | |
938 | -void xen_fire_callback(const char *path, const char *token, void *buf, |
939 | - unsigned int buflen) { |
940 | +void xen_fire_callback(XenInfo *xi, const char *path, const char *token, |
941 | + void *buf, unsigned int buflen) { |
942 | SListElem *elem; |
943 | |
944 | - for (elem = slist_first(handlers); |
945 | + for (elem = slist_first(xi->xi_handlers); |
946 | elem != NULL; |
947 | - elem = slist_next(handlers, elem)) { |
948 | + elem = slist_next(xi->xi_handlers, elem)) { |
949 | token_callback_tuple *t = (token_callback_tuple *)slist_data(elem); |
950 | if (strcmp(token, t->token) == 0) { |
951 | - t->callback(path, buf, buflen, t->token); |
952 | + t->callback(xi, path, buf, buflen, t->token); |
953 | break; |
954 | } |
955 | } |
956 | } |
957 | |
958 | -void *xen_read_path(const char *path, unsigned int *buflen) { |
959 | +void *xen_read_path(XenInfo *xi, const char *path, unsigned int *buflen) { |
960 | void *buf; |
961 | xs_transaction_t t; |
962 | int max_tries = 5; |
963 | |
964 | do { |
965 | - t = xs_transaction_start(xh); |
966 | - if (!(buf = xs_read(xh, t, path, buflen))) { |
967 | + t = xs_transaction_start(xi->xi_handle); |
968 | + if (!(buf = xs_read(xi->xi_handle, t, path, buflen))) { |
969 | /* Documentation on failure modes is lacking, so we |
970 | * just end the transaction (ignoring failure) and |
971 | * bail out. */ |
972 | - xs_transaction_end(xh, t, 0); |
973 | + xs_transaction_end(xi->xi_handle, t, 0); |
974 | return NULL; |
975 | } |
976 | /* I have no clue what it means if ending the transaction |
977 | * fails, even though xs_read succeeded. The docs say |
978 | * we should try again, so let's just do that. */ |
979 | - if (!xs_transaction_end(xh, t, 0)) { |
980 | + if (!xs_transaction_end(xi->xi_handle, t, 0)) { |
981 | if (errno == EAGAIN && max_tries-- > 0) |
982 | continue; |
983 | else |
984 | @@ -337,25 +352,34 @@ |
985 | return buf; |
986 | } |
987 | |
988 | -char **xen_read_dir(const char *path, unsigned int *num_entries) |
989 | +int xen_fill_pollfd(XenInfo *xi, struct pollfd *pfd) |
990 | +{ |
991 | + pfd->fd = xi->xi_handle_fd; |
992 | + pfd->events = POLLIN; |
993 | + pfd->revents = 0; |
994 | + |
995 | + return 0; |
996 | +} |
997 | + |
998 | +char **xen_read_dir(XenInfo *xi, const char *path, unsigned int *num_entries) |
999 | { |
1000 | char **entries; |
1001 | xs_transaction_t t; |
1002 | int max_tries = 5; |
1003 | |
1004 | do { |
1005 | - t = xs_transaction_start(xh); |
1006 | - if (!(entries = xs_directory(xh, t, path, num_entries))) { |
1007 | + t = xs_transaction_start(xi->xi_handle); |
1008 | + if (!(entries = xs_directory(xi->xi_handle, t, path, num_entries))) { |
1009 | /* Documentation on failure modes is lacking, so we |
1010 | * just end the transaction (ignoring failure) and |
1011 | * bail out. */ |
1012 | - xs_transaction_end(xh, t, 0); |
1013 | + xs_transaction_end(xi->xi_handle, t, 0); |
1014 | return NULL; |
1015 | } |
1016 | /* I have no clue what it means if ending the transaction |
1017 | * fails, even though xs_read succeeded. The docs say |
1018 | * we should try again, so let's just do that. */ |
1019 | - if (!xs_transaction_end(xh, t, 0)) { |
1020 | + if (!xs_transaction_end(xi->xi_handle, t, 0)) { |
1021 | if (errno == EAGAIN && max_tries-- > 0) |
1022 | continue; |
1023 | else |
1024 | @@ -366,3 +390,8 @@ |
1025 | |
1026 | return entries; |
1027 | } |
1028 | + |
1029 | +AgentInfo *xen_to_agent_info(XenInfo *xi) |
1030 | +{ |
1031 | + return xi->xi_agent_info; |
1032 | +} |
1033 | |
1034 | === modified file 'src/xen.h' |
1035 | --- src/xen.h 2010-09-09 19:21:25 +0000 |
1036 | +++ src/xen.h 2010-09-16 20:31:06 +0000 |
1037 | @@ -13,17 +13,41 @@ |
1038 | * See the License for the specific language governing permissions and |
1039 | * limitations under the License. |
1040 | */ |
1041 | -#ifndef XEN_H |
1042 | -#define XEN_H |
1043 | +#ifndef __SRC_XEN_H__ |
1044 | +#define __SRC_XEN_H__ |
1045 | + |
1046 | +#include <poll.h> |
1047 | +#include "agent.h" |
1048 | |
1049 | #define XS_MSG_INCOMING_BASE_PATH "data/host" |
1050 | #define XS_MSG_OUTGOING_BASE_PATH "data/guest" |
1051 | |
1052 | -int xen_init(void); |
1053 | -void *xen_read_path(const char *path, unsigned int *buflen); |
1054 | -char **xen_read_dir(const char *path, unsigned int *buflen); |
1055 | -int xen_write_path(const char *path, void *buf, unsigned int buflen); |
1056 | -int xen_register_watch(const char *path, int (*callback)(const char *, const char *, const size_t, const char *), const char *data); |
1057 | -int xen_process_pending_events(void); |
1058 | - |
1059 | -#endif /* XEN_H */ |
1060 | +typedef struct _XenInfo XenInfo; |
1061 | +typedef int (*xen_cb)(XenInfo *, const char *, const char *, const size_t, const char *); |
1062 | + |
1063 | + |
1064 | +/* |
1065 | + * Initialise the connection to Xen Store |
1066 | + * |
1067 | + * @returns a new XenInfo *, or NULL if there was a failure |
1068 | + */ |
1069 | +XenInfo *xen_init(AgentInfo *ai); |
1070 | + |
1071 | +/* |
1072 | + * Initialise the connection to Xen Store |
1073 | + * |
1074 | + * @param xi A previously returned XenInfo * from xen_init() |
1075 | + */ |
1076 | +void xen_deinit(XenInfo *xi); |
1077 | + |
1078 | +void *xen_read_path(XenInfo *xi, const char *path, unsigned int *buflen); |
1079 | +char **xen_read_dir(XenInfo *xi, const char *path, unsigned int *buflen); |
1080 | +int xen_write_path(XenInfo *xi, const char *path, void *buf, unsigned int buflen); |
1081 | +int xen_register_watch(XenInfo *xi, const char *path, xen_cb callback, const char *data); |
1082 | +int xen_process_pending_events(XenInfo *xi); |
1083 | + |
1084 | +int xen_fill_pollfd(XenInfo *xi, struct pollfd *pfd); |
1085 | + |
1086 | +AgentInfo *xen_to_agent_info(XenInfo *xi); |
1087 | + |
1088 | +#endif /* __SRC_XEN_H__ */ |
1089 | |
1090 | === modified file 'tests/check_agent.c' |
1091 | --- tests/check_agent.c 2010-08-25 03:54:18 +0000 |
1092 | +++ tests/check_agent.c 2010-09-16 20:31:06 +0000 |
1093 | @@ -24,6 +24,8 @@ |
1094 | #include "../src/xen.h" |
1095 | #include "../src/spool.h" |
1096 | |
1097 | +extern XenInfo *agent_xen_info(AgentInfo *ai); |
1098 | + |
1099 | char spooldir[255]; |
1100 | char *msgfile; |
1101 | |
1102 | @@ -40,17 +42,19 @@ |
1103 | |
1104 | int spool_to_xen_cb_called = 0; |
1105 | |
1106 | -int spool_to_xen_cb(const char *path, const char *buf, const size_t buflen, const char *token) { |
1107 | +int spool_to_xen_cb(XenInfo *xi, const char *path, const char *buf, const size_t buflen, const char *token) { |
1108 | spool_to_xen_cb_called = 1; |
1109 | return 0; |
1110 | } |
1111 | |
1112 | +#if 0 |
1113 | START_TEST(test_xen_to_spool) |
1114 | { |
1115 | + AgentInfo *ai; |
1116 | char xs_in_msg_path[255], msg_file_path[255], *msgid = "testmsg", *outgoing_spool; |
1117 | struct stat sb; |
1118 | |
1119 | - fail_unless(agent_init("/bin/true") == 0, "agent_init() failed"); |
1120 | + fail_unless((ai = agent_init("/bin/true")) != NULL, "agent_init() failed"); |
1121 | |
1122 | snprintf(xs_in_msg_path, 255, XS_MSG_INCOMING_BASE_PATH "/%s", msgid); |
1123 | xen_write_path(xs_in_msg_path, "Foo", 3); |
1124 | @@ -58,47 +62,54 @@ |
1125 | outgoing_spool = spool_outgoing_dir(); |
1126 | snprintf(msg_file_path, 255, "%s/%s", outgoing_spool, msgid); |
1127 | |
1128 | - agent_loop(); |
1129 | + agent_loop(ai); |
1130 | |
1131 | fail_unless(stat(msg_file_path, &sb) == 0, "File did not get created."); |
1132 | + agent_deinit(ai); |
1133 | } |
1134 | END_TEST |
1135 | +#endif |
1136 | |
1137 | START_TEST(test_spool_to_xen) |
1138 | { |
1139 | + AgentInfo *ai; |
1140 | FILE *fp; |
1141 | char watch_path[255], *msgid; |
1142 | char *incoming_spool; |
1143 | |
1144 | - fail_unless(agent_init("/bin/true") == 0, "agent_init() failed"); |
1145 | + fail_unless((ai = agent_init("/bin/true")) != NULL, "agent_init() failed"); |
1146 | |
1147 | incoming_spool = spool_incoming_dir(); |
1148 | msgfile = tempnam(incoming_spool, NULL); |
1149 | msgid = strrchr(msgfile, '/'); |
1150 | |
1151 | snprintf(watch_path, 255, XS_MSG_OUTGOING_BASE_PATH "/%s", msgid); |
1152 | - xen_register_watch(watch_path, spool_to_xen_cb, "sometoken"); |
1153 | + xen_register_watch(agent_xen_info(ai), watch_path, spool_to_xen_cb, "sometoken"); |
1154 | |
1155 | fp = fopen(msgfile, "w"); |
1156 | fwrite("Hello", 1, 5, fp); |
1157 | fclose(fp); |
1158 | |
1159 | fail_unless(!spool_to_xen_cb_called, "Callback already fired?"); |
1160 | - agent_loop(); |
1161 | + agent_loop(ai); |
1162 | fail_unless(spool_to_xen_cb_called, "Callback didn't fire"); |
1163 | + agent_deinit(ai); |
1164 | } |
1165 | END_TEST |
1166 | |
1167 | START_TEST(test_agent_signals) |
1168 | { |
1169 | - fail_unless(agent_init("/bin/true") == 0, "agent_init() failed"); |
1170 | + AgentInfo *ai; |
1171 | + |
1172 | + fail_unless((ai = agent_init("/bin/true")) != NULL, "agent_init() failed"); |
1173 | |
1174 | fail_unless(kill(getpid(), SIGCHLD) == 0); |
1175 | fail_unless(kill(getpid(), SIGCHLD) == 0); |
1176 | fail_unless(kill(getpid(), SIGPIPE) == 0); |
1177 | fail_unless(kill(getpid(), SIGTERM) == 0); |
1178 | /* agent_loop() should return != 0 for receiving SIGTERM */ |
1179 | - fail_unless(agent_loop() != 0); |
1180 | + fail_unless(agent_loop(ai) != 0); |
1181 | + agent_deinit(ai); |
1182 | } |
1183 | END_TEST |
1184 | |
1185 | @@ -109,7 +120,9 @@ |
1186 | TCase *tc_agent = tcase_create("Agent"); |
1187 | tcase_add_checked_fixture(tc_agent, test_spool_to_xen_setup, test_spool_to_xen_teardown); |
1188 | tcase_add_test(tc_agent, test_spool_to_xen); |
1189 | +#if 0 |
1190 | tcase_add_test(tc_agent, test_xen_to_spool); |
1191 | +#endif |
1192 | tcase_add_test(tc_agent, test_agent_signals); |
1193 | suite_add_tcase(s, tc_agent); |
1194 | |
1195 | |
1196 | === modified file 'tests/check_slist.c' |
1197 | --- tests/check_slist.c 2010-08-25 06:22:40 +0000 |
1198 | +++ tests/check_slist.c 2010-09-16 20:31:06 +0000 |
1199 | @@ -78,6 +78,21 @@ |
1200 | |
1201 | fail_unless(slist_data(elem3) == testdata[2], "3rd element's data attribute not correctly set"); |
1202 | |
1203 | + slist_remove(list, elem); |
1204 | + |
1205 | + fail_unless(slist_first(list) == elem2, "1st element is not old 2nd element after removing first element"); |
1206 | + fail_unless(slist_last(list) == elem3, "Last element is not old 3rd element after removing first element"); |
1207 | + |
1208 | + slist_remove(list, elem3); |
1209 | + |
1210 | + fail_unless(slist_first(list) == elem2, "1st element is not old 2nd element after removing old 3rd element"); |
1211 | + fail_unless(slist_last(list) == elem2, "Last element is not old 2nd element after removing old 3rd element"); |
1212 | + |
1213 | + slist_remove(list, elem2); |
1214 | + |
1215 | + fail_unless(slist_first(list) == NULL, "1st element is not NULL after removing all elements"); |
1216 | + fail_unless(slist_last(list) == NULL, "Last element is not NULL after removing all elements"); |
1217 | + |
1218 | slist_deinit(list); |
1219 | } |
1220 | END_TEST |
1221 | @@ -85,18 +100,18 @@ |
1222 | int destroy_cb_iter; |
1223 | char *destroy_cb_testdata[] = { "foo", "bar", "baz" }; |
1224 | |
1225 | -void _slist_destroy_cb(void *arg) |
1226 | +void _slist_destroy_cb(SListElem *elem) |
1227 | { |
1228 | switch(++destroy_cb_iter) |
1229 | { |
1230 | case 1: |
1231 | - assert(arg == destroy_cb_testdata[0]); |
1232 | + assert(slist_data(elem) == destroy_cb_testdata[0]); |
1233 | break; |
1234 | case 2: |
1235 | - assert(arg == destroy_cb_testdata[1]); |
1236 | + assert(slist_data(elem) == destroy_cb_testdata[1]); |
1237 | break; |
1238 | case 3: |
1239 | - assert(arg == destroy_cb_testdata[2]); |
1240 | + assert(slist_data(elem) == destroy_cb_testdata[2]); |
1241 | break; |
1242 | case 4: |
1243 | break; |
1244 | |
1245 | === modified file 'tests/check_spool.c' |
1246 | --- tests/check_spool.c 2010-08-25 06:22:40 +0000 |
1247 | +++ tests/check_spool.c 2010-09-16 20:31:06 +0000 |
1248 | @@ -103,24 +103,25 @@ |
1249 | |
1250 | char spool_cb_called = 0; |
1251 | |
1252 | -void spool_cb(const char *path) { |
1253 | +void spool_cb(SpoolInfo *si, const char *path) { |
1254 | spool_cb_called = 1; |
1255 | - |
1256 | } |
1257 | |
1258 | START_TEST(test_spool_watch) { |
1259 | FILE *fp; |
1260 | + SpoolInfo *si; |
1261 | |
1262 | setenv("AGENT_MSG_SPOOL", testdir, 1); |
1263 | - fail_unless(spool_init() == 0, "Failed to init spool"); |
1264 | - fail_unless(spool_watch(spool_cb) == 0, "Failed to add watch."); |
1265 | - spool_process_pending_events(); |
1266 | + fail_unless((si = spool_init(NULL)) != NULL, "Failed to init spool"); |
1267 | + fail_unless(spool_watch(si, spool_cb) == 0, "Failed to add watch."); |
1268 | + spool_process_pending_events(si); |
1269 | fail_unless(spool_cb_called == 0, "Spool callback got called even though nothing had happened yet."); |
1270 | fp = fopen(util_join_paths(spool_incoming_dir(), "testfile"), "a+"); |
1271 | fwrite("testing", 1, 8, fp); |
1272 | fclose(fp); |
1273 | - spool_process_pending_events(); |
1274 | + spool_process_pending_events(si); |
1275 | fail_unless(spool_cb_called == 1, "Spool callback didn't get called at all."); |
1276 | + spool_deinit(si); |
1277 | } |
1278 | END_TEST |
1279 | |
1280 | |
1281 | === modified file 'tests/check_xen.c' |
1282 | --- tests/check_xen.c 2010-07-07 09:26:52 +0000 |
1283 | +++ tests/check_xen.c 2010-09-16 20:31:06 +0000 |
1284 | @@ -29,25 +29,26 @@ |
1285 | |
1286 | START_TEST(test_xen_init_success) |
1287 | { |
1288 | - fail_if(xen_init(), "xen_init failed!"); |
1289 | + fail_unless(xen_init(NULL) != NULL, "xen_init failed!"); |
1290 | } |
1291 | END_TEST |
1292 | |
1293 | START_TEST(test_xen_init_failure) |
1294 | { |
1295 | - xs_daemon_open_should_fail = 1; |
1296 | - fail_unless(xen_init(), "xen_init succeeded, but should've failed!"); |
1297 | + xs_daemon_open_should_fail = 1; |
1298 | + fail_unless(xen_init(NULL) == NULL, "xen_init succeeded, but should've failed!"); |
1299 | } |
1300 | END_TEST |
1301 | |
1302 | START_TEST(test_xen_write_and_read_path) |
1303 | { |
1304 | - unsigned int buflen; |
1305 | - void *buf; |
1306 | + XenInfo *xi; |
1307 | + unsigned int buflen; |
1308 | + void *buf; |
1309 | |
1310 | - xen_init(); |
1311 | - xen_write_path(test_read_path, test_data, sizeof(test_data)); |
1312 | - buf = xen_read_path(test_read_path, &buflen); |
1313 | + fail_unless((xi = xen_init(NULL)) != NULL, "xen_init failed!"); |
1314 | + xen_write_path(xi, test_read_path, test_data, sizeof(test_data)); |
1315 | + buf = xen_read_path(xi, test_read_path, &buflen); |
1316 | fail_unless(buflen == sizeof(test_data), |
1317 | "xen_read_path altered the length of the data buffer"); |
1318 | fail_unless(memcmp(buf, test_data, buflen) == 0, |
1319 | @@ -60,7 +61,7 @@ |
1320 | */ |
1321 | static int testcb_called = 0; |
1322 | |
1323 | -static int testcb(const char *path, const char *buf, size_t buflen, const char *data) { |
1324 | +static int testcb(XenInfo *xi, const char *path, const char *buf, size_t buflen, const char *data) { |
1325 | fail_unless(strcmp(path, |
1326 | "/somepath/something") == 0, |
1327 | "Data was at /somepath/something, but that's not what " |
1328 | @@ -78,10 +79,12 @@ |
1329 | |
1330 | START_TEST(test_xen_fire_callback) |
1331 | { |
1332 | - xen_init(); |
1333 | - xen_register_watch(test_watch_path, testcb, test_token); |
1334 | - xen_write_path(test_read_path, test_data, sizeof(test_data)); |
1335 | - xen_process_pending_events(); |
1336 | + XenInfo *xi; |
1337 | + |
1338 | + fail_unless((xi = xen_init(NULL)) != NULL, "xen_init failed!"); |
1339 | + xen_register_watch(xi, test_watch_path, testcb, test_token); |
1340 | + xen_write_path(xi, test_read_path, test_data, sizeof(test_data)); |
1341 | + xen_process_pending_events(xi); |
1342 | fail_unless(testcb_called, "Callback didn't fire at all."); |
1343 | } |
1344 | END_TEST |
1345 | |
1346 | === modified file 'tests/mock_xenstore.c' |
1347 | --- tests/mock_xenstore.c 2010-08-25 15:43:13 +0000 |
1348 | +++ tests/mock_xenstore.c 2010-09-16 20:31:06 +0000 |
1349 | @@ -67,6 +67,13 @@ |
1350 | return xs_daemon_open(); |
1351 | } |
1352 | |
1353 | +void xs_daemon_close(struct xs_handle *xh) |
1354 | +{ |
1355 | + close(xh->clientfd); |
1356 | + close(xh->libraryfd); |
1357 | + free(xh); |
1358 | +} |
1359 | + |
1360 | struct xs_handle *xs_daemon_open(void) { |
1361 | int fds[2]; |
1362 |