use long long int instead of just long long
[rrdtool.git] / src / rrd_daemon.c
index d4cfa94..ef6d83c 100644 (file)
 #include <glib-2.0/glib.h>
 /* }}} */
 
-#define RRDD_LOG(severity, ...) syslog ((severity), __VA_ARGS__)
+#define RRDD_LOG(severity, ...) \
+  do { \
+    if (stay_foreground) \
+      fprintf(stderr, __VA_ARGS__); \
+    syslog ((severity), __VA_ARGS__); \
+  } while (0)
 
 #ifndef __GNUC__
 # define __attribute__(x) /**/
@@ -141,6 +146,9 @@ struct listen_socket_s
   ssize_t wbuf_len;
 
   uint32_t permissions;
+
+  gid_t  socket_group;
+  mode_t socket_permissions;
 };
 typedef struct listen_socket_s listen_socket_t;
 
@@ -175,7 +183,8 @@ struct cache_item_s
 {
   char *file;
   char **values;
-  size_t values_num;
+  size_t values_num;           /* number of valid pointers */
+  size_t values_alloc;         /* number of allocated pointers */
   time_t last_flush_time;
   time_t last_update_stamp;
 #define CI_FLAGS_IN_TREE  (1<<0)
@@ -221,9 +230,6 @@ static uid_t daemon_uid;
 static listen_socket_t *listen_fds = NULL;
 static size_t listen_fds_num = 0;
 
-static gboolean set_socket_group = FALSE;
-static gid_t socket_group;
-
 enum {
   RUNNING,             /* normal operation */
   FLUSHING,            /* flushing remaining values */
@@ -255,6 +261,7 @@ static char *config_pid_file = NULL;
 static char *config_base_dir = NULL;
 static size_t _config_base_dir_len = 0;
 static int config_write_base_only = 0;
+static size_t config_alloc_chunk = 1;
 
 static listen_socket_t **config_listen_address_list = NULL;
 static size_t config_listen_address_list_len = 0;
@@ -642,6 +649,7 @@ static void wipe_ci_values(cache_item_t *ci, time_t when)
 {
   ci->values = NULL;
   ci->values_num = 0;
+  ci->values_alloc = 0;
 
   ci->last_flush_time = when;
   if (config_write_jitter > 0)
@@ -821,9 +829,10 @@ static int flush_old_values (int max_age)
 
   for (k = 0; k < cfd.keys_num; k++)
   {
+    gboolean status = g_tree_remove(cache_tree, cfd.keys[k]);
     /* should never fail, since we have held the cache_lock
      * the entire time */
-    assert( g_tree_remove(cache_tree, cfd.keys[k]) == TRUE );
+    assert(status == TRUE);
   }
 
   if (cfd.keys != NULL)
@@ -1438,7 +1447,8 @@ static int handle_request_update (HANDLER_PROTO) /* {{{ */
     else
       ci->last_update_stamp = stamp;
 
-    if (!rrd_add_strdup(&ci->values, &ci->values_num, value))
+    if (!rrd_add_strdup_chunk(&ci->values, &ci->values_num, value,
+                              &ci->values_alloc, config_alloc_chunk))
     {
       RRDD_LOG (LOG_ERR, "handle_request_update: rrd_add_strdup failed.");
       continue;
@@ -2331,15 +2341,22 @@ static int open_listen_socket_unix (const listen_socket_t *sock) /* {{{ */
   }
 
   /* tweak the sockets group ownership */
-  if (set_socket_group)
+  if (sock->socket_group != (gid_t)-1)
   {
-    if ( (chown(path, getuid(), socket_group) != 0) ||
+    if ( (chown(path, getuid(), sock->socket_group) != 0) ||
         (chmod(path, (S_IRUSR|S_IWUSR|S_IXUSR | S_IRGRP|S_IWGRP)) != 0) )
     {
       fprintf(stderr, "rrdcached: failed to set socket group permissions (%s)\n", strerror(errno));
     }
   }
 
+  if (sock->socket_permissions != (mode_t)-1)
+  {
+    if (chmod(path, sock->socket_permissions) != 0)
+      fprintf(stderr, "rrdcached: failed to set socket file permissions (%o): %s\n",
+          (unsigned int)sock->socket_permissions, strerror(errno));
+  }
+
   status = listen (fd, /* backlog = */ 10);
   if (status != 0)
   {
@@ -2760,7 +2777,10 @@ static int read_options (int argc, char **argv) /* {{{ */
   char **permissions = NULL;
   size_t permissions_len = 0;
 
-  while ((option = getopt(argc, argv, "gl:s:P:f:w:z:t:Bb:p:Fj:h?")) != -1)
+  gid_t  socket_group = (gid_t)-1;
+  mode_t socket_permissions = (mode_t)-1;
+
+  while ((option = getopt(argc, argv, "gl:s:m:P:f:w:z:t:Bb:p:Fj:a:h?")) != -1)
   {
     switch (option)
     {
@@ -2816,6 +2836,9 @@ static int read_options (int argc, char **argv) /* {{{ */
         }
         /* }}} Done adding permissions. */
 
+        new->socket_group = socket_group;
+        new->socket_permissions = socket_permissions;
+
         if (!rrd_add_ptr((void ***)&config_listen_address_list,
                          &config_listen_address_list_len, new))
         {
@@ -2845,7 +2868,6 @@ static int read_options (int argc, char **argv) /* {{{ */
        if (grp)
        {
          socket_group = grp->gr_gid;
-         set_socket_group = TRUE;
        }
        else
        {
@@ -2856,6 +2878,24 @@ static int read_options (int argc, char **argv) /* {{{ */
       }
       break;
 
+      /* set socket file permissions */
+      case 'm':
+      {
+        long  tmp;
+        char *endptr = NULL;
+
+        tmp = strtol (optarg, &endptr, 8);
+        if ((endptr == optarg) || (! endptr) || (*endptr != '\0')
+            || (tmp > 07777) || (tmp < 0)) {
+          fprintf (stderr, "read_options: Invalid file mode \"%s\".\n",
+              optarg);
+          return (5);
+        }
+
+        socket_permissions = (mode_t)tmp;
+      }
+      break;
+
       case 'P':
       {
         char *optcopy;
@@ -3048,6 +3088,19 @@ static int read_options (int argc, char **argv) /* {{{ */
       }
       break;
 
+      case 'a':
+      {
+        int temp = atoi(optarg);
+        if (temp > 0)
+          config_alloc_chunk = temp;
+        else
+        {
+          fprintf(stderr, "Invalid allocation size: %s\n", optarg);
+          return 10;
+        }
+      }
+      break;
+
       case 'h':
       case '?':
         printf ("RRDCacheD %s\n"
@@ -3069,13 +3122,21 @@ static int read_options (int argc, char **argv) /* {{{ */
             "  -g            Do not fork and run in the foreground.\n"
             "  -j <dir>      Directory in which to create the journal files.\n"
             "  -F            Always flush all updates at shutdown\n"
-            "  -s <id|name>  Make socket g+rw to named group\n"
+            "  -s <id|name>  Group owner of all following UNIX sockets\n"
+            "                (the socket will also have read/write permissions "
+                            "for that group)\n"
+            "  -m <mode>     File permissions (octal) of all following UNIX "
+                            "sockets\n"
+            "  -a <size>     Memory allocation chunk size. Default is 1."
             "\n"
             "For more information and a detailed description of all options "
             "please refer\n"
             "to the rrdcached(1) manual page.\n",
             VERSION);
-        status = -1;
+        if (option == 'h')
+          status = -1;
+        else
+          status = 1;
         break;
     } /* switch (option) */
   } /* while (getopt) */