+ char buffer[4096];
+ int buffer_size;
+
+ RRDD_LOG (LOG_DEBUG, "handle_request (%i)", fd);
+
+ buffer_size = read (fd, buffer, sizeof (buffer));
+ if (buffer_size < 1)
+ {
+ RRDD_LOG (LOG_ERR, "handle_request: read(2) failed.");
+ return (-1);
+ }
+ assert (((size_t) buffer_size) <= sizeof (buffer));
+
+ if ((buffer[buffer_size - 2] != 0)
+ || (buffer[buffer_size - 1] != 0))
+ {
+ RRDD_LOG (LOG_INFO, "handle_request: malformed request.");
+ return (-1);
+ }
+
+ /* fields in the buffer a separated by null bytes. */
+ if (strcmp (buffer, "update") == 0)
+ {
+ int offset = strlen ("update") + 1;
+ return (handle_request_update (fd, buffer + offset,
+ buffer_size - offset));
+ }
+ else
+ {
+ RRDD_LOG (LOG_INFO, "handle_request: unknown command: %s.", buffer);
+ return (-1);
+ }
+} /* }}} int handle_request */
+
+static void *connection_thread_main (void *args) /* {{{ */
+{
+ pthread_t self;
+ int i;
+ int fd;
+
+ fd = *((int *) args);
+
+ RRDD_LOG (LOG_DEBUG, "connection_thread_main: Adding myself to "
+ "connetion_threads[]..");
+ pthread_mutex_lock (&connetion_threads_lock);
+ {
+ pthread_t *temp;
+
+ temp = (pthread_t *) realloc (connetion_threads,
+ sizeof (pthread_t) * (connetion_threads_num + 1));
+ if (temp == NULL)
+ {
+ RRDD_LOG (LOG_ERR, "connection_thread_main: realloc failed.");
+ }
+ else
+ {
+ connetion_threads = temp;
+ connetion_threads[connetion_threads_num] = pthread_self ();
+ connetion_threads_num++;
+ }
+ }
+ pthread_mutex_unlock (&connetion_threads_lock);
+ RRDD_LOG (LOG_DEBUG, "connection_thread_main: done");
+
+ while (do_shutdown == 0)
+ {
+ struct pollfd pollfd;
+ int status;
+
+ pollfd.fd = fd;
+ pollfd.events = POLLIN | POLLPRI;
+ pollfd.revents = 0;
+
+ status = poll (&pollfd, 1, /* timeout = */ 500);
+ if (status == 0) /* timeout */
+ continue;
+ else if (status < 0) /* error */
+ {
+ status = errno;
+ if (status == EINTR)
+ continue;
+ RRDD_LOG (LOG_ERR, "connection_thread_main: poll(2) failed.");
+ continue;
+ }
+
+ 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: %#04hx",
+ pollfd.revents);
+ close (fd);
+ break;
+ }
+
+ status = handle_request (fd);
+ if (status != 0)
+ {
+ close (fd);
+ break;
+ }
+ }
+
+ self = pthread_self ();
+ /* Remove this thread from the connection threads list */
+ pthread_mutex_lock (&connetion_threads_lock);
+ /* Find out own index in the array */
+ for (i = 0; i < connetion_threads_num; i++)
+ if (pthread_equal (connetion_threads[i], self) != 0)
+ break;
+ assert (i < connetion_threads_num);
+
+ /* Move the trailing threads forward. */
+ if (i < (connetion_threads_num - 1))
+ {
+ memmove (connetion_threads + i,
+ connetion_threads + i + 1,
+ sizeof (pthread_t) * (connetion_threads_num - i - 1));
+ }
+
+ connetion_threads_num--;
+ pthread_mutex_unlock (&connetion_threads_lock);
+
+ free (args);
+ return (NULL);
+} /* }}} void *connection_thread_main */