author | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Wed, 28 Feb 2007 08:08:19 +0000 (09:08 +0100) | ||
committer | Florian Forster <octo@leeloo.lan.home.verplant.org> | |
Wed, 28 Feb 2007 08:08:19 +0000 (09:08 +0100) |
Conflicts:
src/apache.c
src/apache.c
81 files changed:
diff --git a/configure.in b/configure.in
index cf9fce26a67259fe407f0cfc3f4fb2cf8fa88681..69f111a4d912b9378dbf24ee677e15845d2c0cba 100644 (file)
--- a/configure.in
+++ b/configure.in
AC_SUBST(LIBLTDL)
AC_LIBTOOL_DLOPEN
AC_PROG_LIBTOOL
-#AC_PROG_RANLIB
+AC_PROG_LEX
+AC_PROG_YACC
AC_CONFIG_SUBDIRS(libltdl)
#
AC_CHECK_HEADERS(sys/types.h)
AC_CHECK_HEADERS(sys/socket.h)
AC_CHECK_HEADERS(sys/select.h)
-AC_CHECK_HEADERS(sys/poll.h)
+AC_CHECK_HEADERS(poll.h)
AC_CHECK_HEADERS(netdb.h)
AC_CHECK_HEADERS(arpa/inet.h)
AC_CHECK_HEADERS(sys/resource.h)
# include <netinet/ip6.h>
#endif
])
+AC_CHECK_HEADERS(netinet/tcp.h, [], [],
+[#if HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+# include <netinet/ip.h>
+#endif
+])
AC_CHECK_HEADERS(netinet/udp.h, [], [],
[#if HAVE_STDINT_H
# include <stdint.h>
AC_CHECK_HEADERS(net/if_ppp.h)
AC_CHECK_HEADERS(netinet/if_ether.h)
+# For the multimeter plugin
+AC_CHECK_HEADERS(termios.h)
+AC_CHECK_HEADERS(sys/ioctl.h)
+
dnl Checking for libraries
AC_CHECK_LIB(m, ext)
AC_COLLECTD([cpu], [disable], [module], [cpu usage statistics])
AC_COLLECTD([cpufreq], [disable], [module], [system cpu frequency statistics])
AC_COLLECTD([disk], [disable], [module], [disk/partition statistics])
+AC_COLLECTD([csv], [disable], [module], [csv output plugin])
AC_COLLECTD([df], [disable], [module], [df statistics])
AC_COLLECTD([dns], [disable], [module], [dns statistics])
AC_COLLECTD([email], [disable], [module], [email statistics])
-AC_COLLECTD([quota], [enable], [module], [quota statistics (experimental)])
+AC_COLLECTD([entropy], [disable], [module], [entropy statistics])
+AC_COLLECTD([exec], [disable], [module], [exec of external programs])
AC_COLLECTD([hddtemp], [disable], [module], [hdd temperature statistics])
AC_COLLECTD([irq], [disable], [module], [irq statistics])
AC_COLLECTD([load], [disable], [module], [system load statistics])
AC_COLLECTD([memory], [disable], [module], [memory statistics])
AC_COLLECTD([multimeter],[disable], [module], [multimeter statistics])
AC_COLLECTD([mysql], [disable], [module], [mysql statistics])
+AC_COLLECTD([network], [disable], [module], [network functionality])
AC_COLLECTD([nfs], [disable], [module], [nfs statistics])
AC_COLLECTD([ntpd], [disable], [module], [ntpd statistics])
AC_COLLECTD([ping], [disable], [module], [ping statistics])
AC_COLLECTD([swap], [disable], [module], [swap statistics])
AC_COLLECTD([tape], [disable], [module], [tape statistics])
AC_COLLECTD([traffic], [disable], [module], [system traffic statistics])
+AC_COLLECTD([unixsock], [disable], [module], [UNIX socket plugin])
AC_COLLECTD([users], [disable], [module], [user count statistics])
AC_COLLECTD([vserver], [disable], [module], [vserver statistics])
AC_COLLECTD([wireless], [disable], [module], [wireless link statistics])
-AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/libconfig/Makefile src/liboping/Makefile)
+AC_OUTPUT(Makefile src/Makefile src/collectd.conf src/liboconfig/Makefile src/liboping/Makefile)
cat <<EOF;
battery . . . . . . $enable_battery
cpu . . . . . . . . $enable_cpu
cpufreq . . . . . . $enable_cpufreq
+ csv . . . . . . . . $enable_csv
df . . . . . . . . $enable_df
disk . . . . . . . $enable_disk
dns . . . . . . . . $enable_dns
email . . . . . . . $enable_email
+ entropy . . . . . . $enable_entropy
+ exec . . . . . . . $enable_exec
hddtemp . . . . . . $enable_hddtemp
irq . . . . . . . . $enable_irq
load . . . . . . . $enable_load
memory . . . . . . $enable_memory
multimeter . . . . $enable_multimeter
mysql . . . . . . . $enable_mysql
+ network . . . . . . $enable_network
nfs . . . . . . . . $enable_nfs
ntpd . . . . . . . $enable_ntpd
ping . . . . . . . $enable_ping
swap . . . . . . . $enable_swap
tape . . . . . . . $enable_tape
traffic . . . . . . $enable_traffic
+ unixsock . . . . . $enable_unixsock
users . . . . . . . $enable_users
vserver . . . . . . $enable_vserver
wireless . . . . . $enable_wireless
diff --git a/src/Makefile.am b/src/Makefile.am
index 2e2d63716ca08c9c08e28eb36731011da08c6c31..17eb6091349d09936b771ed588a5bc3c91ad30b5 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
-SUBDIRS = libconfig
+SUBDIRS = liboconfig
if BUILD_WITH_OWN_LIBOPING
SUBDIRS += liboping
endif
endif
sbin_PROGRAMS = collectd
+bin_PROGRAMS = collectd-nagios
collectd_SOURCES = collectd.c collectd.h \
utils_debug.c utils_debug.h \
+ utils_avltree.c utils_avltree.h \
utils_mount.c utils_mount.h \
+ utils_llist.c utils_llist.h \
utils_ignorelist.c utils_ignorelist.h \
common.c common.h \
- network.c network.h \
plugin.c plugin.h \
configfile.c configfile.h
collectd_CPPFLAGS = $(LTDLINCL)
+collectd_CPPFLAGS += -DPREFIX='"${prefix}"'
collectd_CPPFLAGS += -DCONFIGFILE='"${sysconfdir}/${PACKAGE_NAME}.conf"'
collectd_CPPFLAGS += -DPKGLOCALSTATEDIR='"${localstatedir}/lib/${PACKAGE_NAME}"'
if BUILD_FEATURE_DAEMON
# Link to these libraries..
collectd_LDFLAGS = -export-dynamic
-if BUILD_WITH_RRDTOOL
-collectd_LDFLAGS += -lm -lrrd
-endif
if BUILD_WITH_LIBRT
collectd_LDFLAGS += -lrt
endif
endif
-collectd_LDADD = $(LIBLTDL) libconfig/libconfig.la "-dlopen" self
-collectd_DEPENDENCIES = $(LIBLTDL) libconfig/libconfig.la
+collectd_LDADD = $(LIBLTDL) liboconfig/liboconfig.la "-dlopen" self
+collectd_DEPENDENCIES = $(LIBLTDL) liboconfig/liboconfig.la
+
+collectd_nagios_SOURCES = collectd-nagios.c
pkglib_LTLIBRARIES =
collectd_DEPENDENCIES += cpufreq.la
endif
+if BUILD_MODULE_CSV
+pkglib_LTLIBRARIES += csv.la
+csv_la_SOURCES = csv.c
+csv_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" csv.la
+collectd_DEPENDENCIES += csv.la
+endif
+
if BUILD_MODULE_DF
pkglib_LTLIBRARIES += df.la
df_la_SOURCES = df.c
collectd_DEPENDENCIES += email.la
endif
+if BUILD_MODULE_ENTROPY
+pkglib_LTLIBRARIES += entropy.la
+entropy_la_SOURCES = entropy.c
+entropy_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" entropy.la
+collectd_DEPENDENCIES += entropy.la
+endif
+
+if BUILD_MODULE_EXEC
+pkglib_LTLIBRARIES += exec.la
+exec_la_SOURCES = exec.c
+exec_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBPTHREAD
+exec_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" exec.la
+collectd_DEPENDENCIES += exec.la
+endif
+
#if BUILD_MODULE_QUOTA
#pkglib_LTLIBRARIES += quota.la
#quota_la_SOURCES = quota_plugin.c quota_plugin.h
collectd_DEPENDENCIES += mysql.la
endif
+if BUILD_MODULE_NETWORK
+pkglib_LTLIBRARIES += network.la
+network_la_SOURCES = network.c
+network_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBSOCKET
+network_la_LDFLAGS += -lsocket
+endif
+if BUILD_WITH_LIBPTHREAD
+network_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" network.la
+collectd_DEPENDENCIES += network.la
+endif
+
if BUILD_MODULE_NFS
pkglib_LTLIBRARIES += nfs.la
nfs_la_SOURCES = nfs.c
collectd_DEPENDENCIES += processes.la
endif
+if BUILD_WITH_RRDTOOL
+pkglib_LTLIBRARIES += rrdtool.la
+rrdtool_la_SOURCES = rrdtool.c
+rrdtool_la_LDFLAGS = -module -avoid-version -lrrd
+collectd_LDADD += "-dlopen" rrdtool.la
+collectd_DEPENDENCIES += rrdtool.la
+endif
+
if BUILD_MODULE_SENSORS
pkglib_LTLIBRARIES += sensors.la
sensors_la_SOURCES = sensors.c
endif
endif
+if BUILD_MODULE_UNIXSOCK
+pkglib_LTLIBRARIES += unixsock.la
+unixsock_la_SOURCES = unixsock.c
+unixsock_la_LDFLAGS = -module -avoid-version
+if BUILD_WITH_LIBPTHREAD
+unixsock_la_LDFLAGS += -lpthread
+endif
+collectd_LDADD += "-dlopen" unixsock.la
+collectd_DEPENDENCIES += unixsock.la
+endif
+
if BUILD_MODULE_USERS
pkglib_LTLIBRARIES += users.la
users_la_SOURCES = users.c
diff --git a/src/apache.c b/src/apache.c
index 7c48f085bcd02924354115a342bd29f6ffeb8b7d..5156ff66de6d91b080b010e2c7b221f85712ad88 100644 (file)
--- a/src/apache.c
+++ b/src/apache.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "common.h"
#include "plugin.h"
#include "configfile.h"
-
-#define MODULE_NAME "apache"
+#include "utils_debug.h"
#if HAVE_LIBCURL && HAVE_CURL_CURL_H
# define APACHE_HAVE_READ 1
# define APACHE_HAVE_READ 0
#endif
-static char *url = NULL;
-static char *user = NULL;
-static char *pass = NULL;
-static char *cacert = NULL;
-
-#if HAVE_LIBCURL
-static CURL *curl = NULL;
-
-#define ABUFFER_SIZE 16384
-static char apache_buffer[ABUFFER_SIZE];
-static int apache_buffer_len = 0;
-static char apache_curl_error[CURL_ERROR_SIZE];
-#endif /* HAVE_LIBCURL */
-
/* Limit to 2^27 bytes/s. That's what a gigabit-ethernet link can handle, in
* theory. */
-static char *bytes_file = "apache/apache_bytes.rrd";
-static char *bytes_ds_def[] =
+static data_source_t apache_bytes_dsrc[1] =
{
- "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:134217728",
- NULL
+ {"count", DS_TYPE_COUNTER, 0, 134217728.0},
+};
+
+static data_set_t apache_bytes_ds =
+{
+ "apache_bytes", 1, apache_bytes_dsrc
};
-static int bytes_ds_num = 1;
/* Limit to 2^20 requests/s */
-static char *requests_file = "apache/apache_requests.rrd";
-static char *requests_ds_def[] =
+static data_source_t apache_requests_dsrc[1] =
{
- "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:1048576",
- NULL
+ {"count", DS_TYPE_COUNTER, 0, 134217728.0},
};
-static int requests_ds_num = 1;
-static char *scoreboard_file = "apache/apache_scoreboard-%s.rrd";
-static char *scoreboard_ds_def[] =
+static data_set_t apache_requests_ds =
{
- "DS:count:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "apache_requests", 1, apache_requests_dsrc
};
-static int scoreboard_ds_num = 1;
-/* for lighttpd; Limit to 65536 active connections */
-static char *connections_file = "apache/apache_connections.rrd";
-static char *connections_ds_def[] =
+static data_source_t apache_scoreboard_dsrc[1] =
{
- "DS:connections:GAUGE:"COLLECTD_HEARTBEAT":0:65536",
- NULL
+ {"count", DS_TYPE_GAUGE, 0, 65535.0},
+};
+
+static data_set_t apache_scoreboard_ds =
+{
+ "apache_scoreboard", 1, apache_scoreboard_dsrc
};
-static int connections_ds_num = 1;
-static char *config_keys[] =
+static data_source_t apache_connections_dsrc[1] =
+{
+ {"count", DS_TYPE_GAUGE, 0, 65535.0},
+};
+
+static data_set_t apache_connections_ds =
+{
+ "apache_connections", 1, apache_connections_dsrc
+};
+
+#if APACHE_HAVE_READ
+static char *url = NULL;
+static char *user = NULL;
+static char *pass = NULL;
+static char *cacert = NULL;
+
+static CURL *curl = NULL;
+
+#define ABUFFER_SIZE 16384
+static char apache_buffer[ABUFFER_SIZE];
+static int apache_buffer_len = 0;
+static char apache_curl_error[CURL_ERROR_SIZE];
+
+static const char *config_keys[] =
{
"URL",
"User",
};
static int config_keys_num = 4;
-#if HAVE_LIBCURL
static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *stream)
{
size_t len = size * nmemb;
@@ -116,9 +119,8 @@ static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *
return (len);
}
-#endif /* HAVE_LIBCURL */
-static int config_set (char **var, char *value)
+static int config_set (char **var, const char *value)
{
if (*var != NULL)
{
return (0);
}
-static int config (char *key, char *value)
+static int config (const char *key, const char *value)
{
if (strcasecmp (key, "url") == 0)
return (config_set (&url, value));
return (-1);
}
-static void init (void)
+static int init (void)
{
-#if HAVE_LIBCURL
static char credentials[1024];
if (curl != NULL)
if ((curl = curl_easy_init ()) == NULL)
{
syslog (LOG_ERR, "apache: `curl_easy_init' failed.");
- return;
+ return (-1);
}
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024)
{
syslog (LOG_ERR, "apache: Credentials would have been truncated.");
- return;
+ return (-1);
}
curl_easy_setopt (curl, CURLOPT_USERPWD, credentials);
{
curl_easy_setopt (curl, CURLOPT_CAINFO, cacert);
}
-#endif /* HAVE_LIBCURL */
-}
-static void bytes_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, bytes_file, val, bytes_ds_def, bytes_ds_num);
-}
+ return (0);
+} /* int init */
-static void requests_write (char *host, char *inst, char *val)
+static void submit_counter (const char *type, const char *type_instance,
+ unsigned long long value)
{
- rrd_update_file (host, requests_file, val, requests_ds_def, requests_ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void scoreboard_write (char *host, char *inst, char *val)
-{
- char buf[1024];
+ DBG ("type = %s; type_instance = %s; value = %llu;",
+ type, type_instance, value);
- if (snprintf (buf, 1024, scoreboard_file, inst) >= 1024)
- return;
+ values[0].counter = value;
- rrd_update_file (host, buf, val, scoreboard_ds_def, scoreboard_ds_num);
-}
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apache");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-static void connections_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, connections_file, val, connections_ds_def,
- connections_ds_num);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
-#if APACHE_HAVE_READ
-static void submit (char *type, char *inst, long long value)
+static void submit_gauge (const char *type, const char *type_instance,
+ double value)
{
- char buf[1024];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, 1024, "%u:%lli", (unsigned int) curtime, value);
- if (status < 0)
- {
- syslog (LOG_ERR, "apache: bytes_submit: snprintf failed");
- return;
- }
- else if (status >= 1024)
- {
- syslog (LOG_WARNING, "apache: bytes_submit: snprintf was truncated");
- return;
- }
+ DBG ("type = %s; type_instance = %s; value = %lf;",
+ type, type_instance, value);
- plugin_submit (type, inst, buf);
-}
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apache");
+ strcpy (vl.plugin_instance, "");
+
+ if (type_instance != NULL)
+ strncpy (vl.type_instance, type_instance,
+ sizeof (vl.type_instance));
+
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
static void submit_scoreboard (char *buf)
{
else if (buf[i] == 'I') idle_cleanup++;
}
- submit ("apache_scoreboard", "open" , open);
- submit ("apache_scoreboard", "waiting" , waiting);
- submit ("apache_scoreboard", "starting" , starting);
- submit ("apache_scoreboard", "reading" , reading);
- submit ("apache_scoreboard", "sending" , sending);
- submit ("apache_scoreboard", "keepalive", keepalive);
- submit ("apache_scoreboard", "dnslookup", dnslookup);
- submit ("apache_scoreboard", "closing" , closing);
- submit ("apache_scoreboard", "logging" , logging);
- submit ("apache_scoreboard", "finishing", finishing);
- submit ("apache_scoreboard", "idle_cleanup", idle_cleanup);
+ submit_gauge ("apache_scoreboard", "open" , open);
+ submit_gauge ("apache_scoreboard", "waiting" , waiting);
+ submit_gauge ("apache_scoreboard", "starting" , starting);
+ submit_gauge ("apache_scoreboard", "reading" , reading);
+ submit_gauge ("apache_scoreboard", "sending" , sending);
+ submit_gauge ("apache_scoreboard", "keepalive", keepalive);
+ submit_gauge ("apache_scoreboard", "dnslookup", dnslookup);
+ submit_gauge ("apache_scoreboard", "closing" , closing);
+ submit_gauge ("apache_scoreboard", "logging" , logging);
+ submit_gauge ("apache_scoreboard", "finishing", finishing);
+ submit_gauge ("apache_scoreboard", "idle_cleanup", idle_cleanup);
}
-static void apache_read (void)
+static int apache_read (void)
{
int i;
int fields_num;
if (curl == NULL)
- return;
+ return (-1);
if (url == NULL)
- return;
+ return (-1);
apache_buffer_len = 0;
if (curl_easy_perform (curl) != 0)
{
- syslog (LOG_WARNING, "apache: curl_easy_perform failed: %s", apache_curl_error);
- return;
+ syslog (LOG_ERR, "apache: curl_easy_perform failed: %s",
+ apache_curl_error);
+ return (-1);
}
ptr = apache_buffer;
{
if ((strcmp (fields[0], "Total") == 0)
&& (strcmp (fields[1], "Accesses:") == 0))
- submit ("apache_requests", NULL, atoll (fields[2]));
+ submit_counter ("apache_requests", "",
+ atoll (fields[2]));
else if ((strcmp (fields[0], "Total") == 0)
&& (strcmp (fields[1], "kBytes:") == 0))
- submit ("apache_bytes", NULL, 1024LL * atoll (fields[2]));
+ submit_counter ("apache_bytes", "",
+ 1024LL * atoll (fields[2]));
}
else if (fields_num == 2)
{
if (strcmp (fields[0], "Scoreboard:") == 0)
submit_scoreboard (fields[1]);
else if (strcmp (fields[0], "BusyServers:") == 0)
- submit ("apache_connections", NULL, atol (fields[1]));
+ submit_gauge ("apache_connections", NULL, atol (fields[1]));
}
}
apache_buffer_len = 0;
-}
-#else
-# define apache_read NULL
+
+ return (0);
+} /* int apache_read */
#endif /* APACHE_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, init, apache_read, NULL);
- plugin_register ("apache_requests", NULL, NULL, requests_write);
- plugin_register ("apache_bytes", NULL, NULL, bytes_write);
- plugin_register ("apache_scoreboard", NULL, NULL, scoreboard_write);
- plugin_register ("apache_connections", NULL, NULL, connections_write);
- cf_register (MODULE_NAME, config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&apache_bytes_ds);
+ plugin_register_data_set (&apache_requests_ds);
+ plugin_register_data_set (&apache_scoreboard_ds);
+ plugin_register_data_set (&apache_connections_ds);
-#undef MODULE_NAME
+#if APACHE_HAVE_READ
+ plugin_register_config ("apache", config,
+ config_keys, config_keys_num);
+ plugin_register_init ("apache", init);
+ plugin_register_read ("apache", apache_read);
+#endif
+}
diff --git a/src/apcups.c b/src/apcups.c
index cd64426afa01e42125f3b210b7e39dc40f991c12..3060e18c8a66965fbf5955b8fb48bc03e4fa39b3 100644 (file)
--- a/src/apcups.c
+++ b/src/apcups.c
# include <netinet/in.h>
#endif
-#ifndef APCMAIN
-# define APCMAIN 0
-#endif
-
#define NISPORT 3551
#define MAXSTRING 256
#define MODULE_NAME "apcups"
#define APCUPS_DEFAULT_HOST "localhost"
+/*
+ * Private data types
+ */
+struct apc_detail_s
+{
+ double linev;
+ double loadpct;
+ double bcharge;
+ double timeleft;
+ double outputv;
+ double itemp;
+ double battv;
+ double linefreq;
+};
+
+/*
+ * Private variables
+ */
/* Default values for contacting daemon */
-static char *global_host = NULL;
-static int global_port = NISPORT;
+static char *conf_host = NULL;
+static int conf_port = NISPORT;
+
+static int global_sockfd = -1;
/*
* The following are only if not compiled to test the module with its own main.
*/
-#if !APCMAIN
-static char *bvolt_file_template = "apcups/voltage-%s.rrd";
-static char *bvolt_ds_def[] =
+static data_source_t data_source_voltage[1] =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
};
-static int bvolt_ds_num = 1;
-static char *load_file_template = "apcups/load_percent.rrd";
-static char *load_ds_def[] =
+static data_set_t ds_voltage =
{
- "DS:percent:GAUGE:"COLLECTD_HEARTBEAT":0:110",
+ "voltage", 1, data_source_voltage
};
-static int load_ds_num = 1;
-static char *charge_file_template = "apcups/charge_percent.rrd";
-static char *charge_ds_def[] =
+static data_source_t data_source_percent[1] =
{
- "DS:percent:GAUGE:"COLLECTD_HEARTBEAT":0:110",
+ {"percent", DS_TYPE_GAUGE, 0, 100.1}
};
-static int charge_ds_num = 1;
-static char *time_file_template = "apcups/timeleft.rrd";
-static char *time_ds_def[] =
+static data_set_t ds_percent =
{
- "DS:timeleft:GAUGE:"COLLECTD_HEARTBEAT":0:100",
+ "percent", 1, data_source_percent
};
-static int time_ds_num = 1;
-static char *temp_file_template = "apcups/temperature.rrd";
-static char *temp_ds_def[] =
+static data_source_t data_source_timeleft[1] =
{
- /* -273.15 is absolute zero */
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":-274:U",
+ {"timeleft", DS_TYPE_GAUGE, 0, 100.0}
};
-static int temp_ds_num = 1;
-static char *freq_file_template = "apcups/frequency-%s.rrd";
-static char *freq_ds_def[] =
+static data_set_t ds_timeleft =
{
- "DS:frequency:GAUGE:"COLLECTD_HEARTBEAT":0:U",
+ "timeleft", 1, data_source_timeleft
};
-static int freq_ds_num = 1;
-static char *config_keys[] =
+static data_source_t data_source_temperature[1] =
{
- "Host",
- "Port",
- NULL
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
};
-static int config_keys_num = 2;
-#endif /* if APCMAIN */
+static data_set_t ds_temperature =
+{
+ "temperature", 1, data_source_temperature
+};
-struct apc_detail_s
+static data_source_t data_source_frequency[1] =
{
- double linev;
- double loadpct;
- double bcharge;
- double timeleft;
- double outputv;
- double itemp;
- double battv;
- double linefreq;
+ {"frequency", DS_TYPE_GAUGE, 0, NAN}
+};
+
+static data_set_t ds_frequency =
+{
+ "frequency", 1, data_source_frequency
};
-#define BIG_BUF 4096
+static const char *config_keys[] =
+{
+ "Host",
+ "Port",
+ NULL
+};
+static int config_keys_num = 2;
-#if APCMAIN
/* Close the network connection */
-static void net_close (int *fd)
+static int apcups_shutdown (void)
{
uint16_t packet_size = 0;
- assert (*fd >= 0);
+ if (global_sockfd < 0)
+ return (0);
- DBG ("Gracefully shutting down socket %i.", *fd);
+ DBG ("Gracefully shutting down socket %i.", global_sockfd);
/* send EOF sentinel */
- swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+ swrite (global_sockfd, (void *) &packet_size, sizeof (packet_size));
- close (*fd);
- *fd = -1;
-}
-#endif /* APCMAIN */
+ close (global_sockfd);
+ global_sockfd = -1;
+
+ return (0);
+} /* int apcups_shutdown */
/*
* Open a TCP connection to the UPS network server
char *key;
double value;
- static int sockfd = -1;
static complain_t compl;
#if APCMAIN
# define PRINT_VALUE(name, val) /**/
#endif
- if (sockfd < 0)
+ if (global_sockfd < 0)
{
- if ((sockfd = net_open (host, NULL, port)) < 0)
+ if ((global_sockfd = net_open (host, NULL, port)) < 0)
{
plugin_complain (LOG_ERR, &compl, "apcups plugin: "
"Connecting to the apcupsd failed.");
}
}
- if (net_send (&sockfd, "status", 6) < 0)
+ if (net_send (&global_sockfd, "status", 6) < 0)
{
syslog (LOG_ERR, "apcups plugin: Writing to the socket failed.");
return (-1);
}
- while ((n = net_recv (&sockfd, recvline, sizeof (recvline) - 1)) > 0)
+ while ((n = net_recv (&global_sockfd, recvline, sizeof (recvline) - 1)) > 0)
{
assert (n < sizeof (recvline));
recvline[n] = '\0';
syslog (LOG_WARNING, "apcups plugin: Error reading from socket");
return (-1);
}
-#if APCMAIN
- else
- {
- /* close the opened socket */
- net_close (&sockfd);
- }
-#endif /* APCMAIN */
return (0);
}
-#if APCMAIN
-/*
- * This is used for testing apcups in a standalone mode.
- * Usefull for debugging.
- */
-int main (int argc, char **argv)
-{
- /* we are not really going to use this */
- struct apc_detail_s apcups_detail;
-
- openlog ("apcups", LOG_PID | LOG_NDELAY | LOG_LOCAL1, LOG_USER);
-
- if (global_host == NULL || strcmp (global_host, "0.0.0.0") == 0)
- global_host = "localhost";
-
- if(apc_query_server (global_host, global_port, &apcups_detail) < 0)
- {
- printf("apcups: Failed...\n");
- return(-1);
- }
-
- return 0;
-}
-#else
-static int apcups_config (char *key, char *value)
+static int apcups_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
- if (global_host != NULL)
+ if (conf_host != NULL)
{
- free (global_host);
- global_host = NULL;
+ free (conf_host);
+ conf_host = NULL;
}
- if ((global_host = strdup (value)) == NULL)
+ if ((conf_host = strdup (value)) == NULL)
return (1);
}
else if (strcasecmp (key, "Port") == 0)
syslog (LOG_WARNING, "apcups plugin: Invalid port: %i", port_tmp);
return (1);
}
- global_port = port_tmp;
+ conf_port = port_tmp;
}
else
{
return (0);
}
-static void apcups_init (void)
-{
- return;
-}
-
-static void apc_write_voltage (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, bvolt_file_template, inst);
- if ((status < 1) || (status >= 512))
- return;
-
- rrd_update_file (host, file, val, bvolt_ds_def, bvolt_ds_num);
-}
-
-static void apc_write_charge (char *host, char *inst, char *val)
-{
- rrd_update_file (host, charge_file_template, val, charge_ds_def, charge_ds_num);
-}
-
-static void apc_write_percent (char *host, char *inst, char *val)
-{
- rrd_update_file (host, load_file_template, val, load_ds_def, load_ds_num);
-}
-
-static void apc_write_timeleft (char *host, char *inst, char *val)
-{
- rrd_update_file (host, time_file_template, val, time_ds_def, time_ds_num);
-}
-
-static void apc_write_temperature (char *host, char *inst, char *val)
-{
- rrd_update_file (host, temp_file_template, val, temp_ds_def, temp_ds_num);
-}
-
-static void apc_write_frequency (char *host, char *inst, char *val)
+static void apc_submit_generic (char *type, char *type_inst, double value)
{
- char file[512];
- int status;
-
- status = snprintf (file, 512, freq_file_template, inst);
- if ((status < 1) || (status >= 512))
- return;
-
- rrd_update_file (host, file, val, freq_ds_def, freq_ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void apc_submit_generic (char *type, char *inst,
- double value)
-{
- char buf[512];
- int status;
+ values[0].gauge = value;
- status = snprintf (buf, 512, "%u:%f",
- (unsigned int) curtime, value);
- if ((status < 1) || (status >= 512))
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apcups");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- DBG ("plugin_submit (%s, %s, %s);", type, inst, buf);
- plugin_submit (type, inst, buf);
+ plugin_dispatch_values (type, &vl);
}
static void apc_submit (struct apc_detail_s *apcups_detail)
apc_submit_generic ("apcups_voltage", "input", apcups_detail->linev);
apc_submit_generic ("apcups_voltage", "output", apcups_detail->outputv);
apc_submit_generic ("apcups_voltage", "battery", apcups_detail->battv);
- apc_submit_generic ("apcups_charge", "-", apcups_detail->bcharge);
- apc_submit_generic ("apcups_charge_pct", "-", apcups_detail->loadpct);
- apc_submit_generic ("apcups_timeleft", "-", apcups_detail->timeleft);
- apc_submit_generic ("apcups_temp", "-", apcups_detail->itemp);
+ apc_submit_generic ("apcups_charge", "", apcups_detail->bcharge);
+ apc_submit_generic ("apcups_charge_pct", "", apcups_detail->loadpct);
+ apc_submit_generic ("apcups_timeleft", "", apcups_detail->timeleft);
+ apc_submit_generic ("apcups_temp", "", apcups_detail->itemp);
apc_submit_generic ("apcups_frequency", "input", apcups_detail->linefreq);
}
-static void apcups_read (void)
+static int apcups_read (void)
{
struct apc_detail_s apcups_detail;
int status;
apcups_detail.itemp = -300.0;
apcups_detail.linefreq = -1.0;
- status = apc_query_server (global_host == NULL
+ status = apc_query_server (conf_host == NULL
? APCUPS_DEFAULT_HOST
- : global_host,
- global_port, &apcups_detail);
+ : conf_host,
+ conf_port, &apcups_detail);
/*
* if we did not connect then do not bother submitting
if (status != 0)
{
DBG ("apc_query_server (%s, %i) = %i",
- global_host == NULL
+ conf_host == NULL
? APCUPS_DEFAULT_HOST
- : global_host,
- global_port, status);
- return;
+ : conf_host,
+ conf_port, status);
+ return (-1);
}
apc_submit (&apcups_detail);
+
+ return (0);
} /* apcups_read */
void module_register (void)
{
- plugin_register (MODULE_NAME, apcups_init, apcups_read, NULL);
- plugin_register ("apcups_voltage", NULL, NULL, apc_write_voltage);
- plugin_register ("apcups_charge", NULL, NULL, apc_write_charge);
- plugin_register ("apcups_charge_pct", NULL, NULL, apc_write_percent);
- plugin_register ("apcups_timeleft", NULL, NULL, apc_write_timeleft);
- plugin_register ("apcups_temp", NULL, NULL, apc_write_temperature);
- plugin_register ("apcups_frequency", NULL, NULL, apc_write_frequency);
- cf_register (MODULE_NAME, apcups_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&ds_voltage);
+ plugin_register_data_set (&ds_percent);
+ plugin_register_data_set (&ds_timeleft);
+ plugin_register_data_set (&ds_temperature);
+ plugin_register_data_set (&ds_frequency);
-#endif /* if APCMAIN */
-#undef MODULE_NAME
+ plugin_register_config ("apcups", apcups_config, config_keys, config_keys_num);
+
+ plugin_register_read ("apcups", apcups_read);
+ plugin_register_shutdown ("apcups", apcups_shutdown);
+}
diff --git a/src/apple_sensors.c b/src/apple_sensors.c
index 37bd5c3965284f9e32ce39dc3cedda131d3f60c4..33660a92e5268e4e71a9ea31aa87c1348718ea12 100644 (file)
--- a/src/apple_sensors.c
+++ b/src/apple_sensors.c
/**
* collectd - src/apple_sensors.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "apple_sensors"
-
#if HAVE_CTYPE_H
# include <ctype.h>
#endif
static mach_port_t io_master_port = MACH_PORT_NULL;
#endif
-static char *temperature_file = "apple_sensors/temperature-%s.rrd";
-static char *fanspeed_file = "apple_sensors/fanspeed-%s.rrd";
+static data_source_t data_source_fanspeed[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-static char *ds_def[] =
+static data_set_t fanspeed_ds =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "fanspeed", 1, data_source_fanspeed
};
-static int ds_num = 1;
-static void as_init (void)
+static data_source_t data_source_temperature[1] =
{
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
+};
+
+static data_set_t temperature_ds =
+{
+ "temperature", 1, data_source_temperature
+};
+
#if IOKIT_HAVE_READ
+static int as_init (void)
+{
kern_return_t status;
if (io_master_port != MACH_PORT_NULL)
syslog (LOG_ERR, "IOMasterPort failed: %s",
mach_error_string (status));
io_master_port = MACH_PORT_NULL;
- return;
+ return (-1);
}
-#endif /* IOKIT_HAVE_READ */
- return;
+ return (0);
}
-static void as_write (char *host, char *inst, char *val, const char *template)
+static void as_submit (const char *type, const char *type_instance,
+ double val)
{
- char filename[256];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (filename, 256, template, inst);
- if ((status < 1) || (status >= 256))
- return;
+ DBG ("type = %s; type_instance = %s; val = %f;",
+ type, type_instance, val);
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
+ values[0].gauge = val;
-static void temperature_write (char *host, char *inst, char *val)
-{
- as_write (host, inst, val, temperature_file);
-}
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "apple_sensors");
+ strcpy (vl.plugin_instance, "");
+ strcpy (vl.type_instance, type_instance);
-static void fanspeed_write (char *host, char *inst, char *val)
-{
- as_write (host, inst, val, fanspeed_file);
+ plugin_dispatch_values (type, &vl);
}
-#if IOKIT_HAVE_READ
-static void as_submit (char *type, char *inst, double value)
-{
- char buf[128];
-
- if (snprintf (buf, 1024, "%u:%f", (unsigned int) curtime,
- value) >= 128)
- return;
-
- plugin_submit (type, inst, buf);
-}
-
-static void as_read (void)
+static int as_read (void)
{
kern_return_t status;
io_iterator_t iterator;
int i;
if (!io_master_port || (io_master_port == MACH_PORT_NULL))
- return;
+ return (-1);
status = IOServiceGetMatchingServices (io_master_port,
IOServiceNameMatching("IOHWSensor"),
{
syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s",
mach_error_string (status));
- return;
+ return (-1);
}
while ((io_obj = IOIteratorNext (iterator)))
if (strcmp (type, "temperature") == 0)
{
value_double = ((double) value_int) / 65536.0;
- strncpy (type, "apple_temperature", 128);
+ strcpy (type, "temperature");
}
else if (strcmp (type, "temp") == 0)
{
value_double = ((double) value_int) / 10.0;
- strncpy (type, "apple_temperature", 128);
+ strcpy (type, "temperature");
}
else if (strcmp (type, "fanspeed") == 0)
{
value_double = ((double) value_int) / 65536.0;
- strncpy (type, "apple_fanspeed", 128);
+ strcpy (type, "fanspeed");
}
else if (strcmp (type, "voltage") == 0)
{
else if (strcmp (type, "adc") == 0)
{
value_double = ((double) value_int) / 10.0;
- strncpy (type, "apple_temperature", 128);
+ strcpy (type, "fanspeed");
}
else
{
} /* while (iterator) */
IOObjectRelease (iterator);
-}
-#else
-# define as_read NULL
+
+ return (0);
+} /* int as_read */
#endif /* IOKIT_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, as_init, as_read, NULL);
- plugin_register ("apple_temperature", NULL, NULL, temperature_write);
- plugin_register ("apple_fanspeed", NULL, NULL, fanspeed_write);
-}
+ plugin_register_data_set (&fanspeed_ds);
+ plugin_register_data_set (&temperature_ds);
-#undef MODULE_NAME
+#if IOKIT_HAVE_READ
+ plugin_register_init ("apple_sensors", as_init);
+ plugin_register_read ("apple_sensors", as_read);
+#endif /* IOKIT_HAVE_READ */
+}
diff --git a/src/battery.c b/src/battery.c
index 2141a58c725f3515963f71e29566ac0315b0fca8..e52c2c80657d9c97f114116202fee105a38ae1eb 100644 (file)
--- a/src/battery.c
+++ b/src/battery.c
/**
* collectd - src/battery.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "battery"
-#define BUFSIZE 512
-
#if HAVE_MACH_MACH_TYPES_H
# include <mach/mach_types.h>
#endif
#define INVALID_VALUE 47841.29
-static char *battery_current_file = "battery-%s/current.rrd";
-static char *battery_voltage_file = "battery-%s/voltage.rrd";
-static char *battery_charge_file = "battery-%s/charge.rrd";
+static data_source_t data_source_charge[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
+
+static data_set_t charge_ds =
+{
+ "charge", 1, data_source_charge
+};
+
+static data_source_t data_source_current[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
-static char *ds_def_current[] =
+static data_set_t current_ds =
{
- "DS:current:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "current", 1, data_source_current
};
-static int ds_num_current = 1;
-static char *ds_def_voltage[] =
+static data_source_t data_source_voltage[1] =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
};
-static int ds_num_voltage = 1;
-static char *ds_def_charge[] =
+static data_set_t voltage_ds =
{
- "DS:charge:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "voltage", 1, data_source_voltage
};
-static int ds_num_charge = 1;
+#if BATTERY_HAVE_READ
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
/* No global variables */
/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
static char *battery_pmu_file = "/proc/pmu/battery_%i";
#endif /* KERNEL_LINUX */
-static void battery_init (void)
+static int battery_init (void)
{
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
/* No init neccessary */
#elif KERNEL_LINUX
int len;
- char filename[BUFSIZE];
+ char filename[128];
for (battery_pmu_num = 0; ; battery_pmu_num++)
{
- len = snprintf (filename, BUFSIZE, battery_pmu_file, battery_pmu_num);
+ len = snprintf (filename, sizeof (filename), battery_pmu_file, battery_pmu_num);
- if ((len >= BUFSIZE) || (len < 0))
+ if ((len >= sizeof (filename)) || (len < 0))
break;
if (access (filename, R_OK))
}
#endif /* KERNEL_LINUX */
- return;
-}
-
-static void battery_current_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
- int len;
-
- len = snprintf (filename, BUFSIZE, battery_current_file, inst);
- if ((len >= BUFSIZE) || (len < 0))
- return;
-
- rrd_update_file (host, filename, val,
- ds_def_current, ds_num_current);
-}
-
-static void battery_voltage_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
- int len;
-
- len = snprintf (filename, BUFSIZE, battery_voltage_file, inst);
- if ((len >= BUFSIZE) || (len < 0))
- return;
-
- rrd_update_file (host, filename, val,
- ds_def_voltage, ds_num_voltage);
+ return (0);
}
-static void battery_charge_write (char *host, char *inst, char *val)
+static void battery_submit (const char *plugin_instance, const char *type, double value)
{
- char filename[BUFSIZE];
- int len;
-
- len = snprintf (filename, BUFSIZE, battery_charge_file, inst);
- if ((len >= BUFSIZE) || (len < 0))
- return;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- rrd_update_file (host, filename, val,
- ds_def_charge, ds_num_charge);
-}
+ values[0].gauge = value;
-#if BATTERY_HAVE_READ
-static void battery_submit (char *inst, double current, double voltage, double charge)
-{
- int len;
- char buffer[BUFSIZE];
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "battery");
+ strcpy (vl.plugin_instance, plugin_instance);
- if (current != INVALID_VALUE)
- {
- len = snprintf (buffer, BUFSIZE, "N:%.3f", current);
-
- if ((len > 0) && (len < BUFSIZE))
- plugin_submit ("battery_current", inst, buffer);
- }
- else
- {
- plugin_submit ("battery_current", inst, "N:U");
- }
-
- if (voltage != INVALID_VALUE)
- {
- len = snprintf (buffer, BUFSIZE, "N:%.3f", voltage);
-
- if ((len > 0) && (len < BUFSIZE))
- plugin_submit ("battery_voltage", inst, buffer);
- }
- else
- {
- plugin_submit ("battery_voltage", inst, "N:U");
- }
-
- if (charge != INVALID_VALUE)
- {
- len = snprintf (buffer, BUFSIZE, "N:%.3f", charge);
-
- if ((len > 0) && (len < BUFSIZE))
- plugin_submit ("battery_charge", inst, buffer);
- }
- else
- {
- plugin_submit ("battery_charge", inst, "N:U");
- }
-}
+ plugin_dispatch_values (type, &vl);
+} /* void battery_submit */
#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || HAVE_IOKIT_IOKITLIB_H
double dict_get_double (CFDictionaryRef dict, char *key_string)
}
#endif /* HAVE_IOKIT_IOKITLIB_H */
-static void battery_read (void)
+static int battery_read (void)
{
#if HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H
double charge = INVALID_VALUE; /* Current charge in Ah */
if ((charge_rel != INVALID_VALUE) && (charge_abs != INVALID_VALUE))
charge = charge_abs * charge_rel / 100.0;
- if ((charge != INVALID_VALUE)
- || (current != INVALID_VALUE)
- || (voltage != INVALID_VALUE))
- battery_submit ("0", current, voltage, charge);
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
/* #endif HAVE_IOKIT_IOKITLIB_H || HAVE_IOKIT_PS_IOPOWERSOURCES_H */
#elif KERNEL_LINUX
FILE *fh;
- char buffer[BUFSIZE];
- char filename[BUFSIZE];
+ char buffer[1024];
+ char filename[256];
char *fields[8];
int numfields;
for (i = 0; i < battery_pmu_num; i++)
{
- char batnum_str[BUFSIZE];
+ char batnum_str[256];
double current = INVALID_VALUE;
double voltage = INVALID_VALUE;
double charge = INVALID_VALUE;
double *valptr = NULL;
- len = snprintf (filename, BUFSIZE, battery_pmu_file, i);
- if ((len >= BUFSIZE) || (len < 0))
+ len = snprintf (filename, sizeof (filename), battery_pmu_file, i);
+ if ((len >= sizeof (filename)) || (len < 0))
continue;
- len = snprintf (batnum_str, BUFSIZE, "%i", i);
- if ((len >= BUFSIZE) || (len < 0))
+ len = snprintf (batnum_str, sizeof (batnum_str), "%i", i);
+ if ((len >= sizeof (batnum_str)) || (len < 0))
continue;
if ((fh = fopen (filename, "r")) == NULL)
continue;
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
numfields = strsplit (buffer, fields, 8);
}
}
- if ((current != INVALID_VALUE)
- || (voltage != INVALID_VALUE)
- || (charge != INVALID_VALUE))
- battery_submit (batnum_str, current, voltage, charge);
-
fclose (fh);
fh = NULL;
+
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
}
if (access ("/proc/acpi/battery", R_OK | X_OK) == 0)
if ((dh = opendir ("/proc/acpi/battery")) == NULL)
{
syslog (LOG_ERR, "Cannot open `/proc/acpi/battery': %s", strerror (errno));
- return;
+ return (-1);
}
while ((ent = readdir (dh)) != NULL)
if (ent->d_name[0] == '.')
continue;
- len = snprintf (filename, BUFSIZE, "/proc/acpi/battery/%s/state", ent->d_name);
- if ((len >= BUFSIZE) || (len < 0))
+ len = snprintf (filename, sizeof (filename),
+ "/proc/acpi/battery/%s/state",
+ ent->d_name);
+ if ((len >= sizeof (filename)) || (len < 0))
continue;
if ((fh = fopen (filename, "r")) == NULL)
* [11:00] <@tokkee> remaining capacity: 4136 mAh
* [11:00] <@tokkee> present voltage: 12428 mV
*/
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
numfields = strsplit (buffer, fields, 8);
if ((fields[2] == endptr) || (errno != 0))
*valptr = INVALID_VALUE;
}
- }
+ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
+
+ fclose (fh);
if ((current != INVALID_VALUE) && (charging == 0))
current *= -1;
- if ((current != INVALID_VALUE)
- || (voltage != INVALID_VALUE)
- || (charge != INVALID_VALUE))
- battery_submit (ent->d_name, current, voltage, charge);
-
- fclose (fh);
+ if (charge != INVALID_VALUE)
+ battery_submit ("0", "charge", charge);
+ if (current != INVALID_VALUE)
+ battery_submit ("0", "current", current);
+ if (voltage != INVALID_VALUE)
+ battery_submit ("0", "voltage", voltage);
}
closedir (dh);
}
#endif /* KERNEL_LINUX */
+
+ return (0);
}
-#else
-# define battery_read NULL
#endif /* BATTERY_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, battery_init, battery_read, NULL);
- plugin_register ("battery_current", NULL, NULL, battery_current_write);
- plugin_register ("battery_voltage", NULL, NULL, battery_voltage_write);
- plugin_register ("battery_charge", NULL, NULL, battery_charge_write);
-}
+ plugin_register_data_set (&charge_ds);
+ plugin_register_data_set (¤t_ds);
+ plugin_register_data_set (&voltage_ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if BATTERY_HAVE_READ
+ plugin_register_init ("battery", battery_init);
+ plugin_register_read ("battery", battery_read);
+#endif /* BATTERY_HAVE_READ */
+}
diff --git a/src/collectd-nagios.c b/src/collectd-nagios.c
--- /dev/null
+++ b/src/collectd-nagios.c
@@ -0,0 +1,492 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <assert.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
+#define RET_OKAY 0
+#define RET_WARNING 1
+#define RET_CRITICAL 2
+#define RET_UNKNOWN 3
+
+#define CON_NONE 0
+#define CON_AVERAGE 1
+#define CON_SUM 2
+
+struct range_s
+{
+ double min;
+ double max;
+ int invert;
+};
+typedef struct range_s range_t;
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+
+static char *socket_file_g = NULL;
+static char *value_string_g = NULL;
+static char *hostname_g = NULL;
+
+static range_t range_critical_g;
+static range_t range_warning_g;
+static int consolitation_g = CON_NONE;
+
+static char **match_ds_g = NULL;
+static int match_ds_num_g = 0;
+
+static int ignore_ds (const char *name)
+{
+ int i;
+
+ if (match_ds_g == NULL)
+ return (0);
+
+ for (i = 0; i < match_ds_num_g; i++)
+ if (strcasecmp (match_ds_g[i], name) == 0)
+ return (0);
+
+ return (1);
+} /* int ignore_ds */
+
+static void parse_range (char *string, range_t *range)
+{
+ char *min_ptr;
+ char *max_ptr;
+
+ if (*string == '@')
+ {
+ range->invert = 1;
+ string++;
+ }
+
+ max_ptr = strchr (string, ':');
+ if (max_ptr == NULL)
+ {
+ min_ptr = NULL;
+ max_ptr = string;
+ }
+ else
+ {
+ min_ptr = string;
+ *max_ptr = '\0';
+ max_ptr++;
+ }
+
+ assert (max_ptr != NULL);
+
+ /* `10' == `0:10' */
+ if (min_ptr == NULL)
+ range->min = 0.0;
+ /* :10 == ~:10 == -inf:10 */
+ else if ((*min_ptr == '\0') || (*min_ptr == '~'))
+ range->min = NAN;
+ else
+ range->min = atof (min_ptr);
+
+ if ((*max_ptr == '\0') || (*max_ptr == '~'))
+ range->max = NAN;
+ else
+ range->max = atof (max_ptr);
+} /* void parse_range */
+
+int match_range (range_t *range, double value)
+{
+ int ret = 0;
+
+ if ((range->min != NAN) && (range->min > value))
+ ret = 1;
+ if ((range->max != NAN) && (range->max < value))
+ ret = 1;
+
+ return (((ret - range->invert) == 0) ? 0 : 1);
+}
+
+static int get_values (int *ret_values_num, double **ret_values,
+ char ***ret_values_names)
+{
+ struct sockaddr_un sa;
+ int status;
+ int fd;
+ FILE *fh;
+ char buffer[4096];
+
+ int values_num;
+ double *values;
+ char **values_names;
+
+ int i;
+
+ fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0)
+ {
+ fprintf (stderr, "socket failed: %s\n",
+ strerror (errno));
+ return (-1);
+ }
+
+ memset (&sa, '\0', sizeof (sa));
+ sa.sun_family = AF_UNIX;
+ strncpy (sa.sun_path, socket_file_g,
+ sizeof (sa.sun_path) - 1);
+
+ status = connect (fd, (struct sockaddr *) &sa, sizeof (sa));
+ if (status != 0)
+ {
+ fprintf (stderr, "connect failed: %s\n",
+ strerror (errno));
+ return (-1);
+ }
+
+ fh = fdopen (fd, "r+");
+ if (fh == NULL)
+ {
+ fprintf (stderr, "fdopen failed: %s\n",
+ strerror (errno));
+ close (fd);
+ return (-1);
+ }
+
+ fprintf (fh, "GETVAL %s/%s\n", hostname_g, value_string_g);
+ fflush (fh);
+
+ if (fgets (buffer, sizeof (buffer), fh) == NULL)
+ {
+ fprintf (stderr, "fgets failed: %s\n",
+ strerror (errno));
+ close (fd);
+ return (-1);
+ }
+ close (fd); fd = -1;
+
+ values_num = atoi (buffer);
+ if (values_num < 1)
+ return (-1);
+
+ values = (double *) malloc (values_num * sizeof (double));
+ if (values == NULL)
+ {
+ fprintf (stderr, "malloc failed: %s\n",
+ strerror (errno));
+ return (-1);
+ }
+
+ values_names = (char **) malloc (values_num * sizeof (char *));
+ if (values_names == NULL)
+ {
+ fprintf (stderr, "malloc failed: %s\n",
+ strerror (errno));
+ free (values);
+ return (-1);
+ }
+
+ {
+ char *ptr = strchr (buffer, ' ') + 1;
+ char *key;
+ char *value;
+
+ i = 0;
+ while ((key = strtok (ptr, " \t")) != NULL)
+ {
+ ptr = NULL;
+ value = strchr (key, '=');
+ if (value == NULL)
+ continue;
+ *value = '\0'; value++;
+
+ if (ignore_ds (key) != 0)
+ continue;
+
+ values_names[i] = strdup (key);
+ values[i] = atof (value);
+
+ i++;
+ if (i >= values_num)
+ break;
+ }
+ values_num = i;
+ }
+
+ *ret_values_num = values_num;
+ *ret_values = values;
+ *ret_values_names = values_names;
+
+ return (0);
+} /* int get_values */
+
+static void usage (const char *name)
+{
+ fprintf (stderr, "Usage: %s <-s socket> <-n value_spec> <-H hostname> [options]\n"
+ "\n"
+ "Valid options are:\n"
+ " -s <socket> Path to collectd's UNIX-socket.\n"
+ " -n <v_spec> Value specification to get from collectd.\n"
+ " Format: `plugin-instance/type-instance'\n"
+ " -d <ds> Select the DS to examine. May be repeated to examine multiple\n"
+ " DSes. By default all DSes are used.\n"
+ " -g <consol> Method to use to consolidate several DSes.\n"
+ " Valid arguments are `none', `average' and `sum'\n"
+ " -H <host> Hostname to query the values for.\n"
+ " -c <range> Critical range\n"
+ " -w <range> Warning range\n"
+ "\n"
+ "Consolidation functions:\n"
+ " none: Apply the warning- and critical-ranges to each data-source\n"
+ " individually.\n"
+ " average: Calculate the average of all matching DSes and apply the\n"
+ " warning- and critical-ranges to the calculated average.\n"
+ " sum: Apply the ranges to the sum of all DSes.\n"
+ "\n", name);
+ exit (1);
+} /* void usage */
+
+int do_check_con_none (int values_num, double *values, char **values_names)
+{
+ int i;
+
+ int num_critical = 0;
+ int num_warning = 0;
+ int num_okay = 0;
+
+ for (i = 0; i < values_num; i++)
+ {
+ if (values[i] == NAN)
+ num_warning++;
+ else if (match_range (&range_critical_g, values[i]) != 0)
+ num_critical++;
+ else if (match_range (&range_warning_g, values[i]) != 0)
+ num_warning++;
+ else
+ num_okay++;
+ }
+
+ if ((num_critical != 0) || (values_num == 0))
+ {
+ printf ("CRITICAL: %i critical, %i warning, %i okay\n",
+ num_critical, num_warning, num_okay);
+ return (RET_CRITICAL);
+ }
+ else if (num_warning != 0)
+ {
+ printf ("WARNING: %i warning, %i okay\n",
+ num_warning, num_okay);
+ return (RET_WARNING);
+ }
+ else
+ {
+ printf ("OKAY: %i okay\n", num_okay);
+ return (RET_OKAY);
+ }
+
+ return (RET_UNKNOWN);
+} /* int do_check_con_none */
+
+int do_check_con_average (int values_num, double *values, char **values_names)
+{
+ int i;
+ double total;
+ int total_num;
+
+ total = 0.0;
+ total_num = 0;
+ for (i = 0; i < values_num; i++)
+ {
+ if (values[i] != NAN)
+ {
+ total += values[i];
+ total_num++;
+ }
+ }
+
+ if (total_num == 0)
+ {
+ printf ("WARNING: No defined values found\n");
+ return (RET_WARNING);
+ }
+
+ if (match_range (&range_critical_g, total / total_num) != 0)
+ {
+ printf ("CRITICAL: Average = %lf\n",
+ (double) (total / total_num));
+ return (RET_CRITICAL);
+ }
+ else if (match_range (&range_warning_g, total / total_num) != 0)
+ {
+ printf ("WARNING: Average = %lf\n",
+ (double) (total / total_num));
+ return (RET_WARNING);
+ }
+ else
+ {
+ printf ("OKAY: Average = %lf\n",
+ (double) (total / total_num));
+ return (RET_OKAY);
+ }
+
+ return (RET_UNKNOWN);
+} /* int do_check_con_average */
+
+int do_check_con_sum (int values_num, double *values, char **values_names)
+{
+ int i;
+ double total;
+ int total_num;
+
+ total = 0.0;
+ total_num = 0;
+ for (i = 0; i < values_num; i++)
+ {
+ if (values[i] != NAN)
+ {
+ total += values[i];
+ total_num++;
+ }
+ }
+
+ if (total_num == 0)
+ {
+ printf ("WARNING: No defined values found\n");
+ return (RET_WARNING);
+ }
+
+ if (match_range (&range_critical_g, total) != 0)
+ {
+ printf ("CRITICAL: Sum = %lf\n", total);
+ return (RET_CRITICAL);
+ }
+ else if (match_range (&range_warning_g, total) != 0)
+ {
+ printf ("WARNING: Sum = %lf\n", total);
+ return (RET_WARNING);
+ }
+ else
+ {
+ printf ("OKAY: Sum = %lf\n", total);
+ return (RET_OKAY);
+ }
+
+ return (RET_UNKNOWN);
+} /* int do_check_con_sum */
+
+int do_check (void)
+{
+ double *values;
+ char **values_names;
+ int values_num;
+
+ if (get_values (&values_num, &values, &values_names) != 0)
+ {
+ fputs ("ERROR: Cannot get values from daemon\n", stdout);
+ return (RET_CRITICAL);
+ }
+
+ if (consolitation_g == CON_NONE)
+ return (do_check_con_none (values_num, values, values_names));
+ else if (consolitation_g == CON_AVERAGE)
+ return (do_check_con_average (values_num, values, values_names));
+ else if (consolitation_g == CON_SUM)
+ return (do_check_con_sum (values_num, values, values_names));
+
+ free (values);
+ free (values_names);
+
+ return (RET_UNKNOWN);
+}
+
+int main (int argc, char **argv)
+{
+ range_critical_g.min = NAN;
+ range_critical_g.max = NAN;
+ range_critical_g.invert = 0;
+
+ range_warning_g.min = NAN;
+ range_warning_g.max = NAN;
+ range_warning_g.invert = 0;
+
+ while (42)
+ {
+ int c;
+
+ c = getopt (argc, argv, "w:c:s:n:H:g:d:h");
+ if (c < 0)
+ break;
+
+ switch (c)
+ {
+ case 'c':
+ parse_range (optarg, &range_critical_g);
+ break;
+ case 'w':
+ parse_range (optarg, &range_warning_g);
+ break;
+ case 's':
+ socket_file_g = optarg;
+ break;
+ case 'n':
+ value_string_g = optarg;
+ break;
+ case 'H':
+ hostname_g = optarg;
+ break;
+ case 'g':
+ if (strcasecmp (optarg, "none") == 0)
+ consolitation_g = CON_NONE;
+ else if (strcasecmp (optarg, "average") == 0)
+ consolitation_g = CON_AVERAGE;
+ else if (strcasecmp (optarg, "sum") == 0)
+ consolitation_g = CON_SUM;
+ else
+ usage (argv[0]);
+ break;
+ case 'd':
+ {
+ char **tmp;
+ tmp = (char **) realloc (match_ds_g,
+ (match_ds_num_g + 1)
+ * sizeof (char *));
+ if (tmp == NULL)
+ {
+ fprintf (stderr, "realloc failed: %s\n",
+ strerror (errno));
+ return (RET_UNKNOWN);
+ }
+ match_ds_g = tmp;
+ match_ds_g[match_ds_num_g] = strdup (optarg);
+ if (match_ds_g[match_ds_num_g] == NULL)
+ {
+ fprintf (stderr, "strdup failed: %s\n",
+ strerror (errno));
+ return (RET_UNKNOWN);
+ }
+ match_ds_num_g++;
+ break;
+ }
+ default:
+ usage (argv[0]);
+ } /* switch (c) */
+ }
+
+ if ((socket_file_g == NULL) || (value_string_g == NULL)
+ || (hostname_g == NULL))
+ usage (argv[0]);
+
+ return (do_check ());
+} /* int main */
diff --git a/src/collectd.c b/src/collectd.c
index a93cc28675d51e0ef53adc7ed7f270cbe3c71791..ab5564ead694502e0dd510804a406a1bf4e7376c 100644 (file)
--- a/src/collectd.c
+++ b/src/collectd.c
/**
* collectd - src/collectd.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* exported variables
*/
time_t curtime;
-int operating_mode;
static void sigIntHandler (int signal)
{
loop++;
}
-static int change_basedir (char *dir)
+static int change_basedir (const char *orig_dir)
{
- int dirlen = strlen (dir);
+ char *dir = strdup (orig_dir);
+ int dirlen;
+ int status;
+
+ if (dir == NULL)
+ {
+ syslog (LOG_ERR, "strdup failed: %s", strerror (errno));
+ return (-1);
+ }
+ dirlen = strlen (dir);
while ((dirlen > 0) && (dir[dirlen - 1] == '/'))
dir[--dirlen] = '\0';
if (dirlen <= 0)
return (-1);
- if (chdir (dir) == -1)
+ status = chdir (dir);
+ free (dir);
+
+ if (status != 0)
{
if (errno == ENOENT)
{
- if (mkdir (dir, 0755) == -1)
+ if (mkdir (orig_dir, 0755) == -1)
{
- syslog (LOG_ERR, "mkdir (%s): %s", dir, strerror (errno));
+ syslog (LOG_ERR, "mkdir (%s): %s", orig_dir,
+ strerror (errno));
return (-1);
}
- else if (chdir (dir) == -1)
+ else if (chdir (orig_dir) == -1)
{
- syslog (LOG_ERR, "chdir (%s): %s", dir, strerror (errno));
+ syslog (LOG_ERR, "chdir (%s): %s", orig_dir,
+ strerror (errno));
return (-1);
}
}
else
{
- syslog (LOG_ERR, "chdir: %s", strerror (errno));
+ syslog (LOG_ERR, "chdir (%s): %s", orig_dir,
+ strerror (errno));
return (-1);
}
}
exit (0);
} /* static void exit_usage (char *name) */
-static int start_client (void)
+static int do_init (void)
{
- int step;
-
- struct timeval tv_now;
- struct timeval tv_next;
- struct timespec ts_wait;
-
- step = atoi (COLLECTD_STEP);
- if (step <= 0)
- step = 10;
-
#if HAVE_LIBKSTAT
kc = NULL;
update_kstat ();
plugin_init_all ();
+ return (0);
+} /* int do_init () */
+
+
+static int do_loop (void)
+{
+ int step;
+
+ struct timeval tv_now;
+ struct timeval tv_next;
+ struct timespec ts_wait;
+
+ step = atoi (COLLECTD_STEP);
+ if (step <= 0)
+ step = 10;
+
while (loop == 0)
{
if (gettimeofday (&tv_next, NULL) < 0)
if (gettimeofday (&tv_now, NULL) < 0)
{
- syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno));
+ syslog (LOG_ERR, "gettimeofday failed: %s",
+ strerror (errno));
return (-1);
}
if (timeval_sub_timespec (&tv_next, &tv_now, &ts_wait) != 0)
{
- syslog (LOG_WARNING, "Not sleeping because `timeval_sub_timespec' returned non-zero!");
+ syslog (LOG_WARNING, "Not sleeping because "
+ "`timeval_sub_timespec' returned "
+ "non-zero!");
continue;
}
if (errno != EINTR)
{
syslog (LOG_ERR, "nanosleep failed: %s", strerror (errno));
- break;
+ return (-1);
}
}
- }
+ } /* while (loop == 0) */
+ DBG ("return (0);");
return (0);
-} /* static int start_client (void) */
+} /* int do_loop */
-#if HAVE_LIBRRD
-static int start_server (void)
+static int do_shutdown (void)
{
- char *host;
- char *type;
- char *instance;
- char *values;
-
- int error_counter = 0;
- int status;
-
- while ((loop == 0) && (error_counter < 3))
- {
- status = network_receive (&host, &type, &instance, &values);
-
- if (status != 0)
- {
- if (status < 0)
- error_counter++;
- continue;
- }
- error_counter = 0;
-
- plugin_write (host, type, instance, values);
-
- if (host != NULL) free (host); host = NULL;
- if (type != NULL) free (type); type = NULL;
- if (instance != NULL) free (instance); instance = NULL;
- if (values != NULL) free (values); values = NULL;
- }
-
+ plugin_shutdown_all ();
return (0);
-} /* static int start_server (void) */
-#endif /* HAVE_LIBRRD */
+} /* int do_shutdown */
#if COLLECT_DAEMON
-static int pidfile_create (const char *file)
+static int pidfile_create (void)
{
FILE *fh;
-
- if (file == NULL)
- file = PIDFILE;
+ const char *file = global_option_get ("PIDFile");
if ((fh = fopen (file, "w")) == NULL)
{
return (0);
} /* static int pidfile_create (const char *file) */
-#endif /* COLLECT_DAEMON */
-#if COLLECT_DAEMON
-static int pidfile_remove (const char *file)
+static int pidfile_remove (void)
{
- if (file == NULL) {
- file = PIDFILE;
- }
+ const char *file = global_option_get ("PIDFile");
+
+ DBG ("unlink (%s)", (file != NULL) ? file : "<null>");
return (unlink (file));
} /* static int pidfile_remove (const char *file) */
#endif /* COLLECT_DAEMON */
{
struct sigaction sigIntAction;
struct sigaction sigTermAction;
- char *datadir = PKGLOCALSTATEDIR;
char *configfile = CONFIGFILE;
+ const char *datadir;
#if COLLECT_DAEMON
struct sigaction sigChldAction;
- char *pidfile = NULL;
pid_t pid;
int daemonize = 1;
#endif
#if COLLECT_DEBUG
- char *logfile = LOGFILE;
-#endif
-
-#if HAVE_LIBRRD
- operating_mode = MODE_LOCAL;
-#else
- operating_mode = MODE_CLIENT;
+ const char *logfile;
#endif
/* open syslog */
break;
#if COLLECT_DAEMON
case 'P':
- pidfile = optarg;
+ global_option_set ("PIDFile", optarg);
break;
case 'f':
daemonize = 0;
} /* while (1) */
#if COLLECT_DEBUG
- if ((logfile = cf_get_option ("LogFile", LOGFILE)) != NULL)
+ if ((logfile = global_option_get ("LogFile")) != NULL)
DBG_STARTFILE (logfile, "Debug file opened.");
#endif
* Change directory. We do this _after_ reading the config and loading
* modules to relative paths work as expected.
*/
- if ((datadir = cf_get_option ("DataDir", PKGLOCALSTATEDIR)) == NULL)
+ if ((datadir = global_option_get ("BaseDir")) == NULL)
{
fprintf (stderr, "Don't have a datadir to use. This should not happen. Ever.");
return (1);
}
- if (change_basedir (datadir))
+ else if (change_basedir (datadir))
{
fprintf (stderr, "Error: Unable to change to directory `%s'.\n", datadir);
return (1);
/*
* fork off child
*/
+ memset (&sigChldAction, '\0', sizeof (sigChldAction));
sigChldAction.sa_handler = SIG_IGN;
sigaction (SIGCHLD, &sigChldAction, NULL);
- if ((pidfile == NULL)
- && ((pidfile = cf_get_option ("PIDFile", PIDFILE)) == NULL))
- {
- fprintf (stderr, "Cannot obtain pidfile. This shoud not happen. Ever.");
- return (1);
- }
-
if (daemonize)
{
if ((pid = fork ()) == -1)
setsid ();
/* Write pidfile */
- if (pidfile_create (pidfile))
+ if (pidfile_create ())
exit (2);
/* close standard descriptors */
/*
* install signal handlers
*/
+ memset (&sigIntAction, '\0', sizeof (sigIntAction));
sigIntAction.sa_handler = sigIntHandler;
sigaction (SIGINT, &sigIntAction, NULL);
+ memset (&sigTermAction, '\0', sizeof (sigTermAction));
sigTermAction.sa_handler = sigTermHandler;
sigaction (SIGTERM, &sigTermAction, NULL);
/*
* run the actual loops
*/
-#if HAVE_LIBRRD
- if (operating_mode == MODE_SERVER)
- start_server ();
- else /* if (operating_mode == MODE_CLIENT || operating_mode == MODE_LOCAL || operating_mode == MODE_LOG) */
-#endif
- start_client ();
-
- plugin_shutdown_all ();
+ do_init ();
+ do_loop ();
+ do_shutdown ();
#if COLLECT_DEBUG
if (logfile != NULL)
#if COLLECT_DAEMON
if (daemonize)
- pidfile_remove (pidfile);
+ pidfile_remove ();
#endif /* COLLECT_DAEMON */
return (0);
-} /* int main (int argc, char **argv) */
+} /* int main */
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index fcceb5412b5b407f70ddb32b29737a2b30c77e0f..9b6f8bf54d82beae12ae577d8add2d824bf77d4b 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
# http://collectd.org/
#
-# Select one of the following modes:
-@BUILD_WITH_RRDTOOL_TRUE@Mode Local
-#Mode Server
-@BUILD_WITH_RRDTOOL_FALSE@Mode Client
-#Mode Log
-
# Set the IP-address(es) and UDP-port(s) to send packets to. `Listen' can be
# used as a synonym for `Server' to make the config file more readable when in
# server mode. The port option is optional.
#Server ff18::efc0:4a42 25826
#Server 239.192.74.66 25826
-#DataDir /opt/collectd/var/lib/collectd
-#PIDFile /opt/collectd/var/run/collectd.pid
-#PluginDir /opt/collectd/lib/collectd
+#BaseDir "/opt/collectd/var/lib/collectd"
+#PIDFile "/opt/collectd/var/run/collectd.pid"
+#PluginDir "/opt/collectd/lib/collectd"
@BUILD_MODULE_APACHE_TRUE@LoadPlugin apache
@BUILD_MODULE_APCUPS_TRUE@LoadPlugin apcups
@BUILD_MODULE_BATTERY_TRUE@LoadPlugin battery
@BUILD_MODULE_CPU_TRUE@LoadPlugin cpu
@BUILD_MODULE_CPUFREQ_TRUE@LoadPlugin cpufreq
+@BUILD_MODULE_CSV_TRUE@LoadPlugin csv
@BUILD_MODULE_DF_TRUE@LoadPlugin df
@BUILD_MODULE_DISK_TRUE@LoadPlugin disk
@BUILD_MODULE_DNS_TRUE@LoadPlugin dns
+@BUILD_MODULE_EMAIL_TRUE@LoadPlugin email
@BUILD_MODULE_HDDTEMP_TRUE@LoadPlugin hddtemp
@BUILD_MODULE_IRQ_TRUE@LoadPlugin irq
@BUILD_MODULE_LOAD_TRUE@LoadPlugin load
@BUILD_MODULE_MEMORY_TRUE@LoadPlugin memory
@BUILD_MODULE_MULTIMETER_TRUE@LoadPlugin multimeter
@BUILD_MODULE_MYSQL_TRUE@LoadPlugin mysql
+@BUILD_MODULE_NETWORK_TRUE@LoadPlugin network
@BUILD_MODULE_NFS_TRUE@LoadPlugin nfs
@BUILD_MODULE_NTPD_TRUE@LoadPlugin ntpd
@BUILD_MODULE_PING_TRUE@LoadPlugin ping
@BUILD_MODULE_PROCESSES_TRUE@LoadPlugin processes
+@BUILD_WITH_RRDTOOL_TRUE@LoadPlugin rrdtool
@BUILD_MODULE_SENSORS_TRUE@LoadPlugin sensors
@BUILD_MODULE_SERIAL_TRUE@LoadPlugin serial
@BUILD_MODULE_SWAP_TRUE@LoadPlugin swap
@BUILD_MODULE_WIRELESS_TRUE@LoadPlugin wireless
#<Plugin apache>
-# URL http://localhost/status?auto
-# User www-user
-# Password secret
-# CACert /etc/ssl/ca.crt
+# URL "http://localhost/status?auto"
+# User "www-user"
+# Password "secret"
+# CACert "/etc/ssl/ca.crt"
#</Plugin>
#<Plugin apcups>
-# Host localhost
-# Port 3551
+# Host "localhost"
+# Port "3551"
#</Plugin>
#<Plugin dns>
-# Interface eth0
-# IgnoreSource 192.168.0.1
+# Interface "eth0"
+# IgnoreSource "192.168.0.1"
#</Plugin>
#<Plugin hddtemp>
-# Host 127.0.0.1
+# Host "127.0.0.1"
# Port 7634
#</Plugin>
#</Plugin>
#<Plugin mbmon>
-# Host 127.0.0.1
+# Host "127.0.0.1"
# Port 411
#</Plugin>
+#<Plugin network>
+# Server "ff18::efc0:4a42" "25826"
+# Server "239.192.74.66" "25826"
+# Listen "ff18::efc0:4a42" "25826"
+# Listen "239.192.74.66" "25826"
+# TimeToLive "128"
+#</Plugin>
+
#<Plugin ntpd>
-# Host localhost
+# Host "localhost"
# Port 123
#</Plugin>
#<Plugin mysql>
-# Host database.serv.er
-# User db_user
-# Password secret
-# Database db_name
+# Host "database.serv.er"
+# User "db_user"
+# Password "secret"
+# Database "db_name"
#</Plugin>
#<Plugin ping>
-# Host host.foo.bar
+# Host "host.foo.bar"
#</Plugin>
#<Plugin processes>
-# Process name
+# Process "name"
+#</Plugin>
+
+#<Plugin rrdtool>
+# CacheTimeout 120
+# CacheFlush 900
+# DataDir "/opt/collectd/var/lib/collectd"
#</Plugin>
## There are two different naming schemes for the sensors plugin, to preserver
## backwards compatibility. The `extended naming' is prefered, but not the
## default for this reason. See `collectd.conf(5)' for more information.
#<Plugin sensors>
-# ExtendedSensorNaming false
-# Sensor it8712-temp1
-# Sensor it8712-fan3
-# Sensor it8712-in8
-## -- OR --
-# ExtendedSensorNaming true
-# Sensor it8712-isa-0290/temperature-temp1
-# Sensor it8712-isa-0290/fanspeed-fan3
-# Sensor it8712-isa-0290/voltage-in8
+# Sensor "it8712-isa-0290/temperature-temp1"
+# Sensor "it8712-isa-0290/fanspeed-fan3"
+# Sensor "it8712-isa-0290/voltage-in8"
#
# IgnoreSelected false
#</Plugin>
#<Plugin traffic>
-# Interface eth0
+# Interface "eth0"
# IgnoreSelected false
#</Plugin>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 1fba214ed48126d1e9ecaa81c6a75e7b435c465e..ecf7ef687bfd448df5a0cbcc2a0cd0a9aaac0832 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
=head1 SYNOPSIS
- Mode Client
- DataDir /path/to/data/
- PIDFile /path/to/pidfile/collectd.pid
- LogFile /path/to/logfile/collectd.log
- Server 123.123.123.123 12345
+ BaseDir "/path/to/data/"
+ PIDFile "/path/to/pidfile/collectd.pid"
+ LogFile "/path/to/logfile/collectd.log"
+ Server "123.123.123.123" 12345
LoadPlugin cpu
LoadPlugin load
LoadPlugin ping
<Plugin ping>
- Host example.org
- Host provider.net
+ Host "example.org"
+ Host "provider.net"
</Plugin>
=head1 DESCRIPTION
This config file controls how the system statistics collection daemon
-B<collectd> behaves. The most significant options are B<Mode>, which controlls
-if the daemon will act as client, server or will be independent in local mode,
-and B<LoadPlugin> which controls which plugins to load.
+B<collectd> behaves. The most significant option is B<LoadPlugin>, which
+controls which plugins to load. These plugins ultimately define collectd's
+behavior.
The syntax of this config file is similar to the config file of the famos
B<Apache Webserver>. Each line containes either a key-value-pair or a
section-start or -end. Empty lines and everything after the hash-symbol `#' is
-ignored.
+ignored. Values are either string, enclosed in double-quotes,
+(floating-point-)numbers or a boolean extression, i.E<nbsp>e. either B<true> or
+B<false>. String containing of only alphanumeric characters and underscores do
+not need to be quoted.
=head1 GLOBAL OPTIONS
=over 4
-=item B<Mode> (B<Local>|B<Client>|B<Server>|B<Log>)
+=item B<BaseDir> I<Directory>
-Sets the operating mode. See the section B<MODES> in L<collectd(1)> for a
-description. This option determines which other options are allowed. Defaults
-to B<Local>.
+Sets the base directory. This is the directory beneath all RRD-files are
+created. Possibly more subdirectories are created. This is also the working
+directory for the daemon.
=item B<LoadPlugin> I<Plugin>
Sets where to write the PID file to. This file is overwritten when it exists
and deleted when the program ist stopped. Some init-scripts might override this
-setting using the B<-P> commandline option. Available in B<all modes>.
-
-=item B<DataDir> I<Directory>
-
-Sets the data directory. This is the directory beneath all RRD-files are
-created. Possibly more subdirectories are created. This is also the working
-directory for the daemon. Available in B<all modes>, though the B<Client> mode
-won't write to this directory.
+setting using the B<-P> commandline option.
=item B<LogFile> I<File>
Sets the file to write debugging output to. This is only used if compiled with
-debugging enabled. It's ignored otherwise. Available in B<all modes>.
-
-=item B<Listen> I<Host> [I<Port>]
-
-=item B<Server> I<Host> [I<Port>]
-
-In B<client mode> the B<Server> statement sets the server to send datagrams to.
-The statement may occur multiple times to send each datagram to multiple
-destinations.
-
-In B<server mode> the B<Listen> statement sets the interfaces to bind to. When
-multiple statements are found the daemon will bind to multiple interfaces.
-
-The argument I<Host> may be a hostname, an IPv4 address or an IPv6 address. If
-the argument is a multicast address the daemon will join that multicast group.
-
-If no B<Listen> statement is found the server tries join both, the IPv6
-multicast group and the IPv4 multicast group. If no B<Server> statement is
-found the client will try to send data to the IPv6 multicast group first. If
-that failes the client will try the IPv4 multicast group.
-
-The default IPv6 multicast group is C<ff18::efc0:4a42>. The default IPv4
-multicast group is C<239.192.74.66>.
-
-The optional I<Port> argument sets the port to use. It can either be given
-using a numeric port number or a service name. If the argument is omited the
-default port B<25826> is assumed.
-
-=item B<TimeToLive> I<1-255>
-
-Set the time-to-live of sent packets. This applies to all, unicast and
-multicast, and IPv4 and IPv6 packets. The default is to not change this value.
-That means that multicast packets will be sent with a TTL of C<1> (one) on most
-operating systems.
+debugging enabled. It's ignored otherwise.
=back
=back
-=head2 Plugin C<ntpd>
-
-=over 4
-
-=item B<Host> I<Hostname>
-
-Hostname of the host running B<ntpd>. Defaults to B<localhost>.
-
-=item B<Port> I<Port>
-
-UDP-Port to connect to. Defaults to B<123>.
-
-=back
-
=head2 Plugin C<mysql>
=over 4
=back
+=head2 Plugin C<network>
+
+=over 4
+
+=item B<Listen> I<Host> [I<Port>]
+
+=item B<Server> I<Host> [I<Port>]
+
+The B<Server> statement sets the server to send datagrams B<to>. The statement
+may occur multiple times to send each datagram to multiple destinations.
+
+The B<Listen> statement sets the interfaces to bind to. When multiple
+statements are found the daemon will bind to multiple interfaces.
+
+The argument I<Host> may be a hostname, an IPv4 address or an IPv6 address. If
+the argument is a multicast address the daemon will join that multicast group.
+
+If no B<Listen> statement is found the server tries join both, the default IPv6
+multicast group and the default IPv4 multicast group. If no B<Server> statement
+is found the client will try to send data to the IPv6 multicast group first. If
+that failes the client will try the IPv4 multicast group.
+
+The default IPv6 multicast group is C<ff18::efc0:4a42>. The default IPv4
+multicast group is C<239.192.74.66>.
+
+The optional I<Port> argument sets the port to use. It can either be given
+using a numeric port number or a service name. If the argument is omited the
+default port B<25826> is assumed.
+
+=item B<TimeToLive> I<1-255>
+
+Set the time-to-live of sent packets. This applies to all, unicast and
+multicast, and IPv4 and IPv6 packets. The default is to not change this value.
+That means that multicast packets will be sent with a TTL of C<1> (one) on most
+operating systems.
+
+=back
+
+=head2 Plugin C<ntpd>
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<ntpd>. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+UDP-Port to connect to. Defaults to B<123>.
+
+=back
+
=head2 Plugin C<ping>
=over 4
=back
+=head2 Plugin C<rrdtool>
+
+=over 4
+
+=item B<CacheFlush> I<Seconds>
+
+When the C<rrdtool plugin> uses a cache (by setting B<CacheTimeout>, see below)
+it writes all values for a certain RRD-file if the oldest value is older than
+(or equal to) the number of seconds specified. If some RRD-file is not updated
+anymore for some reason (the computer was shut down, the network is broken,
+etc.) some values may still be in the cache. If B<CacheFlush> is set, then the
+entire cache is searched for entries older than B<CacheTimeout> seconds and
+written to disk every I<Seconds> seconds. Since this is kind of expensive and
+does nothing under normal circumstances, this value should not be too small.
+900 seconds might be a good value, though setting this to 7200 seconds doesn't
+normally do much harm either.
+
+=item B<CacheTimeout> I<Seconds>
+
+If this option is set to a value greater than zero, the C<rrdtool plugin> will
+save values in a cache, as described above. Writing multiple values at once
+reduces IO-operations and thus lessens the load produced by updating the files.
+The tradeoff is that the graphs kind of "drag behind" and that more memory is
+used.
+
+=item B<DataDir> I<Directory>
+
+Set the directory to store RRD-files under. Per default RRD-files are generated
+beneath the daemon's working directory, i.E<nbsp>e. the B<BaseDir>.
+
+=back
+
=head2 Plugin C<sensors>
=over 4
-=item B<ExtendedSensorNaming> I<true>|I<false>
-
-If set to I<true> this option switches on the extended sensors and RRD-files
-naming. This option exists to preserve backwards compatibility. It is
-recommended that you set this option to I<true>. The default is I<false> to
-maintain compatibility only.
-
-Sensors get names like I<chip-bus-address/type-feature> (e.g.
-I<it8712-isa-0290/voltage-in1>) and RRD files are therefore stored in a
-standalone directory inside the B<DataDir> directory and get names like
-I<lm_sensors-chip-bus-address/type-feature.rrd> (e.g.
-I<lm_sensors-it8712-isa-0290/voltage-in1.rrd>).
-
-The B<ExtendedSensorNaming> option breaks the compatibility with previous
-sensors and RRD files naming and the place where RRDs are stored. If you turn
-it on, the plugin will create new RRD files in a standalone directory inside
-the B<DataDir> directory and without previous history. You can rename ``old''
-RRD-files to preserve already collected statistics, because the file layout
-hasn't changed. If you have two chips of the same type, you need to use
-B<ExtendedSensorNaming> in order to collect information from both chips.
-
-If not set or set to I<false>, the extended naming is not active. Sensors get
-names like I<chip-feature> (e.g. I<it8712-in1>) and RRD files are stored in the
-main B<DataDir> directory and get names like I<sensors-chip-feature.rrd> (e.g.
-I<sensors-it8712-in1.rrd>). You simply continue using the plugin the old way
-and additionally also getting data for newly added sensors in this mode.
-
-=item B<Sensor> I<chip-feature> or B<Sensor> I<chip-bus-address/type-feature>
-
-Both option modes select the name of the sensor which you want to collect.
-The naming scheme is dependent on the state of the B<ExtendedSensorNaming>
-option (see previous option). Both option modes can also deselect the
-sensor according to the B<IgnoreSelected> option (see below).
-
-For example the option "B<Sensor> I<it8712-in1>" will cause the collectd
-to gather data for the voltage sensor I<in1> of the I<it8712> chip in case
-of the B<ExtendedSensorNaming> option is set to I<false>.
-
-And likewise the option "B<Sensor> I<it8712-isa-0290/voltage-in1>" will
-cause the collectd to gather data for the voltage sensor I<in1> of the I<it8712>
-on the isa bus at the address 0290 in case of the B<ExtendedSensorNaming>
-option set to I<true>.
+=item B<Sensor> I<chip-bus-address/type-feature>
-=item B<IgnoreSelected> I<true>|I<false>
+Selects the name of the sensor which you want to collect or ignore, depending
+on the B<IgnoreSelected> below. For example, the option "B<Sensor>
+I<it8712-isa-0290/voltage-in1>" will cause collectd to gather data for the
+voltage sensor I<in1> of the I<it8712> on the isa bus at the address 0290.
-If no configuration if given, the B<sensors>-plugin will collect data from
-all sensors. This may not be practical, especially for uninteresting sensors.
-Thus, you can use the B<Sensor>-option to pick the sensors you're
-interested in. Sometimes, however, it's easier/prefered to collect all
-sensors I<except> a few ones. This option enables you to
-do that: By setting B<IgnoreSelected> to I<true> the effect of
-B<Sensor> is inversed: All selected sensors are ignored and all
-other sensors are collected.
+=item B<IgnoreSelected> I<true>|I<false>
-back
+If no configuration if given, the B<sensors>-plugin will collect data from all
+sensors. This may not be practical, especially for uninteresting sensors.
+Thus, you can use the B<Sensor>-option to pick the sensors you're interested
+in. Sometimes, however, it's easier/prefered to collect all sensors I<except> a
+few ones. This option enables you to do that: By setting B<IgnoreSelected> to
+I<true> the effect of B<Sensor> is inversed: All selected sensors are ignored
+and all other sensors are collected.
=back
diff --git a/src/collectd.h b/src/collectd.h
index a5c81694753c4c8ecfce7f2d676a1d193534f2bf..7784d5540845de90172ac9da7662fcbd442df139 100644 (file)
--- a/src/collectd.h
+++ b/src/collectd.h
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
# define assert(...) /* nop */
#endif
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
#if HAVE_DIRENT_H
# include <dirent.h>
# define NAMLEN(dirent) strlen((dirent)->d_name)
# define COLLECTD_XFF 0.1
#endif
+#define STATIC_ARRAY_LEN(array) (sizeof (array) / sizeof ((array)[0]))
+
extern time_t curtime;
-#ifdef HAVE_LIBRRD
-extern int operating_mode;
-#endif
+int pidfile_set (const char *file);
+const char *pidfile_get (void);
/* int main (int argc, char **argv); */
diff --git a/src/common.c b/src/common.c
index 5487b326fd34ac31eb8adfe20fa6971ecd0c4fec..365b74f30091599c8d4d703da184c899cd20e26a 100644 (file)
--- a/src/common.c
+++ b/src/common.c
/**
* collectd - src/common.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
*
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* Florian octo Forster <octo at verplant.org>
# include <math.h>
#endif
-extern int operating_mode;
+/* for ntohl and htonl */
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
#ifdef HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
#endif
-#ifdef HAVE_LIBRRD
-#if 0
-static char *rra_def[] =
-{
- "RRA:AVERAGE:0.0:1:1500",
- "RRA:AVERAGE:0.2:6:1500",
- "RRA:AVERAGE:0.1:180:1680",
- "RRA:AVERAGE:0.1:2160:1520",
- "RRA:MIN:0.0:1:1500",
- "RRA:MIN:0.2:6:1500",
- "RRA:MIN:0.1:180:1680",
- "RRA:MIN:0.1:2160:1520",
- "RRA:MAX:0.0:1:1500",
- "RRA:MAX:0.2:6:1500",
- "RRA:MAX:0.1:180:1680",
- "RRA:MAX:0.1:2160:1520",
- NULL
-};
-static int rra_num = 12;
-#endif
-
-static int rra_timespans[] =
-{
- 3600,
- 86400,
- 604800,
- 2678400,
- 31622400,
- 0
-};
-static int rra_timespans_num = 5;
-
-static char *rra_types[] =
-{
- "AVERAGE",
- "MIN",
- "MAX",
- NULL
-};
-static int rra_types_num = 3;
-#endif /* HAVE_LIBRRD */
-
void sstrncpy (char *d, const char *s, int len)
{
strncpy (d, s, len);
@@ -320,7 +279,7 @@ int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct times
return (0);
}
-static int check_create_dir (const char *file_orig)
+int check_create_dir (const char *file_orig)
{
struct stat statbuf;
return (0);
}
-/* * * * *
- * Magic *
- * * * * */
-#if HAVE_LIBRRD
-static int rra_get (char ***ret)
-{
- static char **rra_def = NULL;
- static int rra_num = 0;
-
- int rra_max = rra_timespans_num * rra_types_num;
-
- int step;
- int rows;
- int span;
-
- int cdp_num;
- int cdp_len;
- int i, j;
-
- char buffer[64];
-
- if ((rra_num != 0) && (rra_def != NULL))
- {
- *ret = rra_def;
- return (rra_num);
- }
-
- if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
- return (-1);
- memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
-
- step = atoi (COLLECTD_STEP);
- rows = atoi (COLLECTD_ROWS);
-
- if ((step <= 0) || (rows <= 0))
- {
- *ret = NULL;
- return (-1);
- }
-
- cdp_len = 0;
- for (i = 0; i < rra_timespans_num; i++)
- {
- span = rra_timespans[i];
-
- if ((span / step) < rows)
- continue;
-
- if (cdp_len == 0)
- cdp_len = 1;
- else
- cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
-
- cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
-
- for (j = 0; j < rra_types_num; j++)
- {
- if (rra_num >= rra_max)
- break;
-
- if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
- rra_types[j], COLLECTD_XFF,
- cdp_len, cdp_num) >= sizeof (buffer))
- {
- syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
- continue;
- }
-
- rra_def[rra_num++] = sstrdup (buffer);
- }
- }
-
-#if COLLECT_DEBUG
- DBG ("rra_num = %i", rra_num);
- for (i = 0; i < rra_num; i++)
- DBG (" %s", rra_def[i]);
-#endif
-
- *ret = rra_def;
- return (rra_num);
-}
-#endif /* HAVE_LIBRRD */
-
-static int log_create_file (char *filename, char **ds_def, int ds_num)
-{
- FILE *log;
- int i;
-
- if (check_create_dir (filename))
- return (-1);
-
- log = fopen (filename, "w");
- if (log == NULL)
- {
- syslog (LOG_WARNING, "Failed to create %s: %s", filename,
- strerror(errno));
- return (-1);
- }
-
- fprintf (log, "epoch");
- for (i = 0; i < ds_num; i++)
- {
- char *name;
- char *tmp;
-
- name = strchr (ds_def[i], ':');
- if (name == NULL)
- {
- syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
- ds_def[i], filename);
- fclose(log);
- remove(filename);
- return (-1);
- }
-
- name += 1;
- tmp = strchr (name, ':');
- if (tmp == NULL)
- {
- syslog (LOG_WARNING, "Invalid DS definition '%s' for %s",
- ds_def[i], filename);
- fclose(log);
- remove(filename);
- return (-1);
- }
-
- /* The `%.*s' is needed because there is no null-byte behind
- * the name. */
- fprintf(log, ",%.*s", (int) (tmp - name), name);
- }
- fprintf(log, "\n");
- fclose(log);
-
- return 0;
-}
-
-static int log_update_file (char *host, char *file, char *values,
- char **ds_def, int ds_num)
-{
- char *tmp;
- FILE *fp;
- struct stat statbuf;
- char full_file[1024];
-
- /* Cook the values a bit: Substitute colons with commas */
- strsubstitute (values, ':', ',');
-
- /* host == NULL => local mode */
- if (host != NULL)
- {
- if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
- return (-1);
- }
- else
- {
- if (snprintf (full_file, 1024, "%s", file) >= 1024)
- return (-1);
- }
-
- strncpy (full_file, file, 1024);
-
- tmp = full_file + strlen (full_file) - 4;
- assert ((tmp != NULL) && (tmp > full_file));
-
- /* Change the filename for logfiles. */
- if (strncmp (tmp, ".rrd", 4) == 0)
- {
- time_t now;
- struct tm *tm;
-
- /* TODO: Find a way to minimize the calls to `localtime', since
- * they are pretty expensive.. */
- now = time (NULL);
- tm = localtime (&now);
-
- strftime (tmp, 1024 - (tmp - full_file), "-%Y-%m-%d", tm);
-
- /* `localtime(3)' returns a pointer to static data,
- * therefore the pointer may not be free'd. */
- }
- else
- DBG ("The filename ends with `%s' which is unexpected.", tmp);
-
- if (stat (full_file, &statbuf) == -1)
- {
- if (errno == ENOENT)
- {
- if (log_create_file (full_file, ds_def, ds_num))
- return (-1);
- }
- else
- {
- syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
- return (-1);
- }
- }
- else if (!S_ISREG (statbuf.st_mode))
- {
- syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
- return (-1);
- }
-
-
- fp = fopen (full_file, "a");
- if (fp == NULL)
- {
- syslog (LOG_WARNING, "Failed to append to %s: %s", full_file,
- strerror(errno));
- return (-1);
- }
- fprintf(fp, "%s\n", values);
- fclose(fp);
-
- return (0);
-} /* int log_update_file */
-
-#if HAVE_LIBRRD
-static int rrd_create_file (char *filename, char **ds_def, int ds_num)
-{
- char **argv;
- int argc;
- char **rra_def;
- int rra_num;
- int i, j;
- int status = 0;
-
- if (check_create_dir (filename))
- return (-1);
-
- if ((rra_num = rra_get (&rra_def)) < 1)
- {
- syslog (LOG_ERR, "rra_create failed: Could not calculate RRAs");
- return (-1);
- }
-
- argc = ds_num + rra_num + 4;
-
- if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
- {
- syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
- return (-1);
- }
-
- argv[0] = "create";
- argv[1] = filename;
- argv[2] = "-s";
- argv[3] = COLLECTD_STEP;
-
- j = 4;
- for (i = 0; i < ds_num; i++)
- argv[j++] = ds_def[i];
- for (i = 0; i < rra_num; i++)
- argv[j++] = rra_def[i];
- argv[j] = NULL;
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
- if (rrd_create (argc, argv) == -1)
- {
- syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
- status = -1;
- }
-
- free (argv);
-
- return (status);
-}
-#endif /* HAVE_LIBRRD */
-
-int rrd_update_file (char *host, char *file, char *values,
- char **ds_def, int ds_num)
-{
-#if HAVE_LIBRRD
- struct stat statbuf;
- char full_file[1024];
- char *argv[4] = { "update", full_file, values, NULL };
-#endif /* HAVE_LIBRRD */
-
- /* I'd rather have a function `common_update_file' to make this
- * decission, but for that we'd need to touch all plugins.. */
- if (operating_mode == MODE_LOG)
- return (log_update_file (host, file, values,
- ds_def, ds_num));
-
-#if HAVE_LIBRRD
- /* host == NULL => local mode */
- if (host != NULL)
- {
- if (snprintf (full_file, 1024, "%s/%s", host, file) >= 1024)
- return (-1);
- }
- else
- {
- if (snprintf (full_file, 1024, "%s", file) >= 1024)
- return (-1);
- }
-
- if (stat (full_file, &statbuf) == -1)
- {
- if (errno == ENOENT)
- {
- if (rrd_create_file (full_file, ds_def, ds_num))
- return (-1);
- }
- else
- {
- syslog (LOG_ERR, "stat %s: %s", full_file, strerror (errno));
- return (-1);
- }
- }
- else if (!S_ISREG (statbuf.st_mode))
- {
- syslog (LOG_ERR, "stat %s: Not a regular file!", full_file);
- return (-1);
- }
-
- optind = 0; /* bug in librrd? */
- rrd_clear_error ();
- if (rrd_update (3, argv) == -1)
- {
- syslog (LOG_WARNING, "rrd_update failed: %s: %s", full_file, rrd_get_error ());
- return (-1);
- }
- return (0);
-/* #endif HAVE_LIBRRD */
-
-#else
- syslog (LOG_ERR, "`rrd_update_file' was called, but collectd isn't linked against librrd!");
- return (-1);
-#endif
-}
-
#ifdef HAVE_LIBKSTAT
int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name)
{
return (retval);
}
#endif /* HAVE_LIBKSTAT */
+
+unsigned long long ntohll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return (n);
+#else
+ return (((unsigned long long) ntohl (n)) << 32) + ntohl (n >> 32);
+#endif
+}
+
+unsigned long long htonll (unsigned long long n)
+{
+#if __BYTE_ORDER == __BIG_ENDIAN
+ return (n);
+#else
+ return (((unsigned long long) htonl (n)) << 32) + htonl (n >> 32);
+#endif
+}
diff --git a/src/common.h b/src/common.h
index 2be2ff504b84f58276bc3304ef5696c5623ec52d..9164cc2debd45994ab4bdb1944891e07f7975daa 100644 (file)
--- a/src/common.h
+++ b/src/common.h
/**
* collectd - src/common.h
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
*
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
*
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
* Florian octo Forster <octo at verplant.org>
} \
(ptr) = NULL
+#define STATIC_ARRAY_SIZE(a) (sizeof (a) / sizeof (*(a)))
+
void sstrncpy(char *d, const char *s, int len);
char *sstrdup(const char *s);
void *smalloc(size_t size);
/* FIXME: `timeval_sub_timespec' needs a description */
int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret);
-int rrd_update_file (char *host, char *file, char *values,
- char **ds_def, int ds_num);
+int check_create_dir (const char *file_orig);
#ifdef HAVE_LIBKSTAT
int get_kstat (kstat_t **ksp_ptr, char *module, int instance, char *name);
long long get_kstat_value (kstat_t *ksp, char *name);
#endif
+unsigned long long ntohll (unsigned long long n);
+unsigned long long htonll (unsigned long long n);
+
#endif /* COMMON_H */
diff --git a/src/configfile.c b/src/configfile.c
index 40b46fab2d9fb160639ddf24956fd8263c60ade8..a8f902fd20823f80283375b739e3563915b9a3c5 100644 (file)
--- a/src/configfile.c
+++ b/src/configfile.c
#include "collectd.h"
-#include "libconfig/libconfig.h"
+#include "liboconfig/oconfig.h"
#include "common.h"
#include "plugin.h"
#include "network.h"
#include "utils_debug.h"
-#define SHORTOPT_NONE 0
-
-#define ERR_NOT_NESTED "Sections cannot be nested.\n"
-#define ERR_SECTION_ONLY "`%s' can only be used as section.\n"
-#define ERR_NEEDS_ARG "Section `%s' needs an argument.\n"
-#define ERR_NEEDS_SECTION "`%s' can only be used within a section.\n"
-
#define ESCAPE_NULL(str) ((str) == NULL ? "(null)" : (str))
-#define DEBUG_CALLBACK(shortvar, var, arguments, value) \
- DBG("shortvar = %s, var = %s, arguments = %s, value = %s, ...", \
- ESCAPE_NULL(shortvar), \
- ESCAPE_NULL(var), \
- ESCAPE_NULL(arguments), \
- ESCAPE_NULL(value))
-
-extern int operating_mode;
-
+/*
+ * Private types
+ */
typedef struct cf_callback
{
- char *type;
- int (*callback) (char *, char *);
- char **keys;
+ const char *type;
+ int (*callback) (const char *, const char *);
+ const char **keys;
int keys_num;
struct cf_callback *next;
} cf_callback_t;
-static cf_callback_t *first_callback = NULL;
+typedef struct cf_value_map_s
+{
+ char *key;
+ int (*func) (const oconfig_item_t *);
+} cf_value_map_t;
-typedef struct cf_mode_item
+typedef struct cf_global_option_s
{
char *key;
char *value;
- int mode;
-} cf_mode_item_t;
+ char *def;
+} cf_global_option_t;
+
+/*
+ * Prototypes of callback functions
+ */
+static int dispatch_value_plugindir (const oconfig_item_t *ci);
+static int dispatch_value_loadplugin (const oconfig_item_t *ci);
-/* TODO
- * - LogFile
+/*
+ * Private variables
*/
-static cf_mode_item_t cf_mode_list[] =
+static cf_callback_t *first_callback = NULL;
+
+static cf_value_map_t cf_value_map[] =
{
- {"TimeToLive", NULL, MODE_CLIENT },
- {"PIDFile", NULL, MODE_CLIENT | MODE_SERVER | MODE_LOCAL | MODE_LOG },
- {"DataDir", NULL, MODE_CLIENT | MODE_SERVER | MODE_LOCAL | MODE_LOG },
- {"LogFile", NULL, MODE_CLIENT | MODE_SERVER | MODE_LOCAL | MODE_LOG }
+ {"PluginDir", dispatch_value_plugindir},
+ {"LoadPlugin", dispatch_value_loadplugin}
};
-static int cf_mode_num = 4;
+static int cf_value_map_num = STATIC_ARRAY_LEN (cf_value_map);
-static int nesting_depth = 0;
-static char *current_module = NULL;
-
-/* `cf_register' needs this prototype */
-static int cf_callback_plugin_dispatch (const char *, const char *,
- const char *, const char *, lc_flags_t, void *);
+static cf_global_option_t cf_global_options[] =
+{
+ {"BaseDir", NULL, PKGLOCALSTATEDIR},
+ {"LogFile", NULL, LOGFILE},
+ {"PIDFile", NULL, PIDFILE}
+};
+static int cf_global_options_num = STATIC_ARRAY_LEN (cf_global_options);
/*
* Functions to handle register/unregister, search, and other plugin related
* stuff
*/
-static cf_callback_t *cf_search (char *type)
+static cf_callback_t *cf_search (const char *type)
{
cf_callback_t *cf_cb;
return (cf_cb);
}
-static int cf_dispatch (char *type, const char *orig_key, const char *orig_value)
+static int cf_dispatch (const char *type, const char *orig_key,
+ const char *orig_value)
{
cf_callback_t *cf_cb;
char *key;
@@ -150,415 +149,236 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value
DBG ("return (%i)", ret);
return (ret);
-}
+} /* int cf_dispatch */
-void cf_unregister (char *type)
+static int dispatch_global_option (const oconfig_item_t *ci)
{
- cf_callback_t *this, *prev;
-
- for (prev = NULL, this = first_callback;
- this != NULL;
- prev = this, this = this->next)
- if (strcasecmp (this->type, type) == 0)
- {
- if (prev == NULL)
- first_callback = this->next;
- else
- prev->next = this->next;
+ if (ci->values_num != 1)
+ return (-1);
+ if (ci->values[0].type != OCONFIG_TYPE_STRING)
+ return (-1);
- free (this);
- break;
- }
+ return (global_option_set (ci->key, ci->values[0].value.string));
}
-void cf_register (char *type,
- int (*callback) (char *, char *),
- char **keys, int keys_num)
+static int dispatch_value_plugindir (const oconfig_item_t *ci)
{
- cf_callback_t *cf_cb;
- char buf[64];
- int i;
-
- /* Remove this module from the list, if it already exists */
- cf_unregister (type);
-
- /* This pointer will be free'd in `cf_unregister' */
- if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
- return;
-
- cf_cb->type = type;
- cf_cb->callback = callback;
- cf_cb->keys = keys;
- cf_cb->keys_num = keys_num;
-
- cf_cb->next = first_callback;
- first_callback = cf_cb;
+ assert (strcasecmp (ci->key, "PluginDir") == 0);
+
+ if (ci->values_num != 1)
+ return (-1);
+ if (ci->values[0].type != OCONFIG_TYPE_STRING)
+ return (-1);
- for (i = 0; i < keys_num; i++)
- {
- if (snprintf (buf, 64, "Plugin.%s", keys[i]) < 64)
- {
- /* This may be called multiple times for the same
- * `key', but apparently `lc_register_*' can handle
- * it.. */
- lc_register_callback (buf, SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_plugin_dispatch,
- NULL);
- }
- else
- {
- DBG ("Key was truncated: `%s'", ESCAPE_NULL(keys[i]));
- }
- }
+ plugin_set_dir (ci->values[0].value.string);
+ return (0);
}
-/*
- * Other query functions
- */
-char *cf_get_option (const char *key, char *def)
+static int dispatch_value_loadplugin (const oconfig_item_t *ci)
{
- int i;
+ assert (strcasecmp (ci->key, "LoadPlugin") == 0);
- for (i = 0; i < cf_mode_num; i++)
- {
- if ((cf_mode_list[i].mode & operating_mode) == 0)
- continue;
+ if (ci->values_num != 1)
+ return (-1);
+ if (ci->values[0].type != OCONFIG_TYPE_STRING)
+ return (-1);
- if (strcasecmp (cf_mode_list[i].key, key) != 0)
- continue;
+ return (plugin_load (ci->values[0].value.string));
+} /* int dispatch_value_loadplugin */
- if (cf_mode_list[i].value != NULL)
- return (cf_mode_list[i].value);
- return (def);
- }
-
- return (NULL);
-}
+static int dispatch_value_plugin (const char *plugin, oconfig_item_t *ci)
+{
+ char buffer[4096];
+ char *buffer_ptr;
+ int buffer_free;
+ int i;
-/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * Functions for the actual parsing *
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+ buffer_ptr = buffer;
+ buffer_free = sizeof (buffer);
-/*
- * `cf_callback_mode'
- * Chose the `operating_mode'
- *
- * Mode `value'
- */
-static int cf_callback_mode (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
-{
- DEBUG_CALLBACK (shortvar, var, arguments, value);
-
- if (strcasecmp (value, "Client") == 0)
- operating_mode = MODE_CLIENT;
-#if HAVE_LIBRRD
- else if (strcasecmp (value, "Server") == 0)
- operating_mode = MODE_SERVER;
- else if (strcasecmp (value, "Local") == 0)
- operating_mode = MODE_LOCAL;
-#else /* !HAVE_LIBRRD */
- else if (strcasecmp (value, "Server") == 0)
+ for (i = 0; i < ci->values_num; i++)
{
- fprintf (stderr, "Invalid mode `Server': "
- "You need to link against librrd for this "
- "mode to be available.\n");
- syslog (LOG_ERR, "Invalid mode `Server': "
- "You need to link against librrd for this "
- "mode to be available.");
- return (LC_CBRET_ERROR);
- }
- else if (strcasecmp (value, "Local") == 0)
- {
- fprintf (stderr, "Invalid mode `Local': "
- "You need to link against librrd for this "
- "mode to be available.\n");
- syslog (LOG_ERR, "Invalid mode `Local': "
- "You need to link against librrd for this "
- "mode to be available.");
- return (LC_CBRET_ERROR);
- }
-#endif
- else if (strcasecmp (value, "Log") == 0)
- operating_mode = MODE_LOG;
- else
- {
- syslog (LOG_ERR, "Invalid value for config option `Mode': `%s'", value);
- return (LC_CBRET_ERROR);
+ int status = -1;
+
+ if (ci->values[i].type == OCONFIG_TYPE_STRING)
+ status = snprintf (buffer_ptr, buffer_free, " %s",
+ ci->values[i].value.string);
+ else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
+ status = snprintf (buffer_ptr, buffer_free, " %lf",
+ ci->values[i].value.number);
+ else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
+ status = snprintf (buffer_ptr, buffer_free, " %s",
+ ci->values[i].value.boolean
+ ? "true" : "false");
+
+ if ((status < 0) || (status >= buffer_free))
+ return (-1);
+ buffer_free -= status;
+ buffer_ptr += status;
}
+ /* skip the initial space */
+ buffer_ptr = buffer + 1;
- return (LC_CBRET_OKAY);
-}
-
-/*
- * `cf_callback_mode_plugindir'
- * Change the plugin directory
- *
- * <Mode xxx>
- * PluginDir `value'
- * </Mode>
- */
-static int cf_callback_mode_plugindir (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
-{
- DEBUG_CALLBACK (shortvar, var, arguments, value);
-
- plugin_set_dir (value);
-
- return (LC_CBRET_OKAY);
-}
+ return (cf_dispatch (plugin, ci->key, buffer_ptr));
+} /* int plugin_conf_dispatch */
-static int cf_callback_mode_option (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
+static int dispatch_value (const oconfig_item_t *ci)
{
- cf_mode_item_t *item;
+ int ret = -2;
+ int i;
- DEBUG_CALLBACK (shortvar, var, arguments, value);
+ for (i = 0; i < cf_value_map_num; i++)
+ if (strcasecmp (cf_value_map[i].key, ci->key) == 0)
+ {
+ ret = cf_value_map[i].func (ci);
+ break;
+ }
- if (extra == NULL)
- {
- fprintf (stderr, "No extra..?\n");
- return (LC_CBRET_ERROR);
- }
+ for (i = 0; i < cf_global_options_num; i++)
+ if (strcasecmp (cf_global_options[i].key, ci->key) == 0)
+ {
+ ret = dispatch_global_option (ci);
+ break;
+ }
- item = (cf_mode_item_t *) extra;
+ return (ret);
+} /* int dispatch_value */
- if (strcasecmp (item->key, shortvar))
- {
- fprintf (stderr, "Wrong extra..\n");
- return (LC_CBRET_ERROR);
- }
+static int dispatch_block_plugin (oconfig_item_t *ci)
+{
+ int i;
+ char *name;
- if ((operating_mode & item->mode) == 0)
- {
- fprintf (stderr, "Option `%s' is not valid in this mode!\n", shortvar);
- return (LC_CBRET_ERROR);
- }
+ if (strcasecmp (ci->key, "Plugin") != 0)
+ return (-1);
+ if (ci->values_num != 1)
+ return (-1);
+ if (ci->values[0].type != OCONFIG_TYPE_STRING)
+ return (-1);
- if (item->value != NULL)
- {
- free (item->value);
- item->value = NULL;
- }
+ name = ci->values[0].value.string;
- if ((item->value = strdup (value)) == NULL)
+ for (i = 0; i < ci->children_num; i++)
{
- perror ("strdup");
- return (LC_CBRET_ERROR);
+ if (ci->children[i].children == NULL)
+ dispatch_value_plugin (name, ci->children + i);
+ else
+ {DBG ("No nested config blocks allow for plugins. Yet.");}
}
- return (LC_CBRET_OKAY);
+ return (0);
}
-/*
- * `cf_callback_mode_loadmodule':
- * Load a plugin.
- *
- * <Mode xxx>
- * LoadPlugin `value'
- * </Mode>
- */
-static int cf_callback_mode_loadmodule (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
-{
- DEBUG_CALLBACK (shortvar, var, arguments, value);
- if (plugin_load (value))
- syslog (LOG_ERR, "plugin_load (%s): failed to load plugin", value);
+static int dispatch_block (oconfig_item_t *ci)
+{
+ if (strcasecmp (ci->key, "Plugin") == 0)
+ return (dispatch_block_plugin (ci));
- /* Return `okay' even if there was an error, because it's not a syntax
- * problem.. */
- return (LC_CBRET_OKAY);
+ return (0);
}
-static int cf_callback_socket (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
+/*
+ * Public functions
+ */
+int global_option_set (const char *option, const char *value)
{
- char *buffer;
-
- char *fields[3];
- int numfields;
-
- char *node;
- char *service = NET_DEFAULT_PORT;
-
- DEBUG_CALLBACK (shortvar, var, arguments, value);
-
- buffer = strdup (value);
- if (buffer == NULL)
- return (LC_CBRET_ERROR);
-
- numfields = strsplit (buffer, fields, 3);
+ int i;
- if ((numfields != 1) && (numfields != 2))
- {
- syslog (LOG_ERR, "Invalid number of arguments to `%s'",
- shortvar);
- free (buffer);
- return (LC_CBRET_ERROR);
- }
+ for (i = 0; i < cf_global_options_num; i++)
+ if (strcasecmp (cf_global_options[i].key, option) == 0)
+ break;
- node = fields[0];
- if (numfields == 2)
- service = fields[1];
+ if (i >= cf_global_options_num)
+ return (-1);
- /* Still return `LC_CBRET_OKAY' because this is not an syntax error */
- if (network_create_socket (node, service) < 1)
- syslog (LOG_ERR, "network_create_socket (%s, %s) failed",
- node, service);
+ if (cf_global_options[i].value != NULL)
+ free (cf_global_options[i].value);
- free (buffer);
+ if (value != NULL)
+ cf_global_options[i].value = strdup (value);
+ else
+ cf_global_options[i].value = NULL;
- return (LC_CBRET_OKAY);
+ return (0);
}
-/*
- * `cf_callback_plugin'
- * Start/end section `plugin'
- *
- * <Plugin `arguments'>
- * ...
- * </Plugin>
- */
-static int cf_callback_plugin (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
+const char *global_option_get (const char *option)
{
- DEBUG_CALLBACK (shortvar, var, arguments, value);
-
- if (flags == LC_FLAGS_SECTIONSTART)
- {
- if (nesting_depth != 0)
- {
- fprintf (stderr, ERR_NOT_NESTED);
- return (LC_CBRET_ERROR);
- }
+ int i;
- if (arguments == NULL)
- {
- fprintf (stderr, ERR_NEEDS_ARG, shortvar);
- return (LC_CBRET_ERROR);
- }
+ for (i = 0; i < cf_global_options_num; i++)
+ if (strcasecmp (cf_global_options[i].key, option) == 0)
+ break;
- if ((current_module = strdup (arguments)) == NULL)
- {
- perror ("strdup");
- return (LC_CBRET_ERROR);
- }
+ if (i >= cf_global_options_num)
+ return (NULL);
+
+ return ((cf_global_options[i].value != NULL)
+ ? cf_global_options[i].value
+ : cf_global_options[i].def);
+} /* char *global_option_get */
- nesting_depth++;
+void cf_unregister (const char *type)
+{
+ cf_callback_t *this, *prev;
- if (cf_search (current_module) != NULL)
- return (LC_CBRET_OKAY);
- else
- return (LC_CBRET_IGNORESECTION);
- }
- else if (flags == LC_FLAGS_SECTIONEND)
- {
- if (current_module != NULL)
+ for (prev = NULL, this = first_callback;
+ this != NULL;
+ prev = this, this = this->next)
+ if (strcasecmp (this->type, type) == 0)
{
- free (current_module);
- current_module = NULL;
- }
-
- nesting_depth--;
+ if (prev == NULL)
+ first_callback = this->next;
+ else
+ prev->next = this->next;
- return (LC_CBRET_OKAY);
- }
- else
- {
- fprintf (stderr, ERR_SECTION_ONLY, shortvar);
- return (LC_CBRET_ERROR);
- }
+ free (this);
+ break;
+ }
}
-/*
- * `cf_callback_plugin_dispatch'
- * Send options within `plugin' sections to the plugin that requests it.
- *
- * <Plugin `current_module'>
- * `var' `value'
- * </Plugin>
- */
-static int cf_callback_plugin_dispatch (const char *shortvar, const char *var,
- const char *arguments, const char *value, lc_flags_t flags,
- void *extra)
+void cf_register (const char *type,
+ int (*callback) (const char *, const char *),
+ const char **keys, int keys_num)
{
- DEBUG_CALLBACK (shortvar, var, arguments, value);
-
- if ((nesting_depth == 0) || (current_module == NULL))
- {
- fprintf (stderr, ERR_NEEDS_SECTION, shortvar);
- return (LC_CBRET_ERROR);
- }
-
- /* Send the data to the plugin */
- if (cf_dispatch (current_module, shortvar, value) < 0)
- return (LC_CBRET_ERROR);
-
- return (LC_CBRET_OKAY);
-}
+ cf_callback_t *cf_cb;
-static void cf_init (void)
-{
- static int run_once = 0;
- int i;
+ /* Remove this module from the list, if it already exists */
+ cf_unregister (type);
- if (run_once != 0)
+ /* This pointer will be free'd in `cf_unregister' */
+ if ((cf_cb = (cf_callback_t *) malloc (sizeof (cf_callback_t))) == NULL)
return;
- run_once = 1;
-
- lc_register_callback ("Mode", SHORTOPT_NONE, LC_VAR_STRING,
- cf_callback_mode, NULL);
- lc_register_callback ("Plugin", SHORTOPT_NONE, LC_VAR_SECTION,
- cf_callback_plugin, NULL);
-
- lc_register_callback ("PluginDir", SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_mode_plugindir, NULL);
- lc_register_callback ("LoadPlugin", SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_mode_loadmodule, NULL);
-
- lc_register_callback ("Listen", SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_socket, NULL);
- lc_register_callback ("Server", SHORTOPT_NONE,
- LC_VAR_STRING, cf_callback_socket, NULL);
- for (i = 0; i < cf_mode_num; i++)
- {
- cf_mode_item_t *item;
-
- item = &cf_mode_list[i];
+ cf_cb->type = type;
+ cf_cb->callback = callback;
+ cf_cb->keys = keys;
+ cf_cb->keys_num = keys_num;
- lc_register_callback (item->key, SHORTOPT_NONE, LC_VAR_STRING,
- cf_callback_mode_option, (void *) item);
- }
-}
+ cf_cb->next = first_callback;
+ first_callback = cf_cb;
+} /* void cf_register */
int cf_read (char *filename)
{
- cf_init ();
-
- if (filename == NULL)
- filename = CONFIGFILE;
-
- DBG ("Starting to parse file `%s'", filename);
+ oconfig_item_t *conf;
+ int i;
- /* int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type); */
- if (lc_process_file ("collectd", filename, LC_CONF_APACHE))
+ conf = oconfig_parse_file (filename);
+ if (conf == NULL)
{
- syslog (LOG_ERR, "lc_process_file (%s): %s", filename, lc_geterrstr ());
+ syslog (LOG_ERR, "Unable to read config file %s.", filename);
return (-1);
}
- DBG ("Done parsing file `%s'", filename);
-
- /* free memory and stuff */
- lc_cleanup ();
+ for (i = 0; i < conf->children_num; i++)
+ {
+ if (conf->children[i].children == NULL)
+ dispatch_value (conf->children + i);
+ else
+ dispatch_block (conf->children + i);
+ }
return (0);
-}
+} /* int cf_read */
diff --git a/src/configfile.h b/src/configfile.h
index 0bb11b2a4384b8e7bf697a56e401267728ba1df4..0ee8f33cb19dfd1230846e5a5b05e0f930b52358 100644 (file)
--- a/src/configfile.h
+++ b/src/configfile.h
* `type' Name of the plugin (must be the same as passed to
* `plugin_register'
*/
-void cf_unregister (char *type);
+void cf_unregister (const char *type);
/*
* DESCRIPTION
* exists for each `type' at any time. This means that `cf_register' may be
* called multiple times, but only the last call will have an effect.
*/
-void cf_register (char *type,
- int (*callback) (char *, char *),
- char **keys, int keys_num);
-
-/*
- * DESCRIPTION
- * `cf_get_option' returns various general options.
- *
- * PARAMETERS
- * `key' Name of the option to query.
- * `def' Pointer to return as default value.
- *
- * RETURN VALUE
- * The pointer returned is part of an internal structure and may not be
- * changed. If the option is not found for whatever reason (wrong key, option
- * not allowed for currently selected mode, ...) `NULL' is returned.
- */
-char *cf_get_option (const char *key, char *def);
+void cf_register (const char *type,
+ int (*callback) (const char *, const char *),
+ const char **keys, int keys_num);
/*
* DESCRIPTION
*/
int cf_read (char *filename);
+int global_option_set (const char *option, const char *value);
+const char *global_option_get (const char *option);
+
#endif /* defined(CONFIGFILE_H) */
diff --git a/src/cpu.c b/src/cpu.c
index b087d6654d2edfa84480fd5e6d5dffec80aa5392..437f7587366eb86df69c856bbb5d1a6baf016d2f 100644 (file)
--- a/src/cpu.c
+++ b/src/cpu.c
/**
* collectd - src/cpu.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "cpu"
-
#ifdef HAVE_MACH_KERN_RETURN_H
# include <mach/kern_return.h>
#endif
# define CPU_HAVE_READ 0
#endif
+static data_source_t dsrc[1] =
+{
+ {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t ds =
+{
+ "cpu", 1, dsrc
+};
+
+#if CPU_HAVE_READ
#ifdef PROCESSOR_CPU_LOAD_INFO
static mach_port_t port_host;
static processor_port_array_t cpu_list;
static int numcpu;
#endif /* HAVE_SYSCTLBYNAME */
-static char *cpu_filename = "cpu-%s.rrd";
-
-static char *ds_def[] =
-{
- "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:nice:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:idle:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wait:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
-};
-static int ds_num = 5;
-
-static void cpu_init (void)
+static int init (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
kern_return_t status;
/* FIXME: Free `cpu_list' if it's not NULL */
if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS)
{
- syslog (LOG_ERR, "cpu-plugin: host_processors returned %i\n", (int) status);
+ syslog (LOG_ERR, "cpu plugin: host_processors returned %i", (int) status);
cpu_list_len = 0;
- return;
+ return (-1);
}
DBG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors");
- syslog (LOG_INFO, "cpu-plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
+ syslog (LOG_INFO, "cpu plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s");
collectd_step = atoi (COLLECTD_STEP);
if ((collectd_step > 0) && (collectd_step <= 86400))
numcpu = 0;
if (kc == NULL)
- return;
+ return (-1);
/* Solaris doesn't count linear.. *sigh* */
for (numcpu = 0, ksp_chain = kc->kc_chain;
if (sysctlbyname ("hw.ncpu", &numcpu, &numcpu_size, NULL, 0) < 0)
{
syslog (LOG_WARNING, "cpu: sysctlbyname: %s", strerror (errno));
- return;
+ return (-1);
}
if (numcpu != 1)
syslog (LOG_NOTICE, "cpu: Only one processor supported when using `sysctlbyname' (found %i)", numcpu);
#endif
- return;
-}
+ return (0);
+} /* int init */
-static void cpu_write (char *host, char *inst, char *val)
+static void submit (int cpu_num, const char *type_instance, counter_t value)
{
- char file[512];
- int status;
-
- status = snprintf (file, 512, cpu_filename, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].counter = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "cpu");
+ snprintf (vl.plugin_instance, sizeof (vl.type_instance),
+ "%i", cpu_num);
+ vl.plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+ strcpy (vl.type_instance, type_instance);
+
+ plugin_dispatch_values ("cpu", &vl);
}
-#if CPU_HAVE_READ
-#define BUFSIZE 512
-static void cpu_submit (int cpu_num, unsigned long long user,
- unsigned long long nice, unsigned long long syst,
- unsigned long long idle, unsigned long long wait)
-{
- char buf[BUFSIZE];
- char cpu[16];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu", (unsigned int) curtime,
- user, nice, syst, idle, wait) >= BUFSIZE)
- return;
- snprintf (cpu, 16, "%i", cpu_num);
-
- plugin_submit (MODULE_NAME, cpu, buf);
-}
-#undef BUFSIZE
-
-static void cpu_read (void)
+static int cpu_read (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
int cpu;
PROCESSOR_CPU_LOAD_INFO, &cpu_host,
(processor_info_t) &cpu_info, &cpu_info_len)) != KERN_SUCCESS)
{
- syslog (LOG_ERR, "cpu-plugin: processor_info failed with status %i\n", (int) status);
+ syslog (LOG_ERR, "cpu plugin: processor_info failed with status %i", (int) status);
continue;
}
if (cpu_info_len < CPU_STATE_MAX)
{
- syslog (LOG_ERR, "cpu-plugin: processor_info returned only %i elements..\n", cpu_info_len);
+ syslog (LOG_ERR, "cpu plugin: processor_info returned only %i elements..", cpu_info_len);
continue;
}
- cpu_submit (cpu, cpu_info.cpu_ticks[CPU_STATE_USER],
- cpu_info.cpu_ticks[CPU_STATE_NICE],
- cpu_info.cpu_ticks[CPU_STATE_SYSTEM],
- cpu_info.cpu_ticks[CPU_STATE_IDLE],
- 0ULL);
+ submit (cpu, "user", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "nice", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "system", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
+ submit (cpu, "idle", (counter_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
#endif /* PROCESSOR_CPU_LOAD_INFO */
#if PROCESSOR_TEMPERATURE
/*
cpu_temp, &cpu_temp_len);
if (status != KERN_SUCCESS)
{
- syslog (LOG_ERR, "cpu-plugin: processor_info failed: %s",
+ syslog (LOG_ERR, "cpu plugin: processor_info failed: %s",
mach_error_string (status));
cpu_temp_retry_counter = cpu_temp_retry_step;
/* #endif PROCESSOR_CPU_LOAD_INFO */
#elif defined(KERNEL_LINUX)
-# define BUFSIZE 1024
int cpu;
- unsigned long long user, nice, syst, idle;
- unsigned long long wait, intr, sitr; /* sitr == soft interrupt */
+ counter_t user, nice, syst, idle;
+ counter_t wait, intr, sitr; /* sitr == soft interrupt */
FILE *fh;
- char buf[BUFSIZE];
+ char buf[1024];
char *fields[9];
int numfields;
plugin_complain (LOG_ERR, &complain_obj, "cpu plugin: "
"fopen (/proc/stat) failed: %s",
strerror (errno));
- return;
+ return (-1);
}
plugin_relief (LOG_NOTICE, &complain_obj, "cpu plugin: "
"fopen (/proc/stat) succeeded.");
- while (fgets (buf, BUFSIZE, fh) != NULL)
+ while (fgets (buf, 1024, fh) != NULL)
{
if (strncmp (buf, "cpu", 3))
continue;
syst = atoll (fields[3]);
idle = atoll (fields[4]);
+ submit (cpu, "user", user);
+ submit (cpu, "nice", nice);
+ submit (cpu, "system", syst);
+ submit (cpu, "idle", idle);
+
if (numfields >= 8)
{
wait = atoll (fields[5]);
intr = atoll (fields[6]);
sitr = atoll (fields[7]);
- /* I doubt anyone cares about the time spent in
- * interrupt handlers.. */
- syst += intr + sitr;
- }
- else
- {
- wait = 0LL;
+ submit (cpu, "wait", wait);
+ submit (cpu, "interrupt", intr);
+ submit (cpu, "softirq", sitr);
}
-
- cpu_submit (cpu, user, nice, syst, idle, wait);
}
fclose (fh);
-#undef BUFSIZE
/* #endif defined(KERNEL_LINUX) */
#elif defined(HAVE_LIBKSTAT)
int cpu;
- unsigned long long user, syst, idle, wait;
+ counter_t user, syst, idle, wait;
static cpu_stat_t cs;
if (kc == NULL)
if (kstat_read (kc, ksp[cpu], &cs) == -1)
continue; /* error message? */
- idle = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_IDLE];
- user = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_USER];
- syst = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_KERNEL];
- wait = (unsigned long long) cs.cpu_sysinfo.cpu[CPU_WAIT];
+ idle = (counter_t) cs.cpu_sysinfo.cpu[CPU_IDLE];
+ user = (counter_t) cs.cpu_sysinfo.cpu[CPU_USER];
+ syst = (counter_t) cs.cpu_sysinfo.cpu[CPU_KERNEL];
+ wait = (counter_t) cs.cpu_sysinfo.cpu[CPU_WAIT];
- cpu_submit (ksp[cpu]->ks_instance,
- user, 0LL, syst, idle, wait);
+ submit (ksp[cpu]->ks_instance, "user", user);
+ submit (ksp[cpu]->ks_instance, "system", syst);
+ submit (ksp[cpu]->ks_instance, "idle", idle);
+ submit (ksp[cpu]->ks_instance, "wait", wait);
}
/* #endif defined(HAVE_LIBKSTAT) */
cpuinfo[CP_SYS] += cpuinfo[CP_INTR];
- /* FIXME: Instance is always `0' */
- cpu_submit (0, cpuinfo[CP_USER], cpuinfo[CP_NICE], cpuinfo[CP_SYS], cpuinfo[CP_IDLE], 0LL);
+ submit (0, "user", cpuinfo[CP_USER]);
+ submit (0, "nice", cpuinfo[CP_NICE]);
+ submit (0, "system", cpuinfo[CP_SYS]);
+ submit (0, "idle", cpuinfo[CP_IDLE]);
#endif
- return;
+ return (0);
}
-#else
-# define cpu_read NULL
#endif /* CPU_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, cpu_init, cpu_read, cpu_write);
-}
+ plugin_register_data_set (&ds);
-#undef MODULE_NAME
+#if CPU_HAVE_READ
+ plugin_register_init ("cpu", init);
+ plugin_register_read ("cpu", cpu_read);
+#endif /* CPU_HAVE_READ */
+}
diff --git a/src/cpufreq.c b/src/cpufreq.c
index ba0149ad1f390298af4049690cc56c9458f4c8b7..e53e49523814264bfc03ce900165cf70fa1dc835 100644 (file)
--- a/src/cpufreq.c
+++ b/src/cpufreq.c
/**
* collectd - src/cpufreq.c
- * Copyright (C) 2005,2006 Peter Holik
+ * Copyright (C) 2005-2007 Peter Holik
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
# define CPUFREQ_HAVE_READ 0
#endif
-static char *cpufreq_file = "cpufreq-%s.rrd";
+static data_source_t data_source[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-static char *ds_def[] =
+static data_set_t data_set =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "cpufreq", 1, data_source
};
-static int ds_num = 1;
+#if CPUFREQ_HAVE_READ
#ifdef KERNEL_LINUX
static int num_cpu = 0;
#endif
-#define BUFSIZE 256
-
-static void cpufreq_init (void)
+static int cpufreq_init (void)
{
#ifdef KERNEL_LINUX
int status;
- char filename[BUFSIZE];
+ char filename[256];
num_cpu = 0;
while (1)
{
- status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", num_cpu);
- if (status < 1 || status >= BUFSIZE)
+ status = snprintf (filename, sizeof (filename),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/"
+ "scaling_cur_freq", num_cpu);
+ if (status < 1 || status >= sizeof (filename))
break;
- if (access(filename, R_OK))
+ if (access (filename, R_OK))
break;
num_cpu++;
}
- syslog (LOG_INFO, MODULE_NAME" found %d cpu(s)", num_cpu);
+ syslog (LOG_INFO, "cpufreq plugin: Found %d CPU%s", num_cpu,
+ (num_cpu == 1) ? "" : "s");
+
+ if (num_cpu == 0)
+ plugin_unregister_read ("cpufreq");
#endif /* defined(KERNEL_LINUX) */
- return;
-}
+ return (0);
+} /* int cpufreq_init */
-static void cpufreq_write (char *host, char *inst, char *val)
+static void cpufreq_submit (int cpu_num, double value)
{
- int status;
- char file[BUFSIZE];
-
- status = snprintf (file, BUFSIZE, cpufreq_file, inst);
- if (status < 1 || status >= BUFSIZE)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-#if CPUFREQ_HAVE_READ
-static void cpufreq_submit (int cpu_num, unsigned long long val)
-{
- char buf[BUFSIZE];
- char cpu[16];
+ values[0].gauge = value;
- if (snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, val) >= BUFSIZE)
- return;
- snprintf (cpu, 16, "%i", cpu_num);
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "cpufreq");
+ snprintf (vl.type_instance, sizeof (vl.type_instance),
+ "%i", cpu_num);
- plugin_submit (MODULE_NAME, cpu, buf);
+ plugin_dispatch_values ("cpufreq", &vl);
}
-static void cpufreq_read (void)
+static int cpufreq_read (void)
{
#ifdef KERNEL_LINUX
int status;
unsigned long long val;
int i = 0;
FILE *fp;
- char filename[BUFSIZE];
+ char filename[256];
char buffer[16];
for (i = 0; i < num_cpu; i++)
{
- status = snprintf (filename, BUFSIZE, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
- if (status < 1 || status >= BUFSIZE)
- return;
+ status = snprintf (filename, sizeof (filename),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/"
+ "scaling_cur_freq", i);
+ if (status < 1 || status >= sizeof (filename))
+ return (-1);
if ((fp = fopen (filename, "r")) == NULL)
{
syslog (LOG_WARNING, "cpufreq: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
if (fgets (buffer, 16, fp) == NULL)
{
syslog (LOG_WARNING, "cpufreq: fgets: %s", strerror (errno));
fclose (fp);
- return;
+ return (-1);
}
if (fclose (fp))
}
#endif /* defined(KERNEL_LINUX) */
- return;
-}
-#else
-#define cpufreq_read NULL
-#endif
+ return (0);
+} /* int cpufreq_read */
+#endif /* CPUFREQ_HAVE_READ */
#undef BUFSIZE
void module_register (void)
{
- plugin_register (MODULE_NAME, cpufreq_init, cpufreq_read, cpufreq_write);
-}
+ plugin_register_data_set (&data_set);
-#undef MODULE_NAME
+#if CPUFREQ_HAVE_READ
+ plugin_register_init ("cpufreq", cpufreq_init);
+ plugin_register_read ("cpufreq", cpufreq_read);
+#endif /* CPUFREQ_HAVE_READ */
+}
diff --git a/src/csv.c b/src/csv.c
--- /dev/null
+++ b/src/csv.c
@@ -0,0 +1,214 @@
+/**
+ * collectd - src/csv.c
+ * Copyright (C) 2007 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_debug.h"
+
+static int value_list_to_string (char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ int offset;
+ int status;
+ int i;
+
+ memset (buffer, '\0', sizeof (buffer_len));
+
+ status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+ if ((status < 1) || (status >= buffer_len))
+ return (-1);
+ offset = status;
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if ((ds->ds[i].type != DS_TYPE_COUNTER)
+ && (ds->ds[i].type != DS_TYPE_GAUGE))
+ return (-1);
+
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ status = snprintf (buffer + offset, buffer_len - offset,
+ ",%llu", vl->values[i].counter);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ ",%lf", vl->values[i].gauge);
+
+ if ((status < 1) || (status >= (buffer_len - offset)))
+ return (-1);
+
+ offset += status;
+ } /* for ds->ds_num */
+
+ return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ int offset = 0;
+ int status;
+
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s/", vl->host);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ if (strlen (vl->plugin_instance) > 0)
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s-%s/", vl->plugin, vl->plugin_instance);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s/", vl->plugin);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ if (strlen (vl->type_instance) > 0)
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s-%s", ds->type, vl->type_instance);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s", ds->type);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ {
+ time_t now;
+ struct tm *tm;
+
+ /* TODO: Find a way to minimize the calls to `localtime', since
+ * they are pretty expensive.. */
+ now = time (NULL);
+ tm = localtime (&now);
+
+ strftime (buffer + offset, buffer_len - offset,
+ "-%Y-%m-%d", tm);
+
+ /* `localtime(3)' returns a pointer to static data,
+ * therefore the pointer may not be free'd. */
+ }
+
+ return (0);
+} /* int value_list_to_filename */
+
+static int csv_create_file (const char *filename, const data_set_t *ds)
+{
+ FILE *csv;
+ int i;
+
+ if (check_create_dir (filename))
+ return (-1);
+
+ csv = fopen (filename, "w");
+ if (csv == NULL)
+ {
+ syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s",
+ filename, strerror(errno));
+ return (-1);
+ }
+
+ fprintf (csv, "epoch");
+ for (i = 0; i < ds->ds_num; i++)
+ fprintf (csv, ",%s", ds->ds[i].name);
+
+ fprintf (csv, "\n");
+ fclose (csv);
+
+ return 0;
+} /* int csv_create_file */
+
+static int csv_write (const data_set_t *ds, const value_list_t *vl)
+{
+ struct stat statbuf;
+ char filename[512];
+ char values[512];
+ FILE *csv;
+ int csv_fd;
+ struct flock fl;
+ int status;
+
+ if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
+ return (-1);
+
+ if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+ return (-1);
+
+ if (stat (filename, &statbuf) == -1)
+ {
+ if (errno == ENOENT)
+ {
+ if (csv_create_file (filename, ds))
+ return (-1);
+ }
+ else
+ {
+ syslog (LOG_ERR, "stat(%s) failed: %s",
+ filename, strerror (errno));
+ return (-1);
+ }
+ }
+ else if (!S_ISREG (statbuf.st_mode))
+ {
+ syslog (LOG_ERR, "stat(%s): Not a regular file!",
+ filename);
+ return (-1);
+ }
+
+ csv = fopen (filename, "a");
+ if (csv == NULL)
+ {
+ syslog (LOG_ERR, "csv plugin: fopen (%s) failed: %s",
+ filename, strerror (errno));
+ return (-1);
+ }
+ csv_fd = fileno (csv);
+
+ memset (&fl, '\0', sizeof (fl));
+ fl.l_start = 0;
+ fl.l_len = 0; /* till end of file */
+ fl.l_pid = getpid ();
+ fl.l_type = F_WRLCK;
+ fl.l_whence = SEEK_SET;
+
+ status = fcntl (csv_fd, F_SETLK, &fl);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "csv plugin: flock (%s) failed: %s",
+ filename, strerror (errno));
+ fclose (csv);
+ return (-1);
+ }
+
+ fprintf (csv, "%s\n", values);
+
+ /* The lock is implicitely released. I we don't release it explicitely
+ * because the `FILE *' may need to flush a cache first */
+ fclose (csv);
+
+ return (0);
+} /* int csv_write */
+
+void module_register (void)
+{
+ plugin_register_write ("csv", csv_write);
+}
diff --git a/src/df.c b/src/df.c
index d327164ac601e3a98c59217122240b0e77b8ea4b..dd5e13824660c34da87231606029531fed4e99eb 100644 (file)
--- a/src/df.c
+++ b/src/df.c
/**
* collectd - src/df.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "utils_mount.h"
#include "utils_ignorelist.h"
-#define MODULE_NAME "df"
-
#if HAVE_STATFS || HAVE_STATVFS
# define DF_HAVE_READ 1
#else
# define BLOCKSIZE(s) (s).f_bsize
#endif
-static char *filename_template = "df-%s.rrd";
+/* 2^50 - 1 == 1125899906842623 = 1 Petabyte */
+static data_source_t dsrc[2] =
+{
+ {"free", DS_TYPE_GAUGE, 0, 1125899906842623.0},
+ {"used", DS_TYPE_GAUGE, 0, 1125899906842623.0}
+};
-static char *ds_def[] =
+static data_set_t ds =
{
- "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "df", 2, dsrc
};
-static int ds_num = 2;
-static char *config_keys[] =
+#if DF_HAVE_READ
+static const char *config_keys[] =
{
"Device",
"MountPoint",
static ignorelist_t *il_mountpoint = NULL;
static ignorelist_t *il_fstype = NULL;
-#define BUFSIZE 512
-
-static void df_init (void)
+static int df_init (void)
{
if (il_device == NULL)
il_device = ignorelist_create (1);
if (il_fstype == NULL)
il_fstype = ignorelist_create (1);
- return;
+ return (0);
}
-static int df_config (char *key, char *value)
+static int df_config (const char *key, const char *value)
{
df_init ();
return (-1);
}
-static void df_write (char *host, char *inst, char *val)
-{
- char file[BUFSIZE];
- int status;
-
- status = snprintf (file, BUFSIZE, filename_template, inst);
- if (status < 1)
- return;
- else if (status >= BUFSIZE)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-#if DF_HAVE_READ
static void df_submit (char *df_name,
- unsigned long long df_used,
- unsigned long long df_free)
+ gauge_t df_used,
+ gauge_t df_free)
{
- char buf[BUFSIZE];
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
- df_used, df_free) >= BUFSIZE)
- return;
+ values[0].gauge = df_used;
+ values[1].gauge = df_free;
- plugin_submit (MODULE_NAME, df_name, buf);
-}
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "df");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
-static void df_read (void)
+ plugin_dispatch_values ("df", &vl);
+} /* void df_submit */
+
+static int df_read (void)
{
#if HAVE_STATVFS
struct statvfs statbuf;
cu_mount_t *mnt_ptr;
unsigned long long blocksize;
- unsigned long long df_free;
- unsigned long long df_used;
- char mnt_name[BUFSIZE];
+ gauge_t df_free;
+ gauge_t df_used;
+ char mnt_name[256];
mnt_list = NULL;
if (cu_mount_getlist (&mnt_list) == NULL)
- return;
+ return (-1);
for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
{
if (strcmp (mnt_ptr->dir, "/") == 0)
{
- strncpy (mnt_name, "root", BUFSIZE);
+ strncpy (mnt_name, "root", sizeof (mnt_name));
}
else
{
int i, len;
- strncpy (mnt_name, mnt_ptr->dir + 1, BUFSIZE);
+ strncpy (mnt_name, mnt_ptr->dir + 1, sizeof (mnt_name));
len = strlen (mnt_name);
for (i = 0; i < len; i++)
}
cu_mount_freelist (mnt_list);
-} /* static void df_read (void) */
-#else
-# define df_read NULL
+
+ return (0);
+} /* int df_read */
#endif /* DF_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, df_init, df_read, df_write);
- cf_register (MODULE_NAME, df_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if DF_HAVE_READ
+ plugin_register_config ("df", df_config, config_keys, config_keys_num);
+ plugin_register_init ("df", df_init);
+ plugin_register_read ("df", df_read);
+#endif
+} /* void module_register */
diff --git a/src/disk.c b/src/disk.c
index c809fdb6a33c0762b6b002a6a66367e1a884660c..3cb86e7e29149e3fb0fa5e0f5a053ffef6924f50 100644 (file)
--- a/src/disk.c
+++ b/src/disk.c
/**
* collectd - src/disk.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "plugin.h"
#include "utils_debug.h"
-#define MODULE_NAME "disk"
-
#if HAVE_MACH_MACH_TYPES_H
# include <mach/mach_types.h>
#endif
# define DISK_HAVE_READ 0
#endif
-static char *disk_filename_template = "disk-%s.rrd";
-static char *part_filename_template = "partition-%s.rrd";
+/* 2^34 = 17179869184 = ~17.2GByte/s */
+static data_source_t octets_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 17179869183.0},
+ {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
+};
+
+static data_set_t octets_ds =
+{
+ "disk_octets", 2, octets_dsrc
+};
+
+static data_source_t operations_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
-/* 104857600 == 100 MB */
-static char *disk_ds_def[] =
+static data_set_t operations_ds =
{
- "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "disk_ops", 2, operations_dsrc
};
-static int disk_ds_num = 8;
-static char *part_ds_def[] =
+static data_source_t merged_dsrc[2] =
{
- "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600",
- NULL
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int part_ds_num = 4;
+static data_set_t merged_ds =
+{
+ "disk_merged", 2, merged_dsrc
+};
+
+/* max is 1000000us per second. */
+static data_source_t time_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 1000000.0},
+ {"write", DS_TYPE_COUNTER, 0, 1000000.0}
+};
+
+static data_set_t time_ds =
+{
+ "disk_time", 2, time_dsrc
+};
+
+#if DISK_HAVE_READ
#if HAVE_IOKIT_IOKITLIB_H
static mach_port_t io_master_port = MACH_PORT_NULL;
/* #endif HAVE_IOKIT_IOKITLIB_H */
/* This overflows in roughly 1361 year */
unsigned int poll_count;
- unsigned long long read_sectors;
- unsigned long long write_sectors;
+ counter_t read_sectors;
+ counter_t write_sectors;
- unsigned long long read_bytes;
- unsigned long long write_bytes;
+ counter_t read_bytes;
+ counter_t write_bytes;
struct diskstats *next;
} diskstats_t;
static int numdisk = 0;
#endif /* HAVE_LIBKSTAT */
-static void disk_init (void)
+static int disk_init (void)
{
#if HAVE_IOKIT_IOKITLIB_H
kern_return_t status;
syslog (LOG_ERR, "IOMasterPort failed: %s",
mach_error_string (status));
io_master_port = MACH_PORT_NULL;
- return;
+ return (-1);
}
/* #endif HAVE_IOKIT_IOKITLIB_H */
numdisk = 0;
if (kc == NULL)
- return;
+ return (-1);
for (numdisk = 0, ksp_chain = kc->kc_chain;
(numdisk < MAX_NUMDISK) && (ksp_chain != NULL);
}
#endif /* HAVE_LIBKSTAT */
- return;
-}
+ return (0);
+} /* int disk_init */
-static void disk_write (char *host, char *inst, char *val)
+static void disk_submit (const char *plugin_instance,
+ const char *type,
+ counter_t read, counter_t write)
{
- char file[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (file, 512, disk_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
+ values[0].counter = read;
+ values[1].counter = write;
- rrd_update_file (host, file, val, disk_ds_def, disk_ds_num);
-}
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "disk");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
-static void partition_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, part_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, part_ds_def, part_ds_num);
-}
-
-#if DISK_HAVE_READ
-#define BUFSIZE 512
-static void disk_submit (char *disk_name,
- unsigned long long read_count,
- unsigned long long read_merged,
- unsigned long long read_bytes,
- unsigned long long read_time,
- unsigned long long write_count,
- unsigned long long write_merged,
- unsigned long long write_bytes,
- unsigned long long write_time)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
- (unsigned int) curtime,
- read_count, read_merged, read_bytes, read_time,
- write_count, write_merged, write_bytes,
- write_time) >= BUFSIZE)
- return;
-
- DBG ("disk_name = %s; buf = %s;",
- disk_name, buf);
-
- plugin_submit (MODULE_NAME, disk_name, buf);
-}
-
-#if KERNEL_LINUX || HAVE_LIBKSTAT
-static void partition_submit (char *part_name,
- unsigned long long read_count,
- unsigned long long read_bytes,
- unsigned long long write_count,
- unsigned long long write_bytes)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu",
- (unsigned int) curtime,
- read_count, read_bytes, write_count,
- write_bytes) >= BUFSIZE)
- return;
-
- plugin_submit ("partition", part_name, buf);
-}
-#endif /* KERNEL_LINUX || HAVE_LIBKSTAT */
-#undef BUFSIZE
+ plugin_dispatch_values (type, &vl);
+} /* void disk_submit */
#if HAVE_IOKIT_IOKITLIB_H
static signed long long dict_get_value (CFDictionaryRef dict, const char *key)
}
#endif /* HAVE_IOKIT_IOKITLIB_H */
-static void disk_read (void)
+static int disk_read (void)
{
#if HAVE_IOKIT_IOKITLIB_H
io_registry_entry_t disk;
{
plugin_complain (LOG_ERR, &complain_obj, "disk plugin: "
"IOServiceGetMatchingServices failed.");
- return;
+ return (-1);
}
else if (complain_obj.interval != 0)
{
continue;
}
+ /* kIOBSDNameKey */
disk_major = (int) dict_get_value (child_dict,
kIOBSDMajorKey);
disk_minor = (int) dict_get_value (child_dict,
kIOBlockStorageDriverStatisticsWritesKey);
write_byt = dict_get_value (stats_dict,
kIOBlockStorageDriverStatisticsBytesWrittenKey);
+ /* This property describes the number of nanoseconds spent
+ * performing writes since the block storage driver was
+ * instantiated. It is one of the statistic entries listed
+ * under the top-level kIOBlockStorageDriverStatisticsKey
+ * property table. It has an OSNumber value. */
write_tme = dict_get_value (stats_dict,
kIOBlockStorageDriverStatisticsTotalWriteTimeKey);
}
DBG ("disk_name = %s", disk_name);
- if ((read_ops != -1LL)
- || (read_byt != -1LL)
- || (read_tme != -1LL)
- || (write_ops != -1LL)
- || (write_byt != -1LL)
- || (write_tme != -1LL))
- disk_submit (disk_name,
- read_ops, 0ULL, read_byt, read_tme,
- write_ops, 0ULL, write_byt, write_tme);
+ if ((read_byt != -1LL) || (write_byt != -1LL))
+ disk_submit (disk_name, "disk_octets", read_byt, write_byt);
+ if ((read_ops != -1LL) || (write_ops != -1LL))
+ disk_submit (disk_name, "disk_ops", read_ops, write_ops);
+ if ((read_tme != -1LL) || (write_tme != -1LL))
+ disk_submit (disk_name, "disk_time",
+ read_tme / 1000,
+ write_tme / 1000);
CFRelease (child_dict);
IOObjectRelease (disk_child);
#elif KERNEL_LINUX
FILE *fh;
char buffer[1024];
- char disk_name[128];
char *fields[32];
int numfields;
int major = 0;
int minor = 0;
- unsigned long long read_sectors = 0ULL;
- unsigned long long write_sectors = 0ULL;
-
- unsigned long long read_count = 0ULL;
- unsigned long long read_merged = 0ULL;
- unsigned long long read_bytes = 0ULL;
- unsigned long long read_time = 0ULL;
- unsigned long long write_count = 0ULL;
- unsigned long long write_merged = 0ULL;
- unsigned long long write_bytes = 0ULL;
- unsigned long long write_time = 0ULL;
+ counter_t read_sectors = 0;
+ counter_t write_sectors = 0;
+
+ counter_t read_count = 0;
+ counter_t read_merged = 0;
+ counter_t read_bytes = 0;
+ counter_t read_time = 0;
+ counter_t write_count = 0;
+ counter_t write_merged = 0;
+ counter_t write_bytes = 0;
+ counter_t write_time = 0;
int is_disk = 0;
diskstats_t *ds, *pre_ds;
{
if ((fh = fopen ("/proc/partitions", "r")) == NULL)
{
- plugin_complain (LOG_ERR, &complain_obj, "disk plugin: Failed to open /proc/{diskstats,partitions}.");
- return;
+ plugin_complain (LOG_ERR, &complain_obj,
+ "disk plugin: Failed to open /proc/"
+ "{diskstats,partitions}.");
+ return (-1);
}
/* Kernel is 2.4.* */
fieldshift = 1;
}
- plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: Succeeded to open /proc/{diskstats,partitions}.");
+ plugin_relief (LOG_NOTICE, &complain_obj, "disk plugin: "
+ "Succeeded to open /proc/{diskstats,partitions}.");
- while (fgets (buffer, 1024, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
+ char *disk_name;
+
numfields = strsplit (buffer, fields, 32);
if ((numfields != (14 + fieldshift)) && (numfields != 7))
major = atoll (fields[0]);
minor = atoll (fields[1]);
- if (snprintf (disk_name, 128, "%i-%i", major, minor) < 1)
- continue;
- disk_name[127] = '\0';
+ disk_name = fields[2];
for (ds = disklist, pre_ds = disklist; ds != NULL; pre_ds = ds, ds = ds->next)
if (strcmp (disk_name, ds->name) == 0)
continue;
}
+ if ((read_bytes != -1LL) || (write_bytes != -1LL))
+ disk_submit (disk_name, "disk_octets", read_bytes, write_bytes);
+ if ((read_count != -1LL) || (write_count != -1LL))
+ disk_submit (disk_name, "disk_ops", read_count, write_count);
if (is_disk)
- disk_submit (disk_name, read_count, read_merged, read_bytes, read_time,
- write_count, write_merged, write_bytes, write_time);
- else
- partition_submit (disk_name, read_count, read_bytes, write_count, write_bytes);
- }
+ {
+ if ((read_merged != -1LL) || (write_merged != -1LL))
+ disk_submit (disk_name, "disk_merged",
+ read_merged, write_merged);
+ if ((read_time != -1LL) || (write_time != -1LL))
+ disk_submit (disk_name, "disk_time",
+ read_time * 1000,
+ write_time * 1000);
+ }
+ } /* while (fgets (buffer, sizeof (buffer), fh) != NULL) */
fclose (fh);
/* #endif defined(KERNEL_LINUX) */
int i;
if (kc == NULL)
- return;
+ return (-1);
for (i = 0; i < numdisk; i++)
{
continue;
if (strncmp (ksp[i]->ks_class, "disk", 4) == 0)
- disk_submit (ksp[i]->ks_name,
- kio.reads, 0LL, kio.nread, kio.rtime,
- kio.writes, 0LL, kio.nwritten, kio.wtime);
+ {
+ disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes);
+ disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites);
+ /* FIXME: Convert this to microseconds if necessary */
+ disk_submit (ksp[i]->ks_name, "disk_time", kio.rtime, kio.wtime);
+ }
else if (strncmp (ksp[i]->ks_class, "partition", 9) == 0)
- partition_submit (ksp[i]->ks_name,
- kio.reads, kio.nread,
- kio.writes,kio.nwritten);
+ {
+ disk_submit (ksp[i]->ks_name, "disk_octets", kio.reads, kio.writes);
+ disk_submit (ksp[i]->ks_name, "disk_ops", kio.nreads, kio.nwrites);
+ }
}
#endif /* defined(HAVE_LIBKSTAT) */
-} /* static void disk_read (void) */
-#else
-# define disk_read NULL
+
+ return (0);
+} /* int disk_read */
#endif /* DISK_HAVE_READ */
void module_register (void)
{
- plugin_register ("partition", NULL, NULL, partition_write);
- plugin_register (MODULE_NAME, disk_init, disk_read, disk_write);
-}
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&operations_ds);
+ plugin_register_data_set (&merged_ds);
+ plugin_register_data_set (&time_ds);
-#undef MODULE_NAME
+#if DISK_HAVE_READ
+ plugin_register_init ("disk", disk_init);
+ plugin_register_read ("disk", disk_read);
+#endif /* DISK_HAVE_READ */
+}
diff --git a/src/dns.c b/src/dns.c
index cd73a7e0c7b227d0c5cfcd61d4e92bbe593be3ac..332ef0ea2c25a2305e1d08255e2cdf57e33f3232 100644 (file)
--- a/src/dns.c
+++ b/src/dns.c
/**
* collectd - src/dns.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "dns"
-
#if HAVE_LIBPCAP && HAVE_LIBPTHREAD
# include "utils_dns.h"
# include <pthread.h>
# include <pcap.h>
-# include <sys/poll.h>
+# include <poll.h>
# define DNS_HAVE_READ 1
#else
# define DNS_HAVE_READ 0
/*
* Private variables
*/
-static char *traffic_file = "dns/dns_traffic.rrd";
-static char *qtype_file = "dns/qtype-%s.rrd";
-static char *opcode_file = "dns/opcode-%s.rrd";
-static char *rcode_file = "dns/rcode-%s.rrd";
+static data_source_t octets_dsrc[2] =
+{
+ {"queries", DS_TYPE_COUNTER, 0, 125000000.0},
+ {"responses", DS_TYPE_COUNTER, 0, 125000000.0}
+};
-static char *traffic_ds_def[] =
+static data_set_t octets_ds =
{
- /* Limit to 1GBit/s */
- "DS:queries:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
- "DS:responses:COUNTER:"COLLECTD_HEARTBEAT":0:125000000",
- NULL
+ "dns_octets", 2, octets_dsrc
};
-static int traffic_ds_num = 2;
-static char *qtype_ds_def[] =
+static data_source_t counter_dsrc[1] =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ {"value", DS_TYPE_COUNTER, 0, 65535.0}
};
-static int qtype_ds_num = 1;
-static char *opcode_ds_def[] =
+static data_set_t qtype_ds =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "dns_qtype", 1, counter_dsrc
};
-static int opcode_ds_num = 1;
-static char *rcode_ds_def[] =
+static data_set_t opcode_ds =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "dns_opcode", 1, counter_dsrc
+};
+
+static data_set_t rcode_ds =
+{
+ "dns_rcode", 1, counter_dsrc
};
-static int rcode_ds_num = 1;
#if DNS_HAVE_READ
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Interface",
"IgnoreSource",
#define PCAP_SNAPLEN 1460
static char *pcap_device = NULL;
-static unsigned int tr_queries;
-static unsigned int tr_responses;
+static counter_t tr_queries;
+static counter_t tr_responses;
static counter_list_t *qtype_list;
static counter_list_t *opcode_list;
static counter_list_t *rcode_list;
DBG ("return ()");
}
-static int dns_config (char *key, char *value)
+static int dns_config (const char *key, const char *value)
{
if (strcasecmp (key, "Interface") == 0)
{
return (NULL);
} /* static void dns_child_loop (void) */
-#endif /* DNS_HAVE_READ */
-static void dns_init (void)
+static int dns_init (void)
{
-#if DNS_HAVE_READ
/* clean up an old thread */
int status;
pthread_mutex_unlock (&traffic_mutex);
if (listen_thread_init != 0)
- return;
+ return (-1);
status = pthread_create (&listen_thread, NULL, dns_child_loop,
(void *) 0);
{
syslog (LOG_ERR, "dns plugin: pthread_create failed: %s",
strerror (status));
- return;
+ return (-1);
}
listen_thread_init = 1;
-#endif /* DNS_HAVE_READ */
-}
-
-static void traffic_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, traffic_file, val,
- traffic_ds_def, traffic_ds_num);
-}
-
-static void qtype_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, qtype_file, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, qtype_ds_def, qtype_ds_num);
-}
-
-static void rcode_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, rcode_file, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
- rrd_update_file (host, file, val, rcode_ds_def, rcode_ds_num);
-}
-
-static void opcode_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, opcode_file, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, opcode_ds_def, opcode_ds_num);
-}
-
-#if DNS_HAVE_READ
-static void traffic_submit (unsigned int queries, unsigned int replies)
-{
- char buffer[64];
- int status;
-
- status = snprintf (buffer, 64, "N:%u:%u", queries, replies);
- if ((status < 1) || (status >= 64))
- return;
-
- plugin_submit ("dns_traffic", "-", buffer);
-}
-
-static void qtype_submit (int qtype, unsigned int counter)
-{
- char inst[32];
- char buffer[32];
- int status;
-
- strncpy (inst, qtype_str (qtype), 32);
- inst[31] = '\0';
-
- status = snprintf (buffer, 32, "N:%u", counter);
- if ((status < 1) || (status >= 32))
- return;
-
- plugin_submit ("dns_qtype", inst, buffer);
-}
+ return (0);
+} /* int dns_init */
-static void rcode_submit (int rcode, unsigned int counter)
+static void submit_counter (const char *type, const char *type_instance,
+ counter_t value)
{
- char inst[32];
- char buffer[32];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- strncpy (inst, rcode_str (rcode), 32);
- inst[31] = '\0';
+ values[0].counter = value;
- status = snprintf (buffer, 32, "N:%u", counter);
- if ((status < 1) || (status >= 32))
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "dns");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit ("dns_rcode", inst, buffer);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void submit_counter */
-static void opcode_submit (int opcode, unsigned int counter)
+static void submit_octets (counter_t queries, counter_t responses)
{
- char inst[32];
- char buffer[32];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- strncpy (inst, opcode_str (opcode), 32);
- inst[31] = '\0';
+ values[0].counter = queries;
+ values[1].counter = responses;
- status = snprintf (buffer, 32, "N:%u", counter);
- if ((status < 1) || (status >= 32))
- return;
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "dns");
- plugin_submit ("dns_opcode", inst, buffer);
-}
+ plugin_dispatch_values ("dns_octets", &vl);
+} /* void submit_counter */
-static void dns_read (void)
+static int dns_read (void)
{
unsigned int keys[T_MAX];
unsigned int values[T_MAX];
values[0] = tr_queries;
values[1] = tr_responses;
pthread_mutex_unlock (&traffic_mutex);
- traffic_submit (values[0], values[1]);
+ submit_octets (values[0], values[1]);
pthread_mutex_lock (&qtype_mutex);
for (ptr = qtype_list, len = 0;
for (i = 0; i < len; i++)
{
DBG ("qtype = %u; counter = %u;", keys[i], values[i]);
- qtype_submit (keys[i], values[i]);
+ submit_counter ("dns_qtype", qtype_str (keys[i]), values[i]);
}
pthread_mutex_lock (&opcode_mutex);
for (i = 0; i < len; i++)
{
DBG ("opcode = %u; counter = %u;", keys[i], values[i]);
- opcode_submit (keys[i], values[i]);
+ submit_counter ("dns_opcode", opcode_str (keys[i]), values[i]);
}
pthread_mutex_lock (&rcode_mutex);
for (i = 0; i < len; i++)
{
DBG ("rcode = %u; counter = %u;", keys[i], values[i]);
- rcode_submit (keys[i], values[i]);
+ submit_counter ("dns_rcode", rcode_str (keys[i]), values[i]);
}
-}
-#else /* if !DNS_HAVE_READ */
-# define dns_read NULL
+
+ return (0);
+} /* int dns_read */
#endif
void module_register (void)
{
- plugin_register (MODULE_NAME, dns_init, dns_read, NULL);
- plugin_register ("dns_traffic", NULL, NULL, traffic_write);
- plugin_register ("dns_qtype", NULL, NULL, qtype_write);
- plugin_register ("dns_rcode", NULL, NULL, rcode_write);
- plugin_register ("dns_opcode", NULL, NULL, opcode_write);
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&qtype_ds);
+ plugin_register_data_set (&opcode_ds);
+ plugin_register_data_set (&rcode_ds);
+
#if DNS_HAVE_READ
- cf_register (MODULE_NAME, dns_config, config_keys, config_keys_num);
+ plugin_register_config ("dns", dns_config, config_keys, config_keys_num);
+ plugin_register_init ("dns", dns_init);
+ plugin_register_read ("dns", dns_read);
#endif
-}
-
-#undef MODULE_NAME
+} /* void module_register */
diff --git a/src/entropy.c b/src/entropy.c
--- /dev/null
+++ b/src/entropy.c
@@ -0,0 +1,97 @@
+/**
+ * collectd - src/entropy.c
+ * Copyright (C) 2005,2006 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+#if KERNEL_LINUX
+# define ENTROPY_HAVE_READ 1
+#else
+# define ENTROPY_HAVE_READ 0
+#endif
+
+#define ENTROPY_FILE "/proc/sys/kernel/random/entropy_avail"
+
+static data_source_t dsrc[1] =
+{
+ {"entropy", DS_TYPE_GAUGE, 0.0, 4294967295.0}
+};
+
+static data_set_t ds =
+{
+ "entropy", 1, dsrc
+};
+
+#if ENTROPY_HAVE_READ
+static void entropy_submit (double entropy)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = entropy;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "entropy");
+ strcpy (vl.plugin_instance, "");
+ strcpy (vl.type_instance, "");
+
+ plugin_dispatch_values ("entropy", &vl);
+}
+
+static int entropy_read (void)
+{
+#if KERNEL_LINUX
+ double entropy;
+ FILE *fh;
+ char buffer[64];
+
+ fh = fopen (ENTROPY_FILE, "r");
+ if (fh == NULL)
+ return (-1);
+
+ if (fgets (buffer, sizeof (buffer), fh) == NULL)
+ {
+ fclose (fh);
+ return (-1);
+ }
+ fclose (fh);
+
+ entropy = atof (buffer);
+
+ if (entropy > 0.0)
+ entropy_submit (entropy);
+#endif /* KERNEL_LINUX */
+
+ return (0);
+}
+#endif /* ENTROPY_HAVE_READ */
+
+void module_register (void)
+{
+ plugin_register_data_set (&ds);
+#if ENTROPY_HAVE_READ
+ plugin_register_read ("entropy", entropy_read);
+#endif
+}
diff --git a/src/exec.c b/src/exec.c
--- /dev/null
+++ b/src/exec.c
@@ -0,0 +1,353 @@
+/**
+ * collectd - src/exec.c
+ * Copyright (C) 2007 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "utils_debug.h"
+
+#include <sys/types.h>
+#include <pwd.h>
+
+#include <pthread.h>
+
+/*
+ * Private data types
+ */
+struct program_list_s;
+typedef struct program_list_s program_list_t;
+struct program_list_s
+{
+ char *user;
+ char *exec;
+ int pid;
+ program_list_t *next;
+};
+
+/*
+ * Private variables
+ */
+static data_source_t dsrc_counter[1] =
+{
+ {"value", DS_TYPE_COUNTER, NAN, NAN}
+};
+
+static data_set_t ds_counter =
+{
+ "counter", STATIC_ARRAY_SIZE (dsrc_counter), dsrc_counter
+};
+
+static data_source_t dsrc_gauge[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
+
+static data_set_t ds_gauge =
+{
+ "gauge", STATIC_ARRAY_SIZE (dsrc_gauge), dsrc_gauge
+};
+
+static const char *config_keys[] =
+{
+ "Exec"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static program_list_t *pl_head = NULL;
+
+/*
+ * Functions
+ */
+static int exec_config (const char *key, const char *value)
+{
+ if (strcasecmp ("Exec", key) == 0)
+ {
+ program_list_t *pl;
+ pl = (program_list_t *) malloc (sizeof (program_list_t));
+ if (pl == NULL)
+ return (1);
+ memset (pl, '\0', sizeof (program_list_t));
+
+ pl->user = strdup (value);
+ if (pl->user == NULL)
+ {
+ sfree (pl);
+ return (1);
+ }
+
+ pl->exec = strchr (pl->user, ' ');
+ if (pl->exec == NULL)
+ {
+ sfree (pl->user);
+ sfree (pl);
+ return (1);
+ }
+ while (*pl->exec == ' ')
+ {
+ *pl->exec = '\0';
+ pl->exec++;
+ }
+
+ if (*pl->exec == '\0')
+ {
+ sfree (pl->user);
+ sfree (pl);
+ return (1);
+ }
+
+ pl->next = pl_head;
+ pl_head = pl;
+ }
+ else
+ {
+ return (-1);
+ }
+
+ return (0);
+} /* int exec_config */
+
+static void submit_counter (const char *type_instance, counter_t value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ DBG ("type_instance = %s; value = %llu;", type_instance, value);
+
+ values[0].counter = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "exec");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values ("counter", &vl);
+} /* void submit_counter */
+
+static void submit_gauge (const char *type_instance, gauge_t value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ DBG ("type_instance = %s; value = %lf;", type_instance, value);
+
+ values[0].gauge = value;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "exec");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values ("gauge", &vl);
+} /* void submit_counter */
+
+static void exec_child (program_list_t *pl)
+{
+ struct passwd *sp;
+ int status;
+ int uid;
+ char *arg0;
+
+ /* FIXME: Not thread safe! */
+ sp = getpwnam (pl->user);
+ if (sp == NULL)
+ {
+ syslog (LOG_ERR, "exec plugin: getpwnam failed: %s", strerror (errno));
+ exit (-1);
+ }
+
+ uid = sp->pw_uid;
+ if (uid == 0)
+ {
+ syslog (LOG_ERR, "exec plugin: Cowardly refusing to exec program as root.");
+ exit (-1);
+ }
+
+ status = setuid (uid);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "exec plugin: setuid failed: %s", strerror (errno));
+ exit (-1);
+ }
+
+ arg0 = strrchr (pl->exec, '/');
+ if (arg0 != NULL)
+ arg0++;
+ if ((arg0 == NULL) || (*arg0 == '\0'))
+ arg0 = pl->exec;
+
+ status = execlp (pl->exec, arg0, (char *) 0);
+
+ syslog (LOG_ERR, "exec plugin: exec failed: %s", strerror (errno));
+ exit (-1);
+} /* void exec_child */
+
+static int fork_child (program_list_t *pl)
+{
+ int fd_pipe[2];
+ int status;
+
+ if (pl->pid != 0)
+ return (-1);
+
+ status = pipe (fd_pipe);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "exec plugin: pipe failed: %s", strerror (errno));
+ return (-1);
+ }
+
+ pl->pid = fork ();
+ if (pl->pid < 0)
+ {
+ syslog (LOG_ERR, "exec plugin: fork failed: %s", strerror (errno));
+ return (-1);
+ }
+ else if (pl->pid == 0)
+ {
+ close (fd_pipe[0]);
+
+ /* Connect the pipe to STDOUT and STDERR */
+ if (fd_pipe[1] != STDOUT_FILENO)
+ dup2 (fd_pipe[1], STDOUT_FILENO);
+ if (fd_pipe[1] != STDERR_FILENO)
+ dup2 (fd_pipe[1], STDERR_FILENO);
+ if ((fd_pipe[1] != STDOUT_FILENO) && (fd_pipe[1] != STDERR_FILENO))
+ close (fd_pipe[1]);
+
+ exec_child (pl);
+ /* does not return */
+ }
+
+ close (fd_pipe[1]);
+ return (fd_pipe[0]);
+} /* int fork_child */
+
+static void *exec_read_one (void *arg)
+{
+ program_list_t *pl = (program_list_t *) arg;
+ int fd;
+ FILE *fh;
+ char buffer[1024];
+
+ fd = fork_child (pl);
+ if (fd < 0)
+ pthread_exit ((void *) 1);
+
+ assert (pl->pid != 0);
+
+ fh = fdopen (fd, "r");
+ if (fh == NULL)
+ {
+ syslog (LOG_ERR, "exec plugin: fdopen (%i) failed: %s", fd,
+ strerror (errno));
+ kill (pl->pid, SIGTERM);
+ close (fd);
+ pthread_exit ((void *) 1);
+ }
+
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
+ {
+ int len;
+ char *type;
+ char *type_instance;
+ char *value;
+
+ DBG ("buffer = %s", buffer);
+
+ len = strlen (buffer);
+ if (len < 5)
+ continue;
+
+ if (buffer[0] == '#')
+ continue;
+
+ type = buffer;
+
+ type_instance = strchr (type, ',');
+ if (type_instance == NULL)
+ continue;
+ *type_instance = '\0';
+ type_instance++;
+
+ if ((strcasecmp ("counter", type) != 0)
+ && (strcasecmp ("gauge", type) != 0))
+ {
+ syslog (LOG_WARNING, "exec plugin: Received invalid type: %s", type);
+ continue;
+ }
+
+ value = strchr (type_instance, ',');
+ if (value == NULL)
+ continue;
+ *value = '\0';
+ value++;
+
+ DBG ("value = %s", value);
+
+ if (strcasecmp ("counter", type) == 0)
+ submit_counter (type_instance, atoll (value));
+ else
+ submit_gauge (type_instance, atof (value));
+ } /* while (fgets) */
+
+ fclose (fh);
+ pl->pid = 0;
+
+ pthread_exit ((void *) 0);
+} /* void *exec_read_one */
+
+static int exec_read (void)
+{
+ program_list_t *pl;
+
+ for (pl = pl_head; pl != NULL; pl = pl->next)
+ {
+ pthread_t t;
+ pthread_attr_t attr;
+
+ if (pl->pid != 0)
+ continue;
+
+ pthread_attr_init (&attr);
+ pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
+ pthread_create (&t, &attr, exec_read_one, (void *) pl);
+ } /* for (pl) */
+
+ return (0);
+} /* int exec_read */
+
+void module_register (void)
+{
+ plugin_register_data_set (&ds_counter);
+ plugin_register_data_set (&ds_gauge);
+ plugin_register_config ("exec", exec_config, config_keys, config_keys_num);
+ plugin_register_read ("exec", exec_read);
+} /* void module_register */
+
+/*
+ * vim:shiftwidth=2:softtabstop=2:tabstop=8
+ */
diff --git a/src/hddtemp.c b/src/hddtemp.c
index 80b3419bee76d3e96efacb242bdba4f946efc5be..3f37d507977e86f91ba1a7c5d6a835cfd941f303 100644 (file)
--- a/src/hddtemp.c
+++ b/src/hddtemp.c
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "hddtemp"
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <libgen.h> /* for basename */
+#if HAVE_NETDB_H && HAVE_SYS_SOCKET_H && HAVE_NETINET_IN_H \
+ && HAVE_NETINET_TCP_H && HAVE_LIBGEN_H
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# include <libgen.h> /* for basename */
+# define HDDTEMP_HAVE_READ 1
+#else
+# define HDDTEMP_HAVE_READ 0
+#endif
#if HAVE_LINUX_MAJOR_H
# include <linux/major.h>
#define HDDTEMP_DEF_HOST "127.0.0.1"
#define HDDTEMP_DEF_PORT "7634"
-/* BUFFER_SIZE
- Size of the buffer we use to receive from the hddtemp daemon. */
-#define BUFFER_SIZE 1024
-
-static char *filename_format = "hddtemp-%s.rrd";
+static data_source_t data_source_temperature[1] =
+{
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
+};
-static char *ds_def[] =
+static data_set_t temperature_ds =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "temperature", 1, data_source_temperature
};
-static int ds_num = 1;
-static char *config_keys[] =
+#if HDDTEMP_HAVE_READ
+static const char *config_keys[] =
{
"Host",
"Port",
return (0);
}
-static int hddtemp_config (char *key, char *value)
+static int hddtemp_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
/* In the init-function we initialize the `hddname_t' list used to translate
* disk-names. Under Linux that's done using `/proc/partitions'. Under other
* operating-systems, it's not done at all. */
-static void hddtemp_init (void)
+static int hddtemp_init (void)
{
#if KERNEL_LINUX
FILE *fh;
- char buf[BUFFER_SIZE];
+ char buf[1024];
int buflen;
char *fields[16];
{
DBG ("Looking at /proc/partitions...");
- while (fgets (buf, BUFFER_SIZE, fh) != NULL)
+ while (fgets (buf, sizeof (buf), fh) != NULL)
{
/* Delete trailing newlines */
buflen = strlen (buf);
DBG ("Could not open /proc/partitions: %s",
strerror (errno));
#endif /* KERNEL_LINUX */
-}
-static void hddtemp_write (char *host, char *inst, char *val)
-{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_format, inst);
- if (status < 1)
- return;
- else if (status >= BUFFER_SIZE)
- return;
-
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
+ return (0);
+} /* int hddtemp_init */
/*
* hddtemp_get_name
return (ret);
}
-static void hddtemp_submit (char *inst, double temperature)
+static void hddtemp_submit (char *type_instance, double value)
{
- char buf[BUFFER_SIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = value;
- if (snprintf (buf, BUFFER_SIZE, "%u:%.3f", (unsigned int) curtime, temperature)
- >= BUFFER_SIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "hddtemp");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, inst, buf);
+ plugin_dispatch_values ("temperature", &vl);
}
-static void hddtemp_read (void)
+static int hddtemp_read (void)
{
- char buf[BUFFER_SIZE];
+ char buf[1024];
char *fields[128];
char *ptr;
int num_fields;
int num_disks;
int i;
- static int wait_time = 1;
- static int wait_left = 0;
-
- if (wait_left >= 10)
- {
- wait_left -= 10;
- return;
- }
-
/* get data from daemon */
- if (hddtemp_query_daemon (buf, BUFFER_SIZE) < 0)
- {
- /* This limit is reached in log2(86400) =~ 17 steps. Since
- * there is a 2^n seconds wait between each step it will need
- * roughly one day to reach this limit. -octo */
-
- wait_time *= 2;
- if (wait_time > 86400)
- wait_time = 86400;
-
- wait_left = wait_time;
-
- return;
- }
- else
- {
- wait_time = 1;
- wait_left = 0;
- }
+ if (hddtemp_query_daemon (buf, sizeof (buf)) < 0)
+ return (-1);
/* NB: strtok will eat up "||" and leading "|"'s */
num_fields = 0;
hddtemp_submit (name, temperature);
}
}
-}
+
+ return (0);
+} /* int hddtemp_read */
+#endif /* HDDTEMP_HAVE_READ */
/* module_register
Register collectd plugin. */
void module_register (void)
{
- plugin_register (MODULE_NAME, hddtemp_init, hddtemp_read, hddtemp_write);
- cf_register (MODULE_NAME, hddtemp_config, config_keys, config_keys_num);
+ plugin_register_data_set (&temperature_ds);
+
+#if HDDTEMP_HAVE_READ
+ plugin_register_config ("hddtemp", hddtemp_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("hddtemp", hddtemp_init);
+ plugin_register_read ("hddtemp", hddtemp_read);
+#endif /* HDDTEMP_HAVE_READ */
}
-
-#undef MODULE_NAME
diff --git a/src/libconfig/AUTHORS b/src/libconfig/AUTHORS
--- a/src/libconfig/AUTHORS
+++ /dev/null
@@ -1,17 +0,0 @@
- libconfig 0.1.21
-
-Release information:
- pkg: libconfig version 0.1.21
- url: http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz
- web: http://www.rkeene.org/oss/libconfig/
- date: Tue Oct 18 16:03:55 CDT 2005
- mail: libconfig@rkeene.org
---------------------------------------------------------------------------
-
-Primary Authors:
- * Roy Keene <libconfig@rkeene.org>
- Primary maintainer.
-
-People who have submitted patches:
- * Mirko Buffoni <mirko.buffoni@synthesys.it>
- Fixed installation issues and corrected mistakes in RPM spec file.
diff --git a/src/libconfig/LICENSE b/src/libconfig/LICENSE
--- a/src/libconfig/LICENSE
+++ /dev/null
@@ -1,19 +0,0 @@
-Copyright (c) 2004 Roy Keene, Keene Enterprises
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/src/libconfig/Makefile.am b/src/libconfig/Makefile.am
+++ /dev/null
@@ -1,17 +0,0 @@
-AUTOMAKE_OPTIONS = foreign no-dependencies
-
-EXTRA_DIST = AUTHORS LICENSE README TODO
-
-noinst_LTLIBRARIES = libconfig.la
-
-libconfig_la_CFLAGS =
-libconfig_la_LDFLAGS = -avoid-version
-libconfig_la_SOURCES = \
- libconfig.c libconfig.h \
- conf_apache.c conf_apache.h \
- conf_colon.c conf_colon.h \
- conf_equal.c conf_equal.h \
- conf_section.c conf_section.h \
- conf_space.c conf_space.h \
- conf_xml.c conf_xml.h \
- compat.h libconfig_private.h
diff --git a/src/libconfig/README b/src/libconfig/README
--- a/src/libconfig/README
+++ /dev/null
@@ -1,19 +0,0 @@
- libconfig 0.1.21
-
-Release information:
- pkg: libconfig version 0.1.21
- url: http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz
- web: http://www.rkeene.org/oss/libconfig/
- date: Tue Oct 18 16:03:55 CDT 2005
- mail: libconfig@rkeene.org
---------------------------------------------------------------------------
-
-Tested platforms:
- Mac OS X 10.1
- HP-UX 11.11
- NetBSD 1.6.1
- FreeBSD 4.8
- OpenBSD 3.4
- SunOS 5.9
- Linux (Slackware, RedHat, Fedora Core, Debian)
- IRIX 6.5
diff --git a/src/libconfig/TODO b/src/libconfig/TODO
--- a/src/libconfig/TODO
+++ /dev/null
@@ -1,11 +0,0 @@
- libconfig 0.1.21
-
-Release information:
- pkg: libconfig version 0.1.21
- url: http://www.rkeene.org/files/oss/libconfig/devel/libconfig-0.1.21.tar.gz
- web: http://www.rkeene.org/oss/libconfig/
- date: Tue Oct 18 16:03:55 CDT 2005
- mail: libconfig@rkeene.org
---------------------------------------------------------------------------
-
- More manual pages.
diff --git a/src/libconfig/compat.h b/src/libconfig/compat.h
--- a/src/libconfig/compat.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef RSK_COMPAT_H
-#define RSK_COMPAT_H
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#ifdef __WIN32__
-#include "win32.h"
-#endif
-
-#ifndef LC_LINEBUF_LEN
-#define LC_LINEBUF_LEN 1024
-#endif
-
-#ifdef HAVE_INTTYPES_H
-#include <inttypes.h>
-#endif
-#ifdef HAVE_MEMORY_H
-#include <memory.h>
-#endif
-#ifdef HAVE_STDINT_H
-#include <stdint.h>
-#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_ARPA_INET_H
-#include <arpa/inet.h>
-#endif
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-#ifdef HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-#ifdef HAVE_STDARG_H
-#include <stdarg.h>
-#endif
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-#ifdef TIME_WITH_SYS_TIME
-#include <sys/time.h>
-#include <time.h>
-#else
-#ifdef HAVE_SYS_TIME_H
-#include <sys/time.h>
-#else
-#include <time.h>
-#endif
-#endif
-
-#ifdef HAVE_OPENNET_H
-#include <opennet.h>
-#endif
-#ifdef HAVE_LIBOPENNET
-#define lc_fopen(path, mode) fopen_net(path, mode)
-#define lc_fgets(buf, size, stream) fgets_net(buf, size, stream)
-#define lc_feof(stream) feof_net(stream)
-#define lc_fclose(stream) fclose_net(stream)
-#define LC_FILE NETFILE
-#else
-#define lc_fopen(path, mode) fopen(path, mode)
-#define lc_fgets(buf, size, stream) fgets(buf, size, stream)
-#define lc_feof(stream) feof(stream)
-#define lc_fclose(stream) fclose(stream)
-#define LC_FILE FILE
-#endif
-
-#endif
diff --git a/src/libconfig/conf_apache.c b/src/libconfig/conf_apache.c
+++ /dev/null
@@ -1,371 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_apache.h"
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_SYS_STAT_H
-#include <sys/stat.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_DIRENT_H
-#include <dirent.h>
-#endif
-
-static int lc_process_conf_apache_file(const char *configfile, const char *pathprefix);
-
-static int lc_process_conf_apache_include(const char *pathname, const char *pathprefix) {
- struct stat pathinfo;
- struct dirent *dinfo = NULL;
- char includepath[LC_LINEBUF_LEN] = {0};
- DIR *dh = NULL;
- int statret = -1, lcpcafret = -1;
- int retval = 0;
-
- statret = stat(pathname, &pathinfo);
- if (statret < 0) {
- return(-1);
- }
-
- if (S_ISDIR(pathinfo.st_mode)) {
- dh = opendir(pathname);
- if (dh == NULL) {
- return(-1);
- }
-
- while (1) {
- dinfo = readdir(dh);
- if (dinfo == NULL) {
- break;
- }
-
- /* Skip files that begin with a dot ('.') */
- if (dinfo->d_name[0] == '.') continue;
-
- snprintf(includepath, sizeof(includepath) - 1, "%s/%s", pathname, dinfo->d_name);
- lcpcafret = lc_process_conf_apache_include(includepath, pathprefix);
- if (lcpcafret < 0) {
- retval = -1;
- /* XXX: should we break here (abort further including of files from a directory if one fails ?) */
- }
- }
-
- closedir(dh);
- } else {
- lcpcafret = lc_process_conf_apache_file(pathname, pathprefix);
- if (lcpcafret < 0) {
- retval = -1;
- }
- }
-
- return(retval);
-}
-
-static int lc_process_conf_apache_file(const char *configfile, const char *pathprefix) {
- LC_FILE *configfp = NULL;
- const char *local_lc_errfile;
- char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL, *tmp_ptr = NULL;
- char *lastsection = NULL;
- char qualifbuf[LC_LINEBUF_LEN] = {0};
- char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL;
- char *fgetsret = NULL;
- int lcpvret = -1, lpcafret = -1;
- int invalid_section = 0, ignore_section = 0;
- int local_lc_errline;
- int retval = 0;
- lc_err_t save_lc_errno = LC_ERR_NONE;
-
- if (pathprefix != NULL) {
- /* Copy the prefix, if specified. */
- strncpy(qualifbuf, pathprefix, sizeof(qualifbuf) - 1);
- }
-
- local_lc_errfile = configfile;
- local_lc_errline = 0;
-
- if (configfile == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVDATA;
- return(-1);
- }
-
- configfp = lc_fopen(configfile, "r");
-
- if (configfp == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_CANTOPEN;
- return(-1);
- }
-
- while (1) {
- fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
- if (fgetsret == NULL) {
- break;
- }
- if (lc_feof(configfp)) {
- break;
- }
-
- local_lc_errline++;
-
- /* Remove trailing crap (but not spaces). */
- linebuf_ptr = &linebuf[strlen(linebuf) - 1];
- while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
- *linebuf_ptr = '\0';
- linebuf_ptr--;
- }
-
- /* Remove leading spaces. */
- linebuf_ptr = &linebuf[0];
- while (*linebuf_ptr == ' ' || *linebuf_ptr == '\t') {
- linebuf_ptr++;
- }
-
- /* Handle section header. */
- if (linebuf_ptr[0] == '<' && linebuf_ptr[strlen(linebuf_ptr) - 1] == '>') {
- /* Remove < and > from around the data. */
- linebuf_ptr[strlen(linebuf_ptr) - 1] = '\0';
- linebuf_ptr++;
-
- /* Lowercase the command part of the section. */
- tmp_ptr = linebuf_ptr;
- while (*tmp_ptr != '\0' && *tmp_ptr != ' ') {
- *tmp_ptr = tolower(*tmp_ptr);
- tmp_ptr++;
- }
-
- /* If this is a close section command, handle it */
- if (linebuf_ptr[0] == '/') {
- linebuf_ptr++;
- cmd = linebuf_ptr;
-
- /* Find the last section closed. */
- tmp_ptr = strrchr(qualifbuf, '.');
- if (tmp_ptr == NULL) {
- lastsection = qualifbuf;
- tmp_ptr = qualifbuf;
- } else {
- lastsection = tmp_ptr + 1;
- }
-
- if (strcmp(cmd, lastsection) != 0) {
-#ifdef DEBUG
- fprintf(stderr, "Section closing does not match last opened section.\n");
- fprintf(stderr, "Last opened = \"%s\", Closing = \"%s\"\n", lastsection, cmd);
-#endif
- retval = -1;
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_BADFORMAT;
-
- /* For this error, we abort immediately. */
- break;
- }
-
- lcpvret = lc_process_var(qualifbuf, NULL, NULL, LC_FLAGS_SECTIONEND);
- if (lcpvret < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid section terminating: \"%s\"\n", qualifbuf);
-#endif
- }
-
- /* Remove the "lastsection" part.. */
- *tmp_ptr = '\0';
-
- /* We just sucessfully closed the last section opened,
- we must be in a valid section now since we only open
- sections from within valid sections. */
- invalid_section = 0;
- ignore_section = 0;
-
- continue;
- }
- /* Otherwise, open a new section. */
-
- /* Don't open a section from an invalid section. */
- if (invalid_section == 1 || ignore_section == 1) {
- continue;
- }
-
- /* Parse out any argument passed. */
- sep = strpbrk(linebuf_ptr, " \t");
-
- if (sep != NULL) {
- cmdend = sep;
- /* Delete space at the end of the command. */
- cmdend--; /* It currently derefs to the seperator.. */
- while (*cmdend <= ' ') {
- *cmdend = '\0';
- cmdend--;
- }
-
- /* Delete the seperator char and any leading space. */
- *sep = '\0';
- sep++;
- while (*sep == ' ' || *sep == '\t') {
- sep++;
- }
- value = sep;
- } else {
- /* XXX: should this be "" or NULL ? */
- value = "";
- }
-
- cmd = linebuf_ptr;
-
- if (qualifbuf[0] != '\0') {
- strncat(qualifbuf, ".", sizeof(qualifbuf) - strlen(qualifbuf) - 1);
- }
- strncat(qualifbuf, cmd, sizeof(qualifbuf) - strlen(qualifbuf) - 1);
-
- lcpvret = lc_process_var(qualifbuf, value, NULL, LC_FLAGS_SECTIONSTART);
- if (lcpvret < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid section: \"%s\"\n", qualifbuf);
-#endif
- invalid_section = 1;
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVSECTION;
- retval = -1;
- }
- if (lcpvret == LC_CBRET_IGNORESECTION) {
- ignore_section = 1;
- }
- continue;
- }
-
- /* Drop comments and blank lines. */
- if (*linebuf_ptr == '#' || *linebuf_ptr == '\0') {
- continue;
- }
-
- /* Don't handle things for a section that doesn't exist. */
- if (invalid_section == 1) {
-#ifdef DEBUG
- fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf);
-#endif
- continue;
- }
- if (ignore_section == 1) {
-#ifdef DEBUG
- fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf);
-#endif
- continue;
- }
-
- /* Find the command and the data in the line. */
- sep = strpbrk(linebuf_ptr, " \t");
- if (sep != NULL) {
- cmdend = sep;
-
- /* Delete space at the end of the command. */
- cmdend--; /* It currently derefs to the seperator.. */
- while (*cmdend <= ' ') {
- *cmdend = '\0';
- cmdend--;
- }
-
- /* Delete the seperator char and any leading space. */
- *sep = '\0';
- sep++;
- while (*sep == ' ' || *sep == '\t') {
- sep++;
- }
- value = sep;
- } else {
- value = NULL;
- }
-
- cmd = linebuf_ptr;
-
- /* Handle special commands. */
- if (strcasecmp(cmd, "include") == 0) {
- if (value == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_BADFORMAT;
- retval = -1;
-#ifdef DEBUG
- fprintf(stderr, "Invalid include command.\n");
-#endif
- continue;
- }
-
- lpcafret = lc_process_conf_apache_include(value, qualifbuf);
- if (lpcafret < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Error in included file.\n");
-#endif
- retval = -1;
- }
- continue;
- }
-
- /* Create the fully qualified variable name. */
- if (qualifbuf[0] != '\0') {
- strncat(qualifbuf, ".", sizeof(qualifbuf) - strlen(qualifbuf) - 1);
- }
- strncat(qualifbuf, cmd, sizeof(qualifbuf) - strlen(qualifbuf) - 1);
-
- /* Call the parent and tell them we have data. */
- save_lc_errno = lc_errno;
- lc_errno = LC_ERR_NONE;
- lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR);
- if (lcpvret < 0) {
- if (lc_errno == LC_ERR_NONE) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
-#endif
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVCMD;
- } else {
-#ifdef DEBUG
- fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
-#endif
- }
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- retval = -1;
- } else {
- lc_errno = save_lc_errno;
- }
-
- /* Remove the "cmd" part of the buffer. */
- tmp_ptr = strrchr(qualifbuf, '.');
- if (tmp_ptr == NULL) {
- tmp_ptr = qualifbuf;
- }
- *tmp_ptr = '\0';
- }
-
- lc_fclose(configfp);
-
- return(retval);
-}
-
-int lc_process_conf_apache(const char *appname, const char *configfile) {
- return(lc_process_conf_apache_file(configfile, NULL));
-}
diff --git a/src/libconfig/conf_apache.h b/src/libconfig/conf_apache.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_APACHE_H
-#define LC_CONF_APACHE_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_apache(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_colon.c b/src/libconfig/conf_colon.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_colon.h"
-
-int lc_process_conf_colon(const char *appname, const char *configfile) {
- return(-1);
-}
diff --git a/src/libconfig/conf_colon.h b/src/libconfig/conf_colon.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_COLON_H
-#define LC_CONF_COLON_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_colon(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_equal.c b/src/libconfig/conf_equal.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_equal.h"
-
-int lc_process_conf_equal(const char *appname, const char *configfile) {
- return(-1);
-}
diff --git a/src/libconfig/conf_equal.h b/src/libconfig/conf_equal.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_EQUAL_H
-#define LC_CONF_EQUAL_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_equal(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_section.c b/src/libconfig/conf_section.c
+++ /dev/null
@@ -1,201 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_section.h"
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-int lc_process_conf_section(const char *appname, const char *configfile) {
- LC_FILE *configfp = NULL;
- const char *local_lc_errfile;
- char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL;
- char qualifbuf[LC_LINEBUF_LEN] = {0};
- char *cmd = NULL, *value = NULL, *sep = NULL, *cmdend = NULL;
- char *currsection = NULL;
- char *fgetsret = NULL;
- int lcpvret = -1;
- int invalid_section = 1, ignore_section = 0;
- int local_lc_errline;
- int retval = 0;
- lc_err_t save_lc_errno = LC_ERR_NONE;
-
- local_lc_errfile = configfile;
- local_lc_errline = 0;
-
- if (appname == NULL || configfile == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVDATA;
- return(-1);
- }
-
- configfp = lc_fopen(configfile, "r");
-
- if (configfp == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_CANTOPEN;
- return(-1);
- }
-
- while (1) {
- fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
- if (fgetsret == NULL) {
- break;
- }
- if (lc_feof(configfp)) {
- break;
- }
-
- local_lc_errline++;
-
- /* Remove trailing crap (but not spaces). */
- linebuf_ptr = &linebuf[strlen(linebuf) - 1];
- while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
- *linebuf_ptr = '\0';
- linebuf_ptr--;
- }
-
- /* Handle section header. */
- if (linebuf[0] == '[' && linebuf[strlen(linebuf) - 1] == ']') {
- linebuf[strlen(linebuf) - 1] = '\0';
- linebuf_ptr = &linebuf[1];
-
- /* If a section was open, close it. */
- if (currsection != NULL) {
- lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND);
- if (lcpvret < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection);
-#endif
- }
- free(currsection);
- }
-
- /* Open new section. */
- currsection = strdup(linebuf_ptr);
- lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONSTART);
- if (lcpvret < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid section: \"%s\"\n", currsection);
-#endif
- invalid_section = 1;
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVSECTION;
- retval = -1;
- } else {
- invalid_section = 0;
- ignore_section = 0;
- }
-
- if (lcpvret == LC_CBRET_IGNORESECTION) {
- ignore_section = 1;
- }
- continue;
- }
-
- /* Remove leading spaces. */
- linebuf_ptr = &linebuf[0];
- while (*linebuf_ptr == ' ') {
- linebuf_ptr++;
- }
-
- /* Drop comments and blank lines. */
- if (*linebuf_ptr == ';' || *linebuf_ptr == '\0') {
- continue;
- }
-
- /* Don't handle things for a section that doesn't exist. */
- if (invalid_section == 1) {
-#ifdef DEBUG
- fprintf(stderr, "Ignoring line (because invalid section): %s\n", linebuf);
-#endif
- continue;
- }
-
- /* Don't process commands if this section is specifically ignored. */
- if (ignore_section == 1) {
-#ifdef DEBUG
- fprintf(stderr, "Ignoring line (because ignored section): %s\n", linebuf);
-#endif
- continue;
- }
-
- /* Find the command and the data in the line. */
- cmdend = sep = strpbrk(linebuf_ptr, "=");
- if (sep == NULL) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid line: \"%s\"\n", linebuf);
-#endif
- continue;
- }
-
- /* Delete space at the end of the command. */
- cmdend--; /* It currently derefs to the seperator.. */
- while (*cmdend <= ' ') {
- *cmdend = '\0';
- cmdend--;
- }
-
- cmd = linebuf_ptr;
-
- /* Delete the seperator char and any leading space. */
- *sep = '\0';
- sep++;
- while (*sep == ' ' || *sep == '\t') {
- sep++;
- }
- value = sep;
-
- /* Create the fully qualified variable name. */
- if (currsection == NULL) {
- strncpy(qualifbuf, cmd, sizeof(qualifbuf) - 1);
- } else {
- snprintf(qualifbuf, sizeof(qualifbuf) - 1, "%s.%s", currsection, cmd);
- }
-
- /* Call the parent and tell them we have data. */
- save_lc_errno = lc_errno;
- lc_errno = LC_ERR_NONE;
- lcpvret = lc_process_var(qualifbuf, NULL, value, LC_FLAGS_VAR);
- if (lcpvret < 0) {
- if (lc_errno == LC_ERR_NONE) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
-#endif
- lc_errno = LC_ERR_INVCMD;
- } else {
-#ifdef DEBUG
- fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
-#endif
- }
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- retval = -1;
- } else {
- lc_errno = save_lc_errno;
- }
- }
-
- /* Close any open section, and clean-up. */
- if (currsection != NULL) {
- lcpvret = lc_process_var(currsection, NULL, NULL, LC_FLAGS_SECTIONEND);
- if (lcpvret < 0) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid section terminating: \"%s\"\n", currsection);
-#endif
- }
- free(currsection);
- }
-
- lc_fclose(configfp);
-
- return(retval);
-}
diff --git a/src/libconfig/conf_section.h b/src/libconfig/conf_section.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_SECTION_H
-#define LC_CONF_SECTION_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_section(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_space.c b/src/libconfig/conf_space.c
+++ /dev/null
@@ -1,109 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_space.h"
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-int lc_process_conf_space(const char *appname, const char *configfile) {
- LC_FILE *configfp = NULL;
- const char *local_lc_errfile;
- char linebuf[LC_LINEBUF_LEN] = {0}, *linebuf_ptr = NULL;
- char *cmd = NULL, *value = NULL, *sep = NULL;
- char *fgetsret = NULL;
- int local_lc_errline;
- int lcpvret = -1;
- int retval = 0;
- lc_err_t save_lc_errno = LC_ERR_NONE;
-
- local_lc_errfile = configfile;
- local_lc_errline = 0;
-
- if (appname == NULL || configfile == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVDATA;
- return(-1);
- }
-
- configfp = lc_fopen(configfile, "r");
-
- if (configfp == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_CANTOPEN;
- return(-1);
- }
-
- while (1) {
- fgetsret = lc_fgets(linebuf, sizeof(linebuf) - 1, configfp);
- if (fgetsret == NULL) {
- break;
- }
- if (lc_feof(configfp)) {
- break;
- }
-
- local_lc_errline++;
-
- linebuf_ptr = &linebuf[strlen(linebuf) - 1];
- while (*linebuf_ptr < ' ' && linebuf_ptr >= linebuf) {
- *linebuf_ptr = '\0';
- linebuf_ptr--;
- }
-
- linebuf_ptr = &linebuf[0];
- while (*linebuf_ptr == ' ') {
- linebuf_ptr++;
- }
-
- if (*linebuf_ptr == '#' || *linebuf_ptr == '\0') {
- continue;
- }
-
-
- sep = strpbrk(linebuf_ptr, " \t");
- cmd = linebuf_ptr;
- if (sep != NULL) {
- *sep = '\0';
- sep++;
- while (*sep == ' ' || *sep == '\t') {
- sep++;
- }
- value = sep;
- } else {
- value = NULL;
- }
-
- save_lc_errno = lc_errno;
- lc_errno = LC_ERR_NONE;
- lcpvret = lc_process_var(cmd, NULL, value, LC_FLAGS_VAR);
- if (lcpvret < 0) {
- if (lc_errno == LC_ERR_NONE) {
-#ifdef DEBUG
- fprintf(stderr, "Invalid command: \"%s\"\n", cmd);
-#endif
- lc_errno = LC_ERR_INVCMD;
- } else {
-#ifdef DEBUG
- fprintf(stderr, "Error processing command (command was valid, but an error occured, errno was set)\n");
-#endif
- }
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- retval = -1;
- } else {
- lc_errno = save_lc_errno;
- }
- }
-
- lc_fclose(configfp);
-
- return(retval);
-}
diff --git a/src/libconfig/conf_space.h b/src/libconfig/conf_space.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_SPACE_H
-#define LC_CONF_SPACE_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_space(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/conf_xml.c b/src/libconfig/conf_xml.c
--- a/src/libconfig/conf_xml.c
+++ /dev/null
@@ -1,7 +0,0 @@
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_xml.h"
-
-int lc_process_conf_xml(const char *appname, const char *configfile) {
- return(-1);
-}
diff --git a/src/libconfig/conf_xml.h b/src/libconfig/conf_xml.h
--- a/src/libconfig/conf_xml.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef LC_CONF_XML_H
-#define LC_CONF_XML_H
-#include "libconfig.h"
-#include "libconfig_private.h"
-
-int lc_process_conf_xml(const char *appname, const char *configfile);
-
-#endif
diff --git a/src/libconfig/libconfig.c b/src/libconfig/libconfig.c
+++ /dev/null
@@ -1,1073 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-#include "libconfig_private.h"
-#include "conf_section.h"
-#include "conf_apache.h"
-#include "conf_colon.h"
-#include "conf_equal.h"
-#include "conf_space.h"
-#include "conf_xml.h"
-
-#ifdef HAVE_STRING_H
-#include <string.h>
-#endif
-
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#endif
-
-#ifdef HAVE_CTYPE_H
-#include <ctype.h>
-#endif
-
-#ifdef HAVE_STDIO_H
-#include <stdio.h>
-#endif
-
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-
-#ifdef HAVE_SYS_TYPES_H
-#include <sys/types.h>
-#endif
-
-#ifdef HAVE_PWD_H
-#include <pwd.h>
-#endif
-
-struct lc_varhandler_st *varhandlers = NULL;
-lc_err_t lc_errno = LC_ERR_NONE;
-const char *lc_errfile = NULL;
-int lc_optind = 0;
-int lc_errline = 0;
-
-extern char **environ;
-
-static int lc_process_var_string(void *data, const char *value, const char **endptr) {
- char **dataval;
-
- dataval = data;
- *dataval = strdup(value);
-
- *endptr = NULL;
-
- return(0);
-}
-
-static int lc_process_var_cidr(void *data, const char *value, const char **endptr) {
- return(-1);
-}
-
-static int lc_process_var_hostname6(void *data, const char *value, const char **endptr) {
- return(-1);
-}
-
-static int lc_process_var_hostname4(void *data, const char *value, const char **endptr) {
- return(-1);
-}
-
-static int lc_process_var_ip6(void *data, const char *value, const char **endptr) {
- return(-1);
-}
-
-static int lc_process_var_ip4(void *data, const char *value, const char **endptr) {
- uint32_t *dataval, retval = 0;
- const char *dotptr = NULL;
- int tmpval = -1;
-// int dotcount
-
- dataval = data;
-
- dotptr = value;
-
- while (1) {
- tmpval = atoi(dotptr);
- if (tmpval < 0) {
- break;
- }
-
- retval <<= 8;
- retval |= tmpval;
-
- dotptr = strpbrk(dotptr, "./ \t");
- if (dotptr == NULL) {
- break;
- }
- if (*dotptr != '.') {
- break;
- }
- dotptr++;
- }
-
- *dataval = retval;
-
- *endptr = (char *) dotptr;
-
- return(0);
-}
-
-static int lc_process_var_longlong(void *data, const char *value, const char **endptr) {
- long long *dataval;
-
- dataval = data;
- *dataval = strtoll(value, (char **) endptr, 10);
-
- return(0);
-}
-
-static int lc_process_var_long(void *data, const char *value, const char **endptr) {
- long *dataval;
-
- dataval = data;
- *dataval = strtoll(value, (char **) endptr, 10);
-
- return(0);
-}
-
-static int lc_process_var_int(void *data, const char *value, const char **endptr) {
- int *dataval;
-
- dataval = data;
- *dataval = strtoll(value, (char **) endptr, 10);
-
- return(0);
-}
-
-static int lc_process_var_short(void *data, const char *value, const char **endptr) {
- short *dataval;
-
- dataval = data;
- *dataval = strtoll(value, (char **) endptr, 10);
-
- return(0);
-}
-
-static int lc_process_var_bool_byexistance(void *data, const char *value, const char **endptr) {
- int *dataval;
-
- dataval = data;
-
- *dataval = 1;
-
- *endptr = NULL;
-
- return(0);
-}
-
-static int lc_process_var_bool(void *data, const char *value, const char **endptr) {
- char *trueval[] = {"enable", "true", "yes", "on", "y", "1"};
- char *falseval[] = {"disable", "false", "no", "off", "n", "0"};
- size_t chkvallen, vallen;
- int *dataval;
- int i;
-
- dataval = data;
-
- *dataval = -1;
-
- vallen = strlen(value);
-
- for (i = 0; i < (sizeof(trueval) / sizeof(*trueval)); i++) {
- chkvallen = strlen(trueval[i]);
-
- /*
- * Skip if there's no way we could find a match here.
- */
- if (chkvallen > vallen) {
- continue;
- }
-
- /*
- * Skip if there is no partial match.
- */
- if (strncasecmp(value, trueval[i], chkvallen) != 0) {
- continue;
- }
-
- if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \
- value[chkvallen] == ' ') {
- /* Declare a winner and set the next token. */
- *endptr = value + chkvallen;
- *dataval = 1;
- return(0);
- }
- }
-
- for (i = 0; i < (sizeof(falseval) / sizeof(*falseval)); i++) {
- chkvallen = strlen(falseval[i]);
-
- /*
- * Skip if there's no way we could find a match here.
- */
- if (chkvallen > vallen) {
- continue;
- }
-
- /*
- * Skip if there is no partial match.
- */
- if (strncasecmp(value, falseval[i], chkvallen) != 0) {
- continue;
- }
-
- if (value[chkvallen] == '\0' || value[chkvallen] == ',' || \
- value[chkvallen] == ' ') {
- /* Declare a winner and set the next token. */
- *endptr = value + chkvallen;
- *dataval = 0;
- return(0);
- }
- }
-
- lc_errno = LC_ERR_BADFORMAT;
- return(-1);
-}
-
-static unsigned long long lc_process_size(const char *value, const char **endptr) {
- unsigned long long retval = 0;
- char *mult = NULL;
-
- retval = strtoll(value, &mult, 10);
- if (mult != NULL) {
- switch (tolower(mult[0])) {
- case 'p':
- retval *= 1125899906842624LLU;
- break;
- case 't':
- retval *= 1958505086976LLU;
- break;
- case 'g':
- retval *= 1073741824;
- break;
- case 'm':
- retval *= 1048576;
- break;
- case 'k':
- retval *= 1024;
- break;
- default:
- break;
- }
- }
-
- return(retval);
-}
-
-static int lc_process_var_sizelonglong(void *data, const char *value, const char **endptr) {
- long long *dataval;
-
- dataval = data;
- *dataval = lc_process_size(value, endptr);
-
- return(0);
-}
-
-static int lc_process_var_sizelong(void *data, const char *value, const char **endptr) {
- long *dataval;
-
- dataval = data;
- *dataval = lc_process_size(value, endptr);
-
- return(0);
-}
-
-static int lc_process_var_sizeint(void *data, const char *value, const char **endptr) {
- int *dataval;
-
- dataval = data;
- *dataval = lc_process_size(value, endptr);
-
- return(0);
-}
-
-static int lc_process_var_sizeshort(void *data, const char *value, const char **endptr) {
- short *dataval;
-
- dataval = data;
- *dataval = lc_process_size(value, endptr);
-
- return(0);
-}
-
-static int lc_process_var_sizesizet(void *data, const char *value, const char **endptr) {
- size_t *dataval;
-
- dataval = data;
- *dataval = lc_process_size(value, endptr);
-
- return(0);
-}
-
-
-static int lc_handle_type(lc_var_type_t type, const char *value, void *data) {
- const char *next;
- int is_list;
-
- is_list = type & LC_VAR_LIST;
-
- if (is_list == LC_VAR_LIST) {
- }
-
- switch (type) {
- case LC_VAR_STRING:
- return(lc_process_var_string(data, value, &next));
- break;
- case LC_VAR_LONG_LONG:
- return(lc_process_var_longlong(data, value, &next));
- break;
- case LC_VAR_LONG:
- return(lc_process_var_long(data, value, &next));
- break;
- case LC_VAR_INT:
- return(lc_process_var_int(data, value, &next));
- break;
- case LC_VAR_SHORT:
- return(lc_process_var_short(data, value, &next));
- break;
- case LC_VAR_BOOL:
- return(lc_process_var_bool(data, value, &next));
- break;
- case LC_VAR_SIZE_LONG_LONG:
- return(lc_process_var_sizelonglong(data, value, &next));
- break;
- case LC_VAR_SIZE_LONG:
- return(lc_process_var_sizelong(data, value, &next));
- break;
- case LC_VAR_SIZE_INT:
- return(lc_process_var_sizeint(data, value, &next));
- break;
- case LC_VAR_SIZE_SHORT:
- return(lc_process_var_sizeshort(data, value, &next));
- break;
- case LC_VAR_BOOL_BY_EXISTANCE:
- return(lc_process_var_bool_byexistance(data, value, &next));
- break;
- case LC_VAR_SIZE_SIZE_T:
- return(lc_process_var_sizesizet(data, value, &next));
- break;
- case LC_VAR_IP:
- case LC_VAR_IP4:
- return(lc_process_var_ip4(data, value, &next));
- break;
- case LC_VAR_IP6:
- return(lc_process_var_ip6(data, value, &next));
- break;
- case LC_VAR_HOSTNAME4:
- return(lc_process_var_hostname4(data, value, &next));
- break;
- case LC_VAR_HOSTNAME6:
- return(lc_process_var_hostname6(data, value, &next));
- break;
- case LC_VAR_CIDR:
- return(lc_process_var_cidr(data, value, &next));
- break;
- case LC_VAR_TIME:
- case LC_VAR_DATE:
- case LC_VAR_FILENAME:
- case LC_VAR_DIRECTORY:
-#ifdef DEBUG
- fprintf(stderr, "Not implemented yet!\n");
-#endif
- return(-1);
- case LC_VAR_NONE:
- case LC_VAR_UNKNOWN:
- case LC_VAR_SECTION:
- case LC_VAR_SECTIONSTART:
- case LC_VAR_SECTIONEND:
- return(0);
- break;
- }
-
- return(-1);
-}
-
-static int lc_handle(struct lc_varhandler_st *handler, const char *var, const char *varargs, const char *value, lc_flags_t flags) {
- const char *localvar = NULL;
- int retval;
-
- if (var != NULL) {
- localvar = strrchr(var, '.');
- if (localvar == NULL) {
- localvar = var;
- } else {
- localvar++;
- }
- } else {
- localvar = NULL;
- }
-
- switch (handler->mode) {
- case LC_MODE_CALLBACK:
- if (handler->callback != NULL) {
- retval = handler->callback(localvar, var, varargs, value, flags, handler->extra);
- if (retval < 0) {
- lc_errno = LC_ERR_CALLBACK;
- }
- return(retval);
- }
- break;
- case LC_MODE_VAR:
- return(lc_handle_type(handler->type, value, handler->data));
- break;
- }
-
- return(-1);
-}
-
-static int lc_process_environment(const char *appname) {
-#ifndef ENABLE_SMALL
- struct lc_varhandler_st *handler = NULL;
- size_t appnamelen = 0;
- char varnamebuf[128] = {0};
- char **currvar;
- char *sep = NULL, *value = NULL, *cmd = NULL;
- char *ucase_appname = NULL, *ucase_appname_itr = NULL;
- char *lastcomponent_handler = NULL;
- int varnamelen = 0;
- char *local_lc_errfile;
- int local_lc_errline;
-
- /* Make sure we have an environment to screw with, if not,
- no arguments were found to be in error */
- if (environ == NULL || appname == NULL) {
- return(0);
- }
-
- local_lc_errfile = "<environment>";
- local_lc_errline = 0;
-
- /* Allocate and create our uppercase appname. */
- ucase_appname = strdup(appname);
- if (ucase_appname == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_ENOMEM;
- return(-1);
- }
- for (ucase_appname_itr = ucase_appname; *ucase_appname_itr != '\0'; ucase_appname_itr++) {
- *ucase_appname_itr = toupper(*ucase_appname_itr);
- }
-
- appnamelen = strlen(ucase_appname);
-
- for (currvar = environ; *currvar != NULL; currvar++) {
- /* If it doesn't begin with our appname ignore it completely. */
- if (strncmp(*currvar, ucase_appname, appnamelen) != 0) {
- continue;
- }
-
- /* Find our seperator. */
- sep = strchr(*currvar, '=');
- if (sep == NULL) {
- continue;
- }
-
- varnamelen = sep - *currvar;
-
- /* Skip variables that would overflow our buffer. */
- if (varnamelen >= sizeof(varnamebuf)) {
- continue;
- }
-
- strncpy(varnamebuf, *currvar, varnamelen);
-
- varnamebuf[varnamelen] = '\0';
- value = sep + 1;
-
- /* We ignore APPNAME by itself. */
- if (strlen(varnamebuf) <= appnamelen) {
- continue;
- }
-
- /* Further it must be <APPNAME>_ */
- if (varnamebuf[appnamelen] != '_') {
- continue;
- }
-
- cmd = varnamebuf + appnamelen + 1;
-
- /* We don't allow section specifiers, for reasons see notes in
- the cmdline processor (below). */
- if (strchr(cmd, '.') != NULL) {
- continue;
- }
-
- for (handler = varhandlers; handler != NULL; handler = handler->_next) {
- if (handler->var == NULL) {
- continue;
- }
-
- /* Skip handlers which don't agree with being
- processed outside a config file */
- if (handler->type == LC_VAR_SECTION ||
- handler->type == LC_VAR_SECTIONSTART ||
- handler->type == LC_VAR_SECTIONEND ||
- handler->type == LC_VAR_UNKNOWN) {
- continue;
- }
-
- /* Find the last part of the variable and compare it with
- the option being processed, if a wildcard is given. */
- if (handler->var[0] == '*' && handler->var[1] == '.') {
- lastcomponent_handler = strrchr(handler->var, '.');
- if (lastcomponent_handler == NULL) {
- lastcomponent_handler = handler->var;
- } else {
- lastcomponent_handler++;
- }
- } else {
- lastcomponent_handler = handler->var;
- }
-
- /* Ignore this handler if they don't match. */
- if (strcasecmp(lastcomponent_handler, cmd) != 0) {
- continue;
- }
-
- if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
- value = NULL;
- }
-
- /* We ignore errors from the environment variables,
- they're mostly insignificant. */
- lc_handle(handler, cmd, NULL, value, LC_FLAGS_ENVIRON);
-
- break;
- }
- }
-
- free(ucase_appname);
-
-#endif
- return(0);
-}
-
-static int lc_process_cmdline(int argc, char **argv) {
- struct lc_varhandler_st *handler = NULL;
- char *cmdarg = NULL, *cmdoptarg = NULL;
- char *lastcomponent_handler = NULL;
- char **newargv = NULL;
- char *usedargv = NULL;
- int cmdargidx = 0;
- int newargvidx = 0;
- int retval = 0, chkretval = 0;
- int ch = 0;
- char *local_lc_errfile;
- int local_lc_errline;
-
- local_lc_errfile = "<cmdline>";
- local_lc_errline = 0;
-
- /* Allocate "argc + 1" (+1 for the NULL terminator) elements. */
- newargv = malloc((argc + 1) * sizeof(*newargv));
- if (newargv == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_ENOMEM;
- return(-1);
- }
- newargv[newargvidx++] = argv[0];
- newargv[argc] = NULL;
-
- /* Allocate space to indicate which arguments have been used. */
- usedargv = malloc(argc * sizeof(*usedargv));
- if (usedargv == NULL) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_ENOMEM;
- free(newargv);
- return(-1);
- }
- for (cmdargidx = 0; cmdargidx < argc; cmdargidx++) {
- usedargv[cmdargidx] = 0;
- }
-
- for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
- cmdarg = argv[cmdargidx];
-
- /* Make sure we have an argument here. */
- if (cmdarg == NULL) {
- break;
- }
-
- /* If the argument isn't an option, skip. */
- if (cmdarg[0] != '-') {
- continue;
- }
-
- /* Setup a pointer in the new array for the actual argument. */
- newargv[newargvidx++] = cmdarg;
- usedargv[cmdargidx] = 1;
-
- /* Then shift the argument past the '-' so we can ignore it. */
- cmdarg++;
-
- /* Handle long options. */
- if (cmdarg[0] == '-') {
- cmdarg++;
-
- /* Don't process arguments after the '--' option. */
- if (cmdarg[0] == '\0') {
- break;
- }
-
- /* Look for a variable name that matches */
- for (handler = varhandlers; handler != NULL; handler = handler->_next) {
- /* Skip handlers with no variable name. */
- if (handler->var == NULL) {
- continue;
- }
- /* Skip handlers which don't agree with being
- processed on the command line. */
- if (handler->type == LC_VAR_SECTION ||
- handler->type == LC_VAR_SECTIONSTART ||
- handler->type == LC_VAR_SECTIONEND ||
- handler->type == LC_VAR_UNKNOWN) {
- continue;
- }
-
- /* Find the last part of the variable and compare it with
- the option being processed, if a wildcard is given. */
- if (handler->var[0] == '*' && handler->var[1] == '.') {
- lastcomponent_handler = strrchr(handler->var, '.');
- if (lastcomponent_handler == NULL) {
- lastcomponent_handler = handler->var;
- } else {
- lastcomponent_handler++;
- }
- } else {
- /* Disallow use of the fully qualified name
- since there was no sectionstart portion
- we cannot allow it to handle children of it. */
- if (strchr(cmdarg, '.') != NULL) {
- continue;
- }
- lastcomponent_handler = handler->var;
- }
-
- /* Ignore this handler if they don't match. */
- if (strcasecmp(lastcomponent_handler, cmdarg) != 0) {
- continue;
- }
-
- if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
- cmdoptarg = NULL;
- } else {
- cmdargidx++;
- if (cmdargidx >= argc) {
- fprintf(stderr, "Argument required.\n");
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_BADFORMAT;
- free(usedargv);
- free(newargv);
- return(-1);
- }
- cmdoptarg = argv[cmdargidx];
- newargv[newargvidx++] = cmdoptarg;
- usedargv[cmdargidx] = 1;
- }
-
- chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE);
- if (chkretval < 0) {
- retval = -1;
- }
-
- break;
- }
-
- if (handler == NULL) {
- fprintf(stderr, "Unknown option: --%s\n", cmdarg);
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVCMD;
- free(usedargv);
- free(newargv);
- return(-1);
- }
- } else {
- for (; *cmdarg != '\0'; cmdarg++) {
- ch = *cmdarg;
-
- for (handler = varhandlers; handler != NULL; handler = handler->_next) {
- if (handler->opt != ch || handler->opt == '\0') {
- continue;
- }
- /* Skip handlers which don't agree with being
- processed on the command line. */
- if (handler->type == LC_VAR_SECTION ||
- handler->type == LC_VAR_SECTIONSTART ||
- handler->type == LC_VAR_SECTIONEND ||
- handler->type == LC_VAR_UNKNOWN) {
- continue;
- }
-
- if (handler->type == LC_VAR_NONE || handler->type == LC_VAR_BOOL_BY_EXISTANCE) {
- cmdoptarg = NULL;
- } else {
- cmdargidx++;
- if (cmdargidx >= argc) {
- fprintf(stderr, "Argument required.\n");
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_BADFORMAT;
- free(usedargv);
- free(newargv);
- return(-1);
- }
- cmdoptarg = argv[cmdargidx];
- newargv[newargvidx++] = cmdoptarg;
- usedargv[cmdargidx] = 1;
- }
-
- chkretval = lc_handle(handler, handler->var, NULL, cmdoptarg, LC_FLAGS_CMDLINE);
- if (chkretval < 0) {
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- retval = -1;
- }
-
- break;
- }
-
- if (handler == NULL) {
- fprintf(stderr, "Unknown option: -%c\n", ch);
- lc_errfile = local_lc_errfile;
- lc_errline = local_lc_errline;
- lc_errno = LC_ERR_INVCMD;
- free(usedargv);
- free(newargv);
- return(-1);
- }
- }
- }
- }
-
- if (retval >= 0) {
- lc_optind = newargvidx;
- for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
- if (usedargv[cmdargidx] != 0) {
- continue;
- }
-
- cmdarg = argv[cmdargidx];
-
- newargv[newargvidx++] = cmdarg;
- }
- for (cmdargidx = 1; cmdargidx < argc; cmdargidx++) {
- argv[cmdargidx] = newargv[cmdargidx];
- }
- }
-
- free(usedargv);
- free(newargv);
-
- return(retval);
-}
-
-
-int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags) {
- struct lc_varhandler_st *handler = NULL;
- const char *lastcomponent_handler = NULL, *lastcomponent_var = NULL;
-
- lastcomponent_var = strrchr(var, '.');
- if (lastcomponent_var == NULL) {
- lastcomponent_var = var;
- } else {
- lastcomponent_var++;
- }
-
- for (handler = varhandlers; handler != NULL; handler = handler->_next) {
- /* If either handler->var or var is NULL, skip, unless both are NULL. */
- if (handler->var != var && (handler->var == NULL || var == NULL)) {
- continue;
- }
-
- /* If both are not-NULL, compare them. */
- if (handler->var != NULL) {
- /* Wild-card-ish match. */
- if (handler->var[0] == '*' && handler->var[1] == '.') {
- /* Only compare the last components */
-
- lastcomponent_handler = strrchr(handler->var, '.') + 1; /* strrchr() won't return NULL, because we already checked it. */
-
- if (strcasecmp(lastcomponent_handler, lastcomponent_var) != 0) {
- continue;
- }
- } else if (strcasecmp(handler->var, var) != 0) {
- /* Exact (case-insensitive comparison) failed. */
- continue;
- }
- }
-
- if (value == NULL &&
- handler->type != LC_VAR_NONE &&
- handler->type != LC_VAR_BOOL_BY_EXISTANCE &&
- handler->type != LC_VAR_SECTION &&
- handler->type != LC_VAR_SECTIONSTART &&
- handler->type != LC_VAR_SECTIONEND) {
- lc_errno = LC_ERR_BADFORMAT;
- break;
- }
-
- return(lc_handle(handler, var, varargs, value, flags));
- }
-
- return(-1);
-}
-
-int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *, const char *, const char *, lc_flags_t, void *), void *extra) {
- struct lc_varhandler_st *newhandler = NULL;
-
- newhandler = malloc(sizeof(*newhandler));
-
- if (newhandler == NULL) {
- return(-1);
- }
-
- if (var == NULL) {
- newhandler->var = NULL;
- } else {
- newhandler->var = strdup(var);
- }
- newhandler->mode = LC_MODE_CALLBACK;
- newhandler->type = type;
- newhandler->callback = callback;
- newhandler->opt = opt;
- newhandler->extra = extra;
- newhandler->_next = varhandlers;
-
- varhandlers = newhandler;
-
- return(0);
-}
-
-int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt) {
- struct lc_varhandler_st *newhandler = NULL;
-
- newhandler = malloc(sizeof(*newhandler));
-
- if (newhandler == NULL) {
- return(-1);
- }
-
- if (var == NULL) {
- newhandler->var = NULL;
- } else {
- newhandler->var = strdup(var);
- }
- newhandler->mode = LC_MODE_VAR;
- newhandler->type = type;
- newhandler->data = data;
- newhandler->opt = opt;
- newhandler->extra = NULL;
- newhandler->_next = varhandlers;
-
- varhandlers = newhandler;
-
- return(0);
-}
-
-int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type) {
- int chkretval = 0;
-
- switch (type) {
- case LC_CONF_SECTION:
- chkretval = lc_process_conf_section(appname, pathname);
- break;
- case LC_CONF_APACHE:
- chkretval = lc_process_conf_apache(appname, pathname);
- break;
- case LC_CONF_COLON:
- chkretval = lc_process_conf_colon(appname, pathname);
- break;
- case LC_CONF_EQUAL:
- chkretval = lc_process_conf_equal(appname, pathname);
- break;
- case LC_CONF_SPACE:
- chkretval = lc_process_conf_space(appname, pathname);
- break;
- case LC_CONF_XML:
- chkretval = lc_process_conf_xml(appname, pathname);
- break;
- default:
- chkretval = -1;
- lc_errno = LC_ERR_INVDATA;
- break;
- }
-
- return(chkretval);
-}
-
-static int lc_process_files(const char *appname, lc_conf_type_t type, const char *extraconfig) {
-#ifdef HAVE_GETPWUID
- struct passwd *pwinfo = NULL;
-#endif
- char configfiles[3][13][512] = {{{0}}};
- char *configfile = NULL;
- char *homedir = NULL;
- int configsetidx = 0, configidx = 0;
- int chkretval = 0, retval = 0;
-
- if (extraconfig != NULL) {
- snprintf(configfiles[0][0], sizeof(**configfiles) - 1, "%s", extraconfig);
- }
- snprintf(configfiles[1][0], sizeof(**configfiles) - 1, "/etc/%s.cfg", appname);
- snprintf(configfiles[1][1], sizeof(**configfiles) - 1, "/etc/%s.conf", appname);
- snprintf(configfiles[1][2], sizeof(**configfiles) - 1, "/etc/%s/%s.cfg", appname, appname);
- snprintf(configfiles[1][3], sizeof(**configfiles) - 1, "/etc/%s/%s.conf", appname, appname);
- snprintf(configfiles[1][4], sizeof(**configfiles) - 1, "/usr/etc/%s.cfg", appname);
- snprintf(configfiles[1][5], sizeof(**configfiles) - 1, "/usr/etc/%s.conf", appname);
- snprintf(configfiles[1][6], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.cfg", appname, appname);
- snprintf(configfiles[1][7], sizeof(**configfiles) - 1, "/usr/etc/%s/%s.conf", appname, appname);
- snprintf(configfiles[1][8], sizeof(**configfiles) - 1, "/usr/local/etc/%s.cfg", appname);
- snprintf(configfiles[1][9], sizeof(**configfiles) - 1, "/usr/local/etc/%s.conf", appname);
- snprintf(configfiles[1][10], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.cfg", appname, appname);
- snprintf(configfiles[1][11], sizeof(**configfiles) - 1, "/usr/local/etc/%s/%s.conf", appname, appname);
- if (getuid() != 0) {
- homedir = getenv("HOME");
-#ifdef HAVE_GETPWUID
- if (homedir == NULL) {
- pwinfo = getpwuid(getuid());
- if (pwinfo != NULL) {
- homedir = pwinfo->pw_dir;
- }
- }
-#endif
- if (homedir != NULL) {
- if (strcmp(homedir, "/") != 0 && access(homedir, R_OK|W_OK|X_OK) == 0) {
- snprintf(configfiles[2][0], sizeof(**configfiles) - 1, "%s/.%src", homedir, appname);
- snprintf(configfiles[2][1], sizeof(**configfiles) - 1, "%s/.%s.cfg", homedir, appname);
- snprintf(configfiles[2][2], sizeof(**configfiles) - 1, "%s/.%s.conf", homedir, appname);
- snprintf(configfiles[2][3], sizeof(**configfiles) - 1, "%s/.%s/%s.cfg", homedir, appname, appname);
- snprintf(configfiles[2][4], sizeof(**configfiles) - 1, "%s/.%s/%s.conf", homedir, appname, appname);
- snprintf(configfiles[2][5], sizeof(**configfiles) - 1, "%s/.%s/config", homedir, appname);
- }
- }
- }
-
- for (configsetidx = 0; configsetidx < 3; configsetidx++) {
- for (configidx = 0; configidx < 13; configidx++) {
- configfile = configfiles[configsetidx][configidx];
- if (configfile[0] == '\0') {
- break;
- }
- if (access(configfile, R_OK) == 0) {
- chkretval = lc_process_file(appname, configfile, type);
- if (chkretval < 0) {
- retval = -1;
- }
- break;
- }
- }
- }
-
- return(retval);
-}
-
-void lc_cleanup(void) {
- struct lc_varhandler_st *handler = NULL, *next = NULL;
-
- handler = varhandlers;
- while (handler != NULL) {
- if (handler->var != NULL) {
- free(handler->var);
- }
-
- next = handler->_next;
-
- free(handler);
-
- handler = next;
- }
-
- varhandlers = NULL;
-
- return;
-}
-
-int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra) {
- int retval = 0, chkretval = 0;
-
- /* Handle config files. */
- chkretval = lc_process_files(appname, type, extra);
- if (chkretval < 0) {
- retval = -1;
- }
-
- /* Handle environment variables.*/
- chkretval = lc_process_environment(appname);
- if (chkretval < 0) {
- retval = -1;
- }
-
- /* Handle command line arguments */
- chkretval = lc_process_cmdline(argc, argv);
- if (chkretval < 0) {
- retval = -1;
- }
-
- return(retval);
-}
-
-
-lc_err_t lc_geterrno(void) {
- lc_err_t retval;
-
- retval = lc_errno;
-
- lc_errno = LC_ERR_NONE;
-
- return(retval);
-}
-
-char *lc_geterrstr(void) {
- static char retval[512];
- char *errmsg = NULL;
-
- switch (lc_errno) {
- case LC_ERR_NONE:
- errmsg = "Success";
- break;
- case LC_ERR_INVCMD:
- errmsg = "Invalid command or option";
- break;
- case LC_ERR_INVSECTION:
- errmsg = "Invalid section";
- break;
- case LC_ERR_INVDATA:
- errmsg = "Invalid application data (internal error)";
- break;
- case LC_ERR_BADFORMAT:
- errmsg = "Bad data specified or incorrect format.";
- break;
- case LC_ERR_CANTOPEN:
- errmsg = "Can't open file.";
- break;
- case LC_ERR_CALLBACK:
- errmsg = "Error return from application handler.";
- break;
- case LC_ERR_ENOMEM:
- errmsg = "Insuffcient memory.";
- break;
- }
-
- /*
- * This is not part of the switch statement so we will get warnings
- * about unhandled enum values.
- */
- if (errmsg == NULL) {
- errmsg = "Unknown error";
- }
-
- if (lc_errfile == NULL) {
- snprintf(retval, sizeof(retval), "%s:%i: %s", "<no file>", lc_errline, errmsg);
- } else {
- snprintf(retval, sizeof(retval), "%s:%i: %s", lc_errfile, lc_errline, errmsg);
- }
-
- retval[sizeof(retval) - 1] = '\0';
-
- return(retval);
-}
diff --git a/src/libconfig/libconfig.h b/src/libconfig/libconfig.h
+++ /dev/null
@@ -1,84 +0,0 @@
-# ifndef _RSK_LIBCONFIG_H
-# define _RSK_LIBCONFIG_H
-# ifdef __cplusplus
-extern "C" {
-# endif
-
-# define LC_VAR_LIST 0x80
-
-typedef enum {
- LC_CONF_SECTION,
- LC_CONF_APACHE,
- LC_CONF_COLON,
- LC_CONF_EQUAL,
- LC_CONF_SPACE,
- LC_CONF_XML
-} lc_conf_type_t;
-
-typedef enum {
- LC_VAR_UNKNOWN,
- LC_VAR_NONE,
- LC_VAR_STRING,
- LC_VAR_LONG_LONG,
- LC_VAR_LONG,
- LC_VAR_INT,
- LC_VAR_SHORT,
- LC_VAR_BOOL,
- LC_VAR_FILENAME,
- LC_VAR_DIRECTORY,
- LC_VAR_SIZE_LONG_LONG,
- LC_VAR_SIZE_LONG,
- LC_VAR_SIZE_INT,
- LC_VAR_SIZE_SHORT,
- LC_VAR_TIME,
- LC_VAR_DATE,
- LC_VAR_SECTION,
- LC_VAR_SECTIONSTART,
- LC_VAR_SECTIONEND,
- LC_VAR_BOOL_BY_EXISTANCE,
- LC_VAR_SIZE_SIZE_T,
- LC_VAR_CIDR,
- LC_VAR_IP,
- LC_VAR_IP4,
- LC_VAR_IP6,
- LC_VAR_HOSTNAME4,
- LC_VAR_HOSTNAME6,
-} lc_var_type_t;
-
-typedef enum {
- LC_FLAGS_VAR,
- LC_FLAGS_CMDLINE,
- LC_FLAGS_ENVIRON,
- LC_FLAGS_SECTIONSTART,
- LC_FLAGS_SECTIONEND
-} lc_flags_t;
-
-typedef enum {
- LC_ERR_NONE,
- LC_ERR_INVCMD,
- LC_ERR_INVSECTION,
- LC_ERR_INVDATA,
- LC_ERR_BADFORMAT,
- LC_ERR_CANTOPEN,
- LC_ERR_CALLBACK,
- LC_ERR_ENOMEM
-} lc_err_t;
-
-int lc_process(int argc, char **argv, const char *appname, lc_conf_type_t type, const char *extra);
-int lc_register_callback(const char *var, char opt, lc_var_type_t type, int (*callback)(const char *, const char *, const char *, const char *, lc_flags_t, void *), void *extra);
-int lc_register_var(const char *var, lc_var_type_t type, void *data, char opt);
-lc_err_t lc_geterrno(void);
-char *lc_geterrstr(void);
-int lc_process_file(const char *appname, const char *pathname, lc_conf_type_t type);
-void lc_cleanup(void);
-
-# define LC_CBRET_IGNORESECTION (255)
-# define LC_CBRET_OKAY (0)
-# define LC_CBRET_ERROR (-1)
-
-extern int lc_optind;
-
-# ifdef __cplusplus
-}
-# endif
-# endif
diff --git a/src/libconfig/libconfig_private.h b/src/libconfig/libconfig_private.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef _RSK_LIBCONFIG_PRIVATE_H
-#define _RSK_LIBCONFIG_PRIVATE_H
-
-#include "libconfig.h"
-
-extern lc_err_t lc_errno;
-extern int lc_errline;
-extern const char *lc_errfile;
-
-int lc_process_var(const char *var, const char *varargs, const char *value, lc_flags_t flags);
-
-struct lc_varhandler_st;
-
-struct lc_varhandler_st {
- struct lc_varhandler_st *_next;
- char *var;
- char opt;
- lc_var_type_t type;
- enum {
- LC_MODE_CALLBACK,
- LC_MODE_VAR
- } mode;
- int (*callback)();
- void *data;
- void *extra;
-};
-
-#endif
diff --git a/src/libconfig/test-lc.c b/src/libconfig/test-lc.c
--- a/src/libconfig/test-lc.c
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "compat.h"
-#include "libconfig.h"
-
-int help_cmd(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) {
- printf("Usage info goes here\n");
- printf("\n");
-
- exit(EXIT_FAILURE);
-}
-int sally_cmd(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) {
- fprintf(stderr, "%s sets value: \"%s\" (flags=%i)\n", arg, val, flags);
- return(0);
-}
-
-int cmd_ifmodule(const char *partarg, const char *arg, const char *argarg, const char *val, lc_flags_t flags, void *extra) {
- if (flags == LC_FLAGS_SECTIONEND) {
- return(LC_CBRET_OKAY);
- }
- if (flags != LC_FLAGS_SECTIONSTART) {
- fprintf(stderr, "IfModule can only be used as a section.\n");
- return(LC_CBRET_ERROR);
- }
- if (argarg == NULL) {
- fprintf(stderr, "You must specify an argument to IfModule.\n");
- return(LC_CBRET_ERROR);
- }
-
- fprintf(stderr, "IfModule (%s)\n", argarg);
- return(LC_CBRET_IGNORESECTION);
-}
-
-int main(int argc, char **argv) {
- char *joeval = NULL;
- size_t xval = -1;
- int onoff = -1;
- int lcpret = -1;
- int i = 0;
- int onoff2 = 0;
- uint32_t ipaddr = 0;
-
- lc_register_var("Section", LC_VAR_SECTION, NULL, 0);
- lc_register_var("Somesection", LC_VAR_SECTION, NULL, 0);
- lc_register_var("Section.Test", LC_VAR_STRING, &joeval, 'j');
- lc_register_var("bob", LC_VAR_SIZE_SIZE_T, &xval, 's');
- lc_register_var("Somesection.Free", LC_VAR_BOOL, &onoff, 0);
- lc_register_var("long", LC_VAR_BOOL_BY_EXISTANCE, &onoff2, 'l');
- lc_register_var("ipaddr", LC_VAR_IP, &ipaddr, 'i');
- lc_register_callback("sally", 0, LC_VAR_STRING, sally_cmd, NULL);
- lc_register_callback("HELP", 'h', LC_VAR_NONE, help_cmd, NULL);
- lc_register_callback("*.ifmodule", 0, LC_VAR_NONE, cmd_ifmodule, NULL);
- lcpret = lc_process_file("testapp", "build/test.conf", LC_CONF_APACHE);
- if (lcpret < 0) {
- fprintf(stderr, "Error processing config file: %s\n", lc_geterrstr());
- return(EXIT_FAILURE);
- }
-
- lcpret = lc_process(argc, argv, "testapp", LC_CONF_APACHE, "test.cfg");
- if (lcpret < 0) {
- fprintf(stderr, "Error processing config file: %s\n", lc_geterrstr());
- return(EXIT_FAILURE);
- }
-
- lc_cleanup();
-
- if (joeval != NULL) {
- fprintf(stderr, "joeval = \"%s\"\n", joeval);
- } else {
- fprintf(stderr, "joeval = \"(null)\"\n");
- }
- fprintf(stderr, "xval = %llu\n", (unsigned long long) xval);
- fprintf(stderr, "onoff = %i\n", onoff);
- fprintf(stderr, "long = %i\n", onoff2);
- fprintf(stderr, "ip = %08lx\n", (unsigned long) ipaddr);
- for (i = lc_optind; i < argc; i++) {
- fprintf(stderr, "argv[%i] = \"%s\"\n", i, argv[i]);
- }
-
- return(0);
-}
diff --git a/src/libconfig/win32.h b/src/libconfig/win32.h
--- a/src/libconfig/win32.h
+++ /dev/null
@@ -1,44 +0,0 @@
-#if !defined(_LOCAL_WIN32_H) && defined(__WIN32__) && !defined(__CYGWIN__)
-#define _LOCAL_WIN32_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef __MINGW32__
- /* MingW32 specific stuff here. */
-# if defined(HAVE_WINSOCK2_H) && defined(HAVE_LIBWSOCK32)
- /* We have to override the detected configuration
- because it can't detect the network libraries. */
-# define HAVE_GETHOSTBYNAME 1
-# define HAVE_INET_ADDR 1
-# define HAVE_SOCKET 1
-# endif
-# define sleep(x) Sleep((x) * 1000)
-#else
- /* MSVC++ configuration follows */
-# undef HAVE_UNISTD_H
-# define HAVE_STDLIB_H 1
-# define HAVE_WINDOWS_H 1
-# define HAVE_STDARG_H 1
-# define HAVE_WINSVC_H 1
-# define HAVE_WINSOCK2_H 1
-# define HAVE_WINDOWSX_H 1
-#endif /* __MINGW32__ */
-
-#ifdef HAVE_WINDOWS_H
-# include <windows.h>
-#endif
-#ifdef HAVE_WINDOWSX_H
-# include <windowsx.h>
-#endif
-#ifdef HAVE_WINSOCK2_H
-# include <winsock2.h>
-#endif
-#ifdef HAVE_WINSVC_H
-# include <winsvc.h>
-#endif
-
-#define _USE_WIN32_ 1
-
-#endif /* _LOCAL_WIN32_H */
diff --git a/src/liboconfig/AUTHORS b/src/liboconfig/AUTHORS
diff --git a/src/liboconfig/COPYING b/src/liboconfig/COPYING
--- /dev/null
+++ b/src/liboconfig/COPYING
@@ -0,0 +1,340 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/src/liboconfig/ChangeLog b/src/liboconfig/ChangeLog
--- /dev/null
+++ b/src/liboconfig/ChangeLog
@@ -0,0 +1,5 @@
+2007-02-15, Version 0.1.1
+ * src/parser.y: Fixes a memory leak.
+
+2007-02-11, Version 0.1.0
+ * Initial release.
diff --git a/src/liboconfig/Makefile.am b/src/liboconfig/Makefile.am
--- /dev/null
@@ -0,0 +1,11 @@
+AUTOMAKE_OPTIONS = foreign no-dependencies
+
+BUILT_SOURCES = parser.h
+CLEANFILES = parser.[ch] scanner.c
+AM_YFLAGS = -d
+
+include_HEADERS = oconfig.h
+lib_LTLIBRARIES = liboconfig.la
+
+liboconfig_la_LDFLAGS = -version-info 0:0:0 $(LEXLIB)
+liboconfig_la_SOURCES = oconfig.c oconfig.h scanner.l parser.y
diff --git a/src/liboconfig/aux_types.h b/src/liboconfig/aux_types.h
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef AUX_TYPES_H
+#define AUX_TYPES_H 1
+
+struct statement_list_s
+{
+ oconfig_item_t *statement;
+ int statement_num;
+};
+typedef struct statement_list_s statement_list_t;
+
+struct argument_list_s
+{
+ oconfig_value_t *argument;
+ int argument_num;
+};
+typedef struct argument_list_s argument_list_t;
+
+#endif /* AUX_TYPES_H */
diff --git a/src/liboconfig/oconfig.c b/src/liboconfig/oconfig.c
--- /dev/null
+++ b/src/liboconfig/oconfig.c
@@ -0,0 +1,84 @@
+/**
+ * oconfig - src/oconfig.c
+ * Copyright (C) 2006,2007 Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "oconfig.h"
+
+/* Functions provided by the scanner */
+void yyset_in (FILE *);
+
+oconfig_item_t *ci_root;
+
+oconfig_item_t *oconfig_parse_fh (FILE *fh)
+{
+ int status;
+ oconfig_item_t *ret;
+
+ yyset_in (fh);
+
+ status = yyparse ();
+ if (status != 0)
+ {
+ fprintf (stderr, "yyparse returned error #%i\n", status);
+ return (NULL);
+ }
+
+ ret = ci_root;
+ ci_root = NULL;
+ yyset_in ((FILE *) 0);
+
+ return (ret);
+} /* oconfig_item_t *oconfig_parse_fh */
+
+oconfig_item_t *oconfig_parse_file (const char *file)
+{
+ FILE *fh;
+ oconfig_item_t *ret;
+
+ fh = fopen (file, "r");
+ if (fh == NULL)
+ {
+ fprintf (stderr, "fopen (%s) failed: %s\n", file, strerror (errno));
+ return (NULL);
+ }
+
+ ret = oconfig_parse_fh (fh);
+ fclose (fh);
+
+ return (ret);
+} /* oconfig_item_t *oconfig_parse_file */
+
+void oconfig_free (oconfig_item_t *ci)
+{
+ int i;
+
+ if (ci->values != NULL)
+ free (ci->values);
+
+ for (i = 0; i < ci->children_num; i++)
+ oconfig_free (ci->children + i);
+}
+
+/*
+ * vim:shiftwidth=2:tabstop=8:softtabstop=2
+ */
diff --git a/src/liboconfig/oconfig.h b/src/liboconfig/oconfig.h
--- /dev/null
+++ b/src/liboconfig/oconfig.h
@@ -0,0 +1,67 @@
+#ifndef OCONFIG_H
+#define OCONFIG_H 1
+
+#include <stdio.h>
+
+/**
+ * oconfig - src/oconfig.h
+ * Copyright (C) 2006,2007 Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * Types
+ */
+#define OCONFIG_TYPE_STRING 0
+#define OCONFIG_TYPE_NUMBER 1
+#define OCONFIG_TYPE_BOOLEAN 2
+
+struct oconfig_value_s
+{
+ union
+ {
+ char *string;
+ double number;
+ int boolean;
+ } value;
+ int type;
+};
+typedef struct oconfig_value_s oconfig_value_t;
+
+struct oconfig_item_s;
+typedef struct oconfig_item_s oconfig_item_t;
+struct oconfig_item_s
+{
+ char *key;
+ oconfig_value_t *values;
+ int values_num;
+
+ oconfig_item_t *parent;
+ oconfig_item_t *children;
+ int children_num;
+};
+
+/*
+ * Functions
+ */
+oconfig_item_t *oconfig_parse_fh (FILE *fh);
+oconfig_item_t *oconfig_parse_file (const char *file);
+
+void oconfig_free (oconfig_item_t *ci);
+
+/*
+ * vim: shiftwidth=2:tabstop=8:softtabstop=2
+ */
+#endif /* OCONFIG_H */
diff --git a/src/liboconfig/parser.y b/src/liboconfig/parser.y
--- /dev/null
+++ b/src/liboconfig/parser.y
@@ -0,0 +1,221 @@
+/**
+ * oconfig - src/parser.y
+ * Copyright (C) 2007 Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+%{
+#include <stdlib.h>
+#include <string.h>
+#include "oconfig.h"
+#include "aux_types.h"
+
+static char *unquote (const char *orig);
+static int yyerror (const char *s);
+
+/* Lexer variables */
+extern int yylineno;
+extern char *yytext;
+
+extern oconfig_item_t *ci_root;
+%}
+
+%start entire_file
+
+%union {
+ double number;
+ int boolean;
+ char *string;
+ oconfig_value_t cv;
+ oconfig_item_t ci;
+ argument_list_t al;
+ statement_list_t sl;
+}
+
+%token <number> NUMBER
+%token <boolean> TRUE FALSE
+%token <string> QUOTED_STRING UNQUOTED_STRING
+%token SLASH OPENBRAC CLOSEBRAC EOL
+
+%type <string> string
+%type <string> identifier
+/* arguments */
+%type <cv> argument
+%type <al> argument_list
+/* blocks */
+%type <ci> block_begin
+%type <ci> block
+%type <string> block_end
+/* statements */
+%type <ci> option
+%type <ci> statement
+%type <sl> statement_list
+%type <ci> entire_file
+
+%%
+string:
+ QUOTED_STRING {$$ = unquote ($1);}
+ | UNQUOTED_STRING {$$ = strdup ($1);}
+ ;
+
+argument:
+ NUMBER {$$.value.number = $1; $$.type = OCONFIG_TYPE_NUMBER;}
+ | TRUE {$$.value.boolean = 1; $$.type = OCONFIG_TYPE_BOOLEAN;}
+ | FALSE {$$.value.boolean = 0; $$.type = OCONFIG_TYPE_BOOLEAN;}
+ | string {$$.value.string = $1; $$.type = OCONFIG_TYPE_STRING;}
+ ;
+
+argument_list:
+ argument_list argument
+ {
+ $$ = $1;
+ $$.argument_num++;
+ $$.argument = realloc ($$.argument, $$.argument_num * sizeof (oconfig_value_t));
+ $$.argument[$$.argument_num-1] = $2;
+ }
+ | argument
+ {
+ $$.argument = malloc (sizeof (oconfig_value_t));
+ $$.argument[0] = $1;
+ $$.argument_num = 1;
+ }
+ ;
+
+identifier:
+ UNQUOTED_STRING {$$ = strdup ($1);}
+ ;
+
+option:
+ identifier argument_list EOL
+ {
+ memset (&$$, '\0', sizeof ($$));
+ $$.key = $1;
+ $$.values = $2.argument;
+ $$.values_num = $2.argument_num;
+ }
+ ;
+
+block_begin:
+ OPENBRAC identifier argument_list CLOSEBRAC EOL
+ {
+ memset (&$$, '\0', sizeof ($$));
+ $$.key = $2;
+ $$.values = $3.argument;
+ $$.values_num = $3.argument_num;
+ }
+ ;
+
+block_end:
+ OPENBRAC SLASH identifier CLOSEBRAC EOL
+ {
+ $$ = $3;
+ }
+ ;
+
+block:
+ block_begin statement_list block_end
+ {
+ if (strcmp ($1.key, $3) != 0)
+ {
+ printf ("block_begin = %s; block_end = %s;\n", $1.key, $3);
+ yyerror ("Block not closed..\n");
+ exit (1);
+ }
+ free ($3); $3 = NULL;
+ $$ = $1;
+ $$.children = $2.statement;
+ $$.children_num = $2.statement_num;
+ }
+ ;
+
+statement:
+ option {$$ = $1;}
+ | block {$$ = $1;}
+ | EOL {$$.values_num = 0;}
+ ;
+
+statement_list:
+ statement_list statement
+ {
+ $$ = $1;
+ if ($2.values_num > 0)
+ {
+ $$.statement_num++;
+ $$.statement = realloc ($$.statement, $$.statement_num * sizeof (oconfig_item_t));
+ $$.statement[$$.statement_num-1] = $2;
+ }
+ }
+ | statement
+ {
+ if ($1.values_num > 0)
+ {
+ $$.statement = malloc (sizeof (oconfig_item_t));
+ $$.statement[0] = $1;
+ $$.statement_num = 1;
+ }
+ else
+ {
+ $$.statement = NULL;
+ $$.statement_num = 0;
+ }
+ }
+ ;
+
+entire_file:
+ statement_list
+ {
+ ci_root = malloc (sizeof (oconfig_item_t));
+ memset (ci_root, '\0', sizeof (oconfig_item_t));
+ ci_root->children = $1.statement;
+ ci_root->children_num = $1.statement_num;
+ }
+ ;
+
+%%
+static int yyerror (const char *s)
+{
+ fprintf (stderr, "Error in line %i near `%s': %s\n", yylineno, yytext, s);
+ return (-1);
+} /* int yyerror */
+
+static char *unquote (const char *orig)
+{
+ char *ret = strdup (orig);
+ int len;
+ int i;
+
+ if (ret == NULL)
+ return (NULL);
+
+ len = strlen (ret);
+
+ if ((len < 2) || (ret[0] != '"') || (ret[len - 1] != '"'))
+ return (ret);
+
+ ret++;
+ len -= 2;
+ ret[len] = '\0';
+
+ for (i = 0; i < len; i++)
+ {
+ if (ret[i] == '\\')
+ {
+ memmove (ret + i, ret + (i + 1), len - i);
+ len--;
+ }
+ }
+
+ return (ret);
+} /* char *unquote */
diff --git a/src/liboconfig/scanner.l b/src/liboconfig/scanner.l
--- /dev/null
+++ b/src/liboconfig/scanner.l
@@ -0,0 +1,57 @@
+/**
+ * oconfig - src/scanner.l
+ * Copyright (C) 2007 Florian octo Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+%{
+#include <stdlib.h>
+#include "oconfig.h"
+#include "aux_types.h"
+#include "parser.h"
+%}
+WHITE_SPACE [\ \t\b]
+QUOTED_STRING \"([^\\"]+|\\.)*\"
+UNQUOTED_STRING [0-9A-Za-z_]+
+HEX_NUMBER 0[xX][0-9a-fA-F]+
+OCT_NUMBER 0[0-7]+
+DEC_NUMBER [\+\-]?[0-9]+
+FLOAT_NUMBER [\+\-]?[0-9]*\.[0-9]+([eE][\+\-][0-9]+)?
+NUMBER ({FLOAT_NUMBER}|{HEX_NUMBER}|{OCT_NUMBER}|{DEC_NUMBER})
+BOOL_TRUE (true|yes|on)
+BOOL_FALSE (false|no|off)
+COMMENT #.*
+PORT (6(5(5(3[0-5]|[0-2][0-9])|[0-4][0-9][0-9])|[0-4][0-9][0-9][0-9])|[1-5][0-9][0-9][0-9][0-9]|[1-9][0-9]?[0-9]?[0-9]?)
+IP_BYTE (2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])
+IPV4_ADDR {IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}\.{IP_BYTE}(:{PORT})?
+
+%%
+{WHITE_SPACE} |
+{COMMENT} {/* ignore */}
+
+\n {return (EOL);}
+"/" {return (SLASH);}
+"<" {return (OPENBRAC);}
+">" {return (CLOSEBRAC);}
+{BOOL_TRUE} {yylval.boolean = 1; return (TRUE);}
+{BOOL_FALSE} {yylval.boolean = 0; return (FALSE);}
+
+{IPV4_ADDR} {yylval.string = yytext; return (UNQUOTED_STRING);}
+
+{NUMBER} {yylval.number = strtod (yytext, NULL); return (NUMBER);}
+
+{QUOTED_STRING} {yylval.string = yytext; return (QUOTED_STRING);}
+{UNQUOTED_STRING} {yylval.string = yytext; return (UNQUOTED_STRING);}
+%%
diff --git a/src/load.c b/src/load.c
index 019f952c07066e7c753dbd193cc40d58ccab11d6..491a985e432c1752a504f9f953808741c93ad76a 100644 (file)
--- a/src/load.c
+++ b/src/load.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#endif
#endif /* defined(HAVE_GETLOADAVG) */
-static char *load_file = "load.rrd";
-
-static char *ds_def[] =
+static data_source_t dsrc[3] =
{
- "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
- "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
- "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100",
- NULL
+ {"shortterm", DS_TYPE_GAUGE, 0.0, 100.0},
+ {"midterm", DS_TYPE_GAUGE, 0.0, 100.0},
+ {"longterm", DS_TYPE_GAUGE, 0.0, 100.0}
};
-static int ds_num = 3;
-
-static void load_init (void)
-{
- return;
-}
-static void load_write (char *host, char *inst, char *val)
+static data_set_t ds =
{
- rrd_update_file (host, load_file, val, ds_def, ds_num);
-}
+ "load", 3, dsrc
+};
#if LOAD_HAVE_READ
-#define BUFSIZE 256
static void load_submit (double snum, double mnum, double lnum)
{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%.2f:%.2f:%.2f", (unsigned int) curtime,
- snum, mnum, lnum) >= BUFSIZE)
- return;
-
- plugin_submit (MODULE_NAME, "-", buf);
+ value_t values[3];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = snum;
+ values[1].gauge = mnum;
+ values[2].gauge = lnum;
+
+ vl.values = values;
+ vl.values_len = 3;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "load");
+ strcpy (vl.plugin_instance, "");
+ strcpy (vl.type_instance, "");
+
+ plugin_dispatch_values ("load", &vl);
}
-#undef BUFSIZE
-static void load_read (void)
+static int load_read (void)
{
#if defined(HAVE_GETLOADAVG)
double load[3];
load_submit (snum, mnum, lnum);
#endif /* HAVE_LIBSTATGRAB */
+
+ return (0);
}
-#else
-# define load_read NULL
#endif /* LOAD_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, load_init, load_read, load_write);
+ plugin_register_data_set (&ds);
+#if LOAD_HAVE_READ
+ plugin_register_read ("load", load_read);
+#endif
}
#undef MODULE_NAME
diff --git a/src/mbmon.c b/src/mbmon.c
index a9bf100c9f582480829bca9c747f9d14a7e15338..0d9cd163215b1fd63dffca298c9cbaa3235e8fd2 100644 (file)
--- a/src/mbmon.c
+++ b/src/mbmon.c
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "mbmon"
-
-#include <netdb.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
+#if HAVE_NETDB_H && HAVE_SYS_SOCKET_H && HAVE_NETINET_IN_H && HAVE_NETINET_TCP_H
+# include <netdb.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <netinet/tcp.h>
+# define MBMON_HAVE_READ 1
+#else
+# define MBMON_HAVE_READ 0
+#endif
#define MBMON_DEF_HOST "127.0.0.1"
#define MBMON_DEF_PORT "411" /* the default for Debian */
-/* BUFFER_SIZE
- Size of the buffer we use to receive from the mbmon daemon. */
-#define BUFFER_SIZE 1024
+static data_source_t data_source_fanspeed[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-static char *filename_temperature = "mbmon/temperature-%s.rrd";
-static char *filename_fanspeed = "mbmon/fanspeed-%s.rrd";
-static char *filename_voltage = "mbmon/voltage-%s.rrd";
+static data_set_t fanspeed_ds =
+{
+ "fanspeed", 1, data_source_fanspeed
+};
-/* temperature and fan sensors */
-static char *ds_def[] =
+static data_source_t data_source_temperature[1] =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
};
-static int ds_num = 1;
-/* voltage sensors */
-static char *voltage_ds_def[] =
+static data_set_t temperature_ds =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "temperature", 1, data_source_temperature
+};
+
+static data_source_t data_source_voltage[1] =
+{
+ {"voltage", DS_TYPE_GAUGE, NAN, NAN}
};
-static int voltage_ds_num = 1;
-static char *config_keys[] =
+static data_set_t voltage_ds =
+{
+ "voltage", 1, data_source_voltage
+};
+
+static const char *config_keys[] =
{
"Host",
"Port",
};
static int config_keys_num = 2;
+#if MBMON_HAVE_READ
static char *mbmon_host = NULL;
static char *mbmon_port = NULL;
return (0);
}
-static int mbmon_config (char *key, char *value)
+static int mbmon_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
return (0);
}
-static void mbmon_init (void)
-{
- return;
-}
-
-static void mbmon_write_temperature (char *host, char *inst, char *val)
-{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_temperature, inst);
- if ((status < 1) || (status >= BUFFER_SIZE))
- return;
-
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
-
-static void mbmon_write_fanspeed (char *host, char *inst, char *val)
-{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_fanspeed, inst);
- if ((status < 1) || (status >= BUFFER_SIZE))
- return;
-
- rrd_update_file (host, filename, val, ds_def, ds_num);
-}
-
-static void mbmon_write_voltage (char *host, char *inst, char *val)
+static void mbmon_submit (const char *type, const char *type_instance,
+ double value)
{
- char filename[BUFFER_SIZE];
- int status;
-
- /* construct filename */
- status = snprintf (filename, BUFFER_SIZE, filename_voltage, inst);
- if ((status < 1) || (status >= BUFFER_SIZE))
- return;
-
- rrd_update_file (host, filename, val, voltage_ds_def, voltage_ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void mbmon_submit (char *type, char *inst, double value)
-{
- char buf[BUFFER_SIZE];
+ values[0].gauge = value;
- if (snprintf (buf, BUFFER_SIZE, "%u:%.3f", (unsigned int) curtime, value)
- >= BUFFER_SIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mbmon");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit (type, inst, buf);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void mbmon_submit */
/* Trim trailing whitespace from a string. */
static void trim_spaces (char *s)
s[l] = '\0';
}
-static void mbmon_read (void)
+static int mbmon_read (void)
{
- char buf[BUFFER_SIZE];
+ char buf[1024];
char *s, *t;
- static int wait_time = 1;
- static int wait_left = 0;
-
- if (wait_left >= 10)
- {
- wait_left -= 10;
- return;
- }
-
/* get data from daemon */
- if (mbmon_query_daemon (buf, BUFFER_SIZE) < 0)
- {
- /* This limit is reached in log2(86400) =~ 17 steps. Since
- * there is a 2^n seconds wait between each step it will need
- * roughly one day to reach this limit. -octo */
-
- wait_time *= 2;
- if (wait_time > 86400)
- wait_time = 86400;
-
- wait_left = wait_time;
-
- return;
- }
- else
- {
- wait_time = 1;
- wait_left = 0;
- }
+ if (mbmon_query_daemon (buf, sizeof (buf)) < 0)
+ return (-1);
s = buf;
while ((t = strchr (s, ':')) != NULL)
if (strncmp (s, "TEMP", 4) == 0)
{
inst = s + 4;
- type = "mbmon_temperature";
+ type = "temperature";
}
else if (strncmp (s, "FAN", 3) == 0)
{
inst = s + 3;
- type = "mbmon_fanspeed";
+ type = "fanspeed";
}
else if (strncmp (s, "V", 1) == 0)
{
inst = s + 1;
- type = "mbmon_voltage";
+ type = "voltage";
}
else
{
s = nextc + 1;
}
+
+ return (0);
} /* void mbmon_read */
+#endif /* MBMON_HAVE_READ */
/* module_register
Register collectd plugin. */
void module_register (void)
{
- plugin_register (MODULE_NAME, mbmon_init, mbmon_read, NULL);
- plugin_register ("mbmon_temperature", NULL, NULL, mbmon_write_temperature);
- plugin_register ("mbmon_fanspeed", NULL, NULL, mbmon_write_fanspeed);
- plugin_register ("mbmon_voltage", NULL, NULL, mbmon_write_voltage);
- cf_register (MODULE_NAME, mbmon_config, config_keys, config_keys_num);
+ plugin_register_data_set (&fanspeed_ds);
+ plugin_register_data_set (&temperature_ds);
+ plugin_register_data_set (&voltage_ds);
+
+#if MBMON_HAVE_READ
+ plugin_register_config ("mbmon", mbmon_config, config_keys, config_keys_num);
+ plugin_register_read ("mbmon", mbmon_read);
+#endif /* MBMON_HAVE_READ */
}
-
-#undef MODULE_NAME
diff --git a/src/memory.c b/src/memory.c
index b8b7229f6de74db7f6a2161370c58f08934ff28b..d92ecf30550dd56097c41f9d0108f3b3b18193d6 100644 (file)
--- a/src/memory.c
+++ b/src/memory.c
/**
* collectd - src/memory.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
# define MEMORY_HAVE_READ 0
#endif
-#define MODULE_NAME "memory"
-
-static char *memory_file = "memory.rrd";
+/* 2^48 = 281474976710656 */
+static data_source_t dsrc[4] =
+{
+ {"used", DS_TYPE_GAUGE, 0, 281474976710656.0},
+ {"free", DS_TYPE_GAUGE, 0, 281474976710656.0},
+ {"buffers", DS_TYPE_GAUGE, 0, 281474976710656.0},
+ {"cached", DS_TYPE_GAUGE, 0, 281474976710656.0}
+};
-/* 9223372036854775807 == LLONG_MAX */
-static char *ds_def[] =
+static data_set_t ds =
{
- "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:buffers:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- NULL
+ "memory", 4, dsrc
};
-static int ds_num = 4;
/* vm_statistics_data_t */
#if defined(HOST_VM_INFO)
static kstat_t *ksp;
#endif /* HAVE_LIBKSTAT */
-static void memory_init (void)
+#if MEMORY_HAVE_READ
+static int memory_init (void)
{
#if defined(HOST_VM_INFO)
port_host = mach_host_self ();
ksp = NULL;
#endif /* HAVE_LIBKSTAT */
- return;
-}
-
-static void memory_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, memory_file, val, ds_def, ds_num);
-}
+ return (0);
+} /* int memory_init */
-#if MEMORY_HAVE_READ
-#define BUFSIZE 512
static void memory_submit (long long mem_used, long long mem_buffered,
long long mem_cached, long long mem_free)
{
- char buf[BUFSIZE];
+ value_t values[4];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = mem_used;
+ values[1].gauge = mem_free;
+ values[2].gauge = mem_buffered;
+ values[3].gauge = mem_cached;
- if (snprintf (buf, BUFSIZE, "%u:%lli:%lli:%lli:%lli",
- (unsigned int) curtime, mem_used, mem_free,
- mem_buffered, mem_cached) >= BUFSIZE)
- return;
+ vl.values = values;
+ vl.values_len = 4;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "memory");
- plugin_submit (MODULE_NAME, "-", buf);
+ plugin_dispatch_values ("memory", &vl);
}
-#undef BUFSIZE
-static void memory_read (void)
+static int memory_read (void)
{
#if defined(HOST_VM_INFO)
kern_return_t status;
long long free;
if (!port_host || !pagesize)
- return;
+ return (-1);
vm_data_len = sizeof (vm_data) / sizeof (natural_t);
if ((status = host_statistics (port_host, HOST_VM_INFO,
&vm_data_len)) != KERN_SUCCESS)
{
syslog (LOG_ERR, "memory-plugin: host_statistics failed and returned the value %i", (int) status);
- return;
+ return (-1);
}
/*
{
syslog (LOG_ERR, "memory plugin: sysctlbyname (%s): %s",
sysctl_keys[i], strerror (errno));
- return;
+ return (-1);
}
DBG ("%26s: %6i", sysctl_keys[i], sysctl_vals[i]);
} /* for i */
if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
{
syslog (LOG_WARNING, "memory: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
while (fgets (buffer, 1024, fh) != NULL)
long long mem_lock;
if (ksp == NULL)
- return;
+ return (-1);
mem_used = get_kstat_value (ksp, "pagestotal");
mem_free = get_kstat_value (ksp, "pagesfree");
mem_lock = get_kstat_value (ksp, "pageslocked");
if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
- return;
+ return (-1);
if (mem_used < (mem_free + mem_lock))
- return;
+ return (-1);
mem_used -= mem_free + mem_lock;
mem_used *= pagesize; /* If this overflows you have some serious */
if ((ios = sg_get_mem_stats ()) != NULL)
memory_submit (ios->used, 0LL, ios->cache, ios->free);
#endif /* HAVE_LIBSTATGRAB */
+
+ return (0);
}
-#else
-# define memory_read NULL
#endif /* MEMORY_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, memory_init, memory_read, memory_write);
-}
+ plugin_register_data_set (&ds);
-#undef MODULE_NAME
+#if MEMORY_HAVE_READ
+ plugin_register_init ("memory", memory_init);
+ plugin_register_read ("memory", memory_read);
+#endif /* MEMORY_HAVE_READ */
+}
diff --git a/src/multimeter.c b/src/multimeter.c
index 46438bf37beb6566207aede99b388fb2bce7d8d2..d1cf1903e8f64d5ae5c3af9af202f1178c6b429c 100644 (file)
--- a/src/multimeter.c
+++ b/src/multimeter.c
* Peter Holik <peter at holik.at>
*
* Used multimeter: Metex M-4650CR
- *
**/
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <math.h>
#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "multimeter"
-
-static char *multimeter_file = "multimeter.rrd";
+#if HAVE_TERMIOS_H && HAVE_SYS_IOCTL_H && HAVE_MATH_H
+# include <termios.h>
+# include <sys/ioctl.h>
+# include <math.h>
+# define MULTIMETER_HAVE_READ 1
+#else
+# define MULTIMETER_HAVE_READ 0
+# error "multimeter cannot read!"
+#endif
+
+static data_source_t data_source[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
-static char *ds_def[] =
+static data_set_t data_set =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "multimeter", 1, data_source
};
-static int ds_num = 1;
+#if MULTIMETER_HAVE_READ
static int fd = -1;
static int multimeter_timeval_sub (struct timeval *tv1, struct timeval *tv2,
if (gettimeofday (&time_end, NULL) < 0)
{
- syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
+ syslog (LOG_ERR, "multimeter plugin: gettimeofday failed: %s",
strerror (errno));
return (-1);
}
if (gettimeofday (&time_now, NULL) < 0)
{
- syslog (LOG_ERR, MODULE_NAME": gettimeofday failed: %s",
- strerror (errno));
+ syslog (LOG_ERR, "multimeter plugin: "
+ "gettimeofday failed: %s",
+ strerror (errno));
return (-1);
}
if (multimeter_timeval_sub (&time_end, &time_now, &timeout) == -1)
}
else /* status == -1 */
{
- syslog (LOG_ERR, MODULE_NAME": select failed: %s",
- strerror (errno));
+ syslog (LOG_ERR, "multimeter plugin: "
+ "select failed: %s",
+ strerror (errno));
break;
}
}
} while (--retry);
return (-2); /* no value received */
-}
+} /* int multimeter_read_value */
-static void multimeter_init (void)
+static int multimeter_init (void)
{
int i;
char device[] = "/dev/ttyS ";
tcsetattr(fd, TCSANOW, &tios);
ioctl(fd, TIOCMBIC, &rts);
- if (multimeter_read_value(&value) < -1)
+ if (multimeter_read_value (&value) < -1)
{
- close(fd);
+ close (fd);
fd = -1;
}
else
{
- syslog (LOG_INFO, MODULE_NAME" found (%s)", device);
- return;
+ syslog (LOG_INFO, "multimeter plugin: Device "
+ "found at %s", device);
+ return (0);
}
}
}
- syslog (LOG_ERR, MODULE_NAME" not found");
+
+ syslog (LOG_ERR, "multimeter plugin: No device found");
+ return (-1);
}
#undef LINE_LENGTH
-static void multimeter_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, multimeter_file, val, ds_def, ds_num);
-}
-#define BUFSIZE 128
-static void multimeter_submit (double *value)
+static void multimeter_submit (double value)
{
- char buf[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, *value) >= BUFSIZE)
- return;
+ values[0].gauge = value;
- plugin_submit (MODULE_NAME, "-", buf);
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "multimeter");
+
+ plugin_dispatch_values ("multimeter", &vl);
}
-#undef BUFSIZE
-static void multimeter_read (void)
+static int multimeter_read (void)
{
double value;
- if (fd > -1 && !(multimeter_read_value(&value)))
- multimeter_submit (&value);
+ if (fd < 0)
+ return (-1);
+
+ if (multimeter_read_value (&value) != 0)
+ return (-1);
+
+ multimeter_submit (value);
+ return (0);
+} /* int multimeter_read */
+
+static int multimeter_shutdown (void)
+{
+ if (fd >= 0)
+ {
+ close (fd);
+ fd = -1;
+ }
+
+ return (0);
}
+#endif /* MULTIMETER_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, multimeter_init, multimeter_read, multimeter_write);
-}
+ plugin_register_data_set (&data_set);
-#undef MODULE_NAME
+#if MULTIMETER_HAVE_READ
+ plugin_register_init ("multimeter", multimeter_init);
+ plugin_register_read ("multimeter", multimeter_read);
+ plugin_register_shutdown ("multimeter", multimeter_shutdown);
+#endif /* MULTIMETER_HAVE_READ */
+}
diff --git a/src/mysql.c b/src/mysql.c
index caebdf31f3d0f3e1156398cc9768863f4b4738d5..a928172b51126abbb64cb093ca8bd90a171b5f6a 100644 (file)
--- a/src/mysql.c
+++ b/src/mysql.c
/**
* collectd - src/mysql.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include <mysql/mysql.h>
#endif
-#define MODULE_NAME "mysql"
-
#if COLLECT_LIBMYSQL
# define MYSQL_HAVE_READ 1
#else
# define MYSQL_HAVE_READ 0
#endif
-#define BUFSIZE 512
+/* TODO: Understand `Select_*' and possibly do that stuff as well.. */
-static char *host = "localhost";
-static char *user;
-static char *pass;
-static char *db = NULL;
+static data_source_t data_source_counter[1] =
+{
+ {"value", DS_TYPE_COUNTER, 0, NAN}
+};
-/* TODO
- * understand `Select_*' and possibly do that stuff as well..
- */
+static data_set_t ds_commands =
+{
+ "mysql_commands", 1, data_source_counter
+};
-static char *commands_file = "mysql/mysql_commands-%s.rrd";
-static char *handler_file = "mysql/mysql_handler-%s.rrd";
-static char *qcache_file = "mysql/mysql_qcache.rrd";
-static char *threads_file = "mysql/mysql_threads.rrd";
-static char *traffic_file = "traffic-mysql.rrd";
+static data_set_t ds_handler =
+{
+ "mysql_handler", 1, data_source_counter
+};
-static char *commands_ds_def[] =
+static data_source_t data_source_qcache[5] =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"hits", DS_TYPE_COUNTER, 0, NAN},
+ {"inserts", DS_TYPE_COUNTER, 0, NAN},
+ {"not_cached", DS_TYPE_COUNTER, 0, NAN},
+ {"lowmem_prunes", DS_TYPE_COUNTER, 0, NAN},
+ {"queries_in_cache", DS_TYPE_GAUGE, 0, NAN}
};
-static int commands_ds_num = 1;
-static char *handler_ds_def[] =
+static data_set_t ds_qcache =
{
- "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "mysql_qcache", 5, data_source_qcache
};
-static int handler_ds_num = 1;
-static char *qcache_ds_def[] =
+static data_source_t data_source_threads[4] =
{
- "DS:hits:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:inserts:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:not_cached:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:lowmem_prunes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:queries_in_cache:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"running", DS_TYPE_GAUGE, 0, NAN},
+ {"connected", DS_TYPE_GAUGE, 0, NAN},
+ {"cached", DS_TYPE_GAUGE, 0, NAN},
+ {"created", DS_TYPE_COUNTER, 0, NAN}
};
-static int qcache_ds_num = 5;
-static char *threads_ds_def[] =
+static data_set_t ds_threads =
{
- "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:connected:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:created:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "mysql_threads", 4, data_source_threads
};
-static int threads_ds_num = 4;
-static char *traffic_ds_def[] =
+static data_source_t data_source_octets[2] =
{
- "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int traffic_ds_num = 2;
-static char *config_keys[] =
+static data_set_t ds_octets =
+{
+ "mysql_octets", 2, data_source_octets
+};
+
+#if MYSQL_HAVE_READ
+static const char *config_keys[] =
{
"Host",
"User",
};
static int config_keys_num = 4;
-#if MYSQL_HAVE_READ
+static char *host = "localhost";
+static char *user;
+static char *pass;
+static char *db = NULL;
+
static MYSQL *getconnection (void)
{
static MYSQL *con;
return (con);
}
} /* static MYSQL *getconnection (void) */
-#endif /* MYSQL_HAVE_READ */
-
-static void init (void)
-{
- return;
-}
-static int config (char *key, char *value)
+static int config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
return ((host = strdup (value)) == NULL ? 1 : 0);
return (-1);
}
-static void commands_write (char *host, char *inst, char *val)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, commands_file, inst) >= BUFSIZE)
- return;
-
- rrd_update_file (host, buf, val, commands_ds_def, commands_ds_num);
-}
-
-static void handler_write (char *host, char *inst, char *val)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, handler_file, inst) >= BUFSIZE)
- return;
-
- rrd_update_file (host, buf, val, handler_ds_def, handler_ds_num);
-}
-
-static void qcache_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, qcache_file, val,
- qcache_ds_def, qcache_ds_num);
-}
-
-static void threads_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, threads_file, val,
- threads_ds_def, threads_ds_num);
-}
-
-static void traffic_write (char *host, char *inst, char *val)
+static void counter_submit (const char *type, const char *type_instance,
+ counter_t value)
{
- rrd_update_file (host, traffic_file, val,
- traffic_ds_def, traffic_ds_num);
-}
-
-#if MYSQL_HAVE_READ
-static void commands_submit (char *inst, unsigned long long value)
-{
- char buf[BUFSIZE];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, value);
+ values[0].counter = value;
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit ("mysql_commands", inst, buf);
-}
+ plugin_dispatch_values (type, &vl);
+} /* void counter_submit */
-static void handler_submit (char *inst, unsigned long long value)
+static void qcache_submit (counter_t hits, counter_t inserts,
+ counter_t not_cached, counter_t lowmem_prunes,
+ gauge_t queries_in_cache)
{
- char buf[BUFSIZE];
- int status;
-
- status = snprintf (buf, BUFSIZE, "%u:%llu", (unsigned int) curtime, value);
-
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
-
- plugin_submit ("mysql_handler", inst, buf);
-}
-
-static void qcache_submit (unsigned long long hits, unsigned long long inserts,
- unsigned long long not_cached, unsigned long long lowmem_prunes,
- int queries_in_cache)
-{
- char buf[BUFSIZE];
- int status;
-
- status = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%i",
- (unsigned int) curtime, hits, inserts, not_cached,
- lowmem_prunes, queries_in_cache);
-
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
-
- plugin_submit ("mysql_qcache", "-", buf);
-}
-
-static void threads_submit (int running, int connected, int cached,
- unsigned long long created)
+ value_t values[5];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].counter = hits;
+ values[1].counter = inserts;
+ values[2].counter = not_cached;
+ values[3].counter = lowmem_prunes;
+ values[4].gauge = queries_in_cache;
+
+ vl.values = values;
+ vl.values_len = 5;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
+
+ plugin_dispatch_values ("mysql_qcache", &vl);
+} /* void qcache_submit */
+
+static void threads_submit (gauge_t running, gauge_t connected, gauge_t cached,
+ counter_t created)
{
- char buf[BUFSIZE];
- int status;
+ value_t values[4];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%llu",
- (unsigned int) curtime,
- running, connected, cached, created);
+ values[0].gauge = running;
+ values[1].gauge = connected;
+ values[2].gauge = cached;
+ values[3].counter = created;
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
+ vl.values = values;
+ vl.values_len = 4;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
- plugin_submit ("mysql_threads", "-", buf);
-}
+ plugin_dispatch_values ("mysql_threads", &vl);
+} /* void threads_submit */
-static void traffic_submit (unsigned long long incoming,
- unsigned long long outgoing)
+static void traffic_submit (counter_t rx, counter_t tx)
{
- char buf[BUFSIZE];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
- incoming, outgoing);
+ values[0].counter = rx;
+ values[1].counter = tx;
- if (status < 0)
- {
- syslog (LOG_ERR, "snprintf failed");
- return;
- }
- else if (status >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf was truncated");
- return;
- }
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "mysql");
- plugin_submit ("mysql_traffic", "-", buf);
-}
+ plugin_dispatch_values ("mysql_octets", &vl);
+} /* void traffic_submit */
-static void mysql_read (void)
+static int mysql_read (void)
{
MYSQL *con;
MYSQL_RES *res;
/* An error message will have been printed in this case */
if ((con = getconnection ()) == NULL)
- return;
+ return (-1);
query = "SHOW STATUS";
if (mysql_get_server_version (con) >= 50002)
{
syslog (LOG_ERR, "mysql_real_query failed: %s\n",
mysql_error (con));
- return;
+ return (-1);
}
if ((res = mysql_store_result (con)) == NULL)
{
syslog (LOG_ERR, "mysql_store_result failed: %s\n",
mysql_error (con));
- return;
+ return (-1);
}
field_num = mysql_num_fields (res);
/* Ignore `prepared statements' */
if (strncmp (key, "Com_stmt_", 9) != 0)
- commands_submit (key + 4, val);
+ counter_submit ("mysql_commands", key + 4, val);
}
else if (strncmp (key, "Handler_", 8) == 0)
{
if (val == 0ULL)
continue;
- handler_submit (key + 8, val);
+ counter_submit ("mysql_handler", key + 8, val);
}
else if (strncmp (key, "Qcache_", 7) == 0)
{
/* mysql_close (con); */
- return;
-}
-#else
-# define mysql_read NULL
+ return (0);
+} /* int mysql_read */
#endif /* MYSQL_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, init, mysql_read, NULL);
- plugin_register ("mysql_commands", NULL, NULL, commands_write);
- plugin_register ("mysql_handler", NULL, NULL, handler_write);
- plugin_register ("mysql_qcache", NULL, NULL, qcache_write);
- plugin_register ("mysql_threads", NULL, NULL, threads_write);
- plugin_register ("mysql_traffic", NULL, NULL, traffic_write);
- cf_register (MODULE_NAME, config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&ds_commands);
+ plugin_register_data_set (&ds_handler);
+ plugin_register_data_set (&ds_qcache);
+ plugin_register_data_set (&ds_threads);
+ plugin_register_data_set (&ds_octets);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if MYSQL_HAVE_READ
+ plugin_register_config ("mysql", config, config_keys, config_keys_num);
+ plugin_register_read ("mysql", mysql_read);
+#endif /* MYSQL_HAVE_READ */
+} /* void module_register */
diff --git a/src/network.c b/src/network.c
index e9ba84bb4210037f0cae97a6612c3fe0ef319bb6..cf2a01799cbb1723c710357be176810aac053fb6 100644 (file)
--- a/src/network.c
+++ b/src/network.c
/**
* collectd - src/network.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* Florian octo Forster <octo at verplant.org>
**/
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <syslog.h>
-#include <errno.h>
-
-#include "network.h"
+#include "collectd.h"
+#include "plugin.h"
#include "common.h"
#include "configfile.h"
#include "utils_debug.h"
+#include "network.h"
+
+#if HAVE_PTHREAD_H
+# include <pthread.h>
+#endif
+#if HAVE_SYS_SOCKET_H
+# include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#if HAVE_POLL_H
+# include <poll.h>
+#endif
+
/* 1500 - 40 - 8 = Ethernet packet - IPv6 header - UDP header */
/* #define BUFF_SIZE 1452 */
# endif
#endif /* !IP_ADD_MEMBERSHIP */
-#define BUFF_SIZE 4096
-
-extern int operating_mode;
+#define BUFF_SIZE 1024
+/*
+ * Private data types
+ */
typedef struct sockent
{
int fd;
- int mode;
struct sockaddr_storage *addr;
socklen_t addrlen;
struct sockent *next;
} sockent_t;
-static sockent_t *socklist_head = NULL;
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------+-----------------------+-------------------------------+
+ * ! Ver. ! ! Length !
+ * +-------+-----------------------+-------------------------------+
+ */
+struct part_header_s
+{
+ uint16_t type;
+ uint16_t length;
+};
+typedef struct part_header_s part_header_t;
+
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type ! Length !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4) Bytes :
+ * +---------------------------------------------------------------+
+ */
+struct part_string_s
+{
+ part_header_t *head;
+ char *value;
+};
+typedef struct part_string_s part_string_t;
+
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type ! Length !
+ * +-------------------------------+-------------------------------+
+ * : (Length - 4 == 2 || 4 || 8) Bytes :
+ * +---------------------------------------------------------------+
+ */
+struct part_number_s
+{
+ part_header_t *head;
+ uint64_t *value;
+};
+typedef struct part_number_s part_number_t;
+
+/* 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-------------------------------+-------------------------------+
+ * ! Type ! Length !
+ * +-------------------------------+---------------+---------------+
+ * ! Num of values ! Type0 ! Type1 !
+ * +-------------------------------+---------------+---------------+
+ * ! Value0 !
+ * ! !
+ * +---------------------------------------------------------------+
+ * ! Value1 !
+ * ! !
+ * +---------------------------------------------------------------+
+ */
+struct part_values_s
+{
+ part_header_t *head;
+ uint16_t *num_values;
+ uint8_t *values_types;
+ value_t *values;
+};
+typedef struct part_values_s part_values_t;
+
+/*
+ * Private variables
+ */
+static const char *config_keys[] =
+{
+ "Listen",
+ "Server",
+ "TimeToLive",
+ NULL
+};
+static int config_keys_num = 3;
+
+static int network_config_ttl = 0;
+
+static sockent_t *sending_sockets = NULL;
+
+static struct pollfd *listen_sockets = NULL;
+static int listen_sockets_num = 0;
+static pthread_t listen_thread = 0;
+static int listen_loop = 0;
+
+static char send_buffer[BUFF_SIZE];
+static char *send_buffer_ptr;
+static int send_buffer_fill;
+static value_list_t send_buffer_vl = VALUE_LIST_INIT;
+static char send_buffer_type[DATA_MAX_NAME_LEN];
+
+/*
+ * Private functions
+ */
+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;
+ int i;
+
+ i = 6 + (9 * vl->values_len);
+ if (*ret_buffer_len < i)
+ 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);
+
+ 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++)
+ {
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ pv.values_types[i] = DS_TYPE_COUNTER;
+ pv.values[i].counter = htonll (vl->values[i].counter);
+ }
+ else
+ {
+ pv.values_types[i] = DS_TYPE_GAUGE;
+ pv.values[i].gauge = vl->values[i].gauge;
+ }
+ } /* for (values) */
-static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+ return (0);
+} /* int write_part_values */
+
+static int write_part_number (char **ret_buffer, int *ret_buffer_len,
+ int type, uint64_t value)
{
- char *ttl_str;
- int ttl_int;
+ part_number_t pn;
- ttl_str = cf_get_option ("TimeToLive", NULL);
- if (ttl_str == NULL)
+ if (*ret_buffer_len < 12)
return (-1);
- ttl_int = atoi (ttl_str);
- if ((ttl_int < 1) || (ttl_int > 255))
+ pn.head = (part_header_t *) *ret_buffer;
+ pn.value = (uint64_t *) (pn.head + 1);
+
+ pn.head->type = htons (type);
+ pn.head->length = htons (12);
+ *pn.value = htonll (value);
+
+ *ret_buffer = (char *) (pn.value + 1);
+ *ret_buffer_len -= 12;
+
+ 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;
+
+ len = 4 + str_len + 1;
+ if (*ret_buffer_len < len)
+ return (-1);
+ *ret_buffer_len -= len;
+
+ ps.head = (part_header_t *) *ret_buffer;
+ ps.value = (char *) (ps.head + 1);
+
+ 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));
+
+ return (0);
+} /* int write_part_string */
+
+static int parse_part_values (void **ret_buffer, int *ret_buffer_len,
+ value_t **ret_values, int *ret_num_values)
+{
+ char *buffer = *ret_buffer;
+ int buffer_len = *ret_buffer_len;
+ part_values_t pv;
+ int i;
+
+ uint16_t h_length;
+ uint16_t h_type;
+ uint16_t h_num;
+
+ if (buffer_len < (15))
{
- syslog (LOG_WARNING, "A TTL value of %i is invalid.", ttl_int);
+ DBG ("packet is too short: buffer_len = %i", buffer_len);
return (-1);
}
- DBG ("ttl = %i", ttl_int);
+ pv.head = (part_header_t *) buffer;
+ h_length = ntohs (pv.head->length);
+ h_type = ntohs (pv.head->type);
+
+ assert (h_type == TYPE_VALUES);
+
+ pv.num_values = (uint16_t *) (pv.head + 1);
+ h_num = ntohs (*pv.num_values);
+
+ if (h_num != ((h_length - 6) / 9))
+ {
+ DBG ("`length' and `num of values' don't match");
+ return (-1);
+ }
+
+ pv.values_types = (uint8_t *) (pv.num_values + 1);
+ pv.values = (value_t *) (pv.values_types + h_num);
+
+ for (i = 0; i < h_num; i++)
+ if (pv.values_types[i] == DS_TYPE_COUNTER)
+ pv.values[i].counter = ntohll (pv.values[i].counter);
+
+ *ret_buffer = (void *) (pv.values + h_num);
+ *ret_buffer_len = buffer_len - h_length;
+ *ret_num_values = h_num;
+ *ret_values = pv.values;
+
+ return (0);
+} /* int parse_part_values */
+
+static int parse_part_number (void **ret_buffer, int *ret_buffer_len,
+ uint64_t *value)
+{
+ part_number_t pn;
+ uint16_t len;
+
+ pn.head = (part_header_t *) *ret_buffer;
+ pn.value = (uint64_t *) (pn.head + 1);
+
+ len = ntohs (pn.head->length);
+ if (len != 12)
+ return (-1);
+ if (len > *ret_buffer_len)
+ return (-1);
+ *value = ntohll (*pn.value);
+
+ *ret_buffer = (void *) (pn.value + 1);
+ *ret_buffer_len -= len;
+
+ return (0);
+} /* int parse_part_number */
+
+static int parse_part_string (void **ret_buffer, int *ret_buffer_len,
+ char *output, int output_len)
+{
+ char *buffer = *ret_buffer;
+ int buffer_len = *ret_buffer_len;
+ part_string_t ps;
+
+ uint16_t h_length;
+ uint16_t h_type;
+
+ DBG ("ret_buffer = %p; ret_buffer_len = %i; output = %p; output_len = %i;",
+ *ret_buffer, *ret_buffer_len,
+ (void *) output, output_len);
+
+ ps.head = (part_header_t *) buffer;
+
+ h_length = ntohs (ps.head->length);
+ h_type = ntohs (ps.head->type);
+
+ DBG ("length = %hu; type = %hu;", h_length, h_type);
+
+ if (buffer_len < h_length)
+ {
+ DBG ("packet is too short");
+ return (-1);
+ }
+ assert ((h_type == TYPE_HOST)
+ || (h_type == TYPE_PLUGIN)
+ || (h_type == TYPE_PLUGIN_INSTANCE)
+ || (h_type == TYPE_TYPE)
+ || (h_type == TYPE_TYPE_INSTANCE));
+
+ ps.value = buffer + 4;
+ if (ps.value[h_length - 5] != '\0')
+ {
+ DBG ("String does not end with a nullbyte");
+ return (-1);
+ }
+
+ if (output_len < (h_length - 4))
+ {
+ DBG ("output buffer is too small");
+ return (-1);
+ }
+ strcpy (output, ps.value);
+
+ DBG ("output = %s", output);
+
+ *ret_buffer = (void *) (buffer + h_length);
+ *ret_buffer_len = buffer_len - h_length;
+
+ return (0);
+} /* int parse_part_string */
+
+static int parse_packet (void *buffer, int buffer_len)
+{
+ part_header_t *header;
+ int status;
+
+ value_list_t vl = VALUE_LIST_INIT;
+ char type[DATA_MAX_NAME_LEN];
+
+ DBG ("buffer = %p; buffer_len = %i;", buffer, buffer_len);
+
+ memset (&vl, '\0', sizeof (vl));
+ memset (&type, '\0', sizeof (type));
+ status = 0;
+
+ while ((status == 0) && (buffer_len > sizeof (part_header_t)))
+ {
+ header = (part_header_t *) buffer;
+
+ if (ntohs (header->length) > buffer_len)
+ break;
+
+ if (header->type == htons (TYPE_VALUES))
+ {
+ status = parse_part_values (&buffer, &buffer_len,
+ &vl.values, &vl.values_len);
+
+ if (status != 0)
+ {
+ DBG ("parse_part_values failed.");
+ break;
+ }
+
+ if ((vl.time > 0)
+ && (strlen (vl.host) > 0)
+ && (strlen (vl.plugin) > 0)
+ && (strlen (type) > 0))
+ {
+ DBG ("dispatching values");
+ plugin_dispatch_values (type, &vl);
+ }
+ else
+ {
+ DBG ("NOT dispatching values");
+ }
+ }
+ else if (header->type == ntohs (TYPE_TIME))
+ {
+ uint64_t tmp = 0;
+ status = parse_part_number (&buffer, &buffer_len, &tmp);
+ if (status == 0)
+ vl.time = (time_t) tmp;
+ }
+ else if (header->type == ntohs (TYPE_HOST))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.host, sizeof (vl.host));
+ }
+ else if (header->type == ntohs (TYPE_PLUGIN))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.plugin, sizeof (vl.plugin));
+ }
+ else if (header->type == ntohs (TYPE_PLUGIN_INSTANCE))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.plugin_instance, sizeof (vl.plugin_instance));
+ }
+ else if (header->type == ntohs (TYPE_TYPE))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ type, sizeof (type));
+ }
+ else if (header->type == ntohs (TYPE_TYPE_INSTANCE))
+ {
+ status = parse_part_string (&buffer, &buffer_len,
+ vl.type_instance, sizeof (vl.type_instance));
+ }
+ else
+ {
+ DBG ("Unknown part type: 0x%0hx", header->type);
+ buffer = ((char *) buffer) + header->length;
+ }
+ } /* while (buffer_len > sizeof (part_header_t)) */
+
+ return (0);
+} /* int parse_packet */
+
+static void free_sockent (sockent_t *se)
+{
+ sockent_t *next;
+ while (se != NULL)
+ {
+ next = se->next;
+ free (se->addr);
+ free (se);
+ se = next;
+ }
+} /* void free_sockent */
+
+/*
+ * int network_set_ttl
+ *
+ * Set the `IP_MULTICAST_TTL', `IP_TTL', `IPV6_MULTICAST_HOPS' or
+ * `IPV6_UNICAST_HOPS', depending on which option is applicable.
+ *
+ * The `struct addrinfo' is used to destinguish between unicast and multicast
+ * sockets.
+ */
+static int network_set_ttl (const sockent_t *se, const struct addrinfo *ai)
+{
+ if ((network_config_ttl < 1) || (network_config_ttl > 255))
+ return (-1);
+
+ DBG ("ttl = %i", network_config_ttl);
if (ai->ai_family == AF_INET)
{
optname = IP_TTL;
if (setsockopt (se->fd, IPPROTO_IP, optname,
- &ttl_int, sizeof (ttl_int)) == -1)
+ &network_config_ttl,
+ sizeof (network_config_ttl)) == -1)
{
syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
return (-1);
optname = IPV6_UNICAST_HOPS;
if (setsockopt (se->fd, IPPROTO_IPV6, optname,
- &ttl_int, sizeof (ttl_int)) == -1)
+ &network_config_ttl,
+ sizeof (network_config_ttl)) == -1)
{
syslog (LOG_ERR, "setsockopt: %s", strerror (errno));
return (-1);
}
return (0);
-}
+} /* int network_set_ttl */
static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
{
@@ -200,31 +610,21 @@ static int network_bind_socket (const sockent_t *se, const struct addrinfo *ai)
}
return (0);
-}
+} /* int network_bind_socket */
-int network_create_socket (const char *node, const char *service)
+static sockent_t *network_create_socket (const char *node,
+ const char *service,
+ int listen)
{
- sockent_t *socklist_tail;
-
struct addrinfo ai_hints;
struct addrinfo *ai_list, *ai_ptr;
int ai_return;
- int num_added = 0;
+ sockent_t *se_head = NULL;
+ sockent_t *se_tail = NULL;
DBG ("node = %s, service = %s", node, service);
- if (operating_mode == MODE_LOCAL || operating_mode == MODE_LOG)
- {
- syslog (LOG_WARNING, "network_create_socket: There is no point opening a socket when you are in mode `%s'.",
- operating_mode == MODE_LOCAL ? "Local" : "Log");
- return (-1);
- }
-
- socklist_tail = socklist_head;
- while ((socklist_tail != NULL) && (socklist_tail->next != NULL))
- socklist_tail = socklist_tail->next;
-
memset (&ai_hints, '\0', sizeof (ai_hints));
ai_hints.ai_flags = 0;
#ifdef AI_PASSIVE
#ifdef AI_ADDRCONFIG
ai_hints.ai_flags |= AI_ADDRCONFIG;
#endif
- ai_hints.ai_family = PF_UNSPEC;
+ ai_hints.ai_family = AF_UNSPEC;
ai_hints.ai_socktype = SOCK_DGRAM;
ai_hints.ai_protocol = IPPROTO_UDP;
- if ((ai_return = getaddrinfo (node, service, &ai_hints, &ai_list)) != 0)
+ ai_return = getaddrinfo (node, service, &ai_hints, &ai_list);
+ if (ai_return != 0)
{
syslog (LOG_ERR, "getaddrinfo (%s, %s): %s",
- node == NULL ? "(null)" : node,
- service == NULL ? "(null)" : service,
- ai_return == EAI_SYSTEM ? strerror (errno) : gai_strerror (ai_return));
- return (-1);
+ (node == NULL) ? "(null)" : node,
+ (service == NULL) ? "(null)" : service,
+ (ai_return == EAI_SYSTEM)
+ ? strerror (errno)
+ : gai_strerror (ai_return));
+ return (NULL);
}
for (ai_ptr = ai_list; ai_ptr != NULL; ai_ptr = ai_ptr->ai_next)
memcpy (se->addr, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
se->addrlen = ai_ptr->ai_addrlen;
- se->mode = operating_mode;
- se->fd = socket (ai_ptr->ai_family, ai_ptr->ai_socktype, ai_ptr->ai_protocol);
+ se->fd = socket (ai_ptr->ai_family,
+ ai_ptr->ai_socktype,
+ ai_ptr->ai_protocol);
se->next = NULL;
if (se->fd == -1)
continue;
}
- if (operating_mode == MODE_SERVER)
+ if (listen != 0)
{
if (network_bind_socket (se, ai_ptr) != 0)
{
continue;
}
}
- else if (operating_mode == MODE_CLIENT)
+ else /* listen == 0 */
{
network_set_ttl (se, ai_ptr);
}
- if (socklist_tail == NULL)
+ if (se_tail == NULL)
{
- socklist_head = se;
- socklist_tail = se;
+ se_head = se;
+ se_tail = se;
}
else
{
- socklist_tail->next = se;
- socklist_tail = se;
+ se_tail->next = se;
+ se_tail = se;
}
- num_added++;
-
/* We don't open more than one write-socket per node/service pair.. */
- if (operating_mode == MODE_CLIENT)
+ if (listen == 0)
break;
}
freeaddrinfo (ai_list);
- return (num_added);
-}
+ return (se_head);
+} /* sockent_t *network_create_socket */
-static int network_connect_default (void)
+static sockent_t *network_create_default_socket (int listen)
{
- int ret;
+ sockent_t *se_ptr = NULL;
+ sockent_t *se_head = NULL;
+ sockent_t *se_tail = NULL;
- if (socklist_head != NULL)
- return (0);
+ se_ptr = network_create_socket (NET_DEFAULT_V6_ADDR,
+ NET_DEFAULT_PORT, listen);
- DBG ("socklist_head is NULL");
+ /* Don't send to the same machine in IPv6 and IPv4 if both are available. */
+ if ((listen == 0) && (se_ptr != NULL))
+ return (se_ptr);
+
+ if (se_ptr != NULL)
+ {
+ se_head = se_ptr;
+ se_tail = se_ptr;
+ while (se_tail->next != NULL)
+ se_tail = se_tail->next;
+ }
- ret = 0;
+ se_ptr = network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT, listen);
- if (network_create_socket (NET_DEFAULT_V6_ADDR, NET_DEFAULT_PORT) > 0)
- ret++;
+ if (se_tail == NULL)
+ return (se_ptr);
- /* Don't use IPv4 and IPv6 in parallel by default.. */
- if ((operating_mode == MODE_CLIENT) && (ret != 0))
- return (ret);
+ se_tail->next = se_ptr;
+ return (se_head);
+} /* sockent_t *network_create_default_socket */
- if (network_create_socket (NET_DEFAULT_V4_ADDR, NET_DEFAULT_PORT) > 0)
- ret++;
+static int network_add_listen_socket (const char *node, const char *service)
+{
+ sockent_t *se;
+ sockent_t *se_ptr;
+ int se_num = 0;
- if (ret == 0)
- ret = -1;
+ if (service == NULL)
+ service = NET_DEFAULT_PORT;
- return (ret);
-}
+ if (node == NULL)
+ se = network_create_default_socket (1 /* listen == true */);
+ else
+ se = network_create_socket (node, service, 1 /* listen == true */);
-static int network_get_listen_socket (void)
-{
- int fd;
- int max_fd;
- int status;
+ if (se == NULL)
+ return (-1);
- fd_set readfds;
- sockent_t *se;
+ for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
+ se_num++;
- if (socklist_head == NULL)
- network_connect_default ();
+ listen_sockets = (struct pollfd *) realloc (listen_sockets,
+ (listen_sockets_num + se_num)
+ * sizeof (struct pollfd));
- FD_ZERO (&readfds);
- max_fd = -1;
- for (se = socklist_head; se != NULL; se = se->next)
+ for (se_ptr = se; se_ptr != NULL; se_ptr = se_ptr->next)
{
- if (se->mode != operating_mode)
- continue;
+ listen_sockets[listen_sockets_num].fd = se_ptr->fd;
+ listen_sockets[listen_sockets_num].events = POLLIN | POLLPRI;
+ listen_sockets[listen_sockets_num].revents = 0;
+ listen_sockets_num++;
+ } /* for (se) */
- FD_SET (se->fd, &readfds);
- if (se->fd >= max_fd)
- max_fd = se->fd + 1;
- }
+ free_sockent (se);
+ return (0);
+} /* int network_add_listen_socket */
- if (max_fd == -1)
- {
- syslog (LOG_WARNING, "No listen sockets found!");
+static int network_add_sending_socket (const char *node, const char *service)
+{
+ sockent_t *se;
+ sockent_t *se_ptr;
+
+ if (service == NULL)
+ service = NET_DEFAULT_PORT;
+
+ if (node == NULL)
+ se = network_create_default_socket (0 /* listen == false */);
+ else
+ se = network_create_socket (node, service, 0 /* listen == false */);
+
+ if (se == NULL)
return (-1);
+
+ if (sending_sockets == NULL)
+ {
+ sending_sockets = se;
+ return (0);
}
- status = select (max_fd, &readfds, NULL, NULL, NULL);
+ for (se_ptr = sending_sockets; se_ptr->next != NULL; se_ptr = se_ptr->next)
+ /* seek end */;
+
+ se_ptr->next = se;
+ return (0);
+} /* int network_get_listen_socket */
- if (status == -1)
+int network_receive (void)
+{
+ char buffer[BUFF_SIZE];
+ int buffer_len;
+
+ int i;
+ int status;
+
+ if (listen_sockets_num == 0)
+ network_add_listen_socket (NULL, NULL);
+
+ if (listen_sockets_num == 0)
{
- if (errno != EINTR)
- syslog (LOG_ERR, "select: %s", strerror (errno));
+ syslog (LOG_ERR, "network: Failed to open a listening socket.");
return (-1);
}
- fd = -1;
- for (se = socklist_head; se != NULL; se = se->next)
+ while (listen_loop == 0)
{
- if (se->mode != operating_mode)
- continue;
+ status = poll (listen_sockets, listen_sockets_num, -1);
- if (FD_ISSET (se->fd, &readfds))
+ if (status <= 0)
{
- fd = se->fd;
- break;
+ if (errno == EINTR)
+ continue;
+ syslog (LOG_ERR, "poll failed: %s",
+ strerror (errno));
+ return (-1);
}
- }
- if (fd == -1)
- syslog (LOG_WARNING, "No socket ready..?");
+ for (i = 0; (i < listen_sockets_num) && (status > 0); i++)
+ {
+ if ((listen_sockets[i].revents & (POLLIN | POLLPRI)) == 0)
+ continue;
+ status--;
+
+ buffer_len = recv (listen_sockets[i].fd,
+ buffer, sizeof (buffer),
+ 0 /* no flags */);
+ if (buffer_len < 0)
+ {
+ syslog (LOG_ERR, "recv failed: %s", strerror (errno));
+ return (-1);
+ }
+
+ parse_packet (buffer, buffer_len);
+ } /* for (listen_sockets) */
+ } /* while (listen_loop == 0) */
- DBG ("fd = %i", fd);
- return (fd);
+ return (0);
}
-int network_receive (char **host, char **type, char **inst, char **value)
+static void *receive_thread (void *arg)
{
- int fd;
- char buffer[BUFF_SIZE];
+ return (network_receive () ? (void *) 1 : (void *) 0);
+} /* void *receive_thread */
- struct sockaddr_storage addr;
- socklen_t addrlen;
+static void network_send_buffer (const char *buffer, int buffer_len)
+{
+ sockent_t *se;
int status;
- char *fields[4];
+ DBG ("buffer_len = %i", buffer_len);
- assert (operating_mode == MODE_SERVER);
-
- *host = NULL;
- *type = NULL;
- *inst = NULL;
- *value = NULL;
+ for (se = sending_sockets; se != NULL; se = se->next)
+ {
+ while (42)
+ {
+ status = sendto (se->fd, buffer, buffer_len, 0 /* no flags */,
+ (struct sockaddr *) se->addr, se->addrlen);
+ if (status < 0)
+ {
+ if (errno == EINTR)
+ continue;
+ syslog (LOG_ERR, "network plugin: sendto failed: %s",
+ strerror (errno));
+ break;
+ }
- if ((fd = network_get_listen_socket ()) < 0)
- return (-1);
+ break;
+ } /* while (42) */
+ } /* for (sending_sockets) */
+} /* void network_send_buffer */
- addrlen = sizeof (addr);
- if (recvfrom (fd, buffer, BUFF_SIZE, 0, (struct sockaddr *) &addr, &addrlen) == -1)
+static int add_to_buffer (char *buffer, int buffer_size,
+ value_list_t *vl_def, char *type_def,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ if (strcmp (vl_def->host, vl->host) != 0)
{
- syslog (LOG_ERR, "recvfrom: %s", strerror (errno));
- return (-1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_HOST,
+ vl->host, strlen (vl->host)) != 0)
+ return (-1);
+ strcpy (vl_def->host, vl->host);
+ DBG ("host = %s", vl->host);
}
- if ((*host = (char *) malloc (BUFF_SIZE)) == NULL)
+ if (vl_def->time != vl->time)
{
- syslog (LOG_EMERG, "malloc: %s", strerror (errno));
- return (-1);
+ if (write_part_number (&buffer, &buffer_size, TYPE_TIME,
+ (uint64_t) vl->time))
+ return (-1);
+ vl_def->time = vl->time;
+ DBG ("time = %u", (unsigned int) vl->time);
}
- status = getnameinfo ((struct sockaddr *) &addr, addrlen,
- *host, BUFF_SIZE, NULL, 0, 0);
- if (status != 0)
+ if (strcmp (vl_def->plugin, vl->plugin) != 0)
{
- free (*host); *host = NULL;
- syslog (LOG_ERR, "getnameinfo: %s",
- status == EAI_SYSTEM ? strerror (errno) : gai_strerror (status));
- return (-1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN,
+ vl->plugin, strlen (vl->plugin)) != 0)
+ return (-1);
+ strcpy (vl_def->plugin, vl->plugin);
+ DBG ("plugin = %s", vl->plugin);
}
- if (strsplit (buffer, fields, 4) != 3)
+ if (strcmp (vl_def->plugin_instance, vl->plugin_instance) != 0)
{
- syslog (LOG_WARNING, "Invalid message from `%s'", *host);
- free (*host); *host = NULL;
- return (1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+ vl->plugin_instance,
+ strlen (vl->plugin_instance)) != 0)
+ return (-1);
+ strcpy (vl_def->plugin_instance, vl->plugin_instance);
+ DBG ("plugin_instance = %s", vl->plugin_instance);
}
- if ((*type = strdup (fields[0])) == NULL)
+ if (strcmp (type_def, ds->type) != 0)
{
- syslog (LOG_EMERG, "strdup: %s", strerror (errno));
- free (*host); *host = NULL;
- return (-1);
+ if (write_part_string (&buffer, &buffer_size, TYPE_TYPE,
+ ds->type, strlen (ds->type)) != 0)
+ return (-1);
+ strcpy (type_def, ds->type);
+ DBG ("type = %s", ds->type);
}
- if ((*inst = strdup (fields[1])) == NULL)
+ if (strcmp (vl_def->type_instance, vl->type_instance) != 0)
{
- syslog (LOG_EMERG, "strdup: %s", strerror (errno));
- free (*host); *host = NULL;
- free (*type); *type = NULL;
+ if (write_part_string (&buffer, &buffer_size, TYPE_PLUGIN_INSTANCE,
+ vl->type_instance,
+ strlen (vl->type_instance)) != 0)
+ return (-1);
+ strcpy (vl_def->type_instance, vl->type_instance);
+ DBG ("type_instance = %s", vl->type_instance);
+ }
+
+ if (write_part_values (&buffer, &buffer_size, ds, vl) != 0)
return (-1);
+
+ return (buffer_size);
+} /* int add_to_buffer */
+
+static void flush_buffer (void)
+{
+ network_send_buffer (send_buffer, send_buffer_fill);
+ send_buffer_ptr = send_buffer;
+ send_buffer_fill = 0;
+ memset (&send_buffer_vl, '\0', sizeof (send_buffer_vl));
+ memset (send_buffer_type, '\0', sizeof (send_buffer_type));
+}
+
+static int network_write (const data_set_t *ds, const value_list_t *vl)
+{
+ int status;
+ /* TODO: lock buffer */
+ status = add_to_buffer (send_buffer_ptr,
+ sizeof (send_buffer) - send_buffer_fill,
+ &send_buffer_vl, send_buffer_type,
+ ds, vl);
+ if (status >= 0)
+ {
+ send_buffer_fill += status;
+ send_buffer_ptr += status;
+ }
+ else
+ {
+ flush_buffer ();
+
+ status = add_to_buffer (send_buffer_ptr,
+ sizeof (send_buffer) - send_buffer_fill,
+ &send_buffer_vl, send_buffer_type,
+ ds, vl);
+
+ if (status >= 0)
+ {
+ send_buffer_fill += status;
+ send_buffer_ptr += status;
+ }
}
- if ((*value = strdup (fields[2])) == NULL)
+ if (status < 0)
{
- syslog (LOG_EMERG, "strdup: %s", strerror (errno));
- free (*host); *host = NULL;
- free (*type); *type = NULL;
- free (*inst); *inst = NULL;
- return (-1);
+ syslog (LOG_ERR, "network plugin: Unable to append to the "
+ "buffer for some weird reason");
+ }
+ else if ((sizeof (send_buffer) - send_buffer_fill) < 15)
+ {
+ flush_buffer ();
}
+ /* TODO: unlock buffer */
- DBG ("host = %s, type = %s, inst = %s, value = %s",
- *host, *type, *inst, *value);
+ return ((status < 0) ? -1 : 0);
+} /* int network_write */
+static int network_config (const char *key, const char *val)
+{
+ char *node;
+ char *service;
+
+ char *fields[3];
+ int fields_num;
+
+ if ((strcasecmp ("Listen", key) == 0)
+ || (strcasecmp ("Server", key) == 0))
+ {
+ char *val_cpy = strdup (val);
+ if (val_cpy == NULL)
+ return (1);
+
+ service = NET_DEFAULT_PORT;
+ fields_num = strsplit (val_cpy, fields, 3);
+ if ((fields_num != 1)
+ && (fields_num != 2))
+ return (1);
+ else if (fields_num == 2)
+ service = fields[1];
+ node = fields[0];
+
+ if (strcasecmp ("Listen", key) == 0)
+ network_add_listen_socket (node, service);
+ else
+ network_add_sending_socket (node, service);
+ }
+ else if (strcasecmp ("TimeToLive", key) == 0)
+ {
+ int tmp = atoi (val);
+ if ((tmp > 0) && (tmp < 256))
+ network_config_ttl = tmp;
+ else
+ return (1);
+ }
+ else
+ {
+ return (-1);
+ }
return (0);
}
-int network_send (char *type, char *inst, char *value)
+static int network_shutdown (void)
{
- char buf[BUFF_SIZE];
- int buflen;
+ DBG ("Shutting down.");
- sockent_t *se;
+ listen_loop++;
- int ret;
- int status;
+ pthread_kill (listen_thread, SIGTERM);
+ pthread_join (listen_thread, NULL /* no return value */);
- DBG ("type = %s, inst = %s, value = %s", type, inst, value);
+ listen_thread = 0;
- assert (operating_mode == MODE_CLIENT);
+ return (0);
+}
- buflen = snprintf (buf, BUFF_SIZE, "%s %s %s", type, inst, value);
- if ((buflen >= BUFF_SIZE) || (buflen < 1))
- {
- syslog (LOG_WARNING, "network_send: snprintf failed..");
- return (-1);
- }
- buf[buflen] = '\0';
- buflen++;
+static int network_init (void)
+{
+ plugin_register_shutdown ("network", network_shutdown);
+
+ send_buffer_ptr = send_buffer;
+ send_buffer_fill = 0;
+ memset (&send_buffer_vl, '\0', sizeof (send_buffer_vl));
+ memset (send_buffer_type, '\0', sizeof (send_buffer_type));
- if (socklist_head == NULL)
- network_connect_default ();
+ /* setup socket(s) and so on */
+ if (sending_sockets != NULL)
+ plugin_register_write ("network", network_write);
- ret = 0;
- for (se = socklist_head; se != NULL; se = se->next)
+ if ((listen_sockets_num != 0) && (listen_thread == 0))
{
- if (se->mode != operating_mode)
- continue;
+ int status;
- while (1)
- {
- status = sendto (se->fd, buf, buflen, 0,
- (struct sockaddr *) se->addr, se->addrlen);
+ status = pthread_create (&listen_thread, NULL /* no attributes */,
+ receive_thread, NULL /* no argument */);
- if (status == -1)
- {
- if (errno == EINTR)
- {
- DBG ("sendto was interrupted");
- continue;
- }
- else
- {
- syslog (LOG_ERR, "sendto: %s", strerror (errno));
- ret = -1;
- break;
- }
- }
- else if (ret >= 0)
- ret++;
- break;
- }
+ if (status != 0)
+ syslog (LOG_ERR, "network: pthread_create failed: %s",
+ strerror (errno));
}
+ return (0);
+} /* int network_init */
- if (ret == 0)
- syslog (LOG_WARNING, "Message wasn't sent to anybody..");
-
- return (ret);
+void module_register (void)
+{
+ plugin_register_config ("network", network_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("network", network_init);
}
diff --git a/src/network.h b/src/network.h
index 2df989b3bcf3ba4980d5d712bf1b20ae1d598ae0..b20fc75f837a8f9992aa5e4e1f5f1183e90e9a6d 100644 (file)
--- a/src/network.h
+++ b/src/network.h
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42"
#define NET_DEFAULT_PORT "25826"
-int network_create_socket (const char *node, const char *service);
-int network_receive (char **host, char **type, char **instance, char **value);
-int network_send (char *type, char *instance, char *value);
+#define TYPE_HOST 0x0000
+#define TYPE_TIME 0x0001
+#define TYPE_PLUGIN 0x0002
+#define TYPE_PLUGIN_INSTANCE 0x0003
+#define TYPE_TYPE 0x0004
+#define TYPE_TYPE_INSTANCE 0x0005
+#define TYPE_VALUES 0x0006
#endif /* NETWORK_H */
diff --git a/src/nfs.c b/src/nfs.c
index d0f33c5238269638d00ae52b8bb462b3489ddb0f..1dc64b78a1d948a2b9112ceb3c9484691f60042a 100644 (file)
--- a/src/nfs.c
+++ b/src/nfs.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "collectd.h"
#include "common.h"
#include "plugin.h"
+#include "utils_debug.h"
#define MODULE_NAME "nfs"
# define NFS_HAVE_READ 0
#endif
-static char *nfs2_procedures_file = "nfs2_procedures-%s.rrd";
-static char *nfs3_procedures_file = "nfs3_procedures-%s.rrd";
-
/*
see /proc/net/rpc/nfs
see http://www.missioncriticallinux.com/orph/NFS-Statistics
21 commit
*/
-static char *nfs2_procedures_ds_def[] =
+static data_source_t procedure_dsrc[1] =
+{
+ {"value", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t procedure_ds =
{
- "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:root:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wrcache:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+ "nfs_procedure", 1, procedure_dsrc
+};
+
+#if NFS_HAVE_READ
+static const char *nfs2_procedures_names[] =
+{
+ "null",
+ "getattr",
+ "setattr",
+ "root",
+ "lookup",
+ "readlink",
+ "read",
+ "wrcache",
+ "write",
+ "create",
+ "remove",
+ "rename",
+ "link",
+ "symlink",
+ "mkdir",
+ "rmdir",
+ "readdir",
+ "fsstat",
NULL
};
-static int nfs2_procedures_ds_num = 18;
+static int nfs2_procedures_names_num = 18;
-static char *nfs3_procedures_ds_def[] =
+static const char *nfs3_procedures_names[] =
{
- "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:access:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:mknod:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:readdirplus:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:fsinfo:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:pathconf:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:commit:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+ "null",
+ "getattr",
+ "setattr",
+ "lookup",
+ "access",
+ "readlink",
+ "read",
+ "write",
+ "create",
+ "mkdir",
+ "symlink",
+ "mknod",
+ "remove",
+ "rmdir",
+ "rename",
+ "link",
+ "readdir",
+ "readdirplus",
+ "fsstat",
+ "fsinfo",
+ "pathconf",
+ "commit",
NULL
};
-static int nfs3_procedures_ds_num = 22;
+static int nfs3_procedures_names_num = 22;
#if HAVE_LIBKSTAT && 0
extern kstat_ctl_t *kc;
/* Possibly TODO: NFSv4 statistics */
-static void nfs_init (void)
+#if 0
+static int nfs_init (void)
{
#if HAVE_LIBKSTAT && 0
kstat_t *ksp_chain;
}
#endif
- return;
-}
+ return (0);
+} /* int nfs_init */
+#endif
#define BUFSIZE 1024
-static void nfs2_procedures_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
-
- if (snprintf (filename, BUFSIZE, nfs2_procedures_file, inst) > BUFSIZE)
- return;
-
- rrd_update_file (host, filename, val, nfs2_procedures_ds_def,
- nfs2_procedures_ds_num);
-}
-
-static void nfs3_procedures_write (char *host, char *inst, char *val)
-{
- char filename[BUFSIZE];
-
- if (snprintf (filename, BUFSIZE, nfs3_procedures_file, inst) > BUFSIZE)
- return;
-
- rrd_update_file (host, filename, val, nfs3_procedures_ds_def,
- nfs3_procedures_ds_num);
-}
-
-#if NFS_HAVE_READ
-static void nfs2_procedures_submit (unsigned long long *val, char *inst)
-{
- char buf[BUFSIZE];
- int retval = 0;
-
- retval = snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu", /* 18x %llu */
- (unsigned int) curtime,
- val[0], val[1], val[2], val[3], val[4], val[5], val[6],
- val[7], val[8], val[9], val[10], val[11], val[12],
- val[13], val[14], val[15], val[16], val[17]);
-
-
- if (retval >= BUFSIZE)
- return;
- else if (retval < 0)
- {
- syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
- return;
- }
-
- plugin_submit ("nfs2_procedures", inst, buf);
-}
-
-static void nfs3_procedures_submit (unsigned long long *val, char *inst)
+static void nfs_procedures_submit (const char *plugin_instance,
+ unsigned long long *val, const char **names, int len)
{
- char buf[BUFSIZE];
- int retval = 0;
-
- retval = snprintf(buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu:"
- "%llu:%llu:%llu:%llu:%llu:%llu:%llu", /* 22x %llu */
- (unsigned int) curtime,
- val[0], val[1], val[2], val[3], val[4], val[5], val[6],
- val[7], val[8], val[9], val[10], val[11], val[12],
- val[13], val[14], val[15], val[16], val[17], val[18],
- val[19], val[20], val[21]);
-
- if (retval >= BUFSIZE)
- return;
- else if (retval < 0)
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+ int i;
+
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "nfs");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
+
+ for (i = 0; i < len; i++)
{
- syslog (LOG_ERR, "nfs: snprintf's format failed: %s", strerror (errno));
- return;
+ values[0].counter = val[i];
+ strncpy (vl.type_instance, names[i],
+ sizeof (vl.type_instance));
+ DBG ("%s-%s/nfs_procedure-%s = %llu",
+ vl.plugin, vl.plugin_instance,
+ vl.type_instance, val[i]);
+ plugin_dispatch_values ("nfs_procedure", &vl);
}
-
- plugin_submit("nfs3_procedures", inst, buf);
-}
-#endif /* NFS_HAVE_READ */
+} /* void nfs_procedures_submit */
#if KERNEL_LINUX
static void nfs_read_stats_file (FILE *fh, char *inst)
{
char buffer[BUFSIZE];
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
char *fields[48];
int numfields = 0;
{
numfields = strsplit (buffer, fields, 48);
- if (numfields < 2)
+ if (((numfields - 2) != nfs2_procedures_names_num)
+ && ((numfields - 2)
+ != nfs3_procedures_names_num))
continue;
- if (strncmp (fields[0], "proc2", 5) == 0)
+ if (strcmp (fields[0], "proc2") == 0)
{
int i;
unsigned long long *values;
- if (numfields - 2 != nfs2_procedures_ds_num)
+ if ((numfields - 2) != nfs2_procedures_names_num)
{
- syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS2 statistics.", numfields - 2);
+ syslog (LOG_WARNING, "nfs plugin: Wrong "
+ "number of fields (= %i) "
+ "for NFSv2 statistics.",
+ numfields - 2);
continue;
}
- if ((values = (unsigned long long *) malloc (nfs2_procedures_ds_num * sizeof (unsigned long long))) == NULL)
+ snprintf (plugin_instance, sizeof (plugin_instance),
+ "v2%s", inst);
+ plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+
+ values = (unsigned long long *) malloc (nfs2_procedures_names_num * sizeof (unsigned long long));
+ if (values == NULL)
{
- syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
+ syslog (LOG_ERR, "nfs plugin: malloc "
+ "failed: %s",
+ strerror (errno));
continue;
}
- for (i = 0; i < nfs2_procedures_ds_num; i++)
+ for (i = 0; i < nfs2_procedures_names_num; i++)
values[i] = atoll (fields[i + 2]);
- nfs2_procedures_submit (values, inst);
+ nfs_procedures_submit (plugin_instance, values,
+ nfs2_procedures_names,
+ nfs2_procedures_names_num);
free (values);
}
int i;
unsigned long long *values;
- if (numfields - 2 != nfs3_procedures_ds_num)
+ if ((numfields - 2) != nfs3_procedures_names_num)
{
- syslog (LOG_WARNING, "nfs: Wrong number of fields (= %i) for NFS3 statistics.", numfields - 2);
+ syslog (LOG_WARNING, "nfs plugin: Wrong "
+ "number of fields (= %i) "
+ "for NFSv3 statistics.",
+ numfields - 2);
continue;
}
- if ((values = (unsigned long long *) malloc (nfs3_procedures_ds_num * sizeof (unsigned long long))) == NULL)
+ snprintf (plugin_instance, sizeof (plugin_instance),
+ "v3%s", inst);
+ plugin_instance[DATA_MAX_NAME_LEN - 1] = '\0';
+
+ values = (unsigned long long *) malloc (nfs3_procedures_names_num * sizeof (unsigned long long));
+ if (values == NULL)
{
- syslog (LOG_ERR, "nfs: malloc: %s", strerror (errno));
+ syslog (LOG_ERR, "nfs plugin: malloc "
+ "failed: %s",
+ strerror (errno));
continue;
}
- for (i = 0; i < nfs3_procedures_ds_num; i++)
+ for (i = 0; i < nfs3_procedures_names_num; i++)
values[i] = atoll (fields[i + 2]);
- nfs3_procedures_submit (values, inst);
+ nfs_procedures_submit (plugin_instance, values,
+ nfs3_procedures_names,
+ nfs3_procedures_names_num);
free (values);
}
- }
-}
+ } /* while (fgets (buffer, BUFSIZE, fh) != NULL) */
+} /* void nfs_read_stats_file */
#endif /* defined(KERNEL_LINUX) */
#undef BUFSIZE
}
#endif
-#if NFS_HAVE_READ
-static void nfs_read (void)
+static int nfs_read (void)
{
#if KERNEL_LINUX
FILE *fh;
if (nfs2_ksp_server != NULL)
nfs2_read_kstat (nfs2_ksp_server, "server");
#endif /* defined(HAVE_LIBKSTAT) */
+
+ return (0);
}
-#else
-# define nfs_read NULL
#endif /* NFS_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, nfs_init, nfs_read, NULL);
- plugin_register ("nfs2_procedures", NULL, NULL, nfs2_procedures_write);
- plugin_register ("nfs3_procedures", NULL, NULL, nfs3_procedures_write);
+ plugin_register_data_set (&procedure_ds);
+
+#if NFS_HAVE_READ
+ plugin_register_read ("nfs", nfs_read);
+#endif
}
#undef MODULE_NAME
diff --git a/src/ntpd.c b/src/ntpd.c
index b65a9e8fa72f2dac8e3ed9d1a808f6d9ce4583da..366c24b485f61939c4646bf1755245e2f7349c47 100644 (file)
--- a/src/ntpd.c
+++ b/src/ntpd.c
/**
* collectd - src/ntpd.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "ntpd"
-
#if HAVE_SYS_SOCKET_H
# define NTPD_HAVE_READ 1
#else
#if HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
#endif
-#if HAVE_SYS_POLL_H
-# include <sys/poll.h>
+#if HAVE_POLL_H
+# include <poll.h>
#endif
-static char *config_keys[] =
+static data_source_t seconds_dsrc[1] =
{
- "Host",
- "Port",
- NULL
+ {"seconds", DS_TYPE_GAUGE, -1000000.0, 1000000.0}
+};
+
+static data_set_t time_offset_ds =
+{
+ "time_offset", 1, seconds_dsrc
};
-static int config_keys_num = 2;
-/* drift */
-static char *time_offset_file = "ntpd/time_offset-%s.rrd";
-static char *time_dispersion_file = "ntpd/time_dispersion-%s.rrd";
-static char *time_delay_file = "ntpd/delay-%s.rrd";
+static data_set_t time_dispersion_ds =
+{
+ "time_dispersion", 1, seconds_dsrc
+};
-/* used for `time_offset', `time_dispersion', and `delay' */
-static char *sec_ds_def[] =
+static data_set_t delay_ds =
{
- "DS:seconds:GAUGE:"COLLECTD_HEARTBEAT":-1000000:1000000",
- NULL
+ "delay", 1, seconds_dsrc
+};
+
+static data_source_t ppm_dsrc[1] =
+{
+ {"ppm", DS_TYPE_GAUGE, -1000000.0, 1000000.0}
};
-static int sec_ds_num = 1;
-static char *frequency_offset_file = "ntpd/frequency_offset-%s.rrd";
-static char *frequency_offset_ds_def[] =
+static data_set_t frequency_offset_ds =
{
- "DS:ppm:GAUGE:"COLLECTD_HEARTBEAT":-1000000:1000000",
+ "frequency_offset", 1, ppm_dsrc
+};
+
+static const char *config_keys[] =
+{
+ "Host",
+ "Port",
NULL
};
-static int frequency_offset_ds_num = 1;
+static int config_keys_num = 2;
#if NTPD_HAVE_READ
# define NTPD_DEFAULT_HOST "localhost"
static int sock_descr = -1;
static char *ntpd_host = NULL;
static char *ntpd_port = NULL;
-#endif
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* The following definitions were copied from the NTPd distribution *
* End of the copied stuff.. *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
-static int ntpd_config (char *key, char *value)
+static int ntpd_config (const char *key, const char *value)
{
if (strcasecmp (key, "host") == 0)
{
return (0);
}
-static void ntpd_init (void)
+static void ntpd_submit (char *type, char *type_inst, double value)
{
- return;
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-static void ntpd_write_sec (char *host, char *inst, char *val, char *file)
-{
- char buf[256];
- int status;
+ values[0].gauge = value;
- status = snprintf (buf, 256, file, inst);
- if ((status < 1) || (status >= 256))
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "ntpd");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, type_inst, sizeof (vl.type_instance));
- rrd_update_file (host, buf, val,
- sec_ds_def, sec_ds_num);
-}
-
-static void ntpd_write_time_offset (char *host, char *inst, char *val)
-{
- ntpd_write_sec (host, inst, val, time_offset_file);
-}
-
-static void ntpd_write_time_dispersion (char *host, char *inst, char *val)
-{
- ntpd_write_sec (host, inst, val, time_dispersion_file);
-}
-
-static void ntpd_write_delay (char *host, char *inst, char *val)
-{
- ntpd_write_sec (host, inst, val, time_delay_file);
-}
-
-static void ntpd_write_frequency_offset (char *host, char *inst, char *val)
-{
- char buf[256];
- int status;
-
- status = snprintf (buf, 256, frequency_offset_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- rrd_update_file (host, buf, val,
- frequency_offset_ds_def, frequency_offset_ds_num);
-}
-
-#if NTPD_HAVE_READ
-static void ntpd_submit (char *type, char *inst, double value)
-{
- char buf[256];
-
- if (snprintf (buf, 256, "%u:%.8f", (unsigned int) curtime, value) >= 256)
- return;
-
- DBG ("type = %s; inst = %s; value = %s;",
- type, inst, buf);
-
- plugin_submit (type, inst, buf);
+ plugin_dispatch_values (type, &vl);
}
/* returns `tv0 - tv1' in milliseconds or 0 if `tv1 > tv0' */
return (val_double);
}
-static void ntpd_read (void)
+static int ntpd_read (void)
{
struct info_kernel *ik;
int ik_num;
if (status != 0)
{
DBG ("ntpd_do_query failed with status %i", status);
- return;
+ return (-1);
}
if ((ik == NULL) || (ik_num == 0) || (ik_size == 0))
{
DBG ("ntpd_do_query returned: ik = %p; ik_num = %i; ik_size = %i;",
(void *) ik, ik_num, ik_size);
- return;
+ return (-1);
}
/* kerninfo -> estimated error */
ntpd_read_fp (ik->freq),
ntpd_read_fp (ik->esterror));
- ntpd_submit ("ntpd_frequency_offset", "loop", ntpd_read_fp (ik->freq));
- ntpd_submit ("ntpd_time_offset", "loop", ntpd_read_fp (ik->offset));
- ntpd_submit ("ntpd_time_offset", "error", ntpd_read_fp (ik->esterror));
+ ntpd_submit ("frequency_offset", "loop", ntpd_read_fp (ik->freq));
+ ntpd_submit ("time_offset", "loop", ntpd_read_fp (ik->offset));
+ ntpd_submit ("time_offset", "error", ntpd_read_fp (ik->esterror));
free (ik);
ik = NULL;
if (status != 0)
{
DBG ("ntpd_do_query failed with status %i", status);
- return;
+ return (-1);
}
if ((ps == NULL) || (ps_num == 0) || (ps_size == 0))
{
DBG ("ntpd_do_query returned: ps = %p; ps_num = %i; ps_size = %i;",
(void *) ps, ps_num, ps_size);
- return;
+ return (-1);
}
for (i = 0; i < ps_num; i++)
ntpd_read_fp (ptr->dispersion));
if (refclock_id != 1) /* not the system clock (offset will always be zero.. */
- ntpd_submit ("ntpd_time_offset", peername, offset);
- ntpd_submit ("ntpd_time_dispersion", peername, ntpd_read_fp (ptr->dispersion));
+ ntpd_submit ("time_offset", peername, offset);
+ ntpd_submit ("time_dispersion", peername, ntpd_read_fp (ptr->dispersion));
if (refclock_id == 0) /* not a reference clock */
- ntpd_submit ("ntpd_delay", peername, ntpd_read_fp (ptr->delay));
+ ntpd_submit ("delay", peername, ntpd_read_fp (ptr->delay));
}
free (ps);
ps = NULL;
- return;
-}
-#else
-# define ntpd_read NULL
+ return (0);
+} /* int ntpd_read */
#endif /* NTPD_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, ntpd_init, ntpd_read, NULL);
- plugin_register ("ntpd_time_offset", NULL, NULL, ntpd_write_time_offset);
- plugin_register ("ntpd_time_dispersion", NULL, NULL, ntpd_write_time_dispersion);
- plugin_register ("ntpd_delay", NULL, NULL, ntpd_write_delay);
- plugin_register ("ntpd_frequency_offset", NULL, NULL, ntpd_write_frequency_offset);
- cf_register (MODULE_NAME, ntpd_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&time_offset_ds);
+ plugin_register_data_set (&time_dispersion_ds);
+ plugin_register_data_set (&delay_ds);
+ plugin_register_data_set (&frequency_offset_ds);
-#undef MODULE_NAME
+#if NTPD_HAVE_READ
+ plugin_register_config ("ntpd", ntpd_config, config_keys, config_keys_num);
+ plugin_register_read ("ntpd", ntpd_read);
+#endif /* NTPD_HAVE_READ */
+}
diff --git a/src/ping.c b/src/ping.c
index 2a2f03eb39b80f062b652d4240c8fd3cddcee849..61bad09fd2807385f4594e12d433ebe63feabb3c 100644 (file)
--- a/src/ping.c
+++ b/src/ping.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "configfile.h"
#include "utils_debug.h"
-#define MODULE_NAME "ping"
-
#include <netinet/in.h>
#include "liboping/oping.h"
+/*
+ * Private data types
+ */
struct hostlist_s
{
char *host;
};
typedef struct hostlist_s hostlist_t;
+/*
+ * Private variables
+ */
static pingobj_t *pingobj = NULL;
static hostlist_t *hosts = NULL;
-static char *file_template = "ping-%s.rrd";
+static data_source_t dsrc[1] =
+{
+ {"ping", DS_TYPE_GAUGE, 0, 65535.0},
+};
-static char *ds_def[] =
+static data_set_t ds =
{
- "DS:ping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "ping", 1, dsrc
};
-static int ds_num = 1;
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Host",
"TTL",
};
static int config_keys_num = 2;
+/*
+ * Private functions
+ */
static void add_hosts (void)
{
hostlist_t *hl_this;
}
}
-static void ping_init (void)
+static int ping_init (void)
{
if (hosts != NULL)
add_hosts ();
+
+ return (0);
}
-static int ping_config (char *key, char *value)
+static int ping_config (const char *key, const char *value)
{
if (pingobj == NULL)
{
return (0);
}
-static void ping_write (char *host, char *inst, char *val)
-{
- char file[512];
- int status;
-
- status = snprintf (file, 512, file_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-#define BUFSIZE 256
static void ping_submit (char *host, double latency)
{
- char buf[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = latency;
- if (snprintf (buf, BUFSIZE, "%u:%f", (unsigned int) curtime, latency) >= BUFSIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "ping");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, host, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, host, buf);
+ plugin_dispatch_values ("ping", &vl);
}
-#undef BUFSIZE
-static void ping_read (void)
+static int ping_read (void)
{
pingobj_iter_t *iter;
size_t buf_len;
if (pingobj == NULL)
- return;
+ return (-1);
if (hosts != NULL)
add_hosts ();
{
syslog (LOG_ERR, "ping: `ping_send' failed: %s",
ping_get_error (pingobj));
- return;
+ return (-1);
}
for (iter = ping_iterator_get (pingobj);
DBG ("host = %s, latency = %f", host, latency);
ping_submit (host, latency);
}
-}
+
+ return (0);
+} /* int ping_read */
void module_register (void)
{
- plugin_register (MODULE_NAME, ping_init, ping_read, ping_write);
- cf_register (MODULE_NAME, ping_config, config_keys, config_keys_num);
-}
-
-#undef MODULE_NAME
+ plugin_register_data_set (&ds);
+ plugin_register_init ("ping", ping_init);
+ plugin_register_read ("ping", ping_read);
+ plugin_register_config ("ping", ping_config, config_keys, config_keys_num);
+} /* void module_register */
diff --git a/src/plugin.c b/src/plugin.c
index d708b6bc8a6acc0ffecb47cf6575c8ab3ccaa611..1a029e40ba5060375865723859fec957787fa780 100644 (file)
--- a/src/plugin.c
+++ b/src/plugin.c
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include <ltdl.h>
#include "plugin.h"
-#include "network.h"
+#include "configfile.h"
+#include "utils_llist.h"
#include "utils_debug.h"
-typedef struct plugin
+/*
+ * Private structures
+ */
+struct read_func_s
{
- char *type;
- void (*init) (void);
- void (*read) (void);
- void (*write) (char *host, char *inst, char *val);
- void (*shutdown) (void);
- struct plugin *next;
-} plugin_t;
-
-static plugin_t *first_plugin = NULL;
+ int wait_time;
+ int wait_left;
+ int (*callback) (void);
+};
+typedef struct read_func_s read_func_t;
-extern int operating_mode;
+/*
+ * Private variables
+ */
+static llist_t *list_init;
+static llist_t *list_read;
+static llist_t *list_write;
+static llist_t *list_shutdown;
+static llist_t *list_data_set;
static char *plugindir = NULL;
-char *plugin_get_dir (void)
+char hostname[DATA_MAX_NAME_LEN] = "localhost";
+
+/*
+ * Static functions
+ */
+static const char *plugin_get_dir (void)
{
if (plugindir == NULL)
return (PLUGINDIR);
return (plugindir);
}
-void plugin_set_dir (const char *dir)
+static int register_callback (llist_t **list, const char *name, void *callback)
{
- if (plugindir != NULL)
- free (plugindir);
+ llentry_t *le;
- if (dir == NULL)
- plugindir = NULL;
- else if ((plugindir = strdup (dir)) == NULL)
- syslog (LOG_ERR, "strdup: %s", strerror (errno));
-}
+ if ((*list == NULL)
+ && ((*list = llist_create ()) == NULL))
+ return (-1);
-/*
- * Returns the number of plugins registered
- */
-int plugin_count (void)
-{
- int i;
- plugin_t *p;
+ le = llist_search (*list, name);
+ if (le == NULL)
+ {
+ le = llentry_create (name, callback);
+ if (le == NULL)
+ return (-1);
- for (i = 0, p = first_plugin; p != NULL; p = p->next)
- i++;
+ llist_append (*list, le);
+ }
+ else
+ {
+ le->value = callback;
+ }
- return (i);
-}
+ return (0);
+} /* int register_callback */
-/*
- * Returns the plugins with the type `type' or NULL if it's not found.
- */
-plugin_t *plugin_search (const char *type)
+static int plugin_unregister (llist_t *list, const char *name)
{
- plugin_t *ret;
+ llentry_t *e;
- if (type == NULL)
- return (NULL);
+ e = llist_search (list, name);
- for (ret = first_plugin; ret != NULL; ret = ret->next)
- if (strcmp (ret->type, type) == 0)
- break;
+ if (e == NULL)
+ return (-1);
- return (ret);
-}
+ llist_remove (list, e);
+ llentry_destroy (e);
-/*
- * Returns true if the plugin is loaded (i.e. `exists') and false otherwise.
- * This is used in `configfile.c' to skip sections that are not needed..
- */
-int plugin_exists (char *type)
-{
- if (plugin_search (type) == NULL)
- return (0);
- else
- return (1);
-}
+ return (0);
+} /* int plugin_unregister */
/*
* (Try to) load the shared object `file'. Won't complain if it isn't a shared
* object, but it will bitch about a shared object not having a
* ``module_register'' symbol..
*/
-int plugin_load_file (char *file)
+static int plugin_load_file (char *file)
{
lt_dlhandle dlh;
void (*reg_handle) (void);
return (0);
}
+/*
+ * Public functions
+ */
+void plugin_set_dir (const char *dir)
+{
+ if (plugindir != NULL)
+ free (plugindir);
+
+ if (dir == NULL)
+ plugindir = NULL;
+ else if ((plugindir = strdup (dir)) == NULL)
+ syslog (LOG_ERR, "strdup failed: %s", strerror (errno));
+}
+
#define BUFSIZE 512
int plugin_load (const char *type)
{
DIR *dh;
- char *dir;
+ const char *dir;
char filename[BUFSIZE];
char typename[BUFSIZE];
int typename_len;
dir = plugin_get_dir ();
ret = 1;
- /* don't load twice */
- if (plugin_search (type) != NULL)
- return (0);
-
/* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
* type when matching the filename */
if (snprintf (typename, BUFSIZE, "%s.so", type) >= BUFSIZE)
}
/*
- * (Try to) load all plugins in `dir'. Returns the number of loaded plugins..
+ * The `register_*' functions follow
*/
-int plugin_load_all (char *dir)
+int plugin_register_config (const char *name,
+ int (*callback) (const char *key, const char *val),
+ const char **keys, int keys_num)
{
- DIR *dh;
- struct dirent *de;
- char filename[BUFSIZE];
- struct stat statbuf;
+ cf_register (name, callback, keys, keys_num);
+ return (0);
+} /* int plugin_register_config */
- if (dir == NULL)
- dir = plugin_get_dir ();
- else
- plugin_set_dir (dir);
+int plugin_register_init (const char *name,
+ int (*callback) (void))
+{
+ return (register_callback (&list_init, name, (void *) callback));
+} /* plugin_register_init */
- if ((dh = opendir (dir)) == NULL)
- {
- syslog (LOG_ERR, "opendir (%s): %s", dir, strerror (errno));
- return (0);
- }
+int plugin_register_read (const char *name,
+ int (*callback) (void))
+{
+ read_func_t *rf;
- while ((de = readdir (dh)) != NULL)
+ rf = (read_func_t *) malloc (sizeof (read_func_t));
+ if (rf == NULL)
{
- if (snprintf (filename, BUFSIZE, "%s/%s", dir, de->d_name) >= BUFSIZE)
- {
- syslog (LOG_WARNING, "snprintf: truncated: %s/%s", dir, de->d_name);
- continue;
- }
+ syslog (LOG_ERR, "plugin_register_read: malloc failed: %s",
+ strerror (errno));
+ return (-1);
+ }
- if (lstat (filename, &statbuf) == -1)
- {
- syslog (LOG_WARNING, "stat %s: %s", filename, strerror (errno));
- continue;
- }
- else if (!S_ISREG (statbuf.st_mode))
- {
- continue;
- }
+ memset (rf, '\0', sizeof (read_func_t));
+ rf->wait_time = atoi (COLLECTD_STEP);
+ rf->wait_left = 0;
+ rf->callback = callback;
- plugin_load_file (filename);
- }
+ return (register_callback (&list_read, name, (void *) rf));
+} /* int plugin_register_read */
- closedir (dh);
+int plugin_register_write (const char *name,
+ int (*callback) (const data_set_t *ds, const value_list_t *vl))
+{
+ return (register_callback (&list_write, name, (void *) callback));
+} /* int plugin_register_write */
- return (plugin_count ());
-}
-#undef BUFSIZE
+int plugin_register_shutdown (char *name,
+ int (*callback) (void))
+{
+ return (register_callback (&list_shutdown, name, (void *) callback));
+} /* int plugin_register_shutdown */
-/*
- * Call `init' on all plugins (if given)
- */
-void plugin_init_all (void)
+int plugin_register_data_set (const data_set_t *ds)
{
- plugin_t *p;
+ return (register_callback (&list_data_set, ds->type, (void *) ds));
+} /* int plugin_register_data_set */
- for (p = first_plugin; p != NULL; p = p->next)
- if (p->init != NULL)
- (*p->init) ();
+int plugin_unregister_init (const char *name)
+{
+ return (plugin_unregister (list_init, name));
}
-/*
- * Call `read' on all plugins (if given)
- */
-void plugin_read_all (const int *loop)
+int plugin_unregister_read (const char *name)
{
- plugin_t *p;
+ return (plugin_unregister (list_read, name));
+ llentry_t *e;
+
+ e = llist_search (list_read, name);
+
+ if (e == NULL)
+ return (-1);
+
+ llist_remove (list_read, e);
+ free (e->value);
+ llentry_destroy (e);
- for (p = first_plugin; (*loop == 0) && (p != NULL); p = p->next)
- if (p->read != NULL)
- (*p->read) ();
+ return (0);
}
-/*
- * Call `shutdown' on all plugins (if given)
- */
-void plugin_shutdown_all (void)
+int plugin_unregister_write (const char *name)
{
- plugin_t *p;
+ return (plugin_unregister (list_write, name));
+}
- for (p = first_plugin; NULL != p; p = p->next)
- if (NULL != p->shutdown)
- (*p->shutdown) ();
- return;
+int plugin_unregister_shutdown (const char *name)
+{
+ return (plugin_unregister (list_shutdown, name));
}
-/*
- * Add plugin to the linked list of registered plugins.
- */
-void plugin_register (char *type,
- void (*init) (void),
- void (*read) (void),
- void (*write) (char *, char *, char *))
+int plugin_unregister_data_set (const char *name)
{
- plugin_t *p;
+ return (plugin_unregister (list_data_set, name));
+}
- if (plugin_search (type) != NULL)
- return;
+void plugin_init_all (void)
+{
+ int (*callback) (void);
+ llentry_t *le;
+ int status;
-#ifdef HAVE_LIBRRD
- if (operating_mode != MODE_SERVER)
-#endif
- if ((init != NULL) && (read == NULL))
- syslog (LOG_NOTICE, "Plugin `%s' doesn't provide a read function.", type);
+ gethostname (hostname, sizeof (hostname));
- if ((p = (plugin_t *) malloc (sizeof (plugin_t))) == NULL)
+ if (list_init == NULL)
return;
- if ((p->type = strdup (type)) == NULL)
+ le = llist_head (list_init);
+ while (le != NULL)
{
- free (p);
- return;
+ callback = le->value;
+ status = (*callback) ();
+
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "Initialization of plugin `%s' "
+ "failed with status %i. "
+ "Plugin will be unloaded. TODO!",
+ le->key, status);
+ plugin_unregister_read (le->key);
+ }
+
+ le = le->next;
}
+} /* void plugin_init_all */
- p->init = init;
- p->read = read;
- p->write = write;
+void plugin_read_all (const int *loop)
+{
+ llentry_t *le;
+ read_func_t *rf;
+ int status;
+ int step;
- p->shutdown = NULL;
+ if (list_read == NULL)
+ return;
- p->next = first_plugin;
- first_plugin = p;
-}
+ step = atoi (COLLECTD_STEP);
-/*
- * Register the shutdown function (optional).
- */
-int plugin_register_shutdown (char *type, void (*shutdown) (void))
-{
- plugin_t *p = plugin_search (type);
+ le = llist_head (list_read);
+ while ((*loop == 0) && (le != NULL))
+ {
+ rf = (read_func_t *) le->value;
- if (NULL == p)
- return -1;
+ if (rf->wait_left > 0)
+ rf->wait_left -= step;
+ if (rf->wait_left > 0)
+ {
+ le = le->next;
+ continue;
+ }
- p->shutdown = shutdown;
- return 0;
-}
+ status = rf->callback ();
+ if (status != 0)
+ {
+ rf->wait_left = rf->wait_time;
+ rf->wait_time = rf->wait_time * 2;
+ if (rf->wait_time > 86400)
+ rf->wait_time = 86400;
+
+ syslog (LOG_NOTICE, "read-function of plugin `%s' "
+ "failed. Will syspend it for %i "
+ "seconds.", le->key, rf->wait_left);
+ }
+ else
+ {
+ rf->wait_left = 0;
+ rf->wait_time = step;
+ }
-/*
- * Send received data back to the plugin/module which will append DS
- * definitions and pass it on to ``rrd_update_file''.
- */
-void plugin_write (char *host, char *type, char *inst, char *val)
+ le = le->next;
+ } /* while ((*loop == 0) && (le != NULL)) */
+} /* void plugin_read_all */
+
+void plugin_shutdown_all (void)
{
- plugin_t *p;
+ int (*callback) (void);
+ llentry_t *le;
- if ((p = plugin_search (type)) == NULL)
+ if (list_shutdown == NULL)
return;
- if (p->write == NULL)
- return;
+ le = llist_head (list_shutdown);
+ while (le != NULL)
+ {
+ callback = le->value;
+ (*callback) ();
- (*p->write) (host, inst, val);
-}
+ le = le->next;
+ }
+} /* void plugin_shutdown_all */
-/*
- * Receive data from the plugin/module and get it somehow to ``plugin_write'':
- * Either using ``network_send'' (when in network/client mode) or call it
- * directly (in local mode).
- */
-void plugin_submit (char *type, char *inst, char *val)
+int plugin_dispatch_values (const char *name, const value_list_t *vl)
{
- if (inst == NULL)
- inst = "-";
+ int (*callback) (const data_set_t *, const value_list_t *);
+ data_set_t *ds;
+ llentry_t *le;
+
+ if (list_write == NULL)
+ return (-1);
- if ((type == NULL) || (val == NULL))
+ le = llist_search (list_data_set, name);
+ if (le == NULL)
{
- DBG ("Help! NULL-pointer! type = %s; inst = %s; val = %s;",
- (type == NULL) ? "(null)" : type,
- inst,
- (val == NULL) ? "(null)" : val);
- return;
+ DBG ("No such dataset registered: %s", name);
+ return (-1);
}
- if (operating_mode == MODE_CLIENT)
- network_send (type, inst, val);
- else
- plugin_write (NULL, type, inst, val);
+ ds = (data_set_t *) le->value;
+
+ DBG ("time = %u; host = %s; "
+ "plugin = %s; plugin_instance = %s; "
+ "type = %s; type_instance = %s;",
+ (unsigned int) vl->time, vl->host,
+ vl->plugin, vl->plugin_instance,
+ ds->type, vl->type_instance);
+
+ le = llist_head (list_write);
+ while (le != NULL)
+ {
+ callback = le->value;
+ (*callback) (ds, vl);
+
+ le = le->next;
+ }
+
+ return (0);
}
void plugin_complain (int level, complain_t *c, const char *format, ...)
diff --git a/src/plugin.h b/src/plugin.h
index 45e9b494fc60634b568ee6a7f0d9bc4bc263656f..b0bdbee12f164a3fc96b0c1bd4f1d85f69c44998 100644 (file)
--- a/src/plugin.h
+++ b/src/plugin.h
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* Florian octo Forster <octo at verplant.org>
**/
+#define DATA_MAX_NAME_LEN 64
+
+#define DS_TYPE_COUNTER 0
+#define DS_TYPE_GAUGE 1
+
/*
- *
+ * Public data types
*/
+typedef unsigned long long counter_t;
+typedef double gauge_t;
+
+union value_u
+{
+ counter_t counter;
+ gauge_t gauge;
+};
+typedef union value_u value_t;
+
+struct value_list_s
+{
+ value_t *values;
+ int values_len;
+ time_t time;
+ char host[DATA_MAX_NAME_LEN];
+ char plugin[DATA_MAX_NAME_LEN];
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
+};
+typedef struct value_list_s value_list_t;
+
+#define VALUE_LIST_INIT { NULL, 0, 0, "localhost", "", "", "" }
+
+struct data_source_s
+{
+ char name[DATA_MAX_NAME_LEN];
+ int type;
+ double min;
+ double max;
+};
+typedef struct data_source_s data_source_t;
+
+struct data_set_s
+{
+ char type[DATA_MAX_NAME_LEN];
+ int ds_num;
+ data_source_t *ds;
+};
+typedef struct data_set_s data_set_t;
+
typedef struct complain_s
{
unsigned int interval; /* how long we wait for reporting this error again */
unsigned int delay; /* how many more iterations we still need to wait */
} complain_t;
+extern char hostname[DATA_MAX_NAME_LEN];
+
/*
* NAME
* plugin_set_dir
*/
void plugin_set_dir (const char *dir);
-/*
- * NAME
- * plugin_count
- *
- * DESCRIPTION
- * trivial
- *
- * RETURN VALUE
- * The number of currently loaded plugins
- */
-int plugin_count (void);
-
-/*
- * NAME
- * plugin_exists
- *
- * DESCRIPTION
- * trivial
- *
- * ARGUMENTS
- * `type' Name of the plugin.
- *
- * RETURN VALUE
- * Returns non-zero if a plugin with the name $type is found and zero
- * otherwise.
- */
-int plugin_exists (char *type);
-
/*
* NAME
* plugin_load
* NOTES
* No attempt is made to re-load an already loaded module.
*/
-int plugin_load (const char *type);
+int plugin_load (const char *name);
-int plugin_load_all (char *dir);
void plugin_init_all (void);
void plugin_read_all (const int *loop);
-
void plugin_shutdown_all (void);
-void plugin_register (char *type,
- void (*init) (void),
- void (*read) (void),
- void (*write) (char *, char *, char *));
+/*
+ * The `plugin_register_*' functions are used to make `config', `init',
+ * `read', `write' and `shutdown' functions known to the plugin
+ * infrastructure. Also, the data-formats are made public like this.
+ */
+int plugin_register_config (const char *name,
+ int (*callback) (const char *key, const char *val),
+ const char **keys, int keys_num);
+int plugin_register_init (const char *name,
+ int (*callback) (void));
+int plugin_register_read (const char *name,
+ int (*callback) (void));
+int plugin_register_write (const char *name,
+ int (*callback) (const data_set_t *ds, const value_list_t *vl));
+int plugin_register_shutdown (char *name,
+ int (*callback) (void));
+int plugin_register_data_set (const data_set_t *ds);
-int plugin_register_shutdown (char *, void (*) (void));
+int plugin_unregister_init (const char *name);
+int plugin_unregister_read (const char *name);
+int plugin_unregister_write (const char *name);
+int plugin_unregister_shutdown (const char *name);
+int plugin_unregister_data_set (const char *name);
/*
* NAME
- * plugin_write
+ * plugin_dispatch_values
*
* DESCRIPTION
- * Searches the plugin for `type' in the plugin-list. If found, and a `write'
- * function is registered, it's called. If either the plugin is not found or
- * the plugin doesn't provide a `write' function this function will return
- * without further notice.
+ * This function is called by reading processes with the values they've
+ * aquired. The function fetches the data-set definition (that has been
+ * registered using `plugin_register_data_set') and calls _all_ registered
+ * write-functions.
*
* ARGUMENTS
- * `host' Host(name) from which the data originates.
- * `type' Name of the plugin.
- * `inst' Instance (passed to the plugin's `write' function.
- * `val' Values for the RRD files. Also passed to the plugin.
+ * `name' Name/type of the data-set that describe the values in `vl'.
+ * `vl' Value list of the values that have been read by a `read'
+ * function.
*/
-void plugin_write (char *host, char *type, char *inst, char *val);
-
-void plugin_submit (char *type, char *inst, char *val);
-
+int plugin_dispatch_values (const char *name, const value_list_t *vl);
+/* TODO: Move plugin_{complain,relief} into `utils_complain.[ch]'. -octo */
void plugin_complain (int level, complain_t *c, const char *format, ...);
void plugin_relief (int level, complain_t *c, const char *format, ...);
diff --git a/src/processes.c b/src/processes.c
index 68984458058df5e69769662b7086833867d22c00..c22f0f6f8265e160f61971624a58955744c24638 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
/**
* collectd - src/processes.c
* Copyright (C) 2005 Lyonel Vincent
- * Copyright (C) 2006 Florian Forster (Mach code)
+ * Copyright (C) 2006-2007 Florian Forster (Mach code)
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#define BUFSIZE 256
-static char *processes_file = "processes.rrd";
-static char *processes_ds_def[] =
+static data_source_t state_dsrc[1] =
{
- "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:sleeping:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:zombies:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:stopped:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:paging:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:blocked:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ {"value", DS_TYPE_GAUGE, 0.0, 65535.0}
};
-static int processes_ds_num = 6;
-static char *ps_rss_file = "processes/ps_rss-%s.rrd";
-static char *ps_rss_ds_def[] =
+static data_set_t state_ds =
+{
+ "ps_state", 1, state_dsrc
+};
+
+static data_source_t rss_dsrc[1] =
{
/* max = 2^63 - 1 */
- "DS:byte:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- NULL
+ {"value", DS_TYPE_GAUGE, 0.0, 9223372036854775807.0}
};
-static int ps_rss_ds_num = 1;
-static char *ps_cputime_file = "processes/ps_cputime-%s.rrd";
-static char *ps_cputime_ds_def[] =
+static data_set_t rss_ds =
+{
+ "ps_rss", 1, rss_dsrc
+};
+
+static data_source_t time_dsrc[2] =
{
/* 1 second in user-mode per second ought to be enough.. */
- "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:1000000",
- "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:1000000",
- NULL
+ {"user", DS_TYPE_COUNTER, 0.0, 1000000.0},
+ {"syst", DS_TYPE_COUNTER, 0.0, 1000000.0}
};
-static int ps_cputime_ds_num = 2;
-static char *ps_count_file = "processes/ps_count-%s.rrd";
-static char *ps_count_ds_def[] =
+static data_set_t time_ds =
{
- "DS:processes:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- "DS:threads:GAUGE:"COLLECTD_HEARTBEAT":0:65535",
- NULL
+ "ps_cputime", 2, time_dsrc
+};
+
+static data_source_t count_dsrc[2] =
+{
+ /* 1 second in user-mode per second ought to be enough.. */
+ {"processes", DS_TYPE_GAUGE, 0.0, 1000000.0},
+ {"threads", DS_TYPE_GAUGE, 0.0, 1000000.0}
};
-static int ps_count_ds_num = 2;
-static char *ps_pagefaults_file = "processes/ps_pagefaults-%s.rrd";
-static char *ps_pagefaults_ds_def[] =
+static data_set_t count_ds =
+{
+ "ps_count", 2, count_dsrc
+};
+
+static data_source_t pagefaults_dsrc[2] =
{
/* max = 2^63 - 1 */
- "DS:minflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- "DS:majflt:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807",
- NULL
+ {"minflt", DS_TYPE_COUNTER, 0.0, 9223372036854775807.0},
+ {"majflt", DS_TYPE_COUNTER, 0.0, 9223372036854775807.0}
};
-static int ps_pagefaults_ds_num = 2;
+static data_set_t pagefaults_ds =
+{
+ "ps_pagefaults", 2, pagefaults_dsrc
+};
+
+#if PROCESSES_HAVE_READ
#if HAVE_THREAD_INFO | KERNEL_LINUX
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Process",
NULL
} /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
}
-static int ps_config (char *key, char *value)
+static int ps_config (const char *key, const char *value)
{
if (strcasecmp (key, "Process") == 0)
{
}
#endif /* HAVE_THREAD_INFO | KERNEL_LINUX */
-static void ps_init (void)
+static int ps_init (void)
{
#if HAVE_THREAD_INFO
kern_return_t status;
mach_error_string (status));
pset_list = NULL;
pset_list_len = 0;
- return;
+ return (-1);
}
/* #endif HAVE_THREAD_INFO */
pagesize_g, CONFIG_HZ);
#endif /* KERNEL_LINUX */
- return;
-}
-
-static void ps_write (char *host, char *inst, char *val)
-{
- rrd_update_file (host, processes_file, val,
- processes_ds_def, processes_ds_num);
-}
-
-static void ps_rss_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_rss_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- rrd_update_file (host, filename, val, ps_rss_ds_def, ps_rss_ds_num);
-}
-
-static void ps_cputime_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_cputime_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- DBG ("host = %s; filename = %s; val = %s;",
- host, filename, val);
- rrd_update_file (host, filename, val,
- ps_cputime_ds_def, ps_cputime_ds_num);
-}
-
-static void ps_count_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_count_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- DBG ("host = %s; filename = %s; val = %s;",
- host, filename, val);
- rrd_update_file (host, filename, val,
- ps_count_ds_def, ps_count_ds_num);
-}
-
-static void ps_pagefaults_write (char *host, char *inst, char *val)
-{
- char filename[256];
- int status;
-
- status = snprintf (filename, 256, ps_pagefaults_file, inst);
- if ((status < 1) || (status >= 256))
- return;
-
- DBG ("host = %s; filename = %s; val = %s;",
- host, filename, val);
- rrd_update_file (host, filename, val,
- ps_pagefaults_ds_def, ps_pagefaults_ds_num);
-}
+ return (0);
+} /* int ps_init */
-#if PROCESSES_HAVE_READ
-static void ps_submit (int running,
- int sleeping,
- int zombies,
- int stopped,
- int paging,
- int blocked)
+static void ps_submit_state (const char *state, double value)
{
- char buf[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%i:%i:%i",
- (unsigned int) curtime,
- running, sleeping, zombies, stopped, paging,
- blocked) >= BUFSIZE)
- return;
+ values[0].gauge = value;
- DBG ("running = %i; sleeping = %i; zombies = %i; stopped = %i; paging = %i; blocked = %i;",
- running, sleeping, zombies, stopped, paging, blocked);
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "processes");
+ strcpy (vl.plugin_instance, "");
+ strncpy (vl.type_instance, state, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, "-", buf);
+ plugin_dispatch_values ("ps_state", &vl);
}
static void ps_submit_proc_list (procstat_t *ps)
{
- char buffer[64];
-
- if (ps == NULL)
- return;
-
- snprintf (buffer, 64, "%u:%lu",
- (unsigned int) curtime,
- ps->vmem_rss);
- buffer[63] = '\0';
- plugin_submit ("ps_rss", ps->name, buffer);
-
- snprintf (buffer, 64, "%u:%u:%u",
- (unsigned int) curtime,
- /* Make the counter overflow */
- (unsigned int) (ps->cpu_user_counter & 0xFFFFFFFF),
- (unsigned int) (ps->cpu_system_counter & 0xFFFFFFFF));
- buffer[63] = '\0';
- plugin_submit ("ps_cputime", ps->name, buffer);
-
- snprintf (buffer, 64, "%u:%lu:%lu",
- (unsigned int) curtime,
- ps->num_proc, ps->num_lwp);
- buffer[63] = '\0';
- plugin_submit ("ps_count", ps->name, buffer);
-
- snprintf (buffer, 64, "%u:%lu:%lu",
- (unsigned int) curtime,
- ps->vmem_minflt_counter, ps->vmem_majflt_counter);
- buffer[63] = '\0';
- plugin_submit ("ps_pagefaults", ps->name, buffer);
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "processes");
+ strncpy (vl.plugin_instance, ps->name, sizeof (vl.plugin_instance));
+
+ vl.values[0].gauge = ps->vmem_rss;
+ vl.values_len = 1;
+ plugin_dispatch_values ("ps_rss", &vl);
+
+ vl.values[0].counter = ps->cpu_user_counter;
+ vl.values[1].counter = ps->cpu_system_counter;
+ vl.values_len = 2;
+ plugin_dispatch_values ("ps_cputime", &vl);
+
+ vl.values[0].gauge = ps->num_proc;
+ vl.values[1].gauge = ps->num_lwp;
+ vl.values_len = 2;
+ plugin_dispatch_values ("ps_count", &vl);
+
+ vl.values[0].counter = ps->vmem_minflt_counter;
+ vl.values[1].counter = ps->vmem_majflt_counter;
+ vl.values_len = 2;
+ plugin_dispatch_values ("ps_pagefaults", &vl);
DBG ("name = %s; num_proc = %lu; num_lwp = %lu; vmem_rss = %lu; "
"vmem_minflt_counter = %lu; vmem_majflt_counter = %lu; "
"cpu_user_counter = %lu; cpu_system_counter = %lu;",
ps->name, ps->num_proc, ps->num_lwp, ps->vmem_rss,
- ps->vmem_minflt_counter, ps->vmem_majflt_counter, ps->cpu_user_counter,
- ps->cpu_system_counter);
-
-}
+ ps->vmem_minflt_counter, ps->vmem_majflt_counter,
+ ps->cpu_user_counter, ps->cpu_system_counter);
+} /* void ps_submit_proc_list */
#if KERNEL_LINUX
static int *ps_read_tasks (int pid)
@@ -794,7 +731,7 @@ static int mach_get_task_name (task_t t, int *pid, char *name, size_t name_max_l
}
#endif /* HAVE_THREAD_INFO */
-static void ps_read (void)
+static int ps_read (void)
{
#if HAVE_THREAD_INFO
kern_return_t status;
}
} /* for (pset_list) */
- ps_submit (running, sleeping, zombies, stopped, -1, blocked);
+ ps_submit_state ("running", running);
+ ps_submit_state ("sleeping", sleeping);
+ ps_submit_state ("zombies", zombies);
+ ps_submit_state ("stopped", stopped);
+ ps_submit_state ("blocked", blocked);
for (ps = list_head_g; ps != NULL; ps = ps->next)
ps_submit_proc_list (ps);
if ((proc = opendir ("/proc")) == NULL)
{
syslog (LOG_ERR, "Cannot open `/proc': %s", strerror (errno));
- return;
+ return (-1);
}
while ((ent = readdir (proc)) != NULL)
closedir (proc);
- ps_submit (running, sleeping, zombies, stopped, paging, blocked);
+ ps_submit_state ("running", running);
+ ps_submit_state ("sleeping", sleeping);
+ ps_submit_state ("zombies", zombies);
+ ps_submit_state ("stopped", stopped);
+ ps_submit_state ("paging", paging);
+ ps_submit_state ("blocked", blocked);
for (ps_ptr = list_head_g; ps_ptr != NULL; ps_ptr = ps_ptr->next)
ps_submit_proc_list (ps_ptr);
#endif /* KERNEL_LINUX */
-}
-#else
-# define ps_read NULL
+
+ return (0);
+} /* int ps_read */
#endif /* PROCESSES_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, ps_init, ps_read, ps_write);
- plugin_register ("ps_rss", NULL, NULL, ps_rss_write);
- plugin_register ("ps_cputime", NULL, NULL, ps_cputime_write);
- plugin_register ("ps_count", NULL, NULL, ps_count_write);
- plugin_register ("ps_pagefaults", NULL, NULL, ps_pagefaults_write);
+ plugin_register_data_set (&state_ds);
+ plugin_register_data_set (&rss_ds);
+ plugin_register_data_set (&time_ds);
+ plugin_register_data_set (&count_ds );
+ plugin_register_data_set (&pagefaults_ds );
+
+#if PROCESSES_HAVE_READ
#if HAVE_THREAD_INFO | KERNEL_LINUX
- cf_register (MODULE_NAME, ps_config, config_keys, config_keys_num);
+ plugin_register_config ("processes", ps_config,
+ config_keys, config_keys_num);
#endif
+ plugin_register_init ("processes", ps_init);
+ plugin_register_read ("processes", ps_read);
+#endif /* PROCESSES_HAVE_READ */
}
-#undef BUFSIZE
-#undef MODULE_NAME
diff --git a/src/rrdtool.c b/src/rrdtool.c
--- /dev/null
+++ b/src/rrdtool.c
@@ -0,0 +1,742 @@
+/**
+ * collectd - src/rrdtool.c
+ * Copyright (C) 2006 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_avltree.h"
+#include "utils_debug.h"
+
+/*
+ * This weird macro cascade forces the glibc to define `NAN'. I don't know
+ * another way to solve this, so more intelligent solutions are welcome. -octo
+ */
+#ifndef __USE_ISOC99
+# define DISABLE__USE_ISOC99 1
+# define __USE_ISOC99 1
+#endif
+#include <math.h>
+#ifdef DISABLE__USE_ISOC99
+# undef DISABLE__USE_ISOC99
+# undef __USE_ISOC99
+#endif
+
+/*
+ * Private types
+ */
+struct rrd_cache_s
+{
+ int values_num;
+ char **values;
+ time_t first_value;
+};
+typedef struct rrd_cache_s rrd_cache_t;
+
+/*
+ * Private variables
+ */
+static int rra_timespans[] =
+{
+ 3600,
+ 86400,
+ 604800,
+ 2678400,
+ 31622400,
+ 0
+};
+static int rra_timespans_num = 5;
+
+static char *rra_types[] =
+{
+ "AVERAGE",
+ "MIN",
+ "MAX",
+ NULL
+};
+static int rra_types_num = 3;
+
+static const char *config_keys[] =
+{
+ "CacheTimeout",
+ "CacheFlush",
+ "DataDir",
+ NULL
+};
+static int config_keys_num = 3;
+
+static char *datadir = NULL;
+
+static int cache_timeout = 0;
+static int cache_flush_timeout = 0;
+static time_t cache_flush_last;
+static avl_tree_t *cache = NULL;
+
+/* * * * * * * * * *
+ * WARNING: Magic *
+ * * * * * * * * * */
+static int rra_get (char ***ret)
+{
+ static char **rra_def = NULL;
+ static int rra_num = 0;
+
+ int rra_max = rra_timespans_num * rra_types_num;
+
+ int step;
+ int rows;
+ int span;
+
+ int cdp_num;
+ int cdp_len;
+ int i, j;
+
+ char buffer[64];
+
+ if ((rra_num != 0) && (rra_def != NULL))
+ {
+ *ret = rra_def;
+ return (rra_num);
+ }
+
+ if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL)
+ return (-1);
+ memset (rra_def, '\0', (rra_max + 1) * sizeof (char *));
+
+ step = atoi (COLLECTD_STEP);
+ rows = atoi (COLLECTD_ROWS);
+
+ if ((step <= 0) || (rows <= 0))
+ {
+ *ret = NULL;
+ return (-1);
+ }
+
+ cdp_len = 0;
+ for (i = 0; i < rra_timespans_num; i++)
+ {
+ span = rra_timespans[i];
+
+ if ((span / step) < rows)
+ continue;
+
+ if (cdp_len == 0)
+ cdp_len = 1;
+ else
+ cdp_len = (int) floor (((double) span) / ((double) (rows * step)));
+
+ cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step)));
+
+ for (j = 0; j < rra_types_num; j++)
+ {
+ if (rra_num >= rra_max)
+ break;
+
+ if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u",
+ rra_types[j], COLLECTD_XFF,
+ cdp_len, cdp_num) >= sizeof (buffer))
+ {
+ syslog (LOG_ERR, "rra_get: Buffer would have been truncated.");
+ continue;
+ }
+
+ rra_def[rra_num++] = sstrdup (buffer);
+ }
+ }
+
+#if COLLECT_DEBUG
+ DBG ("rra_num = %i", rra_num);
+ for (i = 0; i < rra_num; i++)
+ DBG (" %s", rra_def[i]);
+#endif
+
+ *ret = rra_def;
+ return (rra_num);
+}
+
+static void ds_free (int ds_num, char **ds_def)
+{
+ int i;
+
+ for (i = 0; i < ds_num; i++)
+ if (ds_def[i] != NULL)
+ free (ds_def[i]);
+ free (ds_def);
+}
+
+static int ds_get (char ***ret, const data_set_t *ds)
+{
+ char **ds_def;
+ int ds_num;
+
+ char min[32];
+ char max[32];
+ char buffer[128];
+
+ DBG ("ds->ds_num = %i", ds->ds_num);
+
+ ds_def = (char **) malloc (ds->ds_num * sizeof (char *));
+ if (ds_def == NULL)
+ {
+ syslog (LOG_ERR, "rrdtool plugin: malloc failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+ memset (ds_def, '\0', ds->ds_num * sizeof (char *));
+
+ for (ds_num = 0; ds_num < ds->ds_num; ds_num++)
+ {
+ data_source_t *d = ds->ds + ds_num;
+ char *type;
+ int status;
+
+ ds_def[ds_num] = NULL;
+
+ if (d->type == DS_TYPE_COUNTER)
+ type = "COUNTER";
+ else if (d->type == DS_TYPE_GAUGE)
+ type = "GAUGE";
+ else
+ {
+ syslog (LOG_ERR, "rrdtool plugin: Unknown DS type: %i",
+ d->type);
+ break;
+ }
+
+ if (d->min == NAN)
+ {
+ strcpy (min, "U");
+ }
+ else
+ {
+ snprintf (min, sizeof (min), "%lf", d->min);
+ min[sizeof (min) - 1] = '\0';
+ }
+
+ if (d->max == NAN)
+ {
+ strcpy (max, "U");
+ }
+ else
+ {
+ snprintf (max, sizeof (max), "%lf", d->max);
+ max[sizeof (max) - 1] = '\0';
+ }
+
+ status = snprintf (buffer, sizeof (buffer),
+ "DS:%s:%s:%s:%s:%s",
+ d->name, type, COLLECTD_HEARTBEAT,
+ min, max);
+ if ((status < 1) || (status >= sizeof (buffer)))
+ break;
+
+ ds_def[ds_num] = sstrdup (buffer);
+ } /* for ds_num = 0 .. ds->ds_num */
+
+#if COLLECT_DEBUG
+{
+ int i;
+ DBG ("ds_num = %i", ds_num);
+ for (i = 0; i < ds_num; i++)
+ DBG (" %s", ds_def[i]);
+}
+#endif
+
+ if (ds_num != ds->ds_num)
+ {
+ ds_free (ds_num, ds_def);
+ return (-1);
+ }
+
+ *ret = ds_def;
+ return (ds_num);
+}
+
+static int rrd_create_file (char *filename, const data_set_t *ds)
+{
+ char **argv;
+ int argc;
+ char **rra_def;
+ int rra_num;
+ char **ds_def;
+ int ds_num;
+ int i, j;
+ int status = 0;
+
+ if (check_create_dir (filename))
+ return (-1);
+
+ if ((rra_num = rra_get (&rra_def)) < 1)
+ {
+ syslog (LOG_ERR, "rrd_create_file failed: Could not calculate RRAs");
+ return (-1);
+ }
+
+ if ((ds_num = ds_get (&ds_def, ds)) < 1)
+ {
+ syslog (LOG_ERR, "rrd_create_file failed: Could not calculate DSes");
+ return (-1);
+ }
+
+ argc = ds_num + rra_num + 4;
+
+ if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL)
+ {
+ syslog (LOG_ERR, "rrd_create failed: %s", strerror (errno));
+ return (-1);
+ }
+
+ argv[0] = "create";
+ argv[1] = filename;
+ argv[2] = "-s";
+ argv[3] = COLLECTD_STEP;
+
+ j = 4;
+ for (i = 0; i < ds_num; i++)
+ argv[j++] = ds_def[i];
+ for (i = 0; i < rra_num; i++)
+ argv[j++] = rra_def[i];
+ argv[j] = NULL;
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+ if (rrd_create (argc, argv) == -1)
+ {
+ syslog (LOG_ERR, "rrd_create failed: %s: %s", filename, rrd_get_error ());
+ status = -1;
+ }
+
+ free (argv);
+ ds_free (ds_num, ds_def);
+
+ return (status);
+}
+
+static int value_list_to_string (char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ int offset;
+ int status;
+ int i;
+
+ memset (buffer, '\0', sizeof (buffer_len));
+
+ status = snprintf (buffer, buffer_len, "%u", (unsigned int) vl->time);
+ if ((status < 1) || (status >= buffer_len))
+ return (-1);
+ offset = status;
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if ((ds->ds[i].type != DS_TYPE_COUNTER)
+ && (ds->ds[i].type != DS_TYPE_GAUGE))
+ return (-1);
+
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ status = snprintf (buffer + offset, buffer_len - offset,
+ ":%llu", vl->values[i].counter);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ ":%lf", vl->values[i].gauge);
+
+ if ((status < 1) || (status >= (buffer_len - offset)))
+ return (-1);
+
+ offset += status;
+ } /* for ds->ds_num */
+
+ return (0);
+} /* int value_list_to_string */
+
+static int value_list_to_filename (char *buffer, int buffer_len,
+ const data_set_t *ds, const value_list_t *vl)
+{
+ int offset = 0;
+ int status;
+
+ if (datadir != NULL)
+ {
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s/", datadir);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+ }
+
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s/", vl->host);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ if (strlen (vl->plugin_instance) > 0)
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s-%s/", vl->plugin, vl->plugin_instance);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s/", vl->plugin);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ if (strlen (vl->type_instance) > 0)
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s-%s.rrd", ds->type, vl->type_instance);
+ else
+ status = snprintf (buffer + offset, buffer_len - offset,
+ "%s.rrd", ds->type);
+ if ((status < 1) || (status >= buffer_len - offset))
+ return (-1);
+ offset += status;
+
+ return (0);
+} /* int value_list_to_filename */
+
+static rrd_cache_t *rrd_cache_insert (const char *filename,
+ const char *value)
+{
+ rrd_cache_t *rc = NULL;
+ int new_rc = 0;
+
+ if (cache != NULL)
+ avl_get (cache, filename, (void *) &rc);
+
+ if (rc == NULL)
+ {
+ rc = (rrd_cache_t *) malloc (sizeof (rrd_cache_t));
+ if (rc == NULL)
+ return (NULL);
+ rc->values_num = 0;
+ rc->values = NULL;
+ rc->first_value = 0;
+ new_rc = 1;
+ }
+
+ rc->values = (char **) realloc ((void *) rc->values,
+ (rc->values_num + 1) * sizeof (char *));
+ if (rc->values == NULL)
+ {
+ syslog (LOG_ERR, "rrdtool plugin: realloc failed: %s",
+ strerror (errno));
+ if (cache != NULL)
+ {
+ void *cache_key = NULL;
+ avl_remove (cache, filename, &cache_key, NULL);
+ sfree (cache_key);
+ }
+ free (rc);
+ return (NULL);
+ }
+
+ rc->values[rc->values_num] = strdup (value);
+ if (rc->values[rc->values_num] != NULL)
+ rc->values_num++;
+
+ if (rc->values_num == 1)
+ rc->first_value = time (NULL);
+
+ /* Insert if this is the first value */
+ if ((cache != NULL) && (new_rc == 1))
+ {
+ void *cache_key = strdup (filename);
+
+ if (cache_key == NULL)
+ {
+ syslog (LOG_ERR, "rrdtool plugin: strdup failed: %s",
+ strerror (errno));
+ sfree (rc->values[0]);
+ sfree (rc->values);
+ sfree (rc);
+ return (NULL);
+ }
+
+ avl_insert (cache, cache_key, rc);
+ }
+
+ DBG ("rrd_cache_insert (%s, %s) = %p", filename, value, (void *) rc);
+
+ return (rc);
+} /* rrd_cache_t *rrd_cache_insert */
+
+static int rrd_write_cache_entry (const char *filename, rrd_cache_t *rc)
+{
+ char **argv;
+ int argc;
+
+ char *fn;
+ int status;
+
+ int i;
+
+ argc = rc->values_num + 2;
+ argv = (char **) malloc ((argc + 1) * sizeof (char *));
+ if (argv == NULL)
+ return (-1);
+
+ fn = strdup (filename);
+ if (fn == NULL)
+ {
+ free (argv);
+ return (-1);
+ }
+
+ argv[0] = "update";
+ argv[1] = fn;
+ memcpy (argv + 2, rc->values, rc->values_num * sizeof (char *));
+ argv[argc] = NULL;
+
+ DBG ("rrd_update (argc = %i, argv = %p)", argc, (void *) argv);
+
+ optind = 0; /* bug in librrd? */
+ rrd_clear_error ();
+ status = rrd_update (argc, argv);
+
+ free (argv);
+ free (fn);
+
+ /* Free the value list of `rc' */
+ for (i = 0; i < rc->values_num; i++)
+ free (rc->values[i]);
+ free (rc->values);
+ rc->values = NULL;
+ rc->values_num = 0;
+
+ if (status != 0)
+ {
+ syslog (LOG_WARNING, "rrd_update failed: %s: %s",
+ filename, rrd_get_error ());
+ return (-1);
+ }
+
+ return (0);
+} /* int rrd_write_cache_entry */
+
+static void rrd_cache_flush (int timeout)
+{
+ rrd_cache_t *rc;
+ time_t now;
+
+ char **keys = NULL;
+ int keys_num = 0;
+
+ char *key;
+ avl_iterator_t *iter;
+ int i;
+
+ if (cache == NULL)
+ return;
+
+ DBG ("Flushing cache, timeout = %i", timeout);
+
+ now = time (NULL);
+
+ /* Build a list of entries to be flushed */
+ iter = avl_get_iterator (cache);
+ while (avl_iterator_next (iter, (void *) &key, (void *) &rc) == 0)
+ {
+ DBG ("key = %s; age = %i;", key, now - rc->first_value);
+ if ((now - rc->first_value) >= timeout)
+ {
+ keys = (char **) realloc ((void *) keys,
+ (keys_num + 1) * sizeof (char *));
+ if (keys == NULL)
+ {
+ DBG ("realloc failed: %s", strerror (errno));
+ syslog (LOG_ERR, "rrdtool plugin: "
+ "realloc failed: %s",
+ strerror (errno));
+ avl_iterator_destroy (iter);
+ return;
+ }
+ keys[keys_num] = key;
+ keys_num++;
+ }
+ } /* while (avl_iterator_next) */
+ avl_iterator_destroy (iter);
+
+ for (i = 0; i < keys_num; i++)
+ {
+ if (avl_remove (cache, keys[i], (void *) &key, (void *) &rc) != 0)
+ {
+ DBG ("avl_remove (%s) failed.", keys[i]);
+ continue;
+ }
+
+ rrd_write_cache_entry (keys[i], rc);
+ /* rc's value-list is free's by `rrd_write_cache_entry' */
+ sfree (rc);
+ sfree (key);
+ keys[i] = NULL;
+ } /* for (i = 0..keys_num) */
+
+ free (keys);
+ DBG ("Flushed %i value(s)", keys_num);
+
+ cache_flush_last = now;
+} /* void rrd_cache_flush */
+
+static int rrd_write (const data_set_t *ds, const value_list_t *vl)
+{
+ struct stat statbuf;
+ char filename[512];
+ char values[512];
+ rrd_cache_t *rc;
+ time_t now;
+
+ if (value_list_to_filename (filename, sizeof (filename), ds, vl) != 0)
+ return (-1);
+
+ if (value_list_to_string (values, sizeof (values), ds, vl) != 0)
+ return (-1);
+
+ if (stat (filename, &statbuf) == -1)
+ {
+ if (errno == ENOENT)
+ {
+ if (rrd_create_file (filename, ds))
+ return (-1);
+ }
+ else
+ {
+ syslog (LOG_ERR, "stat(%s) failed: %s",
+ filename, strerror (errno));
+ return (-1);
+ }
+ }
+ else if (!S_ISREG (statbuf.st_mode))
+ {
+ syslog (LOG_ERR, "stat(%s): Not a regular file!",
+ filename);
+ return (-1);
+ }
+
+ rc = rrd_cache_insert (filename, values);
+ if (rc == NULL)
+ return (-1);
+
+ if (cache == NULL)
+ {
+ rrd_write_cache_entry (filename, rc);
+ /* rc's value-list is free's by `rrd_write_cache_entry' */
+ sfree (rc);
+ return (0);
+ }
+
+ now = time (NULL);
+
+ DBG ("age (%s) = %i", filename, now - rc->first_value);
+
+ /* `rc' is not free'd here, because we'll likely reuse it. If not, then
+ * the next flush will remove this entry. */
+ if ((now - rc->first_value) >= cache_timeout)
+ rrd_write_cache_entry (filename, rc);
+
+ if ((now - cache_flush_last) >= cache_flush_timeout)
+ rrd_cache_flush (cache_flush_timeout);
+
+ return (0);
+} /* int rrd_write */
+
+static int rrd_config (const char *key, const char *val)
+{
+ if (strcasecmp ("CacheTimeout", key) == 0)
+ {
+ int tmp = atoi (val);
+ if (tmp < 0)
+ {
+ fprintf (stderr, "rrdtool: `CacheTimeout' must "
+ "be greater than 0.\n");
+ return (1);
+ }
+ cache_timeout = tmp;
+ }
+ else if (strcasecmp ("CacheFlush", key) == 0)
+ {
+ int tmp = atoi (val);
+ if (tmp < 0)
+ {
+ fprintf (stderr, "rrdtool: `CacheFlush' must "
+ "be greater than 0.\n");
+ return (1);
+ }
+ cache_flush_timeout = tmp;
+ }
+ else if (strcasecmp ("DataDir", key) == 0)
+ {
+ if (datadir != NULL)
+ free (datadir);
+ datadir = strdup (val);
+ if (datadir != NULL)
+ {
+ int len = strlen (datadir);
+ while ((len > 0) && (datadir[len - 1] == '/'))
+ {
+ len--;
+ datadir[len] = '\0';
+ }
+ if (len <= 0)
+ {
+ free (datadir);
+ datadir = NULL;
+ }
+ }
+ }
+ else
+ {
+ return (-1);
+ }
+ return (0);
+} /* int rrd_config */
+
+static int rrd_shutdown (void)
+{
+ rrd_cache_flush (-1);
+ if (cache != NULL)
+ avl_destroy (cache);
+ cache = NULL;
+
+ return (0);
+} /* int rrd_shutdown */
+
+static int rrd_init (void)
+{
+ if (cache_timeout < 2)
+ {
+ cache_timeout = 0;
+ cache_flush_timeout = 0;
+ }
+ else
+ {
+ if (cache_flush_timeout < cache_timeout)
+ cache_flush_timeout = 10 * cache_timeout;
+
+ cache = avl_create ((int (*) (const void *, const void *)) strcmp);
+ cache_flush_last = time (NULL);
+ plugin_register_shutdown ("rrdtool", rrd_shutdown);
+ }
+ return (0);
+} /* int rrd_init */
+
+void module_register (void)
+{
+ plugin_register_config ("rrdtool", rrd_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("rrdtool", rrd_init);
+ plugin_register_write ("rrdtool", rrd_write);
+}
diff --git a/src/sensors.c b/src/sensors.c
index 66cd5b226dea80f8fc22366af2c2a769c7fd59b1..99b925685fa755de65013176d98a6e8cdaff8926 100644 (file)
--- a/src/sensors.c
+++ b/src/sensors.c
/**
* collectd - src/sensors.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "utils_ignorelist.h"
#include "utils_debug.h"
-#define MODULE_NAME "sensors"
-#define MODULE_NAME_VOLTAGE MODULE_NAME"_voltage"
-
#if defined(HAVE_SENSORS_SENSORS_H)
# include <sensors/sensors.h>
#else
# define SENSORS_HAVE_READ 0
#endif
-#define BUFSIZE 512
+static data_source_t data_source_fanspeed[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, NAN}
+};
-/* temperature and fan sensors */
-static char *ds_def[] =
+static data_set_t fanspeed_ds =
{
- "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ "fanspeed", 1, data_source_fanspeed
};
-static int ds_num = 1;
-/* voltage sensors */
-static char *sensor_voltage_ds_def[] =
+static data_source_t data_source_temperature[1] =
{
- "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U",
- NULL
+ {"value", DS_TYPE_GAUGE, -273.15, NAN}
};
-static int sensor_voltage_ds_num = 1;
-/* old naming */
-static char *old_filename_format = "sensors-%s.rrd";
-/* end old naming */
+static data_set_t temperature_ds =
+{
+ "temperature", 1, data_source_temperature
+};
-/* new naming <chip-bus-address/type-feature */
-static char *extended_filename_format = "lm_sensors-%s.rrd";
+static data_source_t data_source_voltage[1] =
+{
+ {"value", DS_TYPE_GAUGE, NAN, NAN}
+};
-#define SENSOR_TYPE_UNKNOWN 0
-#define SENSOR_TYPE_VOLTAGE 1
-#define SENSOR_TYPE_FANSPEED 2
-#define SENSOR_TYPE_TEMPERATURE 3
+static data_set_t voltage_ds =
+{
+ "voltage", 1, data_source_voltage
+};
#if SENSORS_HAVE_READ
-static char *sensor_type_prefix[] =
+#define SENSOR_TYPE_VOLTAGE 0
+#define SENSOR_TYPE_FANSPEED 1
+#define SENSOR_TYPE_TEMPERATURE 2
+#define SENSOR_TYPE_UNKNOWN 3
+
+static char *sensor_to_type[] =
{
- "unknown",
"voltage",
"fanspeed",
"temperature",
NULL
};
-#endif
-typedef struct sensors_labeltypes {
+struct sensors_labeltypes_s
+{
char *label;
int type;
-} sensors_labeltypes;
+};
+typedef struct sensors_labeltypes_s sensors_labeltypes_t;
/*
* finite list of known labels extracted from lm_sensors
*/
-#if SENSORS_HAVE_READ
-static sensors_labeltypes known_features[] =
+static sensors_labeltypes_t known_features[] =
{
{ "fan1", SENSOR_TYPE_FANSPEED },
{ "fan2", SENSOR_TYPE_FANSPEED },
{ "2.5V", SENSOR_TYPE_VOLTAGE },
{ "2.0V", SENSOR_TYPE_VOLTAGE },
{ "12V", SENSOR_TYPE_VOLTAGE },
- { 0, -1 }
+ { (char *) 0, SENSOR_TYPE_UNKNOWN }
};
-#endif
/* end new naming */
-static char *config_keys[] =
+static const char *config_keys[] =
{
"Sensor",
"IgnoreSelected",
- "ExtendedSensorNaming",
NULL
};
-static int config_keys_num = 3;
+static int config_keys_num = 2;
static ignorelist_t *sensor_list;
-/*
- * sensor_extended_naming:
- * 0 => default is to create chip-feature
- * 1 => use new naming scheme chip-bus-address/type-feature
- */
-static int sensor_extended_naming = 0;
-
-#if SENSORS_HAVE_READ
-# ifndef SENSORS_CONF_PATH
-# define SENSORS_CONF_PATH "/etc/sensors.conf"
-# endif
+#ifndef SENSORS_CONF_PATH
+# define SENSORS_CONF_PATH "/etc/sensors.conf"
+#endif
static const char *conffile = SENSORS_CONF_PATH;
/* SENSORS_CONF_PATH */
} featurelist_t;
featurelist_t *first_feature = NULL;
-#endif /* if SENSORS_HAVE_READ */
-static int sensors_config (char *key, char *value)
+static int sensors_config (const char *key, const char *value)
{
if (sensor_list == NULL)
sensor_list = ignorelist_create (1);
{
if (ignorelist_add (sensor_list, value))
{
- syslog (LOG_EMERG, MODULE_NAME": Cannot add value to ignorelist.");
+ syslog (LOG_ERR, "sensors plugin: "
+ "Cannot add value to ignorelist.");
return (1);
}
}
|| (strcasecmp (value, "On") == 0))
ignorelist_set_invert (sensor_list, 0);
}
- else if (strcasecmp (key, "ExtendedSensorNaming") == 0)
- {
- if ((strcasecmp (value, "True") == 0)
- || (strcasecmp (value, "Yes") == 0)
- || (strcasecmp (value, "On") == 0))
- sensor_extended_naming = 1;
- else
- sensor_extended_naming = 0;
- }
else
{
return (-1);
return (0);
}
-#if SENSORS_HAVE_READ
void sensors_free_features (void)
{
featurelist_t *thisft;
status = stat (conffile, &statbuf);
if (status != 0)
{
- syslog (LOG_ERR, MODULE_NAME": stat(%s) failed: %s",
+ syslog (LOG_ERR, "sensors plugin: stat (%s) failed: %s",
conffile, strerror (errno));
sensors_config_mtime = 0;
}
if (sensors_config_mtime != 0)
{
- syslog (LOG_NOTICE, MODULE_NAME": Reloading config from %s",
+ syslog (LOG_NOTICE, "sensors plugin: Reloading config from %s",
conffile);
sensors_free_features ();
sensors_config_mtime = 0;
fh = fopen (conffile, "r");
if (fh == NULL)
{
- syslog (LOG_ERR, MODULE_NAME": fopen(%s) failed: %s",
+ syslog (LOG_ERR, "sensors plugin: fopen(%s) failed: %s",
conffile, strerror(errno));
return;
}
fclose (fh);
if (status != 0)
{
- syslog (LOG_ERR, MODULE_NAME": Cannot initialize sensors. "
+ syslog (LOG_ERR, "sensors plugin: Cannot initialize sensors. "
"Data will not be collected.");
return;
}
DBG ("Adding feature: %s-%s-%s",
chip->prefix,
- sensor_type_prefix[known_features[i].type],
+ sensor_to_type[known_features[i].type],
data->name);
if ((new_feature = (featurelist_t *) malloc (sizeof (featurelist_t))) == NULL)
{
DBG ("malloc: %s", strerror (errno));
- syslog (LOG_ERR, MODULE_NAME": malloc: %s",
+ syslog (LOG_ERR, "sensors plugin: malloc: %s",
strerror (errno));
break;
}
if (first_feature == NULL)
{
sensors_cleanup ();
- syslog (LOG_INFO, MODULE_NAME": lm_sensors reports no features. "
- "Data will not be collected.");
+ syslog (LOG_INFO, "sensors plugin: lm_sensors reports no "
+ "features. Data will not be collected.");
}
} /* void sensors_load_conf */
-#endif /* if SENSORS_HAVE_READ */
-static void collectd_sensors_init (void)
+static int sensors_shutdown (void)
{
- return;
-}
-
-static void sensors_shutdown (void)
-{
-#if SENSORS_HAVE_READ
sensors_free_features ();
-#endif /* if SENSORS_HAVE_READ */
-
- if (NULL != sensor_list)
- ignorelist_free (sensor_list);
-}
-
-static void sensors_voltage_write (char *host, char *inst, char *val)
-{
- char file[BUFSIZE];
- int status;
-
- /* skip ignored in our config */
- if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
- return;
-
- /* extended sensor naming */
- if(sensor_extended_naming)
- status = snprintf (file, BUFSIZE, extended_filename_format, inst);
- else
- status = snprintf (file, BUFSIZE, old_filename_format, inst);
-
- if ((status < 1) || (status >= BUFSIZE))
- return;
+ ignorelist_free (sensor_list);
- rrd_update_file (host, file, val, sensor_voltage_ds_def, sensor_voltage_ds_num);
-}
-
-static void sensors_write (char *host, char *inst, char *val)
-{
- char file[BUFSIZE];
- int status;
-
- /* skip ignored in our config */
- if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
- return;
-
- /* extended sensor naming */
- if (sensor_extended_naming)
- status = snprintf (file, BUFSIZE, extended_filename_format, inst);
- else
- status = snprintf (file, BUFSIZE, old_filename_format, inst);
-
- if ((status < 1) || (status >= BUFSIZE))
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+ return (0);
+} /* int sensors_shutdown */
-#if SENSORS_HAVE_READ
-static void sensors_submit (const char *feat_name,
- const char *chip_prefix, double value, int type)
+static void sensors_submit (const char *plugin_instance,
+ const char *type, const char *type_instance,
+ double val)
{
- char buf[BUFSIZE];
- char inst[BUFSIZE];
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- if (snprintf (inst, BUFSIZE, "%s-%s", chip_prefix, feat_name)
- >= BUFSIZE)
+ if (ignorelist_match (sensor_list, type_instance))
return;
- /* skip ignored in our config */
- if ((NULL != sensor_list) && ignorelist_match (sensor_list, inst))
- return;
+ values[0].gauge = val;
- if (snprintf (buf, BUFSIZE, "%u:%.3f", (unsigned int) curtime,
- value) >= BUFSIZE)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "sensors");
+ strcpy (vl.plugin_instance, plugin_instance);
+ strcpy (vl.type_instance, type_instance);
- if (type == SENSOR_TYPE_VOLTAGE)
- {
- DBG ("%s: %s/%s, %s", MODULE_NAME_VOLTAGE,
- sensor_type_prefix[type], inst, buf);
- plugin_submit (MODULE_NAME_VOLTAGE, inst, buf);
- }
- else
- {
- DBG ("%s: %s/%s, %s", MODULE_NAME,
- sensor_type_prefix[type], inst, buf);
- plugin_submit (MODULE_NAME, inst, buf);
- }
-}
+ plugin_dispatch_values (type, &vl);
+} /* void sensors_submit */
-static void sensors_read (void)
+static int sensors_read (void)
{
featurelist_t *feature;
double value;
- char chip_fullprefix[BUFSIZE];
+
+ char plugin_instance[DATA_MAX_NAME_LEN];
+ char type_instance[DATA_MAX_NAME_LEN];
sensors_load_conf ();
if (sensors_get_feature (*feature->chip, feature->data->number, &value) < 0)
continue;
- if (sensor_extended_naming)
+ /* full chip name logic borrowed from lm_sensors */
+ if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
{
- /* full chip name logic borrowed from lm_sensors */
- if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_ISA)
- {
- if (snprintf (chip_fullprefix, BUFSIZE, "%s-isa-%04x/%s",
- feature->chip->prefix,
- feature->chip->addr,
- sensor_type_prefix[feature->type])
- >= BUFSIZE)
- continue;
- }
- else if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
- {
- if (snprintf (chip_fullprefix, BUFSIZE, "%s-%s-%04x/%s",
- feature->chip->prefix,
- feature->chip->busname,
- feature->chip->addr,
- sensor_type_prefix[feature->type])
- >= BUFSIZE)
- continue;
- }
- else
- {
- if (snprintf (chip_fullprefix, BUFSIZE, "%s-i2c-%d-%02x/%s",
- feature->chip->prefix,
- feature->chip->bus,
- feature->chip->addr,
- sensor_type_prefix[feature->type])
- >= BUFSIZE)
- continue;
- }
-
- sensors_submit (feature->data->name,
- chip_fullprefix,
- value, feature->type);
+ if (snprintf (plugin_instance, DATA_MAX_NAME_LEN, "%s-isa-%04x",
+ feature->chip->prefix,
+ feature->chip->addr)
+ >= 512)
+ continue;
+ }
+ else if (feature->chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY)
+ {
+ if (snprintf (plugin_instance, 512, "%s-%s-%04x",
+ feature->chip->prefix,
+ feature->chip->busname,
+ feature->chip->addr)
+ >= 512)
+ continue;
}
else
{
- sensors_submit (feature->data->name,
- feature->chip->prefix,
- value, feature->type);
+ if (snprintf (plugin_instance, 512, "%s-i2c-%d-%02x",
+ feature->chip->prefix,
+ feature->chip->bus,
+ feature->chip->addr)
+ >= 512)
+ continue;
}
+
+ strncpy (type_instance, feature->data->name, DATA_MAX_NAME_LEN);
+
+ sensors_submit (plugin_instance,
+ sensor_to_type[feature->type],
+ type_instance,
+ value);
} /* for feature = first_feature .. NULL */
-} /* void sensors_read */
-#else
-# define sensors_read NULL
+
+ return (0);
+} /* int sensors_read */
#endif /* SENSORS_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, collectd_sensors_init, sensors_read, sensors_write);
- plugin_register (MODULE_NAME_VOLTAGE, NULL, NULL, sensors_voltage_write);
- plugin_register_shutdown (MODULE_NAME, sensors_shutdown);
- cf_register (MODULE_NAME, sensors_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&fanspeed_ds);
+ plugin_register_data_set (&temperature_ds);
+ plugin_register_data_set (&voltage_ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if SENSORS_HAVE_READ
+ plugin_register_config ("sensors", sensors_config,
+ config_keys, config_keys_num);
+ plugin_register_read ("sensors", sensors_read);
+ plugin_register_shutdown ("sensors", sensors_shutdown);
+#endif
+} /* void module_register */
diff --git a/src/serial.c b/src/serial.c
index 0c6050d72c9a9e7533782ba2dd458627268532e0..6ca752c6bc5e2141810c6d8aa6378daf03486035 100644 (file)
--- a/src/serial.c
+++ b/src/serial.c
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "serial"
-
#if defined(KERNEL_LINUX)
# define SERIAL_HAVE_READ 1
#else
# define SERIAL_HAVE_READ 0
#endif
-static char *serial_filename_template = "serial-%s.rrd";
-
-static char *ds_def[] =
+static data_source_t octets_dsrc[2] =
{
- "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int ds_num = 2;
-static void serial_init (void)
+static data_set_t octets_ds =
{
- return;
-}
+ "serial_octets", 2, octets_dsrc
+};
-static void serial_write (char *host, char *inst, char *val)
+#if SERIAL_HAVE_READ
+static void serial_submit (const char *type_instance,
+ counter_t rx, counter_t tx)
{
- char file[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (file, 512, serial_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
+ values[0].counter = rx;
+ values[1].counter = tx;
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "serial");
+ strncpy (vl.type_instance, type_instance,
+ sizeof (vl.type_instance));
-#if SERIAL_HAVE_READ
-#define BUFSIZE 512
-static void serial_submit (char *device,
- unsigned long long incoming,
- unsigned long long outgoing)
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu", (unsigned int) curtime,
- incoming, outgoing) >= BUFSIZE)
- return;
-
- plugin_submit (MODULE_NAME, device, buf);
+ plugin_dispatch_values ("serial_octets", &vl);
}
-#undef BUFSIZE
-static void serial_read (void)
+static int serial_read (void)
{
#ifdef KERNEL_LINUX
-
FILE *fh;
char buffer[1024];
- unsigned long long incoming, outgoing;
+
+ counter_t rx = 0;
+ counter_t tx = 0;
char *fields[16];
int i, numfields;
(fh = fopen ("/proc/tty/driver/ttyS", "r")) == NULL)
{
syslog (LOG_WARNING, "serial: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
- while (fgets (buffer, 1024, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
int have_rx = 0, have_tx = 0;
- /* stupid compiler:
- * serial.c:87: warning: 'incoming' may be used uninitialized in this function
- * serial.c:87: warning: 'outgoing' may be used uninitialized in this function
- */
- incoming = 0ULL;
- outgoing = 0ULL;
-
numfields = strsplit (buffer, fields, 16);
if (numfields < 6)
if (strncmp (fields[i], "tx:", 3) == 0)
{
- outgoing = atoll (fields[i] + 3);
+ tx = atoll (fields[i] + 3);
have_tx++;
}
else if (strncmp (fields[i], "rx:", 3) == 0)
{
- incoming = atoll (fields[i] + 3);
+ rx = atoll (fields[i] + 3);
have_rx++;
}
}
if ((have_rx == 0) || (have_tx == 0))
continue;
- serial_submit (fields[0], incoming, outgoing);
+ serial_submit (fields[0], rx, tx);
}
fclose (fh);
+ return (0);
#endif /* KERNEL_LINUX */
-}
-#else
-# define serial_read NULL
+} /* int serial_read */
#endif /* SERIAL_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, serial_init, serial_read, serial_write);
-}
+ plugin_register_data_set (&octets_ds);
-#undef MODULE_NAME
+#if SERIAL_HAVE_READ
+ plugin_register_read ("serial", serial_read);
+#endif /* SERIAL_HAVE_READ */
+}
diff --git a/src/swap.c b/src/swap.c
index 43275fc119540406960b2923ac58dee29c9bb1d2..f03a5a9ef930186ecf7e4461b795fff6918da039 100644 (file)
--- a/src/swap.c
+++ b/src/swap.c
/**
* collectd - src/swap.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
# include <kvm.h>
#endif
-#define MODULE_NAME "swap"
-
#if KERNEL_LINUX || HAVE_LIBKSTAT || defined(VM_SWAPUSAGE) || HAVE_LIBKVM || HAVE_LIBSTATGRAB
# define SWAP_HAVE_READ 1
#else
#undef MAX
#define MAX(x,y) ((x) > (y) ? (x) : (y))
-static char *swap_file = "swap.rrd";
+static data_source_t data_source[1] =
+{
+ {"value", DS_TYPE_GAUGE, 0, 1099511627776.0}
+};
-/* 1099511627776 == 1TB ought to be enough for anyone ;) */
-static char *ds_def[] =
+static data_set_t data_set =
{
- "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- "DS:resv:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776",
- NULL
+ "swap", 1, data_source
};
-static int ds_num = 4;
+#if SWAP_HAVE_READ
#if KERNEL_LINUX
/* No global variables */
/* #endif KERNEL_LINUX */
/* No global variables */
#endif /* HAVE_LIBSTATGRAB */
-static void swap_init (void)
+static int swap_init (void)
{
#if KERNEL_LINUX
/* No init stuff */
== NULL)
{
syslog (LOG_ERR, "swap plugin: kvm_open failed.");
- return;
+ return (-1);
}
/* #endif HAVE_LIBKVM */
/* No init stuff */
#endif /* HAVE_LIBSTATGRAB */
- return;
+ return (0);
}
-static void swap_write (char *host, char *inst, char *val)
+static void swap_submit (const char *type_instance, double value)
{
- rrd_update_file (host, swap_file, val, ds_def, ds_num);
-}
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
-#if SWAP_HAVE_READ
-static void swap_submit (unsigned long long swap_used,
- unsigned long long swap_free,
- unsigned long long swap_cached,
- unsigned long long swap_resv)
-{
- char buffer[512];
+ values[0].gauge = value;
- if (snprintf (buffer, 512, "%u:%llu:%llu:%llu:%llu", (unsigned int) curtime,
- swap_used, swap_free, swap_cached, swap_resv) >= 512)
- return;
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "swap");
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- plugin_submit (MODULE_NAME, "-", buffer);
-}
+ plugin_dispatch_values ("swap", &vl);
+} /* void swap_submit */
-static void swap_read (void)
+static int swap_read (void)
{
#if KERNEL_LINUX
FILE *fh;
if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
{
syslog (LOG_WARNING, "memory: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
while (fgets (buffer, 1024, fh) != NULL)
syslog (LOG_WARNING, "memory: fclose: %s", strerror (errno));
if ((swap_total == 0LL) || ((swap_free + swap_cached) > swap_total))
- return;
+ return (-1);
swap_used = swap_total - (swap_free + swap_cached);
- swap_submit (swap_used, swap_free, swap_cached, -1LL);
+ swap_submit ("used", swap_used);
+ swap_submit ("free", swap_free);
+ swap_submit ("cached", swap_cached);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
{
syslog (LOG_ERR, "swap plugin: swapctl failed: %s",
strerror (errno));
- return;
+ return (-1);
}
/*
swap_avail = ai.ani_max - ai.ani_resv;
swap_avail *= pagesize;
- swap_submit (swap_alloc, swap_avail, -1LL, swap_resv - swap_alloc);
+ swap_submit ("used", swap_alloc);
+ swap_submit ("free", swap_avail);
+ swap_submit ("reserved", swap_resv - swap_alloc);
/* #endif HAVE_LIBKSTAT */
#elif defined(VM_SWAPUSAGE)
sw_usage_len = sizeof (struct xsw_usage);
if (sysctl (mib, mib_len, &sw_usage, &sw_usage_len, NULL, 0) != 0)
- return;
+ return (-1);
/* The returned values are bytes. */
- swap_submit (sw_usage.xsu_used, sw_usage.xsu_avail, -1LL, -1LL);
+ swap_submit ("used", sw_usage.xsu_used);
+ swap_submit ("free", sw_usage.xsu_avail);
/* #endif VM_SWAPUSAGE */
#elif HAVE_LIBKVM
unsigned long long total;
if (kvm_obj == NULL)
- return;
+ return (-1);
/* only one structure => only get the grand total, no details */
status = kvm_getswapinfo (kvm_obj, &data_s, 1, 0);
if (status == -1)
- return;
+ return (-1);
total = (unsigned long long) data_s.ksw_total;
used = (unsigned long long) data_s.ksw_used;
free = total - used;
- swap_submit (used, free, -1LL, -1LL);
+ swap_submit ("used", used);
+ swap_submit ("free", free);
/* #endif HAVE_LIBKVM */
#elif HAVE_LIBSTATGRAB
sg_swap_stats *swap;
- if ((swap = sg_get_swap_stats ()) != NULL)
- swap_submit (swap->used, swap->free, -1LL, -1LL);
+ swap = sg_get_swap_stats ();
+
+ if (swap == NULL)
+ return (-1);
+
+ swap_submit ("used", swap->used);
+ swap_submit ("free", swap->free);
#endif /* HAVE_LIBSTATGRAB */
-}
-#else
-# define swap_read NULL
+
+ return (0);
+} /* int swap_read */
#endif /* SWAP_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, swap_init, swap_read, swap_write);
-}
+ plugin_register_data_set (&data_set);
-#undef MODULE_NAME
+#if SWAP_HAVE_READ
+ plugin_register_init ("swap", swap_init);
+ plugin_register_read ("swap", swap_read);
+#endif /* SWAP_HAVE_READ */
+}
diff --git a/src/tape.c b/src/tape.c
index b13cdbd84e6a18db69ff6f822c9f4bc9a9a3ea69..e0b8b51199bd0ff948764d29a283d65b5a9abb62 100644 (file)
--- a/src/tape.c
+++ b/src/tape.c
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "tape"
-
#if defined(HAVE_LIBKSTAT)
# define TAPE_HAVE_READ 1
#else
# define TAPE_HAVE_READ 0
#endif
-static char *tape_filename_template = "tape-%s.rrd";
+/* 2^34 = 17179869184 = ~17.2GByte/s */
+static data_source_t octets_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 17179869183.0},
+ {"write", DS_TYPE_COUNTER, 0, 17179869183.0}
+};
+
+static data_set_t octets_ds =
+{
+ "tape_octets", 2, octets_dsrc
+};
+
+static data_source_t operations_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t operations_ds =
+{
+ "tape_ops", 2, operations_dsrc
+};
+
+static data_source_t merged_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"write", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t merged_ds =
+{
+ "tape_merged", 2, merged_dsrc
+};
+
+/* max is 1000000us per second. */
+static data_source_t time_dsrc[2] =
+{
+ {"read", DS_TYPE_COUNTER, 0, 1000000.0},
+ {"write", DS_TYPE_COUNTER, 0, 1000000.0}
+};
-/* 104857600 == 100 MB */
-static char *tape_ds_def[] =
+static data_set_t time_ds =
{
- "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "tape_time", 2, time_dsrc
};
-static int tape_ds_num = 8;
+#if TAPE_HAVE_READ
#if defined(HAVE_LIBKSTAT)
#define MAX_NUMTAPE 256
extern kstat_ctl_t *kc;
static int numtape = 0;
#endif /* HAVE_LIBKSTAT */
-static void tape_init (void)
+static int tape_init (void)
{
#ifdef HAVE_LIBKSTAT
kstat_t *ksp_chain;
numtape = 0;
if (kc == NULL)
- return;
+ return (-1);
for (numtape = 0, ksp_chain = kc->kc_chain;
(numtape < MAX_NUMTAPE) && (ksp_chain != NULL);
}
#endif
- return;
+ return (0);
}
-static void tape_write (char *host, char *inst, char *val)
+static void tape_submit (const char *plugin_instance,
+ const char *type,
+ counter_t read, counter_t write)
{
- char file[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (file, 512, tape_filename_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, tape_ds_def, tape_ds_num);
-}
+ values[0].counter = read;
+ values[1].counter = write;
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "tape");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
-#if TAPE_HAVE_READ
-#define BUFSIZE 512
-static void tape_submit (char *tape_name,
- unsigned long long read_count,
- unsigned long long read_merged,
- unsigned long long read_bytes,
- unsigned long long read_time,
- unsigned long long write_count,
- unsigned long long write_merged,
- unsigned long long write_bytes,
- unsigned long long write_time)
+ plugin_dispatch_values (type, &vl);
+} /* void tape_submit */
-{
- char buf[BUFSIZE];
-
- if (snprintf (buf, BUFSIZE, "%u:%llu:%llu:%llu:%llu:%llu:%llu:%llu:%llu",
- (unsigned int) curtime,
- read_count, read_merged, read_bytes, read_time,
- write_count, write_merged, write_bytes,
- write_time) >= BUFSIZE)
- return;
-
- plugin_submit (MODULE_NAME, tape_name, buf);
-}
-
-#undef BUFSIZE
-
-static void tape_read (void)
+static int tape_read (void)
{
#if defined(HAVE_LIBKSTAT)
int i;
if (kc == NULL)
- return;
+ return (-1);
+
+ if (numtape <= 0)
+ return (-1);
for (i = 0; i < numtape; i++)
{
continue;
if (strncmp (ksp[i]->ks_class, "tape", 4) == 0)
- tape_submit (ksp[i]->ks_name,
- kio.reads, 0LL, kio.nread, kio.rtime,
- kio.writes, 0LL, kio.nwritten, kio.wtime);
+ {
+ tape_submit (ksp[i]->ks_name, "tape_octets", kio.reads, kio.writes);
+ tape_submit (ksp[i]->ks_name, "tape_ops", kio.nreads, kio.nwrites);
+ /* FIXME: Convert this to microseconds if necessary */
+ tape_submit (ksp[i]->ks_name, "tape_time", kio.rtime, kio.wtime);
+ }
}
#endif /* defined(HAVE_LIBKSTAT) */
+
+ return (0);
}
-#else
-# define tape_read NULL
#endif /* TAPE_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, tape_init, tape_read, tape_write);
-}
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&operations_ds);
+ plugin_register_data_set (&merged_ds);
+ plugin_register_data_set (&time_ds);
-#undef MODULE_NAME
+#if TAPE_HAVE_READ
+ plugin_register_init ("tape", tape_init);
+ plugin_register_read ("tape", tape_read);
+#endif /* TAPE_HAVE_READ */
+}
diff --git a/src/traffic.c b/src/traffic.c
index 14b7dc32b1c6ac9ca33caab29466f5b2a16fd3c2..5fc55d757eecf414fb2e9d232289b38822f1f450 100644 (file)
--- a/src/traffic.c
+++ b/src/traffic.c
/**
* collectd - src/traffic.c
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
# include <ifaddrs.h>
#endif
-#define MODULE_NAME "traffic"
-
/*
* Various people have reported problems with `getifaddrs' and varying versions
* of `glibc'. That's why it's disabled by default. Since more statistics are
# define TRAFFIC_HAVE_READ 0
#endif
-#define BUFSIZE 512
-
/*
* (Module-)Global variables
*/
-/* TODO: Move this to `interface-%s/<blah>.rrd' in version 4. */
-static char *bytes_file = "traffic-%s.rrd";
-static char *packets_file = "interface-%s/if_packets.rrd";
-static char *errors_file = "interface-%s/if_errors.rrd";
-/* TODO: Maybe implement multicast and broadcast counters */
+/* 2^32 = 4294967296 = ~4.2GByte/s = ~34GBit/s */
+static data_source_t octets_dsrc[2] =
+{
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
-static char *config_keys[] =
+static data_set_t octets_ds =
{
- "Interface",
- "IgnoreSelected",
- NULL
+ "if_octets", 2, octets_dsrc
};
-static int config_keys_num = 2;
-static char *bytes_ds_def[] =
+static data_source_t packets_dsrc[2] =
{
- "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
};
-static int bytes_ds_num = 2;
-static char *packets_ds_def[] =
+static data_set_t packets_ds =
{
- "DS:rx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:tx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- NULL
+ "if_packets", 2, packets_dsrc
};
-static int packets_ds_num = 2;
-static char *errors_ds_def[] =
+static data_source_t errors_dsrc[2] =
{
- "DS:rx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
- "DS:tx:COUNTER:"COLLECTD_HEARTBEAT":0:U",
+ {"rx", DS_TYPE_COUNTER, 0, 4294967295.0},
+ {"tx", DS_TYPE_COUNTER, 0, 4294967295.0}
+};
+
+static data_set_t errors_ds =
+{
+ "if_errors", 2, errors_dsrc
+};
+
+static const char *config_keys[] =
+{
+ "Interface",
+ "IgnoreSelected",
NULL
};
-static int errors_ds_num = 2;
+static int config_keys_num = 2;
static char **if_list = NULL;
static int if_list_num = 0;
static int numif = 0;
#endif /* HAVE_LIBKSTAT */
-static int traffic_config (char *key, char *value)
+static int interface_config (const char *key, const char *value)
{
char **temp;
return (0);
}
-static void traffic_init (void)
+#if HAVE_LIBKSTAT
+static int traffic_init (void)
{
-#if HAVE_GETIFADDRS
- /* nothing */
-/* #endif HAVE_GETIFADDRS */
-
-#elif KERNEL_LINUX
- /* nothing */
-/* #endif KERNEL_LINUX */
-
-#elif HAVE_LIBKSTAT
+#if HAVE_LIBKSTAT
kstat_t *ksp_chain;
unsigned long long val;
numif = 0;
if (kc == NULL)
- return;
+ return (-1);
for (numif = 0, ksp_chain = kc->kc_chain;
(numif < MAX_NUMIF) && (ksp_chain != NULL);
continue;
ksp[numif++] = ksp_chain;
}
-/* #endif HAVE_LIBKSTAT */
-
-#elif HAVE_LIBSTATG
- /* nothing */
-#endif /* HAVE_LIBSTATG */
+#endif /* HAVE_LIBKSTAT */
- return;
-}
+ return (0);
+} /* int traffic_init */
+#endif /* HAVE_LIBKSTAT */
/*
* Check if this interface/instance should be ignored. This is called from
if (strcasecmp (interface, if_list[i]) == 0)
return (if_list_action);
return (1 - if_list_action);
-}
-
-static void generic_write (char *host, char *inst, char *val,
- char *file_template,
- char **ds_def, int ds_num)
-{
- char file[512];
- int status;
-
- if (check_ignore_if (inst))
- return;
-
- status = snprintf (file, BUFSIZE, file_template, inst);
- if (status < 1)
- return;
- else if (status >= 512)
- return;
-
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
-
-static void bytes_write (char *host, char *inst, char *val)
-{
- generic_write (host, inst, val, bytes_file, bytes_ds_def, bytes_ds_num);
-}
-
-static void packets_write (char *host, char *inst, char *val)
-{
- generic_write (host, inst, val, packets_file, packets_ds_def, packets_ds_num);
-}
-
-static void errors_write (char *host, char *inst, char *val)
-{
- generic_write (host, inst, val, errors_file, errors_ds_def, errors_ds_num);
-}
+} /* int check_ignore_if */
#if TRAFFIC_HAVE_READ
-static void bytes_submit (char *dev,
- unsigned long long rx,
- unsigned long long tx)
-{
- char buf[512];
- int status;
-
- if (check_ignore_if (dev))
- return;
-
- status = snprintf (buf, 512, "%u:%lld:%lld",
- (unsigned int) curtime,
- rx, tx);
- if ((status >= 512) || (status < 1))
- return;
-
- plugin_submit (MODULE_NAME, dev, buf);
-}
-
-#if HAVE_GETIFADDRS || KERNEL_LINUX || HAVE_LIBKSTAT
-static void packets_submit (char *dev,
+static void if_submit (const char *dev, const char *type,
unsigned long long rx,
unsigned long long tx)
{
- char buf[512];
- int status;
+ value_t values[2];
+ value_list_t vl = VALUE_LIST_INIT;
if (check_ignore_if (dev))
return;
- status = snprintf (buf, 512, "%u:%lld:%lld",
- (unsigned int) curtime,
- rx, tx);
- if ((status >= 512) || (status < 1))
- return;
- plugin_submit ("if_packets", dev, buf);
-}
-
-static void errors_submit (char *dev,
- unsigned long long rx,
- unsigned long long tx)
-{
- char buf[512];
- int status;
+ values[0].counter = rx;
+ values[1].counter = tx;
- if (check_ignore_if (dev))
- return;
+ vl.values = values;
+ vl.values_len = 2;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "interface");
+ strncpy (vl.type_instance, dev, sizeof (vl.type_instance));
- status = snprintf (buf, 512, "%u:%lld:%lld",
- (unsigned int) curtime,
- rx, tx);
- if ((status >= 512) || (status < 1))
- return;
- plugin_submit ("if_errors", dev, buf);
-}
-#endif /* HAVE_GETIFADDRS || KERNEL_LINUX || HAVE_LIBKSTAT */
+ plugin_dispatch_values (type, &vl);
+} /* void if_submit */
-static void traffic_read (void)
+static int traffic_read (void)
{
#if HAVE_GETIFADDRS
struct ifaddrs *if_list;
struct IFA_DATA *if_data;
if (getifaddrs (&if_list) != 0)
- return;
+ return (-1);
for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next)
{
if ((if_data = (struct IFA_DATA *) if_ptr->ifa_data) == NULL)
continue;
- bytes_submit (if_ptr->ifa_name,
+ if_submit (if_ptr->ifa_name, "if_octets",
if_data->IFA_RX_BYTES,
if_data->IFA_TX_BYTES);
- packets_submit (if_ptr->ifa_name,
+ if_submit (if_ptr->ifa_name, "if_packets",
if_data->IFA_RX_PACKT,
if_data->IFA_TX_PACKT);
- errors_submit (if_ptr->ifa_name,
+ if_submit (if_ptr->ifa_name, "if_errors",
if_data->IFA_RX_ERROR,
if_data->IFA_TX_ERROR);
}
if ((fh = fopen ("/proc/net/dev", "r")) == NULL)
{
syslog (LOG_WARNING, "traffic: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
while (fgets (buffer, 1024, fh) != NULL)
incoming = atoll (fields[0]);
outgoing = atoll (fields[8]);
- bytes_submit (device, incoming, outgoing);
+ if_submit (device, "if_octets", incoming, outgoing);
incoming = atoll (fields[1]);
outgoing = atoll (fields[9]);
- packets_submit (device, incoming, outgoing);
+ if_submit (device, "if_packets", incoming, outgoing);
incoming = atoll (fields[2]);
outgoing = atoll (fields[10]);
- errors_submit (device, incoming, outgoing);
+ if_submit (device, "if_errors", incoming, outgoing);
}
fclose (fh);
rx = get_kstat_value (ksp[i], "rbytes");
tx = get_kstat_value (ksp[i], "obytes");
if ((rx != -1LL) || (tx != -1LL))
- bytes_submit (ksp[i]->ks_name, rx, tx);
+ if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
rx = get_kstat_value (ksp[i], "ipackets");
tx = get_kstat_value (ksp[i], "opackets");
if ((rx != -1LL) || (tx != -1LL))
- packets_submit (ksp[i]->ks_name, rx, tx);
+ if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
rx = get_kstat_value (ksp[i], "ierrors");
tx = get_kstat_value (ksp[i], "oerrors");
if ((rx != -1LL) || (tx != -1LL))
- errors_submit (ksp[i]->ks_name, rx, tx);
+ if_submit (ksp[i]->ks_name, "if_errors", rx, tx);
}
/* #endif HAVE_LIBKSTAT */
ios = sg_get_network_io_stats (&num);
for (i = 0; i < num; i++)
- bytes_submit (ios[i].interface_name, ios[i].rx, ios[i].tx);
+ if_submit (ios[i].interface_name, "if_octets", ios[i].rx, ios[i].tx);
#endif /* HAVE_LIBSTATGRAB */
-}
-#else
-#define traffic_read NULL
+
+ return (0);
+} /* int traffic_read */
#endif /* TRAFFIC_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, traffic_init, traffic_read, bytes_write);
- plugin_register ("if_packets", NULL, NULL, packets_write);
- plugin_register ("if_errors", NULL, NULL, errors_write);
- cf_register (MODULE_NAME, traffic_config, config_keys, config_keys_num);
-}
+ plugin_register_data_set (&octets_ds);
+ plugin_register_data_set (&packets_ds);
+ plugin_register_data_set (&errors_ds);
+
+ plugin_register_config ("interface", interface_config,
+ config_keys, config_keys_num);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if HAVE_LIBKSTAT
+ plugin_register_init ("interface", traffic_init);
+#endif
+
+#if TRAFFIC_HAVE_READ
+ plugin_register_read ("interface", traffic_read);
+#endif
+}
diff --git a/src/unixsock.c b/src/unixsock.c
--- /dev/null
+++ b/src/unixsock.c
@@ -0,0 +1,688 @@
+/**
+ * collectd - src/unixsock.c
+ * Copyright (C) 2007 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_debug.h"
+
+/* Folks without pthread will need to disable this plugin. */
+#include <pthread.h>
+
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/poll.h>
+
+#include <grp.h>
+
+#ifndef UNIX_PATH_MAX
+# define UNIX_PATH_MAX sizeof (((struct sockaddr_un *)0)->sun_path)
+#endif
+
+#define US_DEFAULT_PATH PREFIX"/var/run/"PACKAGE_NAME"-unixsock"
+
+/*
+ * Private data structures
+ */
+/* linked list of cached values */
+typedef struct value_cache_s
+{
+ char name[4*DATA_MAX_NAME_LEN];
+ int values_num;
+ gauge_t *gauge;
+ counter_t *counter;
+ const data_set_t *ds;
+ time_t time;
+ struct value_cache_s *next;
+} value_cache_t;
+
+/*
+ * Private variables
+ */
+/* valid configuration file keys */
+static const char *config_keys[] =
+{
+ "SocketFile",
+ "SocketGroup",
+ "SocketPerms",
+ NULL
+};
+static int config_keys_num = 3;
+
+/* socket configuration */
+static int sock_fd = -1;
+static char *sock_file = NULL;
+static char *sock_group = NULL;
+static int sock_perms = S_IRWXU | S_IRWXG;
+
+static pthread_t listen_thread = (pthread_t) 0;
+
+/* Linked list and auxilliary variables for saving values */
+static value_cache_t *cache_head = NULL;
+static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
+static unsigned int cache_oldest = UINT_MAX;
+
+/*
+ * Functions
+ */
+static value_cache_t *cache_search (const char *name)
+{
+ value_cache_t *vc;
+
+ for (vc = cache_head; vc != NULL; vc = vc->next)
+ {
+ if (strcmp (vc->name, name) == 0)
+ break;
+ } /* for vc = cache_head .. NULL */
+
+ return (vc);
+} /* value_cache_t *cache_search */
+
+static int cache_alloc_name (char *ret, int ret_len,
+ const char *hostname,
+ const char *plugin, const char *plugin_instance,
+ const char *type, const char *type_instance)
+{
+ int status;
+
+ assert (plugin != NULL);
+ assert (type != NULL);
+
+ if ((plugin_instance == NULL) || (strlen (plugin_instance) == 0))
+ {
+ if ((type_instance == NULL) || (strlen (type_instance) == 0))
+ status = snprintf (ret, ret_len, "%s/%s/%s",
+ hostname, plugin, type);
+ else
+ status = snprintf (ret, ret_len, "%s/%s/%s-%s",
+ hostname, plugin, type, type_instance);
+ }
+ else
+ {
+ if ((type_instance == NULL) || (strlen (type_instance) == 0))
+ status = snprintf (ret, ret_len, "%s/%s-%s/%s",
+ hostname, plugin, plugin_instance, type);
+ else
+ status = snprintf (ret, ret_len, "%s/%s-%s/%s-%s",
+ hostname, plugin, plugin_instance, type, type_instance);
+ }
+
+ if ((status < 1) || (status >= ret_len))
+ return (-1);
+ return (0);
+} /* int cache_alloc_name */
+
+static int cache_insert (const data_set_t *ds, const value_list_t *vl)
+{
+ /* We're called from `cache_update' so we don't need to lock the mutex */
+ value_cache_t *vc;
+ int i;
+
+ DBG ("ds->ds_num = %i; vl->values_len = %i;",
+ ds->ds_num, vl->values_len);
+ assert (ds->ds_num == vl->values_len);
+
+ vc = (value_cache_t *) malloc (sizeof (value_cache_t));
+ if (vc == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+
+ vc->gauge = (gauge_t *) malloc (sizeof (gauge_t) * vl->values_len);
+ if (vc->gauge == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ free (vc);
+ return (-1);
+ }
+
+ vc->counter = (counter_t *) malloc (sizeof (counter_t) * vl->values_len);
+ if (vc->counter == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ free (vc->gauge);
+ free (vc);
+ return (-1);
+ }
+
+ if (cache_alloc_name (vc->name, sizeof (vc->name),
+ vl->host, vl->plugin, vl->plugin_instance,
+ ds->type, vl->type_instance) != 0)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ syslog (LOG_ERR, "unixsock plugin: cache_alloc_name failed.");
+ free (vc->counter);
+ free (vc->gauge);
+ free (vc);
+ return (-1);
+ }
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ vc->gauge[i] = 0.0;
+ vc->counter[i] = vl->values[i].counter;
+ }
+ else if (ds->ds[i].type == DS_TYPE_GAUGE)
+ {
+ vc->gauge[i] = vl->values[i].gauge;
+ vc->counter[i] = 0;
+ }
+ else
+ {
+ vc->gauge[i] = 0.0;
+ vc->counter[i] = 0;
+ }
+ }
+ vc->values_num = ds->ds_num;
+ vc->ds = ds;
+
+ vc->next = cache_head;
+ cache_head = vc;
+
+ vc->time = vl->time;
+ if (vc->time < cache_oldest)
+ cache_oldest = vc->time;
+
+ pthread_mutex_unlock (&cache_lock);
+ return (0);
+} /* int cache_insert */
+
+static int cache_update (const data_set_t *ds, const value_list_t *vl)
+{
+ char name[4*DATA_MAX_NAME_LEN];;
+ value_cache_t *vc;
+ int i;
+
+ if (cache_alloc_name (name, sizeof (name),
+ vl->host,
+ vl->plugin, vl->plugin_instance,
+ ds->type, vl->type_instance) != 0)
+ return (-1);
+
+ pthread_mutex_lock (&cache_lock);
+
+ vc = cache_search (name);
+
+ if (vc == NULL)
+ return (cache_insert (ds, vl));
+
+ assert (vc->values_num == ds->ds_num);
+ assert (vc->values_num == vl->values_len);
+
+ /*
+ * Update the values. This is possibly a lot more that you'd expect
+ * because we honor min and max values and handle counter overflows here.
+ */
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if (ds->ds[i].type == DS_TYPE_COUNTER)
+ {
+ if (vl->values[i].counter < vc->counter[i])
+ {
+ if (vl->values[i].counter <= 4294967295U)
+ {
+ vc->gauge[i] = ((4294967295U - vl->values[i].counter)
+ + vc->counter[i]) / (vl->time - vc->time);
+ }
+ else
+ {
+ vc->gauge[i] = ((18446744073709551615ULL - vl->values[i].counter)
+ + vc->counter[i]) / (vl->time - vc->time);
+ }
+ }
+ else
+ {
+ vc->gauge[i] = (vl->values[i].counter - vc->counter[i])
+ / (vl->time - vc->time);
+ }
+
+ vc->counter[i] = vl->values[i].counter;
+ }
+ else if (ds->ds[i].type == DS_TYPE_GAUGE)
+ {
+ vc->gauge[i] = vl->values[i].gauge;
+ vc->counter[i] = 0;
+ }
+ else
+ {
+ vc->gauge[i] = NAN;
+ vc->counter[i] = 0;
+ }
+
+ if ((vc->gauge[i] == NAN)
+ || ((ds->ds[i].min != NAN) && (vc->gauge[i] < ds->ds[i].min))
+ || ((ds->ds[i].max != NAN) && (vc->gauge[i] > ds->ds[i].max)))
+ vc->gauge[i] = NAN;
+ } /* for i = 0 .. ds->ds_num */
+
+ vc->ds = ds;
+ vc->time = vl->time;
+
+ if (vc->time < cache_oldest)
+ cache_oldest = vc->time;
+
+ pthread_mutex_unlock (&cache_lock);
+ return (0);
+} /* int cache_update */
+
+static void cache_flush (int max_age)
+{
+ value_cache_t *this;
+ value_cache_t *prev;
+ time_t now;
+
+ pthread_mutex_lock (&cache_lock);
+
+ now = time (NULL);
+
+ if ((now - cache_oldest) <= max_age)
+ {
+ pthread_mutex_unlock (&cache_lock);
+ return;
+ }
+
+ cache_oldest = now;
+
+ prev = NULL;
+ this = cache_head;
+
+ while (this != NULL)
+ {
+ if ((now - this->time) <= max_age)
+ {
+ if (this->time < cache_oldest)
+ cache_oldest = this->time;
+
+ prev = this;
+ this = this->next;
+ continue;
+ }
+
+ if (prev == NULL)
+ cache_head = this->next;
+ else
+ prev->next = this->next;
+
+ free (this->gauge);
+ free (this->counter);
+ free (this);
+
+ if (prev == NULL)
+ this = cache_head;
+ else
+ this = prev->next;
+ } /* while (this != NULL) */
+
+ pthread_mutex_unlock (&cache_lock);
+} /* int cache_flush */
+
+static int us_open_socket (void)
+{
+ struct sockaddr_un sa;
+ int status;
+
+ sock_fd = socket (PF_UNIX, SOCK_STREAM, 0);
+ if (sock_fd < 0)
+ {
+ syslog (LOG_ERR, "unixsock plugin: socket failed: %s",
+ strerror (errno));
+ return (-1);
+ }
+
+ memset (&sa, '\0', sizeof (sa));
+ sa.sun_family = AF_UNIX;
+ strncpy (sa.sun_path, (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ sizeof (sa.sun_path) - 1);
+ /* unlink (sa.sun_path); */
+
+ status = bind (sock_fd, (struct sockaddr *) &sa, sizeof (sa));
+ if (status != 0)
+ {
+ DBG ("bind failed: %s; sa.sun_path = %s",
+ strerror (errno), sa.sun_path);
+ syslog (LOG_ERR, "unixsock plugin: bind failed: %s",
+ strerror (errno));
+ close (sock_fd);
+ sock_fd = -1;
+ return (-1);
+ }
+
+ status = listen (sock_fd, 8);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "unixsock plugin: listen failed: %s",
+ strerror (errno));
+ close (sock_fd);
+ sock_fd = -1;
+ return (-1);
+ }
+
+ do
+ {
+ struct group *g;
+
+ errno = 0;
+ g = getgrnam ((sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME);
+
+ if (errno != 0)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: getgrnam (%s) failed: %s",
+ (sock_group != NULL) ? sock_group : COLLECTD_GRP_NAME,
+ strerror (errno));
+ break;
+ }
+
+ if (g == NULL)
+ break;
+
+ if (chown ((sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ (uid_t) -1, g->gr_gid) != 0)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: chown (%s, -1, %i) failed: %s",
+ (sock_file != NULL) ? sock_file : US_DEFAULT_PATH,
+ (int) g->gr_gid,
+ strerror (errno));
+ }
+ } while (0);
+
+ return (0);
+} /* int us_open_socket */
+
+static int us_handle_getval (FILE *fh, char **fields, int fields_num)
+{
+ char *hostname = fields[1];
+ char *plugin;
+ char *plugin_instance;
+ char *type;
+ char *type_instance;
+ char name[4*DATA_MAX_NAME_LEN];
+ value_cache_t *vc;
+ int status;
+ int i;
+
+ if (fields_num != 2)
+ return (-1);
+
+ plugin = strchr (hostname, '/');
+ if (plugin == NULL)
+ return (-1);
+ *plugin = '\0'; plugin++;
+
+ type = strchr (plugin, '/');
+ if (type == NULL)
+ return (-1);
+ *type = '\0'; type++;
+
+ plugin_instance = strchr (plugin, '-');
+ if (plugin_instance != NULL)
+ {
+ *plugin_instance = '\0';
+ plugin_instance++;
+ }
+
+ type_instance = strchr (type, '-');
+ if (type_instance != NULL)
+ {
+ *type_instance = '\0';
+ type_instance++;
+ }
+
+ status = cache_alloc_name (name, sizeof (name),
+ hostname, plugin, plugin_instance, type, type_instance);
+ if (status != 0)
+ return (-1);
+
+ pthread_mutex_lock (&cache_lock);
+
+ DBG ("vc = cache_search (%s)", name);
+ vc = cache_search (name);
+
+ if (vc == NULL)
+ {
+ DBG ("Did not find cache entry.");
+ fprintf (fh, "-1 No such value");
+ }
+ else
+ {
+ DBG ("Found cache entry.");
+ fprintf (fh, "%i", vc->values_num);
+ for (i = 0; i < vc->values_num; i++)
+ {
+ fprintf (fh, " %s=", vc->ds->ds[i].name);
+ if (vc->gauge[i] == NAN)
+ fprintf (fh, "NaN");
+ else
+ fprintf (fh, "%12e", vc->gauge[i]);
+ }
+ }
+
+ /* Free the mutex as soon as possible and definitely before flushing */
+ pthread_mutex_unlock (&cache_lock);
+
+ fprintf (fh, "\n");
+ fflush (fh);
+
+ return (0);
+} /* int us_handle_getval */
+
+static void *us_handle_client (void *arg)
+{
+ int fd;
+ FILE *fh;
+ char buffer[1024];
+ char *fields[128];
+ int fields_num;
+
+ fd = *((int *) arg);
+ free (arg);
+ arg = NULL;
+
+ DBG ("Reading from fd #%i", fd);
+
+ fh = fdopen (fd, "r+");
+ if (fh == NULL)
+ {
+ syslog (LOG_ERR, "unixsock plugin: fdopen failed: %s",
+ strerror (errno));
+ close (fd);
+ pthread_exit ((void *) 1);
+ }
+
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
+ {
+ int len;
+
+ len = strlen (buffer);
+ while ((len > 0)
+ && ((buffer[len - 1] == '\n') || (buffer[len - 1] == '\r')))
+ buffer[--len] = '\0';
+
+ if (len == 0)
+ continue;
+
+ DBG ("fgets -> buffer = %s; len = %i;", buffer, len);
+
+ fields_num = strsplit (buffer, fields,
+ sizeof (fields) / sizeof (fields[0]));
+
+ if (fields_num < 1)
+ {
+ close (fd);
+ break;
+ }
+
+ if (strcasecmp (fields[0], "getval") == 0)
+ {
+ us_handle_getval (fh, fields, fields_num);
+ }
+ else
+ {
+ fprintf (fh, "Unknown command: %s\n", fields[0]);
+ fflush (fh);
+ }
+ } /* while (fgets) */
+
+ DBG ("Exiting..");
+ close (fd);
+
+ pthread_exit ((void *) 0);
+} /* void *us_handle_client */
+
+static void *us_server_thread (void *arg)
+{
+ int status;
+ int *remote_fd;
+ pthread_t th;
+ pthread_attr_t th_attr;
+
+ if (us_open_socket () != 0)
+ pthread_exit ((void *) 1);
+
+ while (42)
+ {
+ DBG ("Calling accept..");
+ status = accept (sock_fd, NULL, NULL);
+ if (status < 0)
+ {
+ if (errno == EINTR)
+ continue;
+
+ syslog (LOG_ERR, "unixsock plugin: accept failed: %s",
+ strerror (errno));
+ close (sock_fd);
+ sock_fd = -1;
+ pthread_exit ((void *) 1);
+ }
+
+ remote_fd = (int *) malloc (sizeof (int));
+ if (remote_fd == NULL)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: malloc failed: %s",
+ strerror (errno));
+ close (status);
+ continue;
+ }
+ *remote_fd = status;
+
+ DBG ("Spawning child to handle connection on fd #%i", *remote_fd);
+
+ pthread_attr_init (&th_attr);
+ pthread_attr_setdetachstate (&th_attr, PTHREAD_CREATE_DETACHED);
+
+ status = pthread_create (&th, &th_attr, us_handle_client, (void *) remote_fd);
+ if (status != 0)
+ {
+ syslog (LOG_WARNING, "unixsock plugin: pthread_create failed: %s",
+ strerror (status));
+ close (*remote_fd);
+ free (remote_fd);
+ continue;
+ }
+ } /* while (42) */
+
+ return ((void *) 0);
+} /* void *us_server_thread */
+
+static int us_config (const char *key, const char *val)
+{
+ if (strcasecmp (key, "SocketFile") == 0)
+ {
+ sfree (sock_file);
+ sock_file = strdup (val);
+ }
+ else if (strcasecmp (key, "SocketGroup") == 0)
+ {
+ sfree (sock_group);
+ sock_group = strdup (val);
+ }
+ else if (strcasecmp (key, "SocketPerms") == 0)
+ {
+ sock_perms = (int) strtol (val, NULL, 8);
+ }
+ else
+ {
+ return (-1);
+ }
+
+ return (0);
+} /* int us_config */
+
+static int us_init (void)
+{
+ int status;
+
+ status = pthread_create (&listen_thread, NULL, us_server_thread, NULL);
+ if (status != 0)
+ {
+ syslog (LOG_ERR, "unixsock plugin: pthread_create failed: %s",
+ strerror (status));
+ return (-1);
+ }
+
+ return (0);
+} /* int us_init */
+
+static int us_shutdown (void)
+{
+ void *ret;
+
+ if (listen_thread != (pthread_t) 0)
+ {
+ pthread_kill (listen_thread, SIGTERM);
+ pthread_join (listen_thread, &ret);
+ listen_thread = (pthread_t) 0;
+ }
+
+ plugin_unregister_init ("unixsock");
+ plugin_unregister_write ("unixsock");
+ plugin_unregister_shutdown ("unixsock");
+
+ return (0);
+} /* int us_shutdown */
+
+static int us_write (const data_set_t *ds, const value_list_t *vl)
+{
+ cache_update (ds, vl);
+ cache_flush (2 * atoi (COLLECTD_STEP));
+
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_config ("unixsock", us_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("unixsock", us_init);
+ plugin_register_write ("unixsock", us_write);
+ plugin_register_shutdown ("unixsock", us_shutdown);
+} /* void module_register (void) */
+
+/* vim: set sw=4 ts=4 sts=4 tw=78 : */
diff --git a/src/utils_avltree.c b/src/utils_avltree.c
--- /dev/null
+++ b/src/utils_avltree.c
@@ -0,0 +1,708 @@
+/**
+ * collectd - src/utils_avltree.c
+ * Copyright (C) 2006,2007 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "utils_avltree.h"
+
+#define BALANCE(n) ((((n)->left == NULL) ? 0 : (n)->left->height) \
+ - (((n)->right == NULL) ? 0 : (n)->right->height))
+
+/*
+ * private data types
+ */
+struct avl_node_s
+{
+ void *key;
+ void *value;
+
+ int height;
+ struct avl_node_s *left;
+ struct avl_node_s *right;
+ struct avl_node_s *parent;
+};
+typedef struct avl_node_s avl_node_t;
+
+struct avl_tree_s
+{
+ avl_node_t *root;
+ int (*compare) (const void *, const void *);
+};
+
+struct avl_iterator_s
+{
+ avl_tree_t *tree;
+ avl_node_t *node;
+};
+
+/*
+ * private functions
+ */
+#if 0
+static void verify_tree (avl_node_t *n)
+{
+ if (n == NULL)
+ return;
+
+ verify_tree (n->left);
+ verify_tree (n->right);
+
+ assert ((BALANCE (n) >= -1) && (BALANCE (n) <= 1));
+ assert ((n->parent == NULL) || (n->parent->right == n) || (n->parent->left == n));
+} /* void verify_tree */
+#else
+# define verify_tree(n) /**/
+#endif
+
+static void free_node (avl_node_t *n)
+{
+ if (n == NULL)
+ return;
+
+ if (n->left != NULL)
+ free_node (n->left);
+ if (n->right != NULL)
+ free_node (n->right);
+
+ free (n);
+}
+
+static int calc_height (avl_node_t *n)
+{
+ int height_left;
+ int height_right;
+
+ if (n == NULL)
+ return (0);
+
+ height_left = (n->left == NULL) ? 0 : n->left->height;
+ height_right = (n->right == NULL) ? 0 : n->right->height;
+
+ return (((height_left > height_right)
+ ? height_left
+ : height_right) + 1);
+} /* int calc_height */
+
+static avl_node_t *search (avl_tree_t *t, const void *key)
+{
+ avl_node_t *n;
+ int cmp;
+
+ n = t->root;
+ while (n != NULL)
+ {
+ cmp = t->compare (key, n->key);
+ if (cmp == 0)
+ return (n);
+ else if (cmp < 0)
+ n = n->left;
+ else
+ n = n->right;
+ }
+
+ return (NULL);
+}
+
+/* (x) (y)
+ * / \ / \
+ * (y) /\ /\ (x)
+ * / \ /_c\ ==> / a\ / \
+ * /\ /\ /____\/\ /\
+ * / a\ /_b\ /_b\ /_c\
+ * /____\
+ */
+static avl_node_t *rotate_right (avl_tree_t *t, avl_node_t *x)
+{
+ avl_node_t *p;
+ avl_node_t *y;
+ avl_node_t *b;
+
+ p = x->parent;
+ y = x->left;
+ b = y->right;
+
+ x->left = b;
+ if (b != NULL)
+ b->parent = x;
+
+ x->parent = y;
+ y->right = x;
+
+ y->parent = p;
+ assert ((p == NULL) || (p->left == x) || (p->right == x));
+ if (p == NULL)
+ t->root = y;
+ else if (p->left == x)
+ p->left = y;
+ else
+ p->right = y;
+
+ x->height = calc_height (x);
+ y->height = calc_height (y);
+
+ return (y);
+} /* void rotate_left */
+
+/*
+ * (x) (y)
+ * / \ / \
+ * /\ (y) (x) /\
+ * /_a\ / \ ==> / \ / c\
+ * /\ /\ /\ /\/____\
+ * /_b\ / c\ /_a\ /_b\
+ * /____\
+ */
+static avl_node_t *rotate_left (avl_tree_t *t, avl_node_t *x)
+{
+ avl_node_t *p;
+ avl_node_t *y;
+ avl_node_t *b;
+
+ p = x->parent;
+ y = x->right;
+ b = y->left;
+
+ x->right = b;
+ if (b != NULL)
+ b->parent = x;
+
+ x->parent = y;
+ y->left = x;
+
+ y->parent = p;
+ assert ((p == NULL) || (p->left == x) || (p->right == x));
+ if (p == NULL)
+ t->root = y;
+ else if (p->left == x)
+ p->left = y;
+ else
+ p->right = y;
+
+ x->height = calc_height (x);
+ y->height = calc_height (y);
+
+ return (y);
+} /* void rotate_left */
+
+static avl_node_t *rotate_left_right (avl_tree_t *t, avl_node_t *x)
+{
+ rotate_left (t, x->left);
+ return (rotate_right (t, x));
+} /* void rotate_left_right */
+
+static avl_node_t *rotate_right_left (avl_tree_t *t, avl_node_t *x)
+{
+ rotate_right (t, x->right);
+ return (rotate_left (t, x));
+} /* void rotate_right_left */
+
+static void rebalance (avl_tree_t *t, avl_node_t *n)
+{
+ int b_top;
+ int b_bottom;
+
+ while (n != NULL)
+ {
+ b_top = BALANCE (n);
+ assert ((b_top >= -2) && (b_top <= 2));
+
+ if (b_top == -2)
+ {
+ assert (n->right != NULL);
+ b_bottom = BALANCE (n->right);
+ assert ((b_bottom >= -1) || (b_bottom <= 1));
+ if (b_bottom == 1)
+ n = rotate_right_left (t, n);
+ else
+ n = rotate_left (t, n);
+ }
+ else if (b_top == 2)
+ {
+ assert (n->left != NULL);
+ b_bottom = BALANCE (n->left);
+ assert ((b_bottom >= -1) || (b_bottom <= 1));
+ if (b_bottom == -1)
+ n = rotate_left_right (t, n);
+ else
+ n = rotate_right (t, n);
+ }
+ else
+ {
+ int height = calc_height (n);
+ if (height == n->height)
+ break;
+ n->height = height;
+ }
+
+ assert (n->height == calc_height (n));
+
+ n = n->parent;
+ } /* while (n != NULL) */
+} /* void rebalance */
+
+static avl_node_t *avl_node_next (avl_tree_t *t, avl_node_t *n)
+{
+ avl_node_t *r; /* return node */
+
+ if (n == NULL)
+ {
+ return (NULL);
+ }
+
+ /* If we can't descent any further, we have to backtrack to the first
+ * parent that's bigger than we, i. e. who's _left_ child we are. */
+ if (n->right == NULL)
+ {
+ r = n->parent;
+ while ((r != NULL) && (r->parent != NULL))
+ {
+ if (r->left == n)
+ break;
+ n = r;
+ r = n->parent;
+ }
+
+ /* n->right == NULL && r == NULL => t is root and has no next
+ * r->left != n => r->right = n => r->parent == NULL */
+ if ((r == NULL) || (r->left != n))
+ {
+ assert ((r == NULL) || (r->parent == NULL));
+ return (NULL);
+ }
+ else
+ {
+ assert (r->left == n);
+ return (r);
+ }
+ }
+ else
+ {
+ r = n->right;
+ while (r->left != NULL)
+ r = r->left;
+ }
+
+ return (r);
+} /* avl_node_t *avl_node_next */
+
+static avl_node_t *avl_node_prev (avl_tree_t *t, avl_node_t *n)
+{
+ avl_node_t *r; /* return node */
+
+ if (n == NULL)
+ {
+ return (NULL);
+ }
+
+ /* If we can't descent any further, we have to backtrack to the first
+ * parent that's smaller than we, i. e. who's _right_ child we are. */
+ if (n->left == NULL)
+ {
+ r = n->parent;
+ while ((r != NULL) && (r->parent != NULL))
+ {
+ if (r->right == n)
+ break;
+ n = r;
+ r = n->parent;
+ }
+
+ /* n->left == NULL && r == NULL => t is root and has no next
+ * r->right != n => r->left = n => r->parent == NULL */
+ if ((r == NULL) || (r->right != n))
+ {
+ assert ((r == NULL) || (r->parent == NULL));
+ return (NULL);
+ }
+ else
+ {
+ assert (r->right == n);
+ return (r);
+ }
+ }
+ else
+ {
+ r = n->left;
+ while (r->right != NULL)
+ r = r->right;
+ }
+
+ return (r);
+} /* avl_node_t *avl_node_prev */
+
+static int _remove (avl_tree_t *t, avl_node_t *n)
+{
+ assert ((t != NULL) && (n != NULL));
+
+ if ((n->left != NULL) && (n->right != NULL))
+ {
+ avl_node_t *r; /* replacement node */
+ if (BALANCE (n) > 0) /* left subtree is higher */
+ {
+ assert (n->left != NULL);
+ r = avl_node_prev (t, n);
+
+ }
+ else /* right subtree is higher */
+ {
+ assert (n->right != NULL);
+ r = avl_node_next (t, n);
+ }
+
+ assert ((r->left == NULL) || (r->right == NULL));
+
+ /* copy content */
+ n->key = r->key;
+ n->value = r->value;
+
+ n = r;
+ }
+
+ assert ((n->left == NULL) || (n->right == NULL));
+
+ if ((n->left == NULL) && (n->right == NULL))
+ {
+ /* Deleting a leave is easy */
+ if (n->parent == NULL)
+ {
+ assert (t->root == n);
+ t->root = NULL;
+ }
+ else
+ {
+ assert ((n->parent->left == n)
+ || (n->parent->right == n));
+ if (n->parent->left == n)
+ n->parent->left = NULL;
+ else
+ n->parent->right = NULL;
+
+ rebalance (t, n->parent);
+ }
+
+ free_node (n);
+ }
+ else if (n->left == NULL)
+ {
+ assert (BALANCE (n) == -1);
+ assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
+ if (n->parent == NULL)
+ {
+ assert (t->root == n);
+ t->root = n->right;
+ }
+ else if (n->parent->left == n)
+ {
+ n->parent->left = n->right;
+ }
+ else
+ {
+ n->parent->right = n->right;
+ }
+ n->right->parent = n->parent;
+
+ if (n->parent != NULL)
+ rebalance (t, n->parent);
+
+ n->right = NULL;
+ free_node (n);
+ }
+ else if (n->right == NULL)
+ {
+ assert (BALANCE (n) == 1);
+ assert ((n->parent == NULL) || (n->parent->left == n) || (n->parent->right == n));
+ if (n->parent == NULL)
+ {
+ assert (t->root == n);
+ t->root = n->left;
+ }
+ else if (n->parent->left == n)
+ {
+ n->parent->left = n->left;
+ }
+ else
+ {
+ n->parent->right = n->left;
+ }
+ n->left->parent = n->parent;
+
+ if (n->parent != NULL)
+ rebalance (t, n->parent);
+
+ n->left = NULL;
+ free_node (n);
+ }
+ else
+ {
+ assert (0);
+ }
+
+ return (0);
+} /* void *_remove */
+
+/*
+ * public functions
+ */
+avl_tree_t *avl_create (int (*compare) (const void *, const void *))
+{
+ avl_tree_t *t;
+
+ if (compare == NULL)
+ return (NULL);
+
+ if ((t = (avl_tree_t *) malloc (sizeof (avl_tree_t))) == NULL)
+ return (NULL);
+
+ t->root = NULL;
+ t->compare = compare;
+
+ return (t);
+}
+
+void avl_destroy (avl_tree_t *t)
+{
+ free_node (t->root);
+ free (t);
+}
+
+int avl_insert (avl_tree_t *t, void *key, void *value)
+{
+ avl_node_t *new;
+ avl_node_t *nptr;
+ int cmp;
+
+ if ((new = (avl_node_t *) malloc (sizeof (avl_node_t))) == NULL)
+ return (-1);
+
+ new->key = key;
+ new->value = value;
+ new->height = 1;
+ new->left = NULL;
+ new->right = NULL;
+
+ if (t->root == NULL)
+ {
+ new->parent = NULL;
+ t->root = new;
+ return (0);
+ }
+
+ nptr = t->root;
+ while (42)
+ {
+ cmp = t->compare (nptr->key, new->key);
+ if (cmp == 0)
+ {
+ free_node (new);
+ return (-1);
+ }
+ else if (cmp < 0)
+ {
+ /* nptr < new */
+ if (nptr->right == NULL)
+ {
+ nptr->right = new;
+ new->parent = nptr;
+ rebalance (t, nptr);
+ break;
+ }
+ else
+ {
+ nptr = nptr->right;
+ }
+ }
+ else /* if (cmp > 0) */
+ {
+ /* nptr > new */
+ if (nptr->left == NULL)
+ {
+ nptr->left = new;
+ new->parent = nptr;
+ rebalance (t, nptr);
+ break;
+ }
+ else
+ {
+ nptr = nptr->left;
+ }
+ }
+ } /* while (42) */
+
+ verify_tree (t->root);
+ return (0);
+} /* int avl_insert */
+
+int avl_remove (avl_tree_t *t, const void *key, void **rkey, void **rvalue)
+{
+ avl_node_t *n;
+ int status;
+
+ assert (t != NULL);
+
+ n = search (t, key);
+ if (n == NULL)
+ return (-1);
+
+ if (rkey != NULL)
+ *rkey = n->key;
+ if (rvalue != NULL)
+ *rvalue = n->value;
+
+ status = _remove (t, n);
+ verify_tree (t->root);
+ return (status);
+} /* void *avl_remove */
+
+int avl_get (avl_tree_t *t, const void *key, void **value)
+{
+ avl_node_t *n;
+
+ assert (value != NULL);
+
+ n = search (t, key);
+ if (n == NULL)
+ return (-1);
+
+ *value = n->value;
+
+ return (0);
+}
+
+int avl_pick (avl_tree_t *t, void **key, void **value)
+{
+ avl_node_t *n;
+ avl_node_t *p;
+
+ if ((key == NULL) || (value == NULL))
+ return (-1);
+ if (t->root == NULL)
+ return (-1);
+
+ n = t->root;
+ while ((n->left != NULL) || (n->right != NULL))
+ {
+ int height_left = (n->left == NULL) ? 0 : n->left->height;
+ int height_right = (n->right == NULL) ? 0 : n->right->height;
+
+ if (height_left > height_right)
+ n = n->left;
+ else
+ n = n->right;
+ }
+
+ p = n->parent;
+ if (p == NULL)
+ t->root = NULL;
+ else if (p->left == n)
+ p->left = NULL;
+ else
+ p->right = NULL;
+
+ *key = n->key;
+ *value = n->value;
+
+ free_node (n);
+ rebalance (t, p);
+
+ return (0);
+} /* int avl_pick */
+
+avl_iterator_t *avl_get_iterator (avl_tree_t *t)
+{
+ avl_iterator_t *iter;
+
+ if (t == NULL)
+ return (NULL);
+
+ iter = (avl_iterator_t *) malloc (sizeof (avl_iterator_t));
+ if (iter == NULL)
+ return (NULL);
+ memset (iter, '\0', sizeof (avl_iterator_t));
+ iter->tree = t;
+
+ return (iter);
+} /* avl_iterator_t *avl_get_iterator */
+
+int avl_iterator_next (avl_iterator_t *iter, void **key, void **value)
+{
+ avl_node_t *n;
+
+ if ((iter == NULL) || (key == NULL) || (value == NULL))
+ return (-1);
+
+ if (iter->node == NULL)
+ {
+ for (n = iter->tree->root; n != NULL; n = n->left)
+ if (n->left == NULL)
+ break;
+ iter->node = n;
+ }
+ else
+ {
+ n = avl_node_next (iter->tree, iter->node);
+ }
+
+ if (n == NULL)
+ return (-1);
+
+ iter->node = n;
+ *key = n->key;
+ *value = n->value;
+
+ return (0);
+} /* int avl_iterator_next */
+
+int avl_iterator_prev (avl_iterator_t *iter, void **key, void **value)
+{
+ avl_node_t *n;
+
+ if ((iter == NULL) || (key == NULL) || (value == NULL))
+ return (-1);
+
+ if (iter->node == NULL)
+ {
+ for (n = iter->tree->root; n != NULL; n = n->left)
+ if (n->right == NULL)
+ break;
+ iter->node = n;
+ }
+ else
+ {
+ n = avl_node_prev (iter->tree, iter->node);
+ }
+
+ if (n == NULL)
+ return (-1);
+
+ iter->node = n;
+ *key = n->key;
+ *value = n->value;
+
+ return (0);
+} /* int avl_iterator_prev */
+
+void avl_iterator_destroy (avl_iterator_t *iter)
+{
+ free (iter);
+}
diff --git a/src/utils_avltree.h b/src/utils_avltree.h
--- /dev/null
+++ b/src/utils_avltree.h
@@ -0,0 +1,144 @@
+/**
+ * collectd - src/utils_avltree.h
+ * Copyright (C) 2006,2007 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Florian octo Forster <octo at verplant.org>
+ **/
+
+#ifndef UTILS_AVLTREE_H
+#define UTILS_AVLTREE_H 1
+
+struct avl_tree_s;
+typedef struct avl_tree_s avl_tree_t;
+
+struct avl_iterator_s;
+typedef struct avl_iterator_s avl_iterator_t;
+
+/*
+ * NAME
+ * avl_create
+ *
+ * DESCRIPTION
+ * Allocates a new AVL-tree.
+ *
+ * PARAMETERS
+ * `compare' The function-pointer `compare' is used to compare two keys. It
+ * has to return less than zero if it's first argument is smaller
+ * then the second argument, more than zero if the first argument
+ * is bigger than the second argument and zero if they are equal.
+ * If your keys are char-pointers, you can use the `strcmp'
+ * function from the libc here.
+ *
+ * RETURN VALUE
+ * A avl_tree_t-pointer upon success or NULL upon failure.
+ */
+avl_tree_t *avl_create (int (*compare) (const void *, const void *));
+
+
+/*
+ * NAME
+ * avl_destroy
+ *
+ * DESCRIPTION
+ * Deallocates an AVL-tree. Stored value- and key-pointer are lost, but of
+ * course not freed.
+ */
+void avl_destroy (avl_tree_t *t);
+
+/*
+ * NAME
+ * avl_insert
+ *
+ * DESCRIPTION
+ * Stores the key-value-pair in the AVL-tree pointed to by `t'.
+ *
+ * PARAMETERS
+ * `t' AVL-tree to store the data in.
+ * `key' Key used to store the value under. This is used to get back to
+ * the value again.
+ * `value' Value to be stored.
+ *
+ * RETURN VALUE
+ * Zero upon success and non-zero upon failure and if the key is already
+ * stored in the tree.
+ */
+int avl_insert (avl_tree_t *t, void *key, void *value);
+
+/*
+ * NAME
+ * avl_remove
+ *
+ * DESCRIPTION
+ * Removes a key-value-pair from the tree t. The stored key and value may be
+ * returned in `rkey' and `rvalue'.
+ *
+ * PARAMETERS
+ * `t' AVL-tree to remove key-value-pair from.
+ * `key' Key to identify the entry.
+ * `rkey' Pointer to a pointer in which to store the key. May be NULL.
+ * `rvalue' Pointer to a pointer in which to store the value. May be NULL.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if the key isn't found in the tree.
+ */
+int avl_remove (avl_tree_t *t, const void *key, void **rkey, void **rvalue);
+
+/*
+ * NAME
+ * avl_get
+ *
+ * DESCRIPTION
+ * Retrieve the `value' belonging to `key'.
+ *
+ * PARAMETERS
+ * `t' AVL-tree to get the value from.
+ * `key' Key to identify the entry.
+ * `value' Pointer to a pointer in which to store the value. May be NULL.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if the key isn't found in the tree.
+ */
+int avl_get (avl_tree_t *t, const void *key, void **value);
+
+/*
+ * NAME
+ * avl_pick
+ *
+ * DESCRIPTION
+ * Remove a (pseudo-)random element from the tree and return it's `key' and
+ * `value'. Entries are not returned in any particular order. This function
+ * is intended for cache-flushes that don't care about the order but simply
+ * want to remove all elements, one at a time.
+ *
+ * PARAMETERS
+ * `t' AVL-tree to get the value from.
+ * `key' Pointer to a pointer in which to store the key.
+ * `value' Pointer to a pointer in which to store the value.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if the tree is empty or key or value is
+ * NULL.
+ */
+int avl_pick (avl_tree_t *t, void **key, void **value);
+
+avl_iterator_t *avl_get_iterator (avl_tree_t *t);
+int avl_iterator_next (avl_iterator_t *iter, void **key, void **value);
+int avl_iterator_prev (avl_iterator_t *iter, void **key, void **value);
+void avl_iterator_destroy (avl_iterator_t *iter);
+
+#endif /* UTILS_AVLTREE_H */
diff --git a/src/utils_llist.c b/src/utils_llist.c
--- /dev/null
+++ b/src/utils_llist.c
@@ -0,0 +1,148 @@
+/**
+ * collectd - src/utils_llist.c
+ * Copyright (C) 2006 Florian Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; only
+ * version 2 of the Licence is applicable.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Florian Forster <octo at verplant.org>
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils_llist.h"
+
+/*
+ * Private data types
+ */
+struct llist_s
+{
+ llentry_t *head;
+ llentry_t *tail;
+};
+
+/*
+ * Public functions
+ */
+llist_t *llist_create (void)
+{
+ llist_t *ret;
+
+ ret = (llist_t *) malloc (sizeof (llist_t));
+ if (ret == NULL)
+ return (NULL);
+
+ memset (ret, '\0', sizeof (llist_t));
+
+ return (ret);
+}
+
+void llist_destroy (llist_t *l)
+{
+ llentry_t *e_this;
+ llentry_t *e_next;
+
+ for (e_this = l->head; e_this != NULL; e_this = e_next)
+ {
+ e_next = e_this->next;
+ llentry_destroy (e_this);
+ }
+
+ free (l);
+}
+
+llentry_t *llentry_create (const char *key, void *value)
+{
+ llentry_t *e;
+
+ e = (llentry_t *) malloc (sizeof (llentry_t));
+ if (e == NULL)
+ return (NULL);
+
+ e->key = strdup (key);
+ e->value = value;
+ e->next = NULL;
+
+ if (e->key == NULL)
+ {
+ free (e);
+ return (NULL);
+ }
+
+ return (e);
+}
+
+void llentry_destroy (llentry_t *e)
+{
+ free (e->key);
+ free (e);
+}
+
+void llist_append (llist_t *l, llentry_t *e)
+{
+ e->next = NULL;
+
+ if (l->tail == NULL)
+ l->head = e;
+ else
+ l->tail->next = e;
+
+ l->tail = e;
+}
+
+void llist_prepend (llist_t *l, llentry_t *e)
+{
+ e->next = l->head;
+ l->head = e;
+}
+
+void llist_remove (llist_t *l, llentry_t *e)
+{
+ llentry_t *prev;
+
+ prev = l->head;
+ while ((prev != NULL) && (prev->next != e))
+ prev = prev->next;
+
+ if (prev != NULL)
+ prev->next = e->next;
+ if (l->head == e)
+ l->head = e->next;
+ if (l->tail == e)
+ l->tail = prev;
+}
+
+llentry_t *llist_search (llist_t *l, const char *key)
+{
+ llentry_t *e;
+
+ for (e = l->head; e != NULL; e = e->next)
+ if (strcmp (key, e->key) == 0)
+ break;
+
+ return (e);
+}
+
+llentry_t *llist_head (llist_t *l)
+{
+ return (l->head);
+}
+
+llentry_t *llist_tail (llist_t *l)
+{
+ return (l->tail);
+}
diff --git a/src/utils_llist.h b/src/utils_llist.h
--- /dev/null
+++ b/src/utils_llist.h
@@ -0,0 +1,59 @@
+/**
+ * collectd - src/utils_llist.h
+ * Copyright (C) 2006 Florian Forster <octo at verplant.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; only
+ * version 2 of the Licence is applicable.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Florian Forster <octo at verplant.org>
+ */
+
+#ifndef UTILS_LLIST_H
+#define UTILS_LLIST_H 1
+
+/*
+ * Data types
+ */
+struct llentry_s
+{
+ char *key;
+ void *value;
+ struct llentry_s *next;
+};
+typedef struct llentry_s llentry_t;
+
+struct llist_s;
+typedef struct llist_s llist_t;
+
+/*
+ * Functions
+ */
+llist_t *llist_create (void);
+void llist_destroy (llist_t *l);
+
+llentry_t *llentry_create (const char *key, void *value);
+void llentry_destroy (llentry_t *e);
+
+void llist_append (llist_t *l, llentry_t *e);
+void llist_prepend (llist_t *l, llentry_t *e);
+void llist_remove (llist_t *l, llentry_t *e);
+
+llentry_t *llist_search (llist_t *l, const char *key);
+
+llentry_t *llist_head (llist_t *l);
+llentry_t *llist_tail (llist_t *l);
+
+#endif /* UTILS_LLIST_H */
diff --git a/src/wireless.c b/src/wireless.c
index f0b9b01ae1e18d1f7147b63d68eaddd9daf5aab5..929d5d8a711608dc6c7b47e3dd025e3a8dbe058c 100644 (file)
--- a/src/wireless.c
+++ b/src/wireless.c
/**
* collectd - src/wireless.c
- * Copyright (C) 2006 Florian octo Forster
+ * Copyright (C) 2006,2007 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
+ * Free Software Foundation; only version 2 of the License is applicable.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
#include "common.h"
#include "plugin.h"
-#define MODULE_NAME "wireless"
-#define BUFSIZE 1024
-
#if defined(KERNEL_LINUX)
# define WIRELESS_HAVE_READ 1
#else
#define WIRELESS_PROC_FILE "/proc/net/wireless"
-static char *filename_template = "wireless-%s.rrd";
-
-static char *ds_def[] =
+static data_source_t data_source_quality[1] =
{
- "DS:quality:GAUGE:"COLLECTD_HEARTBEAT":0:U",
- "DS:power:GAUGE:"COLLECTD_HEARTBEAT":U:0",
- "DS:noise:GAUGE:"COLLECTD_HEARTBEAT":U:0",
- NULL
+ {"value", DS_TYPE_GAUGE, 0, NAN}
};
-static int ds_num = 3;
-
-#if WIRELESS_HAVE_READ
-static int proc_file_found = 0;
-#endif
-static void wireless_init (void)
+static data_set_t quality_ds =
{
-#if WIRELESS_HAVE_READ
- if (access (WIRELESS_PROC_FILE, R_OK) == 0)
- proc_file_found = 1;
- else
- proc_file_found = 0;
-#endif
-
- return;
-}
+ "signal_quality", 1, data_source_quality
+};
-static void wireless_write (char *host, char *inst, char *val)
+static data_source_t data_source_signal[1] =
{
- char file[BUFSIZE];
- int status;
+ {"value", DS_TYPE_GAUGE, NAN, 0}
+};
- status = snprintf (file, BUFSIZE, filename_template, inst);
- if (status < 1)
- return;
- else if (status >= BUFSIZE)
- return;
+static data_set_t power_ds =
+{
+ "signal_power", 1, data_source_signal
+};
- rrd_update_file (host, file, val, ds_def, ds_num);
-}
+static data_set_t noise_ds =
+{
+ "signal_noise", 1, data_source_signal
+};
#if WIRELESS_HAVE_READ
#if 0
}
#endif
-static void wireless_submit (char *device,
- double quality, double power, double noise)
+static void wireless_submit (const char *plugin_instance, const char *type,
+ double value)
{
- char buf[BUFSIZE];
- int status;
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
- status = snprintf (buf, BUFSIZE, "%u:%f:%f:%f",
- (unsigned int) curtime,
- quality, power, noise);
- if ((status < 1) || (status >= BUFSIZE))
- return;
+ values[0].gauge = value;
- plugin_submit (MODULE_NAME, device, buf);
-}
+ vl.values = values;
+ vl.values_len = 1;
+ vl.time = time (NULL);
+ strcpy (vl.host, hostname);
+ strcpy (vl.plugin, "wireless");
+ strncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
-static void wireless_read (void)
+ plugin_dispatch_values (type, &vl);
+} /* void wireless_submit */
+
+static int wireless_read (void)
{
#ifdef KERNEL_LINUX
-
FILE *fh;
- char buffer[BUFSIZE];
+ char buffer[1024];
char *device;
double quality;
char *fields[8];
int numfields;
+ int devices_found;
int len;
- if (!proc_file_found)
- return;
-
/* there are a variety of names for the wireless device */
if ((fh = fopen (WIRELESS_PROC_FILE, "r")) == NULL)
{
syslog (LOG_WARNING, "wireless: fopen: %s", strerror (errno));
- return;
+ return (-1);
}
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ devices_found = 0;
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
numfields = strsplit (buffer, fields, 8);
if (noise == 0.0)
noise = 1.0; /* noise <= 0 */
- wireless_submit (device, quality, power, noise);
+ wireless_submit (device, "signal_quality", quality);
+ wireless_submit (device, "signal_power", power);
+ wireless_submit (device, "signal_noise", noise);
+
+ devices_found++;
}
fclose (fh);
+
+ /* If no wireless devices are present return an error, so the plugin
+ * code delays our read function. */
+ if (devices_found == 0)
+ return (-1);
#endif /* KERNEL_LINUX */
-}
-#else
-# define wireless_read NULL
+
+ return (0);
+} /* int wireless_read */
#endif /* WIRELESS_HAVE_READ */
void module_register (void)
{
- plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write);
-}
+ plugin_register_data_set (&quality_ds);
+ plugin_register_data_set (&power_ds);
+ plugin_register_data_set (&noise_ds);
-#undef BUFSIZE
-#undef MODULE_NAME
+#if WIRELESS_HAVE_READ
+ plugin_register_read ("wireless", wireless_read);
+#endif /* WIRELESS_HAVE_READ */
+}