Merge branch 'collectd-4.10'
[collectd.git] / src / target_v5upgrade.c
1 /**
2  * collectd - src/target_set.c
3  * Copyright (C) 2008-2010  Florian Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation; only version 2.1 of the License is
8  * applicable.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18  *
19  * Authors:
20  *   Florian Forster <octo at verplant.org>
21  **/
22
23 #include "collectd.h"
24 #include "plugin.h"
25 #include "common.h"
26 #include "filter_chain.h"
27
28 static void v5_swap_instances (value_list_t *vl) /* {{{ */
29 {
30   char tmp[DATA_MAX_NAME_LEN];
31
32   assert (sizeof (tmp) == sizeof (vl->plugin_instance));
33   assert (sizeof (tmp) == sizeof (vl->type_instance));
34
35   memcpy (tmp, vl->plugin_instance, sizeof (tmp));
36   memcpy (vl->plugin_instance, vl->type_instance, sizeof (tmp));
37   memcpy (vl->type_instance, tmp, sizeof (tmp));
38 } /* }}} void v5_swap_instances */
39
40 /*
41  * Df type
42  *
43  * By default, the "df" plugin of version 4.* uses the "df" type and puts the
44  * mount point in the type instance. Detect this behavior and convert the type
45  * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
46  * the "ReportReserved" option of the "df" plugin.
47  */
48 static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
49 {
50   value_list_t new_vl;
51   value_t new_value;
52
53   /* Can't upgrade if both instances have been set. */
54   if ((vl->plugin_instance[0] != 0)
55       && (vl->type_instance[0] != 0))
56     return (FC_TARGET_CONTINUE);
57
58   /* Copy everything: Time, interval, host, ... */
59   memcpy (&new_vl, vl, sizeof (new_vl));
60
61   /* Reset data we can't simply copy */
62   new_vl.values = &new_value;
63   new_vl.values_len = 1;
64   new_vl.meta = NULL;
65
66   /* Move the mount point name to the plugin instance */
67   if (new_vl.plugin_instance[0] == 0)
68     v5_swap_instances (&new_vl);
69
70   /* Change the type to "df_complex" */
71   sstrncpy (new_vl.type, "df_complex", sizeof (new_vl.type));
72
73   /* Dispatch two new value lists instead of this one */
74   new_vl.values[0].gauge = vl->values[0].gauge;
75   sstrncpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
76   plugin_dispatch_values (&new_vl);
77
78   new_vl.values[0].gauge = vl->values[1].gauge;
79   sstrncpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
80   plugin_dispatch_values (&new_vl);
81
82   /* Abort processing */
83   return (FC_TARGET_STOP);
84 } /* }}} int v5_df */
85
86 /*
87  * Interface plugin
88  *
89  * 4.* stores the interface in the type instance and leaves the plugin
90  * instance empty. If this is the case, put the interface name into the plugin
91  * instance and clear the type instance.
92  */
93 static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
94 {
95   if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
96     return (FC_TARGET_CONTINUE);
97
98   v5_swap_instances (vl);
99   return (FC_TARGET_CONTINUE);
100 } /* }}} int v5_interface */
101
102 /*
103  * MySQL query cache
104  *
105  * 4.* uses the "mysql_qcache" type which mixes different types of
106  * information. In 5.* this has been broken up.
107  */
108 static int v5_mysql_qcache (const data_set_t *ds, value_list_t *vl) /* {{{ */
109 {
110   value_list_t new_vl;
111   value_t new_value;
112
113   if (vl->values_len != 5)
114     return (FC_TARGET_STOP);
115
116   /* Copy everything: Time, interval, host, ... */
117   memcpy (&new_vl, vl, sizeof (new_vl));
118
119   /* Reset data we can't simply copy */
120   new_vl.values = &new_value;
121   new_vl.values_len = 1;
122   new_vl.meta = NULL;
123
124   /* Change the type to "cache_result" */
125   sstrncpy (new_vl.type, "cache_result", sizeof (new_vl.type));
126
127   /* Dispatch new value lists instead of this one */
128   new_vl.values[0].derive = (derive_t) vl->values[0].counter;
129   sstrncpy (new_vl.type_instance, "qcache-hits",
130       sizeof (new_vl.type_instance));
131   plugin_dispatch_values (&new_vl);
132
133   new_vl.values[0].derive = (derive_t) vl->values[1].counter;
134   sstrncpy (new_vl.type_instance, "qcache-inserts",
135       sizeof (new_vl.type_instance));
136   plugin_dispatch_values (&new_vl);
137
138   new_vl.values[0].derive = (derive_t) vl->values[2].counter;
139   sstrncpy (new_vl.type_instance, "qcache-not_cached",
140       sizeof (new_vl.type_instance));
141   plugin_dispatch_values (&new_vl);
142
143   new_vl.values[0].derive = (derive_t) vl->values[3].counter;
144   sstrncpy (new_vl.type_instance, "qcache-prunes",
145       sizeof (new_vl.type_instance));
146   plugin_dispatch_values (&new_vl);
147
148   /* The last data source is a gauge value, so we have to use a different type
149    * here. */
150   new_vl.values[0].gauge = vl->values[4].gauge;
151   sstrncpy (new_vl.type, "cache_size", sizeof (new_vl.type));
152   sstrncpy (new_vl.type_instance, "qcache",
153       sizeof (new_vl.type_instance));
154   plugin_dispatch_values (&new_vl);
155
156   /* Abort processing */
157   return (FC_TARGET_STOP);
158 } /* }}} int v5_mysql_qcache */
159
160 /*
161  * MySQL thread count
162  *
163  * 4.* uses the "mysql_threads" type which mixes different types of
164  * information. In 5.* this has been broken up.
165  */
166 static int v5_mysql_threads (const data_set_t *ds, value_list_t *vl) /* {{{ */
167 {
168   value_list_t new_vl;
169   value_t new_value;
170
171   if (vl->values_len != 4)
172     return (FC_TARGET_STOP);
173
174   /* Copy everything: Time, interval, host, ... */
175   memcpy (&new_vl, vl, sizeof (new_vl));
176
177   /* Reset data we can't simply copy */
178   new_vl.values = &new_value;
179   new_vl.values_len = 1;
180   new_vl.meta = NULL;
181
182   /* Change the type to "threads" */
183   sstrncpy (new_vl.type, "threads", sizeof (new_vl.type));
184
185   /* Dispatch new value lists instead of this one */
186   new_vl.values[0].gauge = vl->values[0].gauge;
187   sstrncpy (new_vl.type_instance, "running",
188       sizeof (new_vl.type_instance));
189   plugin_dispatch_values (&new_vl);
190
191   new_vl.values[0].gauge = vl->values[1].gauge;
192   sstrncpy (new_vl.type_instance, "connected",
193       sizeof (new_vl.type_instance));
194   plugin_dispatch_values (&new_vl);
195
196   new_vl.values[0].gauge = vl->values[2].gauge;
197   sstrncpy (new_vl.type_instance, "cached",
198       sizeof (new_vl.type_instance));
199   plugin_dispatch_values (&new_vl);
200
201   /* The last data source is a counter value, so we have to use a different
202    * type here. */
203   new_vl.values[0].derive = (derive_t) vl->values[3].counter;
204   sstrncpy (new_vl.type, "total_threads", sizeof (new_vl.type));
205   sstrncpy (new_vl.type_instance, "created",
206       sizeof (new_vl.type_instance));
207   plugin_dispatch_values (&new_vl);
208
209   /* Abort processing */
210   return (FC_TARGET_STOP);
211 } /* }}} int v5_mysql_threads */
212
213 static int v5_destroy (void **user_data) /* {{{ */
214 {
215   return (0);
216 } /* }}} int v5_destroy */
217
218 static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
219 {
220   *user_data = NULL;
221   return (0);
222 } /* }}} int v5_create */
223
224 static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
225     notification_meta_t __attribute__((unused)) **meta,
226     void __attribute__((unused)) **user_data)
227 {
228   if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
229     return (-EINVAL);
230
231   if (strcmp ("df", vl->type) == 0)
232     return (v5_df (ds, vl));
233   else if (strcmp ("interface", vl->plugin) == 0)
234     return (v5_interface (ds, vl));
235   else if (strcmp ("mysql_qcache", vl->type) == 0)
236     return (v5_mysql_qcache (ds, vl));
237   else if (strcmp ("mysql_threads", vl->type) == 0)
238     return (v5_mysql_threads (ds, vl));
239
240   return (FC_TARGET_CONTINUE);
241 } /* }}} int v5_invoke */
242
243 void module_register (void)
244 {
245         target_proc_t tproc;
246
247         memset (&tproc, 0, sizeof (tproc));
248         tproc.create  = v5_create;
249         tproc.destroy = v5_destroy;
250         tproc.invoke  = v5_invoke;
251         fc_register_target ("v5upgrade", tproc);
252 } /* module_register */
253
254 /* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
255