collectd-tg: Implemented continuous sending of values.
[collectd.git] / src / collectd-tg.c
1 /**
2  * collectd - src/collectd-tg.c
3  * Copyright (C) 2010  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 Forster <ff at octo.it>
20  **/
21
22 #if HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include <string.h>
29 #include <time.h>
30 #include <signal.h>
31
32 #include "utils_heap.h"
33
34 #include "libcollectdclient/collectd/client.h"
35 #include "libcollectdclient/collectd/network.h"
36 #include "libcollectdclient/collectd/network_buffer.h"
37
38 static int conf_num_hosts = 1000;
39 static int conf_num_plugins = 20;
40 static int conf_num_values = 100000;
41
42 static lcc_network_t *net;
43
44 static c_heap_t *values_heap = NULL;
45
46 static struct sigaction sigint_action;
47 static struct sigaction sigterm_action;
48
49 static _Bool loop = 1;
50
51 static void signal_handler (int signal) /* {{{ */
52 {
53   loop = 0;
54 } /* }}} void signal_handler */
55
56 static int compare_time (const void *v0, const void *v1) /* {{{ */
57 {
58   const lcc_value_list_t *vl0 = v0;
59   const lcc_value_list_t *vl1 = v1;
60
61   if (vl0->time < vl1->time)
62     return (-1);
63   else if (vl0->time > vl1->time)
64     return (1);
65   else
66     return (0);
67 } /* }}} int compare_time */
68
69 static int get_boundet_random (int min, int max) /* {{{ */
70 {
71   int range;
72
73   if (min >= max)
74     return (-1);
75   if (min == (max - 1))
76     return (min);
77
78   range = max - min;
79
80   return (min + ((int) (((double) range) * ((double) random ()) / (((double) RAND_MAX) + 1.0))));
81 } /* }}} int get_boundet_random */
82
83 #if 0
84 static int dump_network_buffer (void) /* {{{ */
85 {
86   char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
87   size_t buffer_size;
88   int status;
89   size_t offset;
90
91   memset (buffer, 0, sizeof (buffer));
92   buffer_size = sizeof (buffer);
93
94   status = lcc_network_buffer_get (nb, buffer, &buffer_size);
95   if (status != 0)
96   {
97     fprintf (stderr, "lcc_network_buffer_get failed with status %i.\n",
98         status);
99     return (status);
100   }
101
102   if (buffer_size > sizeof (buffer))
103     buffer_size = sizeof (buffer);
104
105   for (offset = 0; offset < buffer_size; offset += 16)
106   {
107     size_t i;
108
109     for (i = 0; (i < 16) && ((offset + i) < buffer_size); i++)
110     {
111       uint8_t v = (uint8_t) buffer[offset + i];
112       printf ("%02"PRIx8" ", v);
113     }
114     for (; i < 16; i++)
115       printf ("   ");
116     printf ("   ");
117     for (i = 0; (i < 16) && ((offset + i) < buffer_size); i++)
118     {
119       uint8_t v = (uint8_t) buffer[offset + i];
120       if ((v >= 32) && (v < 128))
121         printf ("%c", (int) buffer[offset + i]);
122       else
123         printf (".");
124     }
125     printf ("\n");
126   }
127
128   return (0);
129 } /* }}} int dump_network_buffer */
130 #endif
131
132 static lcc_value_list_t *create_value_list (void) /* {{{ */
133 {
134   lcc_value_list_t *vl;
135   int host_num;
136
137   vl = malloc (sizeof (*vl));
138   if (vl == NULL)
139   {
140     fprintf (stderr, "malloc failed.\n");
141     return (NULL);
142   }
143   memset (vl, 0, sizeof (*vl));
144
145   vl->values = calloc (/* nmemb = */ 1, sizeof (*vl->values));
146   if (vl->values == NULL)
147   {
148     fprintf (stderr, "calloc failed.\n");
149     free (vl);
150     return (NULL);
151   }
152
153   vl->values_types = calloc (/* nmemb = */ 1, sizeof (*vl->values_types));
154   if (vl->values_types == NULL)
155   {
156     fprintf (stderr, "calloc failed.\n");
157     free (vl->values);
158     free (vl);
159     return (NULL);
160   }
161
162   vl->values_len = 1;
163
164   host_num = get_boundet_random (0, conf_num_hosts);
165
166   vl->interval = 10;
167   vl->time = time (NULL) - (host_num % vl->interval);
168
169   if (get_boundet_random (0, 2) == 0)
170     vl->values_types[0] = LCC_TYPE_GAUGE;
171   else
172     vl->values_types[0] = LCC_TYPE_DERIVE;
173
174   snprintf (vl->identifier.host, sizeof (vl->identifier.host),
175       "host%04i", host_num);
176   snprintf (vl->identifier.plugin, sizeof (vl->identifier.plugin),
177       "plugin%03i", get_boundet_random (0, conf_num_plugins));
178   strncpy (vl->identifier.type,
179       (vl->values_types[0] == LCC_TYPE_GAUGE) ? "gauge" : "derive",
180       sizeof (vl->identifier.type));
181   snprintf (vl->identifier.type_instance, sizeof (vl->identifier.type_instance),
182       "ti%li", random ());
183
184   return (vl);
185 } /* }}} int create_value_list */
186
187 static void destroy_value_list (lcc_value_list_t *vl) /* {{{ */
188 {
189   if (vl == NULL)
190     return;
191
192   free (vl->values);
193   free (vl->values_types);
194   free (vl);
195 } /* }}} void destroy_value_list */
196
197 static int send_value (lcc_value_list_t *vl) /* {{{ */
198 {
199   int status;
200
201   if (vl->values_types[0] == LCC_TYPE_GAUGE)
202     vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
203   else
204     vl->values[0].derive += get_boundet_random (0, 100);
205
206   status = lcc_network_values_send (net, vl);
207   if (status != 0)
208     fprintf (stderr, "lcc_network_values_send failed with status %i.\n", status);
209
210   vl->time += vl->interval;
211
212   return (0);
213 } /* }}} int send_value */
214
215 int main (int argc, char **argv) /* {{{ */
216 {
217   int i;
218   time_t last_time;
219   int values_sent = 0;
220
221   sigint_action.sa_handler = signal_handler;
222   sigaction (SIGINT, &sigint_action, /* old = */ NULL);
223
224   sigterm_action.sa_handler = signal_handler;
225   sigaction (SIGTERM, &sigterm_action, /* old = */ NULL);
226
227
228   values_heap = c_heap_create (compare_time);
229   if (values_heap == NULL)
230   {
231     fprintf (stderr, "c_heap_create failed.\n");
232     exit (EXIT_FAILURE);
233   }
234
235   net = lcc_network_create ();
236   if (net == NULL)
237   {
238     fprintf (stderr, "lcc_network_create failed.\n");
239     exit (EXIT_FAILURE);
240   }
241   else
242   {
243     lcc_server_t *srv;
244     
245     srv = lcc_server_create (net, NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT);
246     if (srv == NULL)
247     {
248       fprintf (stderr, "lcc_server_create failed.\n");
249       exit (EXIT_FAILURE);
250     }
251
252     lcc_server_set_ttl (srv, 42);
253 #if 0
254     lcc_server_set_security_level (srv, ENCRYPT,
255         "admin", "password1");
256 #endif
257   }
258
259   fprintf (stdout, "Creating %i values ... ", conf_num_values);
260   fflush (stdout);
261   for (i = 0; i < conf_num_values; i++)
262   {
263     lcc_value_list_t *vl;
264
265     vl = create_value_list ();
266     if (vl == NULL)
267     {
268       fprintf (stderr, "create_value_list failed.\n");
269       exit (EXIT_FAILURE);
270     }
271
272     c_heap_insert (values_heap, vl);
273   }
274   fprintf (stdout, "done\n");
275
276   last_time = 0;
277   while (loop)
278   {
279     lcc_value_list_t *vl = c_heap_get_root (values_heap);
280
281     if (vl == NULL)
282       break;
283
284     if (vl->time != last_time)
285     {
286       printf ("%i values have been sent.\n", values_sent);
287
288       /* Check if we need to sleep */
289       time_t now = time (NULL);
290
291       while (now < vl->time)
292       {
293         /* 1 / 100 second */
294         struct timespec ts = { 0, 10000000 };
295         nanosleep (&ts, /* remaining = */ NULL);
296         now = time (NULL);
297       }
298       last_time = vl->time;
299     }
300
301     send_value (vl);
302     values_sent++;
303
304     c_heap_insert (values_heap, vl);
305   }
306
307   fprintf (stdout, "Shutting down.\n");
308   fflush (stdout);
309
310   while (42)
311   {
312     lcc_value_list_t *vl = c_heap_get_root (values_heap);
313     if (vl == NULL)
314       break;
315     destroy_value_list (vl);
316   }
317   c_heap_destroy (values_heap);
318
319   lcc_network_destroy (net);
320   exit (EXIT_SUCCESS);
321   return (0);
322 } /* }}} int main */
323
324 /* vim: set sw=2 sts=2 et fdm=marker : */