2 * collectd - src/utils_logtail.c
3 * Copyright (C) 2007-2008 C-Ware, Inc.
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.
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.
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
19 * Luke Heberling <lukeh at c-ware.com>
22 * Encapsulates useful code to plugins which must parse a log file.
28 #include "utils_tail.h"
29 #include "utils_llist.h"
30 #include "utils_avltree.h"
32 struct logtail_instance_s
39 unsigned long *counters;
41 typedef struct logtail_instance_s logtail_instance_t;
43 static void submit (const char *plugin, const char *plugin_instance,
44 const char *name, value_t value)
46 value_list_t vl = VALUE_LIST_INIT;
53 vl.time = time (NULL);
54 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
55 sstrncpy (vl.plugin, plugin, sizeof (vl.plugin));
56 sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
57 sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
59 plugin_dispatch_values (name, &vl);
60 } /* static void submit */
62 static int destroy_instance (logtail_instance_t *inst)
68 if (inst->tail != NULL)
70 cu_tail_destroy (inst->tail);
73 if (inst->tree != NULL)
75 c_avl_destroy (inst->tree);
78 assert ((inst->list == NULL) || (llist_size (inst->list) == 0));
79 if (inst->list != NULL)
81 llist_destroy (inst->list);
85 sfree (inst->counters);
89 } /* int destroy_instance */
91 int logtail_term (llist_t **instances)
99 logtail_instance_t *instance;
101 if (*instances != NULL)
103 entry = llist_head (*instances);
109 instance = prev->value;
110 if (instance->list != NULL)
112 lentry = llist_head (instance->list);
116 lentry = lentry->next;
117 if (lprev->key != NULL)
119 if (lprev->value != NULL)
121 llist_remove (instance->list, lprev);
122 llentry_destroy (lprev);
126 llist_remove (*instances, prev);
127 llentry_destroy (prev);
128 destroy_instance (instance);
131 llist_destroy (*instances);
136 } /* int logtail_term */
138 int logtail_init (llist_t **instances)
140 if (*instances == NULL)
141 *instances = llist_create();
143 return (*instances == NULL);
144 } /* int logtail_init */
146 int logtail_read (llist_t **instances, tailfunc *func, char *plugin,
147 char **counter_instances)
154 for (entry = llist_head (*instances); entry != NULL; entry = entry->next )
156 logtail_instance_t *instance = (logtail_instance_t *) entry->value;
158 status = cu_tail_read (instance->tail, buffer, sizeof (buffer),
163 for (i = 0; counter_instances[i] != NULL; i++)
165 char *name = counter_instances[i];
168 value.counter = (counter_t) instance->counters[i];
170 submit (plugin, instance->name, name, value);
175 } /* int logtail_read */
177 int logtail_config (llist_t **instances, oconfig_item_t *ci, char *plugin,
178 char **names, char *default_file, int default_cache_size)
181 logtail_instance_t *instance;
186 oconfig_item_t *gchild;
189 oconfig_item_t *child = ci->children;
190 int children = ci->children_num;
192 while (*(names++) != NULL)
193 counterslen += sizeof (unsigned long);
195 if (*instances == NULL)
197 *instances = llist_create();
198 if (*instances == NULL)
203 for (; children; --children, ++child)
207 if (strcmp (child->key, "Instance") != 0)
209 WARNING ("%s plugin: Ignoring unknown"
210 " config option `%s'.", plugin, child->key);
214 if ((child->values_num != 1) ||
215 (child->values[0].type != OCONFIG_TYPE_STRING))
217 WARNING ("%s plugin: `Instance' needs exactly"
218 " one string argument.", plugin);
222 instance = malloc (sizeof (logtail_instance_t));
223 if (instance == NULL)
225 ERROR ("%s plugin: `malloc' failed.", plugin);
228 memset (instance, '\0', sizeof (logtail_instance_t));
230 instance->counters = malloc (counterslen);
231 if (instance->counters == NULL)
233 ERROR ("%s plugin: `malloc' failed.", plugin);
234 destroy_instance (instance);
237 memset (instance->counters, '\0', counterslen);
239 instance->name = strdup (child->values[0].value.string);
240 if (instance->name == NULL)
242 ERROR ("%s plugin: `strdup' failed.", plugin);
243 destroy_instance (instance);
247 instance->list = llist_create();
248 if (instance->list == NULL)
250 ERROR ("%s plugin: `llist_create' failed.", plugin);
251 destroy_instance (instance);
255 instance->tree = c_avl_create ((void *)strcmp);
256 if (instance->tree == NULL)
258 ERROR ("%s plugin: `c_avl_create' failed.", plugin);
259 destroy_instance (instance);
263 entry = llentry_create (instance->name, instance);
266 ERROR ("%s plugin: `llentry_create' failed.", plugin);
267 destroy_instance (instance);
271 gchild = child->children;
272 gchildren = child->children_num;
274 for (; gchildren; --gchildren, ++gchild)
276 if (strcmp (gchild->key, "LogFile") == 0)
278 if (gchild->values_num != 1 ||
279 gchild->values[0].type != OCONFIG_TYPE_STRING)
281 WARNING ("%s plugin: config option `%s'"
282 " should have exactly one string value.",
283 plugin, gchild->key);
286 if (tail_file != NULL)
288 WARNING ("%s plugin: ignoring extraneous"
289 " `LogFile' config option.", plugin);
292 tail_file = gchild->values[0].value.string;
294 else if (strcmp (gchild->key, "CacheSize") == 0)
296 if (gchild->values_num != 1
297 || gchild->values[0].type != OCONFIG_TYPE_NUMBER)
299 WARNING ("%s plugin: config option `%s'"
300 " should have exactly one numerical value.",
301 plugin, gchild->key);
304 if (instance->cache_size)
306 WARNING ("%s plugin: ignoring extraneous"
307 " `CacheSize' config option.", plugin);
310 instance->cache_size = gchild->values[0].value.number;
314 WARNING ("%s plugin: Ignoring unknown config option"
315 " `%s'.", plugin, gchild->key);
319 if (gchild->children_num)
321 WARNING ("%s plugin: config option `%s' should not"
322 " have children.", plugin, gchild->key);
326 if (tail_file == NULL)
327 tail_file = default_file;
328 instance->tail = cu_tail_create (tail_file);
329 if (instance->tail == NULL)
331 ERROR ("%s plugin: `cu_tail_create' failed.", plugin);
332 destroy_instance (instance);
334 llentry_destroy (entry);
338 if (instance->cache_size == 0)
339 instance->cache_size = default_cache_size;
341 llist_append (*instances, entry);
345 } /* int logtail_config */
347 unsigned long *logtail_counters (logtail_instance_t *instance)
349 return instance->counters;
350 } /* unsigned log *logtail_counters */
352 int logtail_cache (logtail_instance_t *instance, char *plugin, char *key, void **data, int len)
354 llentry_t *entry = NULL;
356 if (c_avl_get (instance->tree, key, (void*)&entry) == 0)
358 *data = entry->value;
362 if ((key = strdup (key)) == NULL)
364 ERROR ("%s plugin: `strdup' failed.", plugin);
368 if (data != NULL && (*data = malloc (len)) == NULL)
370 ERROR ("%s plugin: `malloc' failed.", plugin);
376 memset (*data, '\0', len);
378 entry = llentry_create (key, data == NULL ? NULL : *data);
381 ERROR ("%s plugin: `llentry_create' failed.", plugin);
388 if (c_avl_insert (instance->tree, key, entry) != 0)
390 ERROR ("%s plugin: `c_avl_insert' failed.", plugin);
391 llentry_destroy (entry);
398 llist_prepend (instance->list, entry);
400 while (llist_size (instance->list) > instance->cache_size &&
401 (entry = llist_tail (instance->list)) != NULL )
403 c_avl_remove (instance->tree, entry->key, NULL, NULL);
404 llist_remove (instance->list, entry);
406 if (entry->value != NULL)
408 llentry_destroy (entry);
414 void logtail_decache (logtail_instance_t *instance, char *key)
416 llentry_t *entry = NULL;
417 if (c_avl_remove (instance->tree, key, NULL, (void*)&entry))
420 llist_remove (instance->list, entry);
422 if (entry->value != NULL)
425 llentry_destroy (entry);
428 /* vim: set sw=2 sts=2 ts=8 : */