rrdcached: pull in rrd_config.h so we can use its defines
[rrdtool.git] / src / rrd_daemon.c
index 40785b0..c6211a6 100644 (file)
 /*
  * Now for some includes..
  */
-#include "rrd.h" /* {{{ */
+/* {{{ */
+#if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__CYGWIN32__) && !defined(HAVE_CONFIG_H)
+#include "../win32/config.h"
+#else
+#ifdef HAVE_CONFIG_H
+#include "../rrd_config.h"
+#endif
+#endif
+
+#include "rrd.h"
 #include "rrd_client.h"
 
 #include <stdlib.h>
@@ -564,6 +573,7 @@ static void wipe_ci_values(cache_item_t *ci, time_t when)
 static void remove_from_queue(cache_item_t *ci) /* {{{ */
 {
   if (ci == NULL) return;
+  if ((ci->flags & CI_FLAGS_IN_QUEUE) == 0) return; /* not queued */
 
   if (ci->prev == NULL)
     cache_queue_head = ci->next; /* reset head */
@@ -625,9 +635,8 @@ static int enqueue_cache_item (cache_item_t *ci, /* {{{ */
     if (cache_queue_head == ci)
       return 0;
 
-    /* remove from the double linked list */
-    if (ci->flags & CI_FLAGS_IN_QUEUE)
-      remove_from_queue(ci);
+    /* remove if further down in queue */
+    remove_from_queue(ci);
 
     ci->prev = NULL;
     ci->next = cache_queue_head;
@@ -681,20 +690,20 @@ static gboolean tree_callback_flush (gpointer key, gpointer value, /* {{{ */
   ci = (cache_item_t *) value;
   cfd = (callback_flush_data_t *) data;
 
+  if (ci->flags & CI_FLAGS_IN_QUEUE)
+    return FALSE;
+
   if ((ci->last_flush_time <= cfd->abs_timeout)
-      && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)
       && (ci->values_num > 0))
   {
     enqueue_cache_item (ci, TAIL);
   }
   else if ((do_shutdown != 0)
-      && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)
       && (ci->values_num > 0))
   {
     enqueue_cache_item (ci, TAIL);
   }
   else if (((cfd->now - ci->last_flush_time) >= config_flush_interval)
-      && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)
       && (ci->values_num <= 0))
   {
     char **temp;
@@ -1450,6 +1459,7 @@ static int handle_request_update (listen_socket_t *sock, /* {{{ */
 
     wipe_ci_values(ci, now);
     ci->flags = CI_FLAGS_IN_TREE;
+    pthread_cond_init(&ci->flushed, NULL);
 
     pthread_mutex_lock(&cache_lock);
     g_tree_insert (cache_tree, (void *) ci->file, (void *) ci);
@@ -2031,7 +2041,7 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */
       sizeof (listen_fds[0]) * (listen_fds_num + 1));
   if (temp == NULL)
   {
-    RRDD_LOG (LOG_ERR, "open_listen_socket_unix: realloc failed.");
+    fprintf (stderr, "rrdcached: open_listen_socket_unix: realloc failed.\n");
     return (-1);
   }
   listen_fds = temp;
@@ -2040,7 +2050,8 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */
   fd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0);
   if (fd < 0)
   {
-    RRDD_LOG (LOG_ERR, "open_listen_socket_unix: socket(2) failed.");
+    fprintf (stderr, "rrdcached: unix socket(2) failed: %s\n",
+             rrd_strerror(errno));
     return (-1);
   }
 
@@ -2048,19 +2059,26 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */
   sa.sun_family = AF_UNIX;
   strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
 
+  /* if we've gotten this far, we own the pid file.  any daemon started
+   * with the same args must not be alive.  therefore, ensure that we can
+   * create the socket...
+   */
+  unlink(path);
+
   status = bind (fd, (struct sockaddr *) &sa, sizeof (sa));
   if (status != 0)
   {
-    RRDD_LOG (LOG_ERR, "open_listen_socket_unix: bind(2) failed.");
+    fprintf (stderr, "rrdcached: bind(%s) failed: %s.\n",
+             path, rrd_strerror(errno));
     close (fd);
-    unlink (path);
     return (-1);
   }
 
   status = listen (fd, /* backlog = */ 10);
   if (status != 0)
   {
-    RRDD_LOG (LOG_ERR, "open_listen_socket_unix: listen(2) failed.");
+    fprintf (stderr, "rrdcached: listen(%s) failed: %s.\n",
+             path, rrd_strerror(errno));
     close (fd);
     unlink (path);
     return (-1);
@@ -2106,8 +2124,7 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
     port = strchr (addr, ']');
     if (port == NULL)
     {
-      RRDD_LOG (LOG_ERR, "open_listen_socket_network: Malformed address: %s",
-          sock->addr);
+      fprintf (stderr, "rrdcached: Malformed address: %s\n", sock->addr);
       return (-1);
     }
     *port = 0;
@@ -2119,8 +2136,7 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
       port = NULL;
     else
     {
-      RRDD_LOG (LOG_ERR, "open_listen_socket_network: Garbage after address: %s",
-          port);
+      fprintf (stderr, "rrdcached: Garbage after address: %s\n", port);
       return (-1);
     }
   } /* if (*addr = ']') */
@@ -2139,8 +2155,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
                         &ai_hints, &ai_res);
   if (status != 0)
   {
-    RRDD_LOG (LOG_ERR, "open_listen_socket_network: getaddrinfo(%s) failed: "
-        "%s", addr, gai_strerror (status));
+    fprintf (stderr, "rrdcached: getaddrinfo(%s) failed: %s\n",
+             addr, gai_strerror (status));
     return (-1);
   }
 
@@ -2154,7 +2170,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
         sizeof (listen_fds[0]) * (listen_fds_num + 1));
     if (temp == NULL)
     {
-      RRDD_LOG (LOG_ERR, "open_listen_socket_network: realloc failed.");
+      fprintf (stderr,
+               "rrdcached: open_listen_socket_network: realloc failed.\n");
       continue;
     }
     listen_fds = temp;
@@ -2163,7 +2180,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
     fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
     if (fd < 0)
     {
-      RRDD_LOG (LOG_ERR, "open_listen_socket_network: socket(2) failed.");
+      fprintf (stderr, "rrdcached: network socket(2) failed: %s.\n",
+               rrd_strerror(errno));
       continue;
     }
 
@@ -2172,7 +2190,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
     status = bind (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
     if (status != 0)
     {
-      RRDD_LOG (LOG_ERR, "open_listen_socket_network: bind(2) failed.");
+      fprintf (stderr, "rrdcached: bind(%s) failed: %s.\n",
+               sock->addr, rrd_strerror(errno));
       close (fd);
       continue;
     }
@@ -2180,7 +2199,8 @@ static int open_listen_socket_network(const listen_socket_t *sock) /* {{{ */
     status = listen (fd, /* backlog = */ 10);
     if (status != 0)
     {
-      RRDD_LOG (LOG_ERR, "open_listen_socket_network: listen(2) failed.");
+      fprintf (stderr, "rrdcached: listen(%s) failed: %s\n.",
+               sock->addr, rrd_strerror(errno));
       close (fd);
       return (-1);
     }
@@ -2231,21 +2251,9 @@ static void *listen_thread_main (void *args __attribute__((unused))) /* {{{ */
   int status;
   int i;
 
-  for (i = 0; i < config_listen_address_list_len; i++)
-    open_listen_socket (config_listen_address_list[i]);
-
-  if (config_listen_address_list_len < 1)
-  {
-    listen_socket_t sock;
-    memset(&sock, 0, sizeof(sock));
-    strncpy(sock.addr, RRDCACHED_DEFAULT_ADDRESS, sizeof(sock.addr));
-    open_listen_socket (&sock);
-  }
-
   if (listen_fds_num < 1)
   {
-    RRDD_LOG (LOG_ERR, "listen_thread_main: No listen sockets "
-        "could be opened. Sorry.");
+    RRDD_LOG(LOG_ERR, "listen_thread_main: no listen_fds !");
     return (NULL);
   }
 
@@ -2358,7 +2366,6 @@ static void *listen_thread_main (void *args __attribute__((unused))) /* {{{ */
 
 static int daemonize (void) /* {{{ */
 {
-  int status;
   int pid_fd;
   char *base_dir;
 
@@ -2370,6 +2377,26 @@ static int daemonize (void) /* {{{ */
   if (pid_fd < 0)
     return pid_fd;
 
+  /* open all the listen sockets */
+  if (config_listen_address_list_len > 0)
+  {
+    for (int i = 0; i < config_listen_address_list_len; i++)
+      open_listen_socket (config_listen_address_list[i]);
+  }
+  else
+  {
+    listen_socket_t sock;
+    memset(&sock, 0, sizeof(sock));
+    strncpy(sock.addr, RRDCACHED_DEFAULT_ADDRESS, sizeof(sock.addr));
+    open_listen_socket (&sock);
+  }
+
+  if (listen_fds_num < 1)
+  {
+    fprintf (stderr, "rrdcached: FATAL: cannot open any listen sockets\n");
+    goto error;
+  }
+
   if (!stay_foreground)
   {
     pid_t child;
@@ -2378,12 +2405,10 @@ static int daemonize (void) /* {{{ */
     if (child < 0)
     {
       fprintf (stderr, "daemonize: fork(2) failed.\n");
-      return (-1);
+      goto error;
     }
     else if (child > 0)
-    {
-      return (1);
-    }
+      exit(0);
 
     /* Become session leader */
     setsid ();
@@ -2402,11 +2427,11 @@ static int daemonize (void) /* {{{ */
   base_dir = (config_base_dir != NULL)
     ? config_base_dir
     : "/tmp";
-  status = chdir (base_dir);
-  if (status != 0)
+
+  if (chdir (base_dir) != 0)
   {
     fprintf (stderr, "daemonize: chdir (%s) failed.\n", base_dir);
-    return (-1);
+    goto error;
   }
 
   install_signal_handlers();
@@ -2418,11 +2443,14 @@ static int daemonize (void) /* {{{ */
   if (cache_tree == NULL)
   {
     RRDD_LOG (LOG_ERR, "daemonize: g_tree_new failed.");
-    return (-1);
+    goto error;
   }
 
-  status = write_pidfile (pid_fd);
-  return status;
+  return write_pidfile (pid_fd);
+
+error:
+  remove_pidfile();
+  return -1;
 } /* }}} int daemonize */
 
 static int cleanup (void) /* {{{ */
@@ -2697,19 +2725,9 @@ int main (int argc, char **argv)
   }
 
   status = daemonize ();
-  if (status == 1)
-  {
-    struct sigaction sigchld;
-
-    memset (&sigchld, 0, sizeof (sigchld));
-    sigchld.sa_handler = SIG_IGN;
-    sigaction (SIGCHLD, &sigchld, NULL);
-
-    return (0);
-  }
-  else if (status != 0)
+  if (status != 0)
   {
-    fprintf (stderr, "daemonize failed, exiting.\n");
+    fprintf (stderr, "rrdcached: daemonize failed, exiting.\n");
     return (1);
   }