src/librrdc.c: When sending an `update', wait for the reply before closing the socket.
[rrdd.git] / src / librrdc.c
1 /**
2  * collectd - src/rrdc.c
3  * Copyright (C) 2008 Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; only version 2 of the License is applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
17  *
18  * Authors:
19  *   Florian octo Forster <octo at verplant.org>
20  **/
21
22 #include "rrdd.h"
23 #include "rrdc.h"
24
25 static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
26 static int sd;
27 static FILE *sh;
28
29 static int buffer_add_string (const char *str,
30     char **buffer_ret, size_t *buffer_size_ret)
31 {
32   size_t str_size;
33
34   str_size = strlen (str) + 1;
35
36   if (*buffer_size_ret < str_size)
37     return (-1);
38
39   memcpy (*buffer_ret, str, str_size);
40   *buffer_ret += str_size;
41   *buffer_size_ret -= str_size;
42
43   return (0);
44 } /* int buffer_add_string */
45
46 static int buffer_add_value (const char *value,
47     char **buffer_ret, size_t *buffer_size_ret)
48 {
49   char temp[4096];
50
51   if (strncmp (value, "N:", 2) == 0)
52     snprintf (temp, sizeof (temp), "%lu:%s",
53         (unsigned long) time (NULL), value + 2);
54   else
55     strncpy (temp, value, sizeof (temp));
56   temp[sizeof (temp) - 1] = 0;
57
58   return (buffer_add_string (temp, buffer_ret, buffer_size_ret));
59 } /* int buffer_add_value */
60
61 int rrdd_connect (const char *path)
62 {
63   struct sockaddr_un sa;
64   int status;
65
66   pthread_mutex_lock (&lock);
67
68   if (sh != NULL)
69   {
70     pthread_mutex_unlock (&lock);
71     return (0);
72   }
73
74   sd = socket (PF_UNIX, SOCK_STREAM, /* protocol = */ 0);
75   if (sd < 0)
76   {
77     status = errno;
78     pthread_mutex_unlock (&lock);
79     return (status);
80   }
81
82   memset (&sa, 0, sizeof (sa));
83   sa.sun_family = AF_UNIX;
84   strncpy (sa.sun_path, path, sizeof (sa.sun_path) - 1);
85
86   status = connect (sd, (struct sockaddr *) &sa, sizeof (sa));
87   if (status != 0)
88   {
89     status = errno;
90     pthread_mutex_unlock (&lock);
91     return (status);
92   }
93
94   sh = fdopen (sd, "w+");
95   if (sh == NULL)
96   {
97     status = errno;
98     close (sd);
99     sd = -1;
100     pthread_mutex_unlock (&lock);
101     return (status);
102   }
103
104   pthread_mutex_unlock (&lock);
105
106   return (0);
107 } /* int rrdd_connect */
108
109 int rrdd_disconnect (void)
110 {
111   int status;
112
113   pthread_mutex_lock (&lock);
114
115   if (sh == NULL)
116   {
117     pthread_mutex_unlock (&lock);
118     return (-1);
119   }
120
121   status = fclose (sh);
122   if (status != 0)
123     status = errno;
124
125   sh = NULL;
126   sd = -1;
127
128   pthread_mutex_unlock (&lock);
129
130   return (status);
131 } /* int rrdd_disconnect */
132
133 int rrdd_update (const char *filename, int values_num,
134                 const char * const *values)
135 {
136   char buffer[4096];
137   char *buffer_ptr;
138   size_t buffer_size;
139   int status;
140   int i;
141
142   memset (buffer, 0, sizeof (buffer));
143   buffer_ptr = &buffer[0];
144   buffer_size = sizeof (buffer) - 1;
145
146   buffer_add_string ("update", &buffer_ptr, &buffer_size);
147   buffer_add_string (filename, &buffer_ptr, &buffer_size);
148   for (i = 0; i < values_num; i++)
149     buffer_add_value (values[i], &buffer_ptr, &buffer_size);
150
151   pthread_mutex_lock (&lock);
152
153   if (sh == NULL)
154   {
155     pthread_mutex_unlock (&lock);
156     return (ENOTCONN);
157   }
158
159   status = write (sd, buffer, sizeof (buffer) - buffer_size);
160
161   status = read (sd, buffer, sizeof (buffer));
162   if (status < 0)
163   {
164     status = errno;
165     pthread_mutex_unlock (&lock);
166     return (status);
167   }
168   else if (status == 0)
169   {
170     pthread_mutex_unlock (&lock);
171     return (ENODATA);
172   }
173
174   status = atoi (buffer);
175
176   pthread_mutex_unlock (&lock);
177
178   return (status);
179 } /* int rrd_update_daemon */
180
181 /*
182  * vim: set sw=2 sts=2 ts=8 et fdm=marker :
183  */