Add ReconnectInterval option to Network plugin
authorJohn Ferlito <johnf@inodes.org>
Sat, 13 Sep 2014 01:24:14 +0000 (11:24 +1000)
committerJohn Ferlito <johnf@inodes.org>
Sun, 14 Sep 2014 06:45:16 +0000 (16:45 +1000)
The Network plugin only performs DNS resolution at initialization. This
can be problematic when trying to performs migrations of collectd
infrastructure or when trying to create HA solutions which are dependant
on DNS.

The ReconnectInterval options forces a reconnect of all the sockets at
the defined number of seconds. By default no re-connections are attempted
if this option is not set.

src/collectd.conf.in
src/collectd.conf.pod
src/network.c

index 38b2ba4..91c040a 100644 (file)
 #              Username "user"
 #              Password "secret"
 #              Interface "eth0"
+#              ResolveInterval 14400
 @LOAD_PLUGIN_NETWORK@  </Server>
 #      TimeToLive "128"
 #
index ba99b60..8ecc92d 100644 (file)
@@ -3890,6 +3890,12 @@ behavior is to let the kernel choose the appropriate interface. Be warned
 that the manual selection of an interface for unicast traffic is only
 necessary in rare cases.
 
+=item B<ResolveInterval> I<Seconds>
+
+Sets the interval at which to re-resolve the DNS for the I<Host>. This is
+useful to force a regular DNS lookup to support a high availability setup. If
+not specified, re-resolves are never attempted.
+
 =back
 
 =item B<E<lt>Listen> I<Host> [I<Port>]B<E<gt>>
index 9ad4dea..bf0b2bc 100644 (file)
@@ -117,6 +117,8 @@ struct sockent_client
        gcry_cipher_hd_t cypher;
        unsigned char password_hash[32];
 #endif
+       cdtime_t next_resolve_reconnect;
+       cdtime_t resolve_interval;
 };
 
 struct sockent_server
@@ -2031,6 +2033,8 @@ static sockent_t *sockent_create (int type) /* {{{ */
        {
                se->data.client.fd = -1;
                se->data.client.addr = NULL;
+               se->data.client.resolve_interval = 0;
+               se->data.client.next_resolve_reconnect = 0;
 #if HAVE_LIBGCRYPT
                se->data.client.security_level = SECURITY_LEVEL_NONE;
                se->data.client.username = NULL;
@@ -2125,12 +2129,22 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
        struct addrinfo  ai_hints;
        struct addrinfo *ai_list = NULL, *ai_ptr;
        int status;
+       _Bool reconnect = 0;
+       cdtime_t now;
 
        if ((se == NULL) || (se->type != SOCKENT_TYPE_CLIENT))
                return (EINVAL);
 
        client = &se->data.client;
-       if (client->fd >= 0) /* already connected */
+
+       now = cdtime ();
+       if (client->resolve_interval != 0 && client->next_resolve_reconnect < now) {
+               DEBUG("network plugin: Reconnecting socket, resolve_interval = %lf, next_resolve_reconnect = %lf",
+                       CDTIME_T_TO_DOUBLE(client->resolve_interval), CDTIME_T_TO_DOUBLE(client->next_resolve_reconnect));
+               reconnect = 1;
+       }
+
+       if (client->fd >= 0 && !reconnect) /* already connected and not stale*/
                return (0);
 
        memset (&ai_hints, 0, sizeof (ai_hints));
@@ -2162,6 +2176,9 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
 
        for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
        {
+               if (client->fd >= 0) /* when we reconnect */
+                       sockent_client_disconnect(se);
+
                client->fd = socket (ai_ptr->ai_family,
                                ai_ptr->ai_socktype,
                                ai_ptr->ai_protocol);
@@ -2199,6 +2216,9 @@ static int sockent_client_connect (sockent_t *se) /* {{{ */
        freeaddrinfo (ai_list);
        if (client->fd < 0)
                return (-1);
+
+       if (client->resolve_interval > 0)
+               client->next_resolve_reconnect = now + client->resolve_interval;
        return (0);
 } /* }}} int sockent_client_connect */
 
@@ -3209,6 +3229,8 @@ static int network_config_add_server (const oconfig_item_t *ci) /* {{{ */
     if (strcasecmp ("Interface", child->key) == 0)
       network_config_set_interface (child,
           &se->interface);
+               else if (strcasecmp ("ResolveInterval", child->key) == 0)
+                       cf_util_get_cdtime(child, &se->data.client.resolve_interval);
     else
     {
       WARNING ("network plugin: Option `%s' is not allowed here.",