{GPL, other}: Relicense to MIT license.
[collectd.git] / src / target_v5upgrade.c
1 /**
2  * collectd - src/target_v5upgrade.c
3  * Copyright (C) 2008-2010  Florian Forster
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *   Florian Forster <octo at collectd.org>
25  **/
26
27 #include "collectd.h"
28 #include "plugin.h"
29 #include "common.h"
30 #include "filter_chain.h"
31
32 static void v5_swap_instances (value_list_t *vl) /* {{{ */
33 {
34   char tmp[DATA_MAX_NAME_LEN];
35
36   assert (sizeof (tmp) == sizeof (vl->plugin_instance));
37   assert (sizeof (tmp) == sizeof (vl->type_instance));
38
39   memcpy (tmp, vl->plugin_instance, sizeof (tmp));
40   memcpy (vl->plugin_instance, vl->type_instance, sizeof (tmp));
41   memcpy (vl->type_instance, tmp, sizeof (tmp));
42 } /* }}} void v5_swap_instances */
43
44 /*
45  * Df type
46  *
47  * By default, the "df" plugin of version 4.* uses the "df" type and puts the
48  * mount point in the type instance. Detect this behavior and convert the type
49  * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
50  * the "ReportReserved" option of the "df" plugin.
51  */
52 static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
53 {
54   value_list_t new_vl;
55   value_t new_value;
56
57   /* Can't upgrade if both instances have been set. */
58   if ((vl->plugin_instance[0] != 0)
59       && (vl->type_instance[0] != 0))
60     return (FC_TARGET_CONTINUE);
61
62   /* Copy everything: Time, interval, host, ... */
63   memcpy (&new_vl, vl, sizeof (new_vl));
64
65   /* Reset data we can't simply copy */
66   new_vl.values = &new_value;
67   new_vl.values_len = 1;
68   new_vl.meta = NULL;
69
70   /* Move the mount point name to the plugin instance */
71   if (new_vl.plugin_instance[0] == 0)
72     v5_swap_instances (&new_vl);
73
74   /* Change the type to "df_complex" */
75   sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
76
77   /* Dispatch two new value lists instead of this one */
78   new_vl.values[0].gauge = vl->values[0].gauge;
79   sstrncpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
80   plugin_dispatch_values (&new_vl);
81
82   new_vl.values[0].gauge = vl->values[1].gauge;
83   sstrncpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
84   plugin_dispatch_values (&new_vl);
85
86   /* Abort processing */
87   return (FC_TARGET_STOP);
88 } /* }}} int v5_df */
89
90 /*
91  * Interface plugin
92  *
93  * 4.* stores the interface in the type instance and leaves the plugin
94  * instance empty. If this is the case, put the interface name into the plugin
95  * instance and clear the type instance.
96  */
97 static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
98 {
99   if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
100     return (FC_TARGET_CONTINUE);
101
102   v5_swap_instances (vl);
103   return (FC_TARGET_CONTINUE);
104 } /* }}} int v5_interface */
105
106 /*
107  * MySQL query cache
108  *
109  * 4.* uses the "mysql_qcache" type which mixes different types of
110  * information. In 5.* this has been broken up.
111  */
112 static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
113 {
114   value_list_t new_vl;
115   value_t new_value;
116
117   if (vl->values_len != 5)
118     return (FC_TARGET_STOP);
119
120   /* Copy everything: Time, interval, host, ... */
121   memcpy (&new_vl, vl, sizeof (new_vl));
122
123   /* Reset data we can't simply copy */
124   new_vl.values = &new_value;
125   new_vl.values_len = 1;
126   new_vl.meta = NULL;
127
128   /* Change the type to "cache_result" */
129   sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
130
131   /* Dispatch new value lists instead of this one */
132   new_vl.values[0].derive = (derive_t) vl->values[0].counter;
133   sstrncpy (new_vl.type_instance, "qcache-hits",
134       sizeof (new_vl.type_instance));
135   plugin_dispatch_values (&new_vl);
136
137   new_vl.values[0].derive = (derive_t) vl->values[1].counter;
138   sstrncpy (new_vl.type_instance, "qcache-inserts",
139       sizeof (new_vl.type_instance));
140   plugin_dispatch_values (&new_vl);
141
142   new_vl.values[0].derive = (derive_t) vl->values[2].counter;
143   sstrncpy (new_vl.type_instance, "qcache-not_cached",
144       sizeof (new_vl.type_instance));
145   plugin_dispatch_values (&new_vl);
146
147   new_vl.values[0].derive = (derive_t) vl->values[3].counter;
148   sstrncpy (new_vl.type_instance, "qcache-prunes",
149       sizeof (new_vl.type_instance));
150   plugin_dispatch_values (&new_vl);
151
152   /* The last data source is a gauge value, so we have to use a different type
153    * here. */
154   new_vl.values[0].gauge = vl->values[4].gauge;
155   sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
156   sstrncpy (new_vl.type_instance, "qcache",
157       sizeof (new_vl.type_instance));
158   plugin_dispatch_values (&new_vl);
159
160   /* Abort processing */
161   return (FC_TARGET_STOP);
162 } /* }}} int v5_mysql_qcache */
163
164 /*
165  * MySQL thread count
166  *
167  * 4.* uses the "mysql_threads" type which mixes different types of
168  * information. In 5.* this has been broken up.
169  */
170 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
171 {
172   value_list_t new_vl;
173   value_t new_value;
174
175   if (vl->values_len != 4)
176     return (FC_TARGET_STOP);
177
178   /* Copy everything: Time, interval, host, ... */
179   memcpy (&new_vl, vl, sizeof (new_vl));
180
181   /* Reset data we can't simply copy */
182   new_vl.values = &new_value;
183   new_vl.values_len = 1;
184   new_vl.meta = NULL;
185
186   /* Change the type to "threads" */
187   sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
188
189   /* Dispatch new value lists instead of this one */
190   new_vl.values[0].gauge = vl->values[0].gauge;
191   sstrncpy (new_vl.type_instance, "running",
192       sizeof (new_vl.type_instance));
193   plugin_dispatch_values (&new_vl);
194
195   new_vl.values[0].gauge = vl->values[1].gauge;
196   sstrncpy (new_vl.type_instance, "connected",
197       sizeof (new_vl.type_instance));
198   plugin_dispatch_values (&new_vl);
199
200   new_vl.values[0].gauge = vl->values[2].gauge;
201   sstrncpy (new_vl.type_instance, "cached",
202       sizeof (new_vl.type_instance));
203   plugin_dispatch_values (&new_vl);
204
205   /* The last data source is a counter value, so we have to use a different
206    * type here. */
207   new_vl.values[0].derive = (derive_t) vl->values[3].counter;
208   sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
209   sstrncpy (new_vl.type_instance, "created",
210       sizeof (new_vl.type_instance));
211   plugin_dispatch_values (&new_vl);
212
213   /* Abort processing */
214   return (FC_TARGET_STOP);
215 } /* }}} int v5_mysql_threads */
216
217 /*
218  * ZFS ARC hit and miss counters
219  *
220  * 4.* uses the flawed "arc_counts" type. In 5.* this has been replaced by the
221  * more generic "cache_result" type.
222  */
223 static int v5_zfs_arc_counts (const data_set_t *ds, value_list_t *vl) /* {{{ */
224 {
225   value_list_t new_vl;
226   value_t new_value;
227   _Bool is_hits;
228
229   if (vl->values_len != 4)
230     return (FC_TARGET_STOP);
231
232   if (strcmp ("hits", vl->type_instance) == 0)
233     is_hits = 1;
234   else if (strcmp ("misses", vl->type_instance) == 0)
235     is_hits = 0;
236   else
237     return (FC_TARGET_STOP);
238
239   /* Copy everything: Time, interval, host, ... */
240   memcpy (&new_vl, vl, sizeof (new_vl));
241
242   /* Reset data we can't simply copy */
243   new_vl.values = &new_value;
244   new_vl.values_len = 1;
245   new_vl.meta = NULL;
246
247   /* Change the type to "cache_result" */
248   sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
249
250   /* Dispatch new value lists instead of this one */
251   new_vl.values[0].derive = (derive_t) vl->values[0].counter;
252   ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
253       "demand_data-%s",
254       is_hits ? "hit" : "miss");
255   plugin_dispatch_values (&new_vl);
256
257   new_vl.values[0].derive = (derive_t) vl->values[1].counter;
258   ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
259       "demand_metadata-%s",
260       is_hits ? "hit" : "miss");
261   plugin_dispatch_values (&new_vl);
262
263   new_vl.values[0].derive = (derive_t) vl->values[2].counter;
264   ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
265       "prefetch_data-%s",
266       is_hits ? "hit" : "miss");
267   plugin_dispatch_values (&new_vl);
268
269   new_vl.values[0].derive = (derive_t) vl->values[3].counter;
270   ssnprintf (new_vl.type_instance, sizeof (new_vl.type_instance),
271       "prefetch_metadata-%s",
272       is_hits ? "hit" : "miss");
273   plugin_dispatch_values (&new_vl);
274
275   /* Abort processing */
276   return (FC_TARGET_STOP);
277 } /* }}} int v5_zfs_arc_counts */
278
279 /*
280  * ZFS ARC L2 bytes
281  *
282  * "arc_l2_bytes" -> "io_octets-L2".
283  */
284 static int v5_zfs_arc_l2_bytes (const data_set_t *ds, value_list_t *vl) /* {{{ */
285 {
286   value_list_t new_vl;
287   value_t new_values[2];
288
289   if (vl->values_len != 2)
290     return (FC_TARGET_STOP);
291
292   /* Copy everything: Time, interval, host, ... */
293   memcpy (&new_vl, vl, sizeof (new_vl));
294
295   /* Reset data we can't simply copy */
296   new_vl.values = new_values;
297   new_vl.values_len = 2;
298   new_vl.meta = NULL;
299
300   /* Change the type/-instance to "io_octets-L2" */
301   sstrncpy (new_vl.type, "io_octets", sizeof (new_vl.type));
302   sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
303
304   /* Copy the actual values. */
305   new_vl.values[0].derive = (derive_t) vl->values[0].counter;
306   new_vl.values[1].derive = (derive_t) vl->values[1].counter;
307
308   /* Dispatch new value lists instead of this one */
309   plugin_dispatch_values (&new_vl);
310
311   /* Abort processing */
312   return (FC_TARGET_STOP);
313 } /* }}} int v5_zfs_arc_l2_bytes */
314
315 /*
316  * ZFS ARC L2 cache size
317  *
318  * 4.* uses a separate type for this. 5.* uses the generic "cache_size" type
319  * instead.
320  */
321 static int v5_zfs_arc_l2_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
322 {
323   value_list_t new_vl;
324   value_t new_value;
325
326   if (vl->values_len != 1)
327     return (FC_TARGET_STOP);
328
329   /* Copy everything: Time, interval, host, ... */
330   memcpy (&new_vl, vl, sizeof (new_vl));
331
332   /* Reset data we can't simply copy */
333   new_vl.values = &new_value;
334   new_vl.values_len = 1;
335   new_vl.meta = NULL;
336
337   new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
338
339   /* Change the type to "cache_size" */
340   sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
341
342   /* Adapt the type instance */
343   sstrncpy (new_vl.type_instance, "L2", sizeof (new_vl.type_instance));
344
345   /* Dispatch new value lists instead of this one */
346   plugin_dispatch_values (&new_vl);
347
348   /* Abort processing */
349   return (FC_TARGET_STOP);
350 } /* }}} int v5_zfs_arc_l2_size */
351
352 /*
353  * ZFS ARC ratio
354  *
355  * "arc_ratio-L1" -> "cache_ratio-arc"
356  * "arc_ratio-L2" -> "cache_ratio-L2"
357  */
358 static int v5_zfs_arc_ratio (const data_set_t *ds, value_list_t *vl) /* {{{ */
359 {
360   value_list_t new_vl;
361   value_t new_value;
362
363   if (vl->values_len != 1)
364     return (FC_TARGET_STOP);
365
366   /* Copy everything: Time, interval, host, ... */
367   memcpy (&new_vl, vl, sizeof (new_vl));
368
369   /* Reset data we can't simply copy */
370   new_vl.values = &new_value;
371   new_vl.values_len = 1;
372   new_vl.meta = NULL;
373
374   new_vl.values[0].gauge = (gauge_t) vl->values[0].gauge;
375
376   /* Change the type to "cache_ratio" */
377   sstrncpy (new_vl.type, "cache_ratio", sizeof (new_vl.type));
378
379   /* Adapt the type instance */
380   if (strcmp ("L1", vl->type_instance) == 0)
381     sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
382
383   /* Dispatch new value lists instead of this one */
384   plugin_dispatch_values (&new_vl);
385
386   /* Abort processing */
387   return (FC_TARGET_STOP);
388 } /* }}} int v5_zfs_arc_ratio */
389
390 /*
391  * ZFS ARC size
392  *
393  * 4.* uses the "arc_size" type with four data sources. In 5.* this has been
394  * replaces with the "cache_size" type and static data has been removed.
395  */
396 static int v5_zfs_arc_size (const data_set_t *ds, value_list_t *vl) /* {{{ */
397 {
398   value_list_t new_vl;
399   value_t new_value;
400
401   if (vl->values_len != 4)
402     return (FC_TARGET_STOP);
403
404   /* Copy everything: Time, interval, host, ... */
405   memcpy (&new_vl, vl, sizeof (new_vl));
406
407   /* Reset data we can't simply copy */
408   new_vl.values = &new_value;
409   new_vl.values_len = 1;
410   new_vl.meta = NULL;
411
412   /* Change the type to "cache_size" */
413   sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
414
415   /* Dispatch new value lists instead of this one */
416   new_vl.values[0].derive = (derive_t) vl->values[0].counter;
417   sstrncpy (new_vl.type_instance, "arc", sizeof (new_vl.type_instance));
418   plugin_dispatch_values (&new_vl);
419
420   /* Abort processing */
421   return (FC_TARGET_STOP);
422 } /* }}} int v5_zfs_arc_size */
423
424 static int v5_destroy (void **user_data) /* {{{ */
425 {
426   return (0);
427 } /* }}} int v5_destroy */
428
429 static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
430 {
431   *user_data = NULL;
432   return (0);
433 } /* }}} int v5_create */
434
435 static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
436     notification_meta_t __attribute__((unused)) **meta,
437     void __attribute__((unused)) **user_data)
438 {
439   if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
440     return (-EINVAL);
441
442   if (strcmp ("df", vl->type) == 0)
443     return (v5_df (ds, vl));
444   else if (strcmp ("interface", vl->plugin) == 0)
445     return (v5_interface (ds, vl));
446   else if (strcmp ("mysql_qcache", vl->type) == 0)
447     return (v5_mysql_qcache (ds, vl));
448   else if (strcmp ("mysql_threads", vl->type) == 0)
449     return (v5_mysql_threads (ds, vl));
450   else if (strcmp ("arc_counts", vl->type) == 0)
451     return (v5_zfs_arc_counts (ds, vl));
452   else if (strcmp ("arc_l2_bytes", vl->type) == 0)
453     return (v5_zfs_arc_l2_bytes (ds, vl));
454   else if (strcmp ("arc_l2_size", vl->type) == 0)
455     return (v5_zfs_arc_l2_size (ds, vl));
456   else if (strcmp ("arc_ratio", vl->type) == 0)
457     return (v5_zfs_arc_ratio (ds, vl));
458   else if (strcmp ("arc_size", vl->type) == 0)
459     return (v5_zfs_arc_size (ds, vl));
460
461   return (FC_TARGET_CONTINUE);
462 } /* }}} int v5_invoke */
463
464 void module_register (void)
465 {
466         target_proc_t tproc;
467
468         memset (&tproc, 0, sizeof (tproc));
469         tproc.create  = v5_create;
470         tproc.destroy = v5_destroy;
471         tproc.invoke  = v5_invoke;
472         fc_register_target ("v5upgrade", tproc);
473 } /* module_register */
474
475 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
476