src/plugin.c: Add a user_data_t pointer to notification callbacks.
[collectd.git] / src / network.c
index 9e391bb..c9a92ac 100644 (file)
@@ -498,7 +498,7 @@ static int parse_part_values (void **ret_buffer, int *ret_buffer_len,
 
        exp_size = 3 * sizeof (uint16_t)
                + pkg_numval * (sizeof (uint8_t) + sizeof (value_t));
-       if (buffer_len < exp_size)
+       if ((buffer_len < 0) || ((size_t) buffer_len < exp_size))
        {
                WARNING ("network plugin: parse_part_values: "
                                "Packet too short: "
@@ -562,7 +562,7 @@ static int parse_part_number (void **ret_buffer, int *ret_buffer_len,
        uint16_t pkg_length;
        uint16_t pkg_type;
 
-       if (buffer_len < exp_size)
+       if ((buffer_len < 0) || ((size_t) buffer_len < exp_size))
        {
                WARNING ("network plugin: parse_part_number: "
                                "Packet too short: "
@@ -602,7 +602,7 @@ static int parse_part_string (void **ret_buffer, int *ret_buffer_len,
        uint16_t pkg_length;
        uint16_t pkg_type;
 
-       if (buffer_len < header_size)
+       if ((buffer_len < 0) || ((size_t) buffer_len < header_size))
        {
                WARNING ("network plugin: parse_part_string: "
                                "Packet too short: "
@@ -644,7 +644,8 @@ static int parse_part_string (void **ret_buffer, int *ret_buffer_len,
        /* Check that the package data fits into the output buffer.
         * The previous if-statement ensures that:
         * `pkg_length > header_size' */
-       if ((pkg_length - header_size) > output_len)
+       if ((output_len < 0)
+                       || ((size_t) output_len < ((size_t) pkg_length - header_size)))
        {
                WARNING ("network plugin: parse_part_string: "
                                "Output buffer too small.");
@@ -1240,7 +1241,7 @@ static int network_add_sending_socket (const char *node, const char *service)
        return (0);
 } /* int network_get_listen_socket */
 
-static void *dispatch_thread (void *arg)
+static void *dispatch_thread (void __attribute__((unused)) *arg)
 {
   while (42)
   {
@@ -1279,6 +1280,9 @@ static int network_receive (void)
        int i;
        int status;
 
+       receive_list_entry_t *private_list_head;
+       receive_list_entry_t *private_list_tail;
+
        if (listen_sockets_num == 0)
                network_add_listen_socket (NULL, NULL);
 
@@ -1288,6 +1292,9 @@ static int network_receive (void)
                return (-1);
        }
 
+       private_list_head = NULL;
+       private_list_tail = NULL;
+
        while (listen_loop == 0)
        {
                status = poll (listen_sockets, listen_sockets_num, -1);
@@ -1328,7 +1335,8 @@ static int network_receive (void)
                                ERROR ("network plugin: malloc failed.");
                                return (-1);
                        }
-                       memset (ent, '\0', sizeof (receive_list_entry_t));
+                       memset (ent, 0, sizeof (receive_list_entry_t));
+                       ent->next = NULL;
 
                        /* Hopefully this be optimized out by the compiler. It
                         * might help prevent stupid bugs in the future though.
@@ -1338,26 +1346,53 @@ static int network_receive (void)
                        memcpy (ent->data, buffer, buffer_len);
                        ent->data_len = buffer_len;
 
-                       pthread_mutex_lock (&receive_list_lock);
-                       if (receive_list_head == NULL)
-                       {
-                               receive_list_head = ent;
-                               receive_list_tail = ent;
-                       }
+                       if (private_list_head == NULL)
+                               private_list_head = ent;
                        else
+                               private_list_tail->next = ent;
+                       private_list_tail = ent;
+
+                       /* Do not block here. Blocking here has led to
+                        * insufficient performance in the past. */
+                       if (pthread_mutex_trylock (&receive_list_lock) == 0)
                        {
-                               receive_list_tail->next = ent;
-                               receive_list_tail = ent;
+                               if (receive_list_head == NULL)
+                                       receive_list_head = private_list_head;
+                               else
+                                       receive_list_tail->next = private_list_head;
+                               receive_list_tail = private_list_tail;
+
+                               private_list_head = NULL;
+                               private_list_tail = NULL;
+
+                               pthread_cond_signal (&receive_list_cond);
+                               pthread_mutex_unlock (&receive_list_lock);
                        }
-                       pthread_cond_signal (&receive_list_cond);
-                       pthread_mutex_unlock (&receive_list_lock);
                } /* for (listen_sockets) */
        } /* while (listen_loop == 0) */
 
+       /* Make sure everything is dispatched before exiting. */
+       if (private_list_head != NULL)
+       {
+               pthread_mutex_lock (&receive_list_lock);
+
+               if (receive_list_head == NULL)
+                       receive_list_head = private_list_head;
+               else
+                       receive_list_tail->next = private_list_head;
+               receive_list_tail = private_list_tail;
+
+               private_list_head = NULL;
+               private_list_tail = NULL;
+
+               pthread_cond_signal (&receive_list_cond);
+               pthread_mutex_unlock (&receive_list_lock);
+       }
+
        return (0);
 }
 
-static void *receive_thread (void *arg)
+static void *receive_thread (void __attribute__((unused)) *arg)
 {
        return (network_receive () ? (void *) 1 : (void *) 0);
 } /* void *receive_thread */
@@ -1472,7 +1507,8 @@ static void flush_buffer (void)
        memset (&send_buffer_vl, 0, sizeof (send_buffer_vl));
 }
 
-static int network_write (const data_set_t *ds, const value_list_t *vl)
+static int network_write (const data_set_t *ds, const value_list_t *vl,
+               user_data_t __attribute__((unused)) *user_data)
 {
        int status;
 
@@ -1596,7 +1632,8 @@ static int network_config (const char *key, const char *val)
        return (0);
 } /* int network_config */
 
-static int network_notification (const notification_t *n)
+static int network_notification (const notification_t *n,
+               user_data_t __attribute__((unused)) *user_data)
 {
   char  buffer[BUFF_SIZE];
   char *buffer_ptr = buffer;
@@ -1732,8 +1769,10 @@ static int network_init (void)
        /* setup socket(s) and so on */
        if (sending_sockets != NULL)
        {
-               plugin_register_write ("network", network_write);
-               plugin_register_notification ("network", network_notification);
+               plugin_register_write ("network", network_write,
+                               /* user_data = */ NULL);
+               plugin_register_notification ("network", network_notification,
+                               /* user_data = */ NULL);
        }
 
        if ((listen_sockets_num != 0) && (receive_thread_id == 0))
@@ -1774,7 +1813,9 @@ static int network_init (void)
  * just send the buffer if `flush'  is called - if the requested value was in
  * there, good. If not, well, then there is nothing to flush.. -octo
  */
-static int network_flush (int timeout, const char *identifier)
+static int network_flush (int timeout,
+               const char __attribute__((unused)) *identifier,
+               user_data_t __attribute__((unused)) *user_data)
 {
        pthread_mutex_lock (&send_buffer_lock);
 
@@ -1794,5 +1835,6 @@ void module_register (void)
        plugin_register_config ("network", network_config,
                        config_keys, config_keys_num);
        plugin_register_init   ("network", network_init);
-       plugin_register_flush   ("network", network_flush);
+       plugin_register_flush   ("network", network_flush,
+                       /* user_data = */ NULL);
 } /* void module_register */