X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Frrdd.c;h=a9a1e0593e360d3d582ffebe56a174ac2e359804;hb=70a037337b955840904a4d78ed45a67ce24aa8ac;hp=8aa5a585165fc590ebe56bd1ebe9d2088e9a7063;hpb=f12d8ef6cc3a2094d4532a183305eef10f2c1d86;p=rrdd.git diff --git a/src/rrdd.c b/src/rrdd.c index 8aa5a58..a9a1e05 100644 --- a/src/rrdd.c +++ b/src/rrdd.c @@ -29,6 +29,8 @@ # define RRDD_LOG(severity, ...) syslog ((severity), __VA_ARGS__) #endif +#define DEFAULT_PORT "42217" + /* * Types */ @@ -75,6 +77,12 @@ static cache_item_t *cache_queue_tail = NULL; static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t cache_cond = PTHREAD_COND_INITIALIZER; +static int config_write_interval = 300; +static int config_flush_interval = 3600; + +static char **config_listen_address_list = NULL; +static int config_listen_address_list_len = 0; + /* * Functions */ @@ -160,7 +168,7 @@ static void *queue_thread_main (void *args) /* {{{ */ RRDD_LOG (LOG_DEBUG, "queue_thread_main: rrd_update (%s, %i, %p)", file, values_num, (void *) values); - status = rrd_update_r (file, NULL, values_num, values); + status = rrd_update_r (file, NULL, values_num, (void *) values); if (status != 0) { RRDD_LOG (LOG_ERR, "queue_thread_main: " @@ -188,6 +196,7 @@ static int handle_request_update (int fd, /* {{{ */ char *value; char *buffer_ptr; int values_num = 0; + int status; time_t now; @@ -282,8 +291,7 @@ static int handle_request_update (int fd, /* {{{ */ values_num++; } - /* FIXME: Timeout should not be hard-coded. */ - if (((now - ci->last_flush_time) > 300) + if (((now - ci->last_flush_time) >= config_write_interval) && ((ci->flags & CI_FLAGS_IN_QUEUE) == 0)) { RRDD_LOG (LOG_DEBUG, "handle_request_update: Adding %s to the update queue.", @@ -305,7 +313,13 @@ static int handle_request_update (int fd, /* {{{ */ snprintf (answer, sizeof (answer), "0 Enqueued %i value(s)\n", values_num); answer[sizeof (answer) - 1] = 0; - write (fd, answer, sizeof (answer)); + status = write (fd, answer, sizeof (answer)); + if (status < 0) + { + status = errno; + RRDD_LOG (LOG_INFO, "handle_request_update: write(2) returned an error."); + return (status); + } return (0); } /* }}} int handle_request_update */ @@ -399,13 +413,16 @@ static void *connection_thread_main (void *args) /* {{{ */ if ((pollfd.revents & POLLHUP) != 0) /* normal shutdown */ { + RRDD_LOG (LOG_DEBUG, "connection_thread_main: " + "poll(2) returned POLLHUP."); close (fd); break; } else if ((pollfd.revents & (POLLIN | POLLPRI)) == 0) { - RRDD_LOG (LOG_WARNING, "connection_thread_main: poll(2) returned " - "something unexpected."); + RRDD_LOG (LOG_WARNING, "connection_thread_main: " + "poll(2) returned something unexpected: %#04hx", + pollfd.revents); close (fd); break; } @@ -442,7 +459,7 @@ static void *connection_thread_main (void *args) /* {{{ */ return (NULL); } /* }}} void *connection_thread_main */ -static int open_listen_socket (const char *path) /* {{{ */ +static int open_listen_socket_unix (const char *path) /* {{{ */ { int fd; struct sockaddr_un sa; @@ -453,7 +470,7 @@ static int open_listen_socket (const char *path) /* {{{ */ sizeof (listen_fds[0]) * (listen_fds_num + 1)); if (temp == NULL) { - RRDD_LOG (LOG_ERR, "open_listen_socket: realloc failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: realloc failed."); return (-1); } listen_fds = temp; @@ -462,7 +479,7 @@ static int open_listen_socket (const char *path) /* {{{ */ fd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0); if (fd < 0) { - RRDD_LOG (LOG_ERR, "open_listen_socket: socket(2) failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: socket(2) failed."); return (-1); } @@ -473,7 +490,7 @@ static int open_listen_socket (const char *path) /* {{{ */ status = bind (fd, (struct sockaddr *) &sa, sizeof (sa)); if (status != 0) { - RRDD_LOG (LOG_ERR, "open_listen_socket: bind(2) failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: bind(2) failed."); close (fd); unlink (path); return (-1); @@ -482,7 +499,7 @@ static int open_listen_socket (const char *path) /* {{{ */ status = listen (fd, /* backlog = */ 10); if (status != 0) { - RRDD_LOG (LOG_ERR, "open_listen_socket: listen(2) failed."); + RRDD_LOG (LOG_ERR, "open_listen_socket_unix: listen(2) failed."); close (fd); unlink (path); return (-1); @@ -494,6 +511,85 @@ static int open_listen_socket (const char *path) /* {{{ */ listen_fds_num++; return (0); +} /* }}} int open_listen_socket_unix */ + +static int open_listen_socket (const char *addr) /* {{{ */ +{ + struct addrinfo ai_hints; + struct addrinfo *ai_res; + struct addrinfo *ai_ptr; + int status; + + assert (addr != NULL); + + if (strncmp ("unix:", addr, strlen ("unix:")) == 0) + return (open_listen_socket_unix (addr + strlen ("unix:"))); + else if (addr[0] == '/') + return (open_listen_socket_unix (addr)); + + memset (&ai_hints, 0, sizeof (ai_hints)); + ai_hints.ai_flags = 0; +#ifdef AI_ADDRCONFIG + ai_hints.ai_flags |= AI_ADDRCONFIG; +#endif + ai_hints.ai_family = AF_UNSPEC; + ai_hints.ai_socktype = SOCK_STREAM; + + ai_res = NULL; + status = getaddrinfo (addr, DEFAULT_PORT, &ai_hints, &ai_res); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: getaddrinfo(%s) failed: " + "%s", addr, gai_strerror (status)); + return (-1); + } + + for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next) + { + int fd; + struct sockaddr_storage sa; + listen_socket_t *temp; + + temp = (listen_socket_t *) realloc (listen_fds, + sizeof (listen_fds[0]) * (listen_fds_num + 1)); + if (temp == NULL) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: realloc failed."); + continue; + } + listen_fds = temp; + memset (listen_fds + listen_fds_num, 0, sizeof (listen_fds[0])); + + fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol); + if (fd < 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: socket(2) failed."); + continue; + } + + status = bind (fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: bind(2) failed."); + close (fd); + continue; + } + + status = listen (fd, /* backlog = */ 10); + if (status != 0) + { + RRDD_LOG (LOG_ERR, "open_listen_socket: listen(2) failed."); + close (fd); + return (-1); + } + + listen_fds[listen_fds_num].fd = fd; + strncpy (listen_fds[listen_fds_num].path, addr, + sizeof (listen_fds[listen_fds_num].path) - 1); + listen_fds_num++; + } /* for (ai_ptr) */ + + return (0); } /* }}} int open_listen_socket */ static int close_listen_sockets (void) /* {{{ */ @@ -519,17 +615,24 @@ static void *listen_thread_main (void *args) /* {{{ */ int status; int i; - status = open_listen_socket (RRDD_SOCK_PATH); - if (status != 0) + for (i = 0; i < config_listen_address_list_len; i++) + { + RRDD_LOG (LOG_DEBUG, "listen_thread_main: config_listen_address_list[%i] " + "= %s", i, config_listen_address_list[i]); + open_listen_socket (config_listen_address_list[i]); + } + + if (listen_fds_num < 1) { - RRDD_LOG (LOG_ERR, "listen_thread_main: open_listen_socket failed."); + RRDD_LOG (LOG_ERR, "listen_thread_main: No listen sockets " + "could be opened. Sorry."); return (NULL); } while (do_shutdown == 0) { int *client_sd; - struct sockaddr_un client_sa; + struct sockaddr_storage client_sa; socklen_t client_sa_size; pthread_t tid; @@ -632,6 +735,10 @@ static int daemonize (void) /* {{{ */ memset (&sa, 0, sizeof (sa)); sa.sa_handler = sig_term_handler; sigaction (SIGINT, &sa, NULL); + + memset (&sa, 0, sizeof (sa)); + sa.sa_handler = SIG_IGN; + sigaction (SIGPIPE, &sa, NULL); } openlog ("rrdd", LOG_PID, LOG_DAEMON); @@ -671,12 +778,102 @@ static int cleanup (void) /* {{{ */ return (0); } /* }}} int cleanup */ +static int read_options (int argc, char **argv) /* {{{ */ +{ + int option; + int status = 0; + + while ((option = getopt(argc, argv, "l:f:w:h?")) != -1) + { + switch (option) + { + case 'l': + { + char **temp; + + temp = (char **) realloc (config_listen_address_list, + sizeof (char *) * (config_listen_address_list_len + 1)); + if (temp == NULL) + { + fprintf (stderr, "read_options: realloc failed.\n"); + return (2); + } + config_listen_address_list = temp; + + temp[config_listen_address_list_len] = strdup (optarg); + if (temp[config_listen_address_list_len] == NULL) + { + fprintf (stderr, "read_options: strdup failed.\n"); + return (2); + } + config_listen_address_list_len++; + } + break; + + case 'f': + { + int temp; + + temp = atoi (optarg); + if (temp > 0) + config_flush_interval = temp; + else + { + fprintf (stderr, "Invalid flush interval: %s\n", optarg); + status = 3; + } + } + break; + + case 'w': + { + int temp; + + temp = atoi (optarg); + if (temp > 0) + config_write_interval = temp; + else + { + fprintf (stderr, "Invalid write interval: %s\n", optarg); + status = 2; + } + } + break; + + case 'h': + case '?': + printf ("RRDd %s Copyright (C) 2008 Florian octo Forster\n" + "\n" + "Usage: rrdd [options]\n" + "\n" + "Valid options are:\n" + " -l
Socket address to listen to.\n" + " -w Interval in which to write data.\n" + " -f Interval in which to flush dead data.\n" + "\n" + "For more information and a detailed description of all options " + "please refer\n" + "to the rrdd(1) manual page.\n", + PACKAGE_VERSION); + status = -1; + break; + } /* switch (option) */ + } /* while (getopt) */ + + return (status); +} /* }}} int read_options */ + int main (int argc, char **argv) { int status; - printf ("%s by Florian Forster, Version %s\n", - PACKAGE_NAME, PACKAGE_VERSION); + status = read_options (argc, argv); + if (status != 0) + { + if (status < 0) + status = 0; + return (status); + } status = daemonize (); if (status == 1)