collectd-tg: Add a first draft of a collectd traffic generator.
[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
31 #include "libcollectdclient/collectd/client.h"
32 #include "libcollectdclient/collectd/network.h"
33 #include "libcollectdclient/collectd/network_buffer.h"
34
35 static int conf_num_hosts = 1000;
36 static int conf_num_plugins = 20;
37 static int conf_num_values = 100000;
38
39 static lcc_network_buffer_t *nb;
40
41 static lcc_value_list_t **values;
42 static size_t values_num;
43
44 static int compare_time (const void *v0, const void *v1) /* {{{ */
45 {
46   lcc_value_list_t * const *vl0 = v0;
47   lcc_value_list_t * const *vl1 = v1;
48
49   if ((*vl0)->time < (*vl1)->time)
50     return (-1);
51   else if ((*vl0)->time > (*vl1)->time)
52     return (1);
53   else
54     return (lcc_identifier_compare (&(*vl0)->identifier, /* Ouch, somebody */
55           &(*vl1)->identifier));          /* is going to hate me for this. */
56 } /* }}} int compare_time */
57
58 static int get_boundet_random (int min, int max) /* {{{ */
59 {
60   int range;
61
62   if (min >= max)
63     return (-1);
64   if (min == (max - 1))
65     return (min);
66
67   range = max - min;
68
69   return (min + ((int) (((double) range) * ((double) random ()) / (((double) RAND_MAX) + 1.0))));
70 } /* }}} int get_boundet_random */
71
72 static int dump_network_buffer (void) /* {{{ */
73 {
74   char buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
75   size_t buffer_size;
76   int status;
77   size_t offset;
78
79   memset (buffer, 0, sizeof (buffer));
80   buffer_size = sizeof (buffer);
81
82   status = lcc_network_buffer_get (nb, buffer, &buffer_size);
83   if (status != 0)
84   {
85     fprintf (stderr, "lcc_network_buffer_get failed with status %i.\n",
86         status);
87     return (status);
88   }
89
90   if (buffer_size > sizeof (buffer))
91     buffer_size = sizeof (buffer);
92
93   for (offset = 0; offset < buffer_size; offset += 16)
94   {
95     size_t i;
96
97     for (i = 0; (i < 16) && ((offset + i) < buffer_size); i++)
98     {
99       uint8_t v = (uint8_t) buffer[offset + i];
100       printf ("%02"PRIx8" ", v);
101     }
102     for (; i < 16; i++)
103       printf ("   ");
104     printf ("   ");
105     for (i = 0; (i < 16) && ((offset + i) < buffer_size); i++)
106     {
107       uint8_t v = (uint8_t) buffer[offset + i];
108       if ((v >= 32) && (v < 128))
109         printf ("%c", (int) buffer[offset + i]);
110       else
111         printf (".");
112     }
113     printf ("\n");
114   }
115
116   return (0);
117 } /* }}} int dump_network_buffer */
118
119 static lcc_value_list_t *create_value_list (void) /* {{{ */
120 {
121   lcc_value_list_t *vl;
122   int host_num;
123
124   vl = malloc (sizeof (*vl));
125   if (vl == NULL)
126   {
127     fprintf (stderr, "malloc failed.\n");
128     return (NULL);
129   }
130   memset (vl, 0, sizeof (*vl));
131
132   vl->values = calloc (/* nmemb = */ 1, sizeof (*vl->values));
133   if (vl->values == NULL)
134   {
135     fprintf (stderr, "calloc failed.\n");
136     free (vl);
137     return (NULL);
138   }
139
140   vl->values_types = calloc (/* nmemb = */ 1, sizeof (*vl->values_types));
141   if (vl->values_types == NULL)
142   {
143     fprintf (stderr, "calloc failed.\n");
144     free (vl->values);
145     free (vl);
146     return (NULL);
147   }
148
149   vl->values_len = 1;
150
151   host_num = get_boundet_random (0, conf_num_hosts);
152
153   vl->interval = 10;
154   vl->time = time (NULL) - (host_num % vl->interval);
155
156   if (get_boundet_random (0, 2) == 0)
157     vl->values_types[0] = LCC_TYPE_GAUGE;
158   else
159     vl->values_types[0] = LCC_TYPE_DERIVE;
160
161   snprintf (vl->identifier.host, sizeof (vl->identifier.host),
162       "host%04i", host_num);
163   snprintf (vl->identifier.plugin, sizeof (vl->identifier.plugin),
164       "plugin%03i", get_boundet_random (0, conf_num_plugins));
165   strncpy (vl->identifier.type,
166       (vl->values_types[0] == LCC_TYPE_GAUGE) ? "gauge" : "derive",
167       sizeof (vl->identifier.type));
168   snprintf (vl->identifier.type_instance, sizeof (vl->identifier.type_instance),
169       "ti%li", random ());
170
171   return (vl);
172 } /* }}} int create_value_list */
173
174 static void destroy_value_list (lcc_value_list_t *vl) /* {{{ */
175 {
176   if (vl == NULL)
177     return;
178
179   free (vl->values);
180   free (vl->values_types);
181   free (vl);
182 } /* }}} void destroy_value_list */
183
184 static int send_value (lcc_value_list_t *vl) /* {{{ */
185 {
186   int status;
187
188   if (vl->values_types[0] == LCC_TYPE_GAUGE)
189     vl->values[0].gauge = 100.0 * ((gauge_t) random ()) / (((gauge_t) RAND_MAX) + 1.0);
190   else
191     vl->values[0].derive += get_boundet_random (0, 100);
192
193   status = lcc_network_buffer_add_value (nb, vl);
194   if (status != 0)
195   {
196     lcc_network_buffer_finalize (nb);
197     dump_network_buffer ();
198     lcc_network_buffer_initialize (nb);
199
200     status = lcc_network_buffer_add_value (nb, vl);
201   }
202
203   vl->time += vl->interval;
204
205   return (0);
206 } /* }}} int send_value */
207
208 int main (int argc, char **argv) /* {{{ */
209 {
210   size_t i;
211
212   nb = lcc_network_buffer_create (/* size = */ 0);
213   if (nb == NULL)
214   {
215     fprintf (stderr, "lcc_network_buffer_create failed.\n");
216     exit (EXIT_FAILURE);
217   }
218
219   values_num = (size_t) conf_num_values;
220   values = calloc (values_num, sizeof (*values));
221   if (values == NULL)
222   {
223     fprintf (stderr, "calloc failed.\n");
224     exit (EXIT_FAILURE);
225   }
226
227   fprintf (stdout, "Creating %i values ... ", conf_num_values);
228   fflush (stdout);
229   for (i = 0; i < values_num; i++)
230   {
231     values[i] = create_value_list ();
232     if (values[i] == NULL)
233     {
234       fprintf (stderr, "create_value_list failed.\n");
235       exit (EXIT_FAILURE);
236     }
237   }
238   fprintf (stdout, "done\n");
239
240   fprintf (stdout, "Sorting values by time ... ");
241   fflush (stdout);
242   qsort (values, values_num, sizeof (*values), compare_time);
243   fprintf (stdout, "done\n");
244
245   lcc_network_buffer_initialize (nb);
246   for (i = 0; i < values_num; i++)
247     send_value (values[i]);
248   lcc_network_buffer_finalize (nb);
249   dump_network_buffer ();
250
251   for (i = 0; i < values_num; i++)
252     destroy_value_list (values[i]);
253   free (values);
254
255   lcc_network_buffer_destroy (nb);
256   exit (EXIT_SUCCESS);
257   return (0);
258 } /* }}} int main */
259
260 /* vim: set sw=2 sts=2 et fdm=marker : */