utils_cache.c utils_cache.h \
utils_ignorelist.c utils_ignorelist.h \
utils_llist.c utils_llist.h \
+ utils_tail_match.c utils_tail_match.h \
+ utils_match.c utils_match.h \
utils_mount.c utils_mount.h \
+ utils_tail.c utils_tail.h \
utils_threshold.c utils_threshold.h \
types_list.c types_list.h
collectd_CPPFLAGS = $(LTDLINCL)
if BUILD_PLUGIN_EXEC
pkglib_LTLIBRARIES += exec.la
- exec_la_SOURCES = exec.c utils_cmd_putval.c utils_cmd_putval.h
+ exec_la_SOURCES = exec.c \
+ utils_cmd_putnotif.c utils_cmd_putnotif.h \
+ utils_cmd_putval.c utils_cmd_putval.h
exec_la_LDFLAGS = -module -avoid-version
if BUILD_WITH_LIBPTHREAD
exec_la_LDFLAGS += -lpthread
collectd_DEPENDENCIES += syslog.la
endif
+if BUILD_PLUGIN_TAIL
+pkglib_LTLIBRARIES += tail.la
+tail_la_SOURCES = tail.c
+tail_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" tail.la
+collectd_DEPENDENCIES += tail.la
+endif
+
if BUILD_PLUGIN_TAPE
pkglib_LTLIBRARIES += tape.la
tape_la_SOURCES = tape.c
if BUILD_PLUGIN_UNIXSOCK
pkglib_LTLIBRARIES += unixsock.la
-unixsock_la_SOURCES = unixsock.c utils_cmd_putval.h utils_cmd_putval.c utils_cmd_putnotif.h utils_cmd_putnotif.c
+unixsock_la_SOURCES = unixsock.c \
+ utils_cmd_getval.h utils_cmd_getval.c \
+ utils_cmd_putval.h utils_cmd_putval.c \
+ utils_cmd_putnotif.h utils_cmd_putnotif.c
unixsock_la_LDFLAGS = -module -avoid-version -lpthread
collectd_LDADD += "-dlopen" unixsock.la
collectd_DEPENDENCIES += unixsock.la
static int write_part_values (char **ret_buffer, int *ret_buffer_len,
const data_set_t *ds, const value_list_t *vl)
{
- part_values_t pv;
+ char *packet_ptr;
+ int packet_len;
+ int num_values;
+
+ part_header_t pkg_ph;
+ uint16_t pkg_num_values;
+ uint8_t *pkg_values_types;
+ value_t *pkg_values;
+
+ int offset;
int i;
- i = 6 + (9 * vl->values_len);
- if (*ret_buffer_len < i)
+ num_values = vl->values_len;
+ packet_len = sizeof (part_header_t) + sizeof (uint16_t)
+ + (num_values * sizeof (uint8_t))
+ + (num_values * sizeof (value_t));
+
+ if (*ret_buffer_len < packet_len)
return (-1);
- *ret_buffer_len -= i;
- pv.head = (part_header_t *) *ret_buffer;
- pv.num_values = (uint16_t *) (pv.head + 1);
- pv.values_types = (uint8_t *) (pv.num_values + 1);
- pv.values = (value_t *) (pv.values_types + vl->values_len);
- *ret_buffer = (void *) (pv.values + vl->values_len);
+ pkg_values_types = (uint8_t *) malloc (num_values * sizeof (uint8_t));
+ if (pkg_values_types == NULL)
+ {
+ ERROR ("network plugin: write_part_values: malloc failed.");
+ return (-1);
+ }
- pv.head->type = htons (TYPE_VALUES);
- pv.head->length = htons (6 + (9 * vl->values_len));
- *pv.num_values = htons ((uint16_t) vl->values_len);
-
- for (i = 0; i < vl->values_len; i++)
+ pkg_values = (value_t *) malloc (num_values * sizeof (value_t));
+ if (pkg_values == NULL)
+ {
+ free (pkg_values_types);
+ ERROR ("network plugin: write_part_values: malloc failed.");
+ return (-1);
+ }
+
+ pkg_ph.type = htons (TYPE_VALUES);
+ pkg_ph.length = htons (packet_len);
+
+ pkg_num_values = htons ((uint16_t) vl->values_len);
+
+ for (i = 0; i < num_values; i++)
{
if (ds->ds[i].type == DS_TYPE_COUNTER)
{
- pv.values_types[i] = DS_TYPE_COUNTER;
- pv.values[i].counter = htonll (vl->values[i].counter);
+ pkg_values_types[i] = DS_TYPE_COUNTER;
+ pkg_values[i].counter = htonll (vl->values[i].counter);
}
else
{
- pv.values_types[i] = DS_TYPE_GAUGE;
- pv.values[i].gauge = vl->values[i].gauge;
+ pkg_values_types[i] = DS_TYPE_GAUGE;
+ pkg_values[i].gauge = vl->values[i].gauge;
}
- } /* for (values) */
+ }
+
+ /*
+ * Use `memcpy' to write everything to the buffer, because the pointer
+ * may be unaligned and some architectures, such as SPARC, can't handle
+ * that.
+ */
+ packet_ptr = *ret_buffer;
+ offset = 0;
+ memcpy (packet_ptr + offset, &pkg_ph, sizeof (pkg_ph));
+ offset += sizeof (pkg_ph);
+ memcpy (packet_ptr + offset, &pkg_num_values, sizeof (pkg_num_values));
+ offset += sizeof (pkg_num_values);
+ memcpy (packet_ptr + offset, pkg_values_types, num_values * sizeof (uint8_t));
+ offset += num_values * sizeof (uint8_t);
+ memcpy (packet_ptr + offset, pkg_values, num_values * sizeof (value_t));
+ offset += num_values * sizeof (value_t);
+
+ assert (offset == packet_len);
+
+ *ret_buffer = packet_ptr + packet_len;
+ *ret_buffer_len -= packet_len;
+
+ free (pkg_values_types);
+ free (pkg_values);
return (0);
} /* int write_part_values */
static int write_part_number (char **ret_buffer, int *ret_buffer_len,
int type, uint64_t value)
{
- part_number_t pn;
+ char *packet_ptr;
+ int packet_len;
+
+ part_header_t pkg_head;
+ uint64_t pkg_value;
+
+ int offset;
+
+ packet_len = sizeof (pkg_head) + sizeof (pkg_value);
- if (*ret_buffer_len < 12)
+ if (*ret_buffer_len < packet_len)
return (-1);
- pn.head = (part_header_t *) *ret_buffer;
- pn.value = (uint64_t *) (pn.head + 1);
+ pkg_head.type = htons (type);
+ pkg_head.length = htons (packet_len);
+ pkg_value = htonll (value);
- pn.head->type = htons (type);
- pn.head->length = htons (12);
- *pn.value = htonll (value);
+ packet_ptr = *ret_buffer;
+ offset = 0;
+ memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head));
+ offset += sizeof (pkg_head);
+ memcpy (packet_ptr + offset, &pkg_value, sizeof (pkg_value));
+ offset += sizeof (pkg_value);
- *ret_buffer = (char *) (pn.value + 1);
- *ret_buffer_len -= 12;
+ assert (offset == packet_len);
+
+ *ret_buffer = packet_ptr + packet_len;
+ *ret_buffer_len -= packet_len;
return (0);
} /* int write_part_number */
static int write_part_string (char **ret_buffer, int *ret_buffer_len,
int type, const char *str, int str_len)
{
- part_string_t ps;
- int len;
+ char *packet_ptr;
+ int packet_len;
+
+ part_header_t pkg_head;
+
+ int offset;
- len = 4 + str_len + 1;
- if (*ret_buffer_len < len)
+ packet_len = sizeof (pkg_head) + str_len + 1;
+ if (*ret_buffer_len < packet_len)
return (-1);
- *ret_buffer_len -= len;
- ps.head = (part_header_t *) *ret_buffer;
- ps.value = (char *) (ps.head + 1);
+ pkg_head.type = htons (type);
+ pkg_head.length = htons (packet_len);
+
+ packet_ptr = *ret_buffer;
+ offset = 0;
+ memcpy (packet_ptr + offset, &pkg_head, sizeof (pkg_head));
+ offset += sizeof (pkg_head);
+ memcpy (packet_ptr + offset, str, str_len);
+ offset += str_len;
+ memset (packet_ptr + offset, '\0', 1);
+ offset += 1;
+
+ assert (offset == packet_len);
- ps.head->type = htons ((uint16_t) type);
- ps.head->length = htons ((uint16_t) str_len + 5);
- if (str_len > 0)
- memcpy (ps.value, str, str_len);
- ps.value[str_len] = '\0';
- *ret_buffer = (void *) (ps.value + (str_len + 1));
+ *ret_buffer = packet_ptr + packet_len;
+ *ret_buffer_len -= packet_len;
return (0);
} /* int write_part_string */
return (0);
} /* int network_init */
+static int network_flush (int timeout)
+{
+ pthread_mutex_lock (&send_buffer_lock);
+
+ if (((time (NULL) - cache_flush_last) >= timeout)
+ && (send_buffer_fill > 0))
+ {
+ flush_buffer ();
+ }
+
+ pthread_mutex_unlock (&send_buffer_lock);
+
+ return (0);
+} /* int network_flush */
+
void module_register (void)
{
plugin_register_config ("network", network_config,
config_keys, config_keys_num);
plugin_register_init ("network", network_init);
+ plugin_register_flush ("network", network_flush);
} /* void module_register */
return (strcmp (a->name, b->name));
} /* int cache_compare */
+ static cache_entry_t *cache_alloc (int values_num)
+ {
+ cache_entry_t *ce;
+
+ ce = (cache_entry_t *) malloc (sizeof (cache_entry_t));
+ if (ce == NULL)
+ {
+ ERROR ("utils_cache: cache_alloc: malloc failed.");
+ return (NULL);
+ }
+ memset (ce, '\0', sizeof (cache_entry_t));
+ ce->values_num = values_num;
+
+ ce->values_gauge = (gauge_t *) calloc (values_num, sizeof (gauge_t));
+ ce->values_counter = (counter_t *) calloc (values_num, sizeof (counter_t));
+ if ((ce->values_gauge == NULL) || (ce->values_counter == NULL))
+ {
+ sfree (ce->values_gauge);
+ sfree (ce->values_counter);
+ sfree (ce);
+ ERROR ("utils_cache: cache_alloc: calloc failed.");
+ return (NULL);
+ }
+
+ return (ce);
+ } /* cache_entry_t *cache_alloc */
+
+ static void cache_free (cache_entry_t *ce)
+ {
+ if (ce == NULL)
+ return;
+
+ sfree (ce->values_gauge);
+ sfree (ce->values_counter);
+ sfree (ce);
+ } /* void cache_free */
+
static int uc_send_notification (const char *name)
{
cache_entry_t *ce = NULL;
ERROR ("uc_check_timeout: c_avl_remove (%s) failed.", keys[i]);
}
sfree (keys[i]);
- sfree (ce);
+ cache_free (ce);
}
else /* (status > 0); ``service'' is interesting */
{
else /* key is not found */
{
int i;
- size_t ce_size = sizeof (cache_entry_t)
- + ds->ds_num * (sizeof (counter_t) + sizeof (gauge_t));
char *key;
key = strdup (name);
return (-1);
}
- ce = (cache_entry_t *) malloc (ce_size);
+ ce = cache_alloc (ds->ds_num);
if (ce == NULL)
{
pthread_mutex_unlock (&cache_lock);
- ERROR ("uc_insert: malloc (%u) failed.", (unsigned int) ce_size);
+ ERROR ("uc_insert: cache_alloc (%i) failed.", ds->ds_num);
return (-1);
}
- memset (ce, '\0', ce_size);
-
- strncpy (ce->name, name, sizeof (ce->name));
- ce->name[sizeof (ce->name) - 1] = '\0';
-
- ce->values_num = ds->ds_num;
- ce->values_gauge = (gauge_t *) (ce + 1);
- ce->values_counter = (counter_t *) (ce->values_gauge + ce->values_num);
+ sstrncpy (ce->name, name, sizeof (ce->name));
for (i = 0; i < ds->ds_num; i++)
{
return (0);
} /* int uc_insert */
-gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+int uc_get_rate_by_name (const char *name, gauge_t **ret_values, size_t *ret_values_num)
{
- char name[6 * DATA_MAX_NAME_LEN];
gauge_t *ret = NULL;
+ size_t ret_num = 0;
cache_entry_t *ce = NULL;
-
- if (FORMAT_VL (name, sizeof (name), vl, ds) != 0)
- {
- ERROR ("uc_insert: FORMAT_VL failed.");
- return (NULL);
- }
+ int status = 0;
pthread_mutex_lock (&cache_lock);
if (c_avl_get (cache_tree, name, (void *) &ce) == 0)
{
assert (ce != NULL);
- assert (ce->values_num == ds->ds_num);
- ret = (gauge_t *) malloc (ce->values_num * sizeof (gauge_t));
+ ret_num = ce->values_num;
+ ret = (gauge_t *) malloc (ret_num * sizeof (gauge_t));
if (ret == NULL)
{
- ERROR ("uc_get_rate: malloc failed.");
+ ERROR ("utils_cache: uc_get_rate_by_name: malloc failed.");
+ status = -1;
}
else
{
- memcpy (ret, ce->values_gauge, ce->values_num * sizeof (gauge_t));
+ memcpy (ret, ce->values_gauge, ret_num * sizeof (gauge_t));
}
}
+ else
+ {
+ DEBUG ("utils_cache: uc_get_rate_by_name: No such value: %s", name);
+ status = -1;
+ }
pthread_mutex_unlock (&cache_lock);
+ if (status == 0)
+ {
+ *ret_values = ret;
+ *ret_values_num = ret_num;
+ }
+
+ return (status);
+} /* gauge_t *uc_get_rate_by_name */
+
+gauge_t *uc_get_rate (const data_set_t *ds, const value_list_t *vl)
+{
+ char name[6 * DATA_MAX_NAME_LEN];
+ gauge_t *ret = NULL;
+ size_t ret_num = 0;
+ int status;
+
+ if (FORMAT_VL (name, sizeof (name), vl, ds) != 0)
+ {
+ ERROR ("uc_insert: FORMAT_VL failed.");
+ return (NULL);
+ }
+
+ status = uc_get_rate_by_name (name, &ret, &ret_num);
+ if (status != 0)
+ return (NULL);
+
+ /* This is important - the caller has no other way of knowing how many
+ * values are returned. */
+ if (ret_num != ds->ds_num)
+ {
+ ERROR ("utils_cache: uc_get_rate: ds[%s] has %i values, "
+ "but uc_get_rate_by_name returned %i.",
+ ds->type, ds->ds_num, ret_num);
+ sfree (ret);
+ return (NULL);
+ }
+
return (ret);
} /* gauge_t *uc_get_rate */