]> git.itanic.dy.fi Git - rrdd/blobdiff - onewire_parser.c
onewire_parser: Keep server handle open at all time
[rrdd] / onewire_parser.c
index eb2ccd212b490ecead3ac58587087d1cac41d1e1..9f4b404c480bdcc87ef2c88c37f3b6c9eb5441e9 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <ownetapi.h>
 
+#include "process.h"
 #include "parser.h"
 #include "debug.h"
 #include "string.h"
@@ -8,6 +9,11 @@
 #include "plugin.h"
 #include "version.h"
 
+static struct mutex server_lock = {
+       .name = "server_addr_lock",
+       .lock = PTHREAD_MUTEX_INITIALIZER,
+};
+
 static int parse_opts(const char *str, char *ow_path, size_t pathlen, double *offset)
 {
        char *endptr;
@@ -75,8 +81,8 @@ static int make_uncached(char *path, size_t len)
 
 static int onewire_parser(char *rrd_data, const char **parser_data)
 {
-       OWNET_HANDLE h;
-       const char *server_addr;
+       static OWNET_HANDLE handle;
+       static char *server_addr;
        char buf[24], *tmp;
        int i = 1, ret;
        int max_str = RRD_DATA_MAX_LEN;
@@ -86,16 +92,36 @@ static int onewire_parser(char *rrd_data, const char **parser_data)
                return -1;
        }
 
-       server_addr = parser_data[0];
-
-       if (!server_addr) {
+       if (!parser_data[0]) {
                pr_err("Server address not specified\n");
                return -1;
        }
 
-       h = OWNET_init(server_addr);
-       if (h < 0) {
+       /*
+        * No point trying to connect to the server more than
+        * once. Also we don't know how thread safe libownet is. One
+        * lock to protect it all.
+        */
+       mutex_lock(&server_lock);
+       /*
+        * Keep one server connection alive at all times. This
+        * prevents file descriptor leak with older libownet.
+        */
+       if (!server_addr || handle < 0) {
+               if (server_addr)
+                       free(server_addr);
+               server_addr = strdup(parser_data[0]);
+               handle = OWNET_init(server_addr);
+       } else if (strcmp(server_addr, parser_data[0])) {
+               OWNET_close(handle);
+               free(server_addr);
+               server_addr = strdup(parser_data[0]);
+               handle = OWNET_init(server_addr);
+       }
+
+       if (handle < 0) {
                pr_err("Failed to connect to server %s\n", server_addr);
+               mutex_unlock(&server_lock);
                return -1;
        }
 
@@ -121,8 +147,9 @@ undefined:
 
                        pr_info("Reading data for entry %s with offset of %.2f\n",
                                ow_path, offset);
-                       ret = OWNET_read(h, ow_path, &tmp);
-
+                       ret = OWNET_read(handle, ow_path, &tmp);
+                       if (ret < 0)
+                               goto err;
                        /* Skip leading white space */
                        tmp2 = tmp;
                        for (j = 0; j < ret && *tmp2 == ' '; j++)
@@ -142,6 +169,7 @@ undefined:
                                break;
 
                        ret = make_uncached(ow_path, sizeof(ow_path));
+err:
                        if (retries >= 10 || ret < 0) {
                                pr_err("Failed to read entry %s: %m\n",
                                        parser_data[i]);
@@ -179,7 +207,7 @@ next:
        }
        rrd_data = 0;
 
-       OWNET_finish();
+       mutex_unlock(&server_lock);
        return 0;
 }