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;
" --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" },
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);
exit (1);
}
break;
+ case 'C':
+ libvirt_uri = optarg;
+ libvirt_uri_set_on_cmdline = 1;
+ break;
case 'f':
foreground = 1;
foreground_set_on_cmdline = 1;
/* Read the config file. */
read_main_conf_file ();
+ /* Connect to libvirt. */
+ init_libvirt ();
+
/* Monitor the socket directory. */
monitor_socket_dir ();
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");
}
/* Poll. */
+ numdescs = 0;
+ descs = NULL;
r = apr_pollset_poll (set, -1, &numdescs, &descs);
if (r != APR_SUCCESS) {
paprerror (r, "apr_pollset_poll");
* 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.
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;
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);
/* 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);
}
/* 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)
{
*/
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);
+ }
+}