src/rrd_client.[ch]: Add files that handle the the network communication.
authorFlorian Forster <octo@leeloo.home.verplant.org>
Sun, 22 Jun 2008 15:04:30 +0000 (17:04 +0200)
committerFlorian Forster <octo@leeloo.home.verplant.org>
Sun, 22 Jun 2008 15:04:30 +0000 (17:04 +0200)
The files have been developed as `librrdc.so' as part of the `RRDd'
package. They have been renamed and adapted for inclusion into
`RRDTool'.

src/Makefile.am
src/rrd_client.c [new file with mode: 0644]
src/rrd_client.h [new file with mode: 0644]

index c567679..5311592 100644 (file)
@@ -25,6 +25,7 @@ UPD_C_FILES =         \
        rrd_info.c      \
        rrd_error.c     \
        rrd_open.c      \
+       rrd_client.c    \
        rrd_nan_inf.c   \
        rrd_rpncalc.c   \
        rrd_update.c
diff --git a/src/rrd_client.c b/src/rrd_client.c
new file mode 100644 (file)
index 0000000..619a32a
--- /dev/null
@@ -0,0 +1,271 @@
+/**
+ * RRDTool - src/rrd_client.c
+ * Copyright (C) 2008 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "rrd.h"
+#include "rrd_client.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+static int sd;
+static FILE *sh;
+
+static int buffer_add_string (const char *str, /* {{{ */
+    char **buffer_ret, size_t *buffer_size_ret)
+{
+  size_t str_size;
+
+  str_size = strlen (str) + 1;
+
+  if (*buffer_size_ret < str_size)
+    return (-1);
+
+  memcpy (*buffer_ret, str, str_size);
+  *buffer_ret += str_size;
+  *buffer_size_ret -= str_size;
+
+  return (0);
+} /* }}} int buffer_add_string */
+
+static int buffer_add_value (const char *value, /* {{{ */
+    char **buffer_ret, size_t *buffer_size_ret)
+{
+  char temp[4096];
+
+  if (strncmp (value, "N:", 2) == 0)
+    snprintf (temp, sizeof (temp), "%lu:%s",
+        (unsigned long) time (NULL), value + 2);
+  else
+    strncpy (temp, value, sizeof (temp));
+  temp[sizeof (temp) - 1] = 0;
+
+  return (buffer_add_string (temp, buffer_ret, buffer_size_ret));
+} /* }}} int buffer_add_value */
+
+static int rrdd_connect_unix (const char *path) /* {{{ */
+{
+  struct sockaddr_un sa;
+  int status;
+
+  if (path == NULL)
+    path = RRDD_SOCK_PATH;
+
+  pthread_mutex_lock (&lock);
+
+  if (sh != NULL)
+  {
+    pthread_mutex_unlock (&lock);
+    return (0);
+  }
+
+  sd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0);
+  if (sd < 0)
+  {
+    status = errno;
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+
+  memset (&sa, 0, sizeof (sa));
+  sa.sun_family = AF_UNIX;
+  strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
+
+  status = connect (sd, (struct sockaddr *) &sa, sizeof (sa));
+  if (status != 0)
+  {
+    status = errno;
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+
+  sh = fdopen (sd, "w+");
+  if (sh == NULL)
+  {
+    status = errno;
+    close (sd);
+    sd = -1;
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+
+  pthread_mutex_unlock (&lock);
+
+  return (0);
+} /* }}} int rrdd_connect_unix */
+
+int rrdd_connect (const char *addr) /* {{{ */
+{
+  struct addrinfo ai_hints;
+  struct addrinfo *ai_res;
+  struct addrinfo *ai_ptr;
+  int status;
+
+  if (addr == NULL)
+    addr = RRDD_SOCK_PATH;
+
+  if (strncmp ("unix:", addr, strlen ("unix:")) == 0)
+    return (rrdd_connect_unix (addr + strlen ("unix:")));
+  else if (addr[0] == '/')
+    return (rrdd_connect_unix (addr));
+
+  pthread_mutex_lock (&lock);
+
+  if (sh != NULL)
+  {
+    pthread_mutex_unlock (&lock);
+    return (0);
+  }
+
+  memset (&ai_hints, 0, sizeof (ai_hints));
+  ai_hints.ai_flags = 0;
+#ifdef AI_ADDRCONFIG
+  ai_hints.ai_flags |= AI_ADDRCONFIG;
+#endif
+  ai_hints.ai_family = AF_UNSPEC;
+  ai_hints.ai_socktype = SOCK_STREAM;
+
+  ai_res = NULL;
+  status = getaddrinfo (addr, DEFAULT_PORT, &ai_hints, &ai_res);
+  if (status != 0)
+  {
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+
+  for (ai_ptr = ai_res; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
+  {
+    sd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+    if (sd < 0)
+    {
+      status = errno;
+      sd = -1;
+      continue;
+    }
+
+    status = connect (sd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
+    if (status != 0)
+    {
+      status = errno;
+      close (sd);
+      sd = -1;
+      continue;
+    }
+
+    sh = fdopen (sd, "w+");
+    if (sh == NULL)
+    {
+      status = errno;
+      close (sd);
+      sd = -1;
+      continue;
+    } 
+
+    assert (status == 0);
+    break;
+  } /* for (ai_ptr) */
+  pthread_mutex_unlock (&lock);
+
+  return (status);
+} /* }}} int rrdd_connect */
+
+int rrdd_disconnect (void) /* {{{ */
+{
+  int status;
+
+  pthread_mutex_lock (&lock);
+
+  if (sh == NULL)
+  {
+    pthread_mutex_unlock (&lock);
+    return (-1);
+  }
+
+  status = fclose (sh);
+  if (status != 0)
+    status = errno;
+
+  sh = NULL;
+  sd = -1;
+
+  pthread_mutex_unlock (&lock);
+
+  return (status);
+} /* }}} int rrdd_disconnect */
+
+int rrdd_update (const char *filename, int values_num, /* {{{ */
+               const char * const *values)
+{
+  char buffer[4096];
+  char *buffer_ptr;
+  size_t buffer_size;
+  int status;
+  int i;
+
+  memset (buffer, 0, sizeof (buffer));
+  buffer_ptr = &buffer[0];
+  buffer_size = sizeof (buffer) - 1;
+
+  buffer_add_string ("update", &buffer_ptr, &buffer_size);
+  buffer_add_string (filename, &buffer_ptr, &buffer_size);
+  for (i = 0; i < values_num; i++)
+    buffer_add_value (values[i], &buffer_ptr, &buffer_size);
+
+  pthread_mutex_lock (&lock);
+
+  if (sh == NULL)
+  {
+    pthread_mutex_unlock (&lock);
+    return (ENOTCONN);
+  }
+
+  status = write (sd, buffer, sizeof (buffer) - buffer_size);
+
+  status = read (sd, buffer, sizeof (buffer));
+  if (status < 0)
+  {
+    status = errno;
+    pthread_mutex_unlock (&lock);
+    return (status);
+  }
+  else if (status == 0)
+  {
+    pthread_mutex_unlock (&lock);
+    return (ENODATA);
+  }
+
+  status = atoi (buffer);
+
+  pthread_mutex_unlock (&lock);
+
+  return (status);
+} /* }}} int rrd_update_daemon */
+
+/*
+ * vim: set sw=2 sts=2 ts=8 et fdm=marker :
+ */
diff --git a/src/rrd_client.h b/src/rrd_client.h
new file mode 100644 (file)
index 0000000..e4b012e
--- /dev/null
@@ -0,0 +1,34 @@
+/**
+ * RRDTool - src/rrd_client.h
+ * Copyright (C) 2008 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef __RRD_CLIENT_H
+#define __RRD_CLIENT_H 1
+
+#define RRDD_SOCK_PATH "unix:/tmp/rrdd.sock"
+#define DEFAULT_PORT "42217"
+
+int rrdd_connect (const char *addr);
+int rrdd_disconnect (void);
+
+int rrdd_update (const char *filename, int values_num,
+        const char * const *values);
+
+#endif /* __RRD_CLIENT_H */