X-Git-Url: http://git.annexia.org/?a=blobdiff_plain;f=hostinfod%2Fmain.c;h=b27338eee7bed679c887c4c1a974baf4cd0adea4;hb=e43e15284e3c91f9cdc2ba1e48b81f2c5ebe36fc;hp=fa835bb363f58ef4749e35f7c720a2728f08e2e9;hpb=19feefcaa1b219675e09c7d52169f7b0815aa123;p=virt-hostinfo.git diff --git a/hostinfod/main.c b/hostinfod/main.c index fa835bb..b27338e 100644 --- a/hostinfod/main.c +++ b/hostinfod/main.c @@ -51,11 +51,15 @@ static void do_reread_socket_dir (void); static struct guest_description *guest_added (const char *sock_path, const char *name); static void guest_removed (struct guest_description *); static void guest_event (const apr_pollfd_t *, void *); +static void modify_pollfd_reqevents (struct guest_description *, apr_int16_t); const char *conf_file = DEFAULT_CONF_FILE; char *socket_dir = NULL; char *guests_file = NULL; +char *libvirt_uri = NULL; +int libvirt_uri_set_on_cmdline = 0; + int verbose = 0; int verbose_set_on_cmdline = 0; int foreground = 0; @@ -90,17 +94,28 @@ usage (void) " --help Display full usage\n" " -c file | --config file\n" " Configuration file (default: %s)\n" + " -C uri | --connect uri\n" + " Set libvirt connection URI (default: NULL)\n" " -f | --foreground\n" " Run in the foreground (don't fork)\n" " -v Enable verbose messages (sent to syslog)\n", DEFAULT_CONF_FILE); } +void +initialize (void) +{ + apr_initialize (); + apr_pool_create (&pool, NULL); + init_syslog (); +} + int main (int argc, char *argv[]) { static const apr_getopt_option_t options[] = { { "config", 'c', TRUE, "configuration file" }, + { "connect", 'C', TRUE, "libvirt connection URI" }, { "foreground", 'f', FALSE, "run in foreground (don't fork)" }, { "verbose", 'v', FALSE, "enable verbose messages" }, { "help", '?', FALSE, "display help" }, @@ -111,13 +126,16 @@ main (int argc, char *argv[]) int c; const char *optarg; - apr_initialize (); - apr_pool_create (&pool, NULL); + /* REGISTER_COMMAND macro should have caused this to be + * initialized. If it's not, then something is badly wrong ... + */ + if (!pool) { + error ("internal error: daemon not initialized - no commands registered"); + exit (1); + } apr_getopt_init (&opt, pool, argc, argv); - init_syslog (); - socket_dir = apr_pstrdup (pool, DEFAULT_SOCKET_DIR); guests_file = apr_pstrdup (pool, DEFAULT_GUESTS_FILE); @@ -134,6 +152,10 @@ main (int argc, char *argv[]) exit (1); } break; + case 'C': + libvirt_uri = optarg; + libvirt_uri_set_on_cmdline = 1; + break; case 'f': foreground = 1; foreground_set_on_cmdline = 1; @@ -157,6 +179,9 @@ main (int argc, char *argv[]) /* Read the config file. */ read_main_conf_file (); + /* Connect to libvirt. */ + init_libvirt (); + /* Monitor the socket directory. */ monitor_socket_dir (); @@ -169,7 +194,7 @@ main (int argc, char *argv[]) paprerror (r, "apr_pollset_create"); exit (1); } - apr_socket_t *tsock; + apr_socket_t *tsock = NULL; r = apr_os_sock_put (&tsock, &sockets_inotify_fd, pool); if (r != APR_SUCCESS) { paprerror (r, "apr_os_sock_put"); @@ -229,6 +254,8 @@ main_loop (void) } /* Poll. */ + numdescs = 0; + descs = NULL; r = apr_pollset_poll (set, -1, &numdescs, &descs); if (r != APR_SUCCESS) { paprerror (r, "apr_pollset_poll"); @@ -340,7 +367,12 @@ do_reread_socket_dir (void) * been updated. */ for (hi = apr_hash_first (pool, guests); hi; hi = apr_hash_next (hi)) { - apr_hash_this(hi, NULL, NULL, (void **) &hval); + /* On RHEL 5 this gives: + * dereferencing type-punned pointer will break strict-aliasing rules + * XXX + */ + apr_hash_this (hi, NULL, NULL, (void **) &hval); + if (hval->counter != count) { /* This hash table implementation allows you to delete the * current entry safely. @@ -370,7 +402,7 @@ guest_added (const char *sock_path, const char *name) int r; unsigned retries = 0, tns; enum guest_state state; - apr_pool_t *guest_pool; + apr_pool_t *guest_pool = NULL; struct sockaddr_un addr; struct timespec ts; @@ -443,6 +475,7 @@ guest_added (const char *sock_path, const char *name) hval->sock = sock; hval->request_max = 4096; hval->request = apr_palloc (hval->pool, hval->request_max); + hval->lasttime = apr_hash_make (hval->pool); /* Convert Unix fd into APR socket type. */ r = apr_os_sock_put (&hval->aprsock, &sock, hval->pool); @@ -491,7 +524,7 @@ guest_removed (struct guest_description *hval) /* Unregister the socket from the pollset. */ r = apr_pollset_remove (set, &hval->pollfd); if (r != APR_SUCCESS) - paprerror (r, "apr_pollset_remove for %s", hval->name); + paprerror (r, "%s: apr_pollset_remove", hval->name); if (close (hval->sock) == -1) pwarningf ("close: %s", hval->sock_path); @@ -516,7 +549,7 @@ guest_force_close (struct guest_description *hval) } /* Difference between two timespec structures (r = a - b) */ -static struct timespec * +struct timespec * diff_timespec (struct timespec *r, const struct timespec *a, const struct timespec *b) { @@ -692,16 +725,40 @@ guest_event (const apr_pollfd_t *pollfd, void *hvalv) */ switch (hval->state) { case guest_state_connecting: - hval->pollfd.reqevents = APR_POLLOUT; + modify_pollfd_reqevents (hval, APR_POLLOUT); break; case guest_state_request: - hval->pollfd.reqevents = APR_POLLIN; + modify_pollfd_reqevents (hval, APR_POLLIN); break; case guest_state_reply: - hval->pollfd.reqevents = APR_POLLOUT; + modify_pollfd_reqevents (hval, APR_POLLOUT); break; case guest_state_dead: - hval->pollfd.reqevents = 0; + modify_pollfd_reqevents (hval, 0); break; } } + +/* It turns out you can't just update the pollfd->reqevents + * field. Instead you have to remove the pollfd and reregister + * it in the pollset. + */ +static void +modify_pollfd_reqevents (struct guest_description *hval, + apr_int16_t new_reqevents) +{ + apr_status_t r; + + if (hval->pollfd.reqevents != new_reqevents) { + r = apr_pollset_remove (set, &hval->pollfd); + if (r != APR_SUCCESS) { + paprerror (r, "%s: apr_pollset_remove", hval->name); + return; + } + + hval->pollfd.reqevents = new_reqevents; + r = apr_pollset_add (set, &hval->pollfd); + if (r != APR_SUCCESS) + paprerror (r, "%s: apr_pollset_add", hval->name); + } +}