Skip to content

Commit

Permalink
apcups plugin: Retry sending the "status" command.
Browse files Browse the repository at this point in the history
If that fails more than twice in the first 10 iterations, gracefully shut
down the socket in all future iterations.

This should fix Github issue #15.
  • Loading branch information
octo committed Sep 13, 2012
1 parent 3855d8f commit dce4923
Showing 1 changed file with 54 additions and 12 deletions.
66 changes: 54 additions & 12 deletions src/apcups.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* collectd - src/apcups.c
* Copyright (C) 2006-2007 Florian octo Forster
* Copyright (C) 2006-2012 Florian octo Forster
* Copyright (C) 2006 Anthony Gialluca <tonyabg at charter.net>
* Copyright (C) 2000-2004 Kern Sibbald
* Copyright (C) 1996-1999 Andre M. Hedrick <andre at suse.com>
Expand Down Expand Up @@ -73,6 +73,10 @@ static int conf_port = NISPORT;

static int global_sockfd = -1;

static int count_retries = 0;
static int count_iterations = 0;
static _Bool close_socket = 0;

static const char *config_keys[] =
{
"Host",
Expand Down Expand Up @@ -266,28 +270,60 @@ static int apc_query_server (char *host, int port,
char *toksaveptr;
char *key;
double value;
_Bool retry = 1;
int status;

#if APCMAIN
# define PRINT_VALUE(name, val) printf(" Found property: name = %s; value = %f;\n", name, val)
#else
# define PRINT_VALUE(name, val) /**/
#endif

if (global_sockfd < 0)
while (retry)
{
global_sockfd = net_open (host, port);
if (global_sockfd < 0)
{
ERROR ("apcups plugin: Connecting to the "
"apcupsd failed.");
global_sockfd = net_open (host, port);
if (global_sockfd < 0)
{
ERROR ("apcups plugin: Connecting to the "
"apcupsd failed.");
return (-1);
}
}


status = net_send (&global_sockfd, "status", strlen ("status"));
if (status != 0)
{
/* net_send is closing the socket on error. */
assert (global_sockfd < 0);
if (retry)
{
retry = 0;
count_retries++;
continue;
}

ERROR ("apcups plugin: Writing to the socket failed.");
return (-1);
}
}

if (net_send (&global_sockfd, "status", 6) < 0)
break;
} /* while (retry) */

/* When collectd's collection interval is larger than apcupsd's
* timeout, we would have to retry / re-connect each iteration. Try to
* detect this situation and shut down the socket gracefully in that
* case. Otherwise, keep the socket open to avoid overhead. */
count_iterations++;
if ((count_iterations == 10) && (count_retries > 2))
{
ERROR ("apcups plugin: Writing to the socket failed.");
return (-1);
NOTICE ("apcups plugin: There have been %i retries in the "
"first %i iterations. Will close the socket "
"in future iterations.",
count_retries, count_iterations);
close_socket = 1;
}

while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
Expand All @@ -311,7 +347,7 @@ static int apc_query_server (char *host, int port,

if (strcmp ("LINEV", key) == 0)
apcups_detail->linev = value;
else if (strcmp ("BATTV", key) == 0)
else if (strcmp ("BATTV", key) == 0)
apcups_detail->battv = value;
else if (strcmp ("ITEMP", key) == 0)
apcups_detail->itemp = value;
Expand All @@ -329,10 +365,16 @@ static int apc_query_server (char *host, int port,
tokptr = strtok_r (NULL, ":", &toksaveptr);
} /* while (tokptr != NULL) */
}

status = errno; /* save errno, net_shutdown() may re-set it. */

if (close_socket)
net_shutdown (&global_sockfd);

if (n < 0)
{
WARNING ("apcups plugin: Error reading from socket");
char errbuf[1024];
ERROR ("apcups plugin: Reading from socket failed: %s",
sstrerror (status, errbuf, sizeof (errbuf)));
return (-1);
}

Expand Down

0 comments on commit dce4923

Please sign in to comment.