my %cf_callbacks : shared = ();
my %types = (
+ TYPE_CONFIG, "config",
TYPE_INIT, "init",
TYPE_READ, "read",
TYPE_WRITE, "write",
if test "x$with_python" = "xyes"
then
AC_MSG_CHECKING([for Python CPPFLAGS])
- python_include_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_python_inc()" | "$with_python_prog" 2>&1`
+ python_include_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_python_inc())" | "$with_python_prog" 2>&1`
python_config_status=$?
if test "$python_config_status" -ne 0 || test "x$python_include_path" = "x"
if test "x$with_python" = "xyes"
then
AC_MSG_CHECKING([for Python LDFLAGS])
- python_library_path=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0)" | "$with_python_prog" 2>&1`
+ python_library_path=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"LIBDIR\").__getitem__(0))" | "$with_python_prog" 2>&1`
python_config_status=$?
if test "$python_config_status" -ne 0 || test "x$python_library_path" = "x"
if test "x$with_python" = "xyes"
then
AC_MSG_CHECKING([for Python LIBS])
- python_library_flags=`echo "import distutils.sysconfig;print distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0)" | "$with_python_prog" 2>&1`
+ python_library_flags=`echo "import distutils.sysconfig;import sys;sys.stdout.write(distutils.sysconfig.get_config_vars(\"BLDLIBRARY\").__getitem__(0))" | "$with_python_prog" 2>&1`
python_config_status=$?
if test "$python_config_status" -ne 0 || test "x$python_library_flags" = "x"
#!/usr/bin/perl
#
# collectd - snmp-probe-host.px
-# Copyright (C) 2008 Florian octo Forster
+# Copyright (C) 2008,2009 Florian octo Forster
+# Copyright (C) 2009 noris network AG
#
# 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
use Getopt::Long ('GetOptions');
use Socket6;
+our %ExcludeOptions =
+(
+ 'IF-MIB64' => qr/^\.?1\.3\.6\.1\.2\.1\.31/,
+ 'IF-MIB32' => qr/^\.?1\.3\.6\.1\.2\.1\.2/
+);
+
sub get_config
{
my %conf;
{
my $sess = shift;
my $conf = shift;
+ my $excludes = @_ ? shift : [];
my @oids;
my $cmd = 'GET';
my $vl;
$oid_orig = $tmp;
}
+ for (@$excludes)
+ {
+ if ($oid_orig =~ $_)
+ {
+ return;
+ }
+ }
+
$vb = SNMP::Varbind->new ([$oid_orig]);
if ($cmd eq 'GET')
my $host = shift;
my $community = shift;
my $data = shift;
+ my $excludes = @_ ? shift : [];
my $version = 2;
my @valid_data = ();
my $begin;
for (keys %$data)
{
my $name = $_;
- if (probe_one ($sess, $data->{$name}))
+ if (probe_one ($sess, $data->{$name}, $excludes))
{
push (@valid_data, $name);
}
-C | --config Path to config file holding the SNMP data blocks.
-c | --community SNMP community to use. Default: `public'.
-h | --help Print this information and exit.
+ -x | --exclude Exclude a specific MIB. Call with "help" for more
+ information.
USAGE
exit (1);
}
+sub exit_usage_exclude
+{
+ print "Available exclude MIBs:\n\n";
+ for (sort (keys %ExcludeOptions))
+ {
+ print " $_\n";
+ }
+ print "\n";
+ exit (1);
+}
+
=head1 NAME
snmp-probe-host.px - Find out what information an SNMP device provides.
my $community = 'public';
my $conf;
my $working_data;
+my @excludes = ();
=head1 OPTIONS
SNMP community to use. Should be pretty straight forward.
+=item B<--exclude> I<MIB>
+
+This option can be used to exclude specific data from being enabled in the
+generated config. Currently the following MIBs are understood:
+
+=over 4
+
+=item B<IF-MIB>
+
+Exclude interface information, such as I<ifOctets> and I<ifPackets>.
+
+=back
+
=back
=cut
GetOptions ('H|host|hostname=s' => \$host,
'C|conf|config=s' => \$file,
'c|community=s' => \$community,
+ 'x|exclude=s' => \@excludes,
'h|help' => \&exit_usage) or die;
if (!$host)
exit (1);
}
+if (@excludes)
+{
+ my $tmp = join (',', @excludes);
+ my @tmp = split (/\s*,\s*/, $tmp);
+
+ @excludes = ();
+ for (@tmp)
+ {
+ my $mib = uc ($_);
+ if ($mib eq 'HELP')
+ {
+ exit_usage_exclude ();
+ }
+ elsif (!exists ($ExcludeOptions{$mib}))
+ {
+ print STDERR "No such MIB: $mib\n";
+ exit_usage_exclude ();
+ }
+ push (@excludes, $ExcludeOptions{$mib});
+ }
+}
+
$conf = get_config ($file) or die ("Cannot read config");
if (!defined ($conf->{'plugin'})
exit (1);
}
-probe_all ($host, $community, $conf->{'plugin'}{'snmp'}{'data'});
+probe_all ($host, $community, $conf->{'plugin'}{'snmp'}{'data'}, \@excludes);
exit (0);
if (0 == access (battery_acpi_dir, R_OK))
walk_directory (battery_acpi_dir, battery_read_acpi,
- /* user_data = */ NULL);
+ /* user_data = */ NULL,
+ /* include hidden */ 0);
else
{
char errbuf[1024];
Python-script every time you want to read a value with the C<exec plugin> (see
L<collectd-exec(5)>) and provides a lot more functionality, too.
-Currently only I<Python 2> is supported and at least I<version 2.3> is
-required.
+At least python I<version 2.3> is required.
=head1 CONFIGURATION
=back
+=head1 STRINGS
+
+There are a lot of places where strings are send from collectd to python and
+from python to collectd. How exactly this works depends on wheather byte or
+unicode strings or python2 or python3 are used.
+
+Python2 has I<str>, which is just bytes, and I<unicode>. Python3 has I<str>,
+which is a unicode object, and I<bytes>.
+
+When passing strings from python to collectd all of these object are supported
+in all places, however I<str> should be used if possible. These strings must
+not contain a NUL byte. Ignoring this will result in a I<TypeError> exception.
+If a byte string was used it will be used as is by collectd. If a unicode
+object was used it will be encoded using the default encoding (see above). If
+this is not possible python will raise a I<UnicodeEncodeError> exception.
+
+Wenn passing strings from collectd to python the behavior depends on the
+python version used. Python2 will always receive a I<str> object. Python3 will
+usually receive a I<str> object as well, however the original string will be
+decoded to unicode using the default encoding. If this fails because the
+string is not a valid sequence for this encoding a I<bytes> object will be
+returned instead.
+
=head1 WRITING YOUR OWN PLUGINS
Writing your own plugins is quite simple. collectd manages plugins by means of
# Password "dozaiTh4"
# CollectInterface true
# CollectRegistrationTable true
+# CollectCPULoad true
+# CollectMemory true
+# CollectDF true
+# CollectDisk true
# </Router>
#</Plugin>
Controls whether or not to recurse into subdirectories. Enabled by default.
+=item B<IncludeHidden> I<true>|I<false>
+
+Controls whether or not to include "hidden" files and directories in the count.
+"Hidden" files and directories are those, whose name begins with a dot.
+Defaults to I<false>, i.e. by default hidden files and directories are ignored.
+
=back
=head2 Plugin C<GenericJMX>
User "collectd"
Password "secr3t"
CollectInterface true
+ CollectCPULoad true
+ CollectMemory true
</Router>
<Router>
Host "router1.example.com"
Password "5ecret"
CollectInterface true
CollectRegistrationTable true
+ CollectDF true
+ CollectDisk true
</Router>
</Plugin>
When set to B<true>, information about wireless LAN connections will be
collected. Defaults to B<false>.
+=item B<CollectCPULoad> B<true>|B<false>
+
+When set to B<true>, information about the CPU usage will be collected. The
+number is a dimensionless value where zero indicates no CPU usage at all.
+Defaults to B<false>.
+
+=item B<CollectMemory> B<true>|B<false>
+
+When enabled, the amount of used and free memory will be collected. How used
+memory is calculated is unknown, for example whether or not caches are counted
+as used space.
+Defaults to B<false>.
+
+=item B<CollectDF> B<true>|B<false>
+
+When enabled, the amount of used and free disk space will be collected.
+Defaults to B<false>.
+
+=item B<CollectDisk> B<true>|B<false>
+
+When enabled, the number of sectors written and bad blocks will be collected.
+Defaults to B<false>.
+
=back
=head2 Plugin C<rrdcached>
} /* int notification_init */
int walk_directory (const char *dir, dirwalk_callback_f callback,
- void *user_data)
+ void *user_data, int include_hidden)
{
struct dirent *ent;
DIR *dh;
while ((ent = readdir (dh)) != NULL)
{
int status;
-
- if (ent->d_name[0] == '.')
- continue;
+
+ if (include_hidden)
+ {
+ if ((strcmp (".", ent->d_name) == 0)
+ || (strcmp ("..", ent->d_name) == 0))
+ continue;
+ }
+ else /* if (!include_hidden) */
+ {
+ if (ent->d_name[0]=='.')
+ continue;
+ }
status = (*callback) (dir, ent->d_name, user_data);
if (status != 0)
typedef int (*dirwalk_callback_f)(const char *dirname, const char *filename,
void *user_data);
int walk_directory (const char *dir, dirwalk_callback_f callback,
- void *user_data);
+ void *user_data, int hidden);
int read_file_contents (const char *filename, char *buf, int bufsize);
counter_t counter_diff (counter_t old_value, counter_t new_value);
# define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif
+/* This macro is a shortcut for calls like
+ * x = PyObject_Repr(x);
+ * This can't be done like this example because this would leak
+ * a reference the the original x and crash in case of x == NULL.
+ * This calling syntax is less than elegant but it works, saves
+ * a lot of lines and avoids potential refcount errors. */
+
+#define CPY_SUBSTITUTE(func, a, ...) do {\
+ if ((a) != NULL) {\
+ PyObject *__tmp = (a);\
+ (a) = func(__VA_ARGS__);\
+ Py_DECREF(__tmp);\
+ }\
+} while(0)
+
+/* Python3 compatibility layer. To keep the actual code as clean as possible
+ * do a lot of defines here. */
+
+#if PY_MAJOR_VERSION >= 3
+#define IS_PY3K
+#endif
+
+#ifdef IS_PY3K
+
+#define PyInt_FromLong PyLong_FromLong
+#define CPY_INIT_TYPE PyVarObject_HEAD_INIT(NULL, 0)
+#define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyBytes_Check(o))
+#define CPY_STRCAT_AND_DEL(a, b) do {\
+ CPY_STRCAT((a), (b));\
+ Py_XDECREF((b));\
+} while (0)
+static inline void CPY_STRCAT(PyObject **a, PyObject *b) {
+ PyObject *ret;
+
+ if (!a || !*a)
+ return;
+
+ ret = PyUnicode_Concat(*a, b);
+ Py_DECREF(*a);
+ *a = ret;
+}
+
+#else
+
+#define CPY_INIT_TYPE PyObject_HEAD_INIT(NULL) 0,
+#define IS_BYTES_OR_UNICODE(o) (PyUnicode_Check(o) || PyString_Check(o))
+#define CPY_STRCAT_AND_DEL PyString_ConcatAndDel
+#define CPY_STRCAT PyString_Concat
+
+#endif
+
+static inline const char *cpy_unicode_or_bytes_to_string(PyObject **o) {
+ if (PyUnicode_Check(*o)) {
+ PyObject *tmp;
+ tmp = PyUnicode_AsEncodedString(*o, NULL, NULL); /* New reference. */
+ if (tmp == NULL)
+ return NULL;
+ Py_DECREF(*o);
+ *o = tmp;
+ }
+#ifdef IS_PY3K
+ return PyBytes_AsString(*o);
+#else
+ return PyString_AsString(*o);
+#endif
+}
+
+static inline PyObject *cpy_string_to_unicode_or_bytes(const char *buf) {
+#ifdef IS_PY3K
+/* Python3 preferrs unicode */
+ PyObject *ret;
+ ret = PyUnicode_Decode(buf, strlen(buf), NULL, NULL);
+ if (ret != NULL)
+ return ret;
+ PyErr_Clear();
+ return PyBytes_FromString(buf);
+#else
+ return PyString_FromString(buf);
+#endif
+}
+
+ /* Python object declarations. */
+
typedef struct {
PyObject_HEAD /* No semicolon! */
PyObject *parent; /* Config */
#include <fnmatch.h>
#define FC_RECURSIVE 1
+#define FC_HIDDEN 2
struct fc_directory_conf_s
{
return (0);
} /* int fc_config_add_dir_size */
-static int fc_config_add_dir_recursive (fc_directory_conf_t *dir,
- oconfig_item_t *ci)
+static int fc_config_add_dir_option (fc_directory_conf_t *dir,
+ oconfig_item_t *ci, int bit)
{
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
}
if (ci->values[0].value.boolean)
- dir->options |= FC_RECURSIVE;
+ dir->options |= bit;
else
- dir->options &= ~FC_RECURSIVE;
+ dir->options &= ~bit;
return (0);
-} /* int fc_config_add_dir_recursive */
+} /* int fc_config_add_dir_option */
static int fc_config_add_dir (oconfig_item_t *ci)
{
else if (strcasecmp ("Size", option->key) == 0)
status = fc_config_add_dir_size (dir, option);
else if (strcasecmp ("Recursive", option->key) == 0)
- status = fc_config_add_dir_recursive (dir, option);
+ status = fc_config_add_dir_option (dir, option, FC_RECURSIVE);
+ else if (strcasecmp ("IncludeHidden", option->key) == 0)
+ status = fc_config_add_dir_option (dir, option, FC_HIDDEN);
else
{
WARNING ("filecount plugin: fc_config_add_dir: "
if (S_ISDIR (statbuf.st_mode) && (dir->options & FC_RECURSIVE))
{
- status = walk_directory (abs_path, fc_read_dir_callback, dir);
+ status = walk_directory (abs_path, fc_read_dir_callback, dir,
+ /* include hidden = */ (dir->options & FC_HIDDEN) ? 1 : 0);
return (status);
}
else if (!S_ISREG (statbuf.st_mode))
if (dir->mtime != 0)
dir->now = time (NULL);
-
- status = walk_directory (dir->path, fc_read_dir_callback, dir);
+
+ status = walk_directory (dir->path, fc_read_dir_callback, dir,
+ /* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0);
if (status != 0)
{
WARNING ("filecount plugin: walk_directory (%s) failed.", dir->path);
#include <pthread.h>
/*
- * Defines
- */
-#define MD_TYPE_STRING 1
-#define MD_TYPE_SIGNED_INT 2
-#define MD_TYPE_UNSIGNED_INT 3
-#define MD_TYPE_DOUBLE 4
-#define MD_TYPE_BOOLEAN 5
-
-/*
* Data types
*/
union meta_value_u
return (0);
} /* }}} int meta_data_exists */
+int meta_data_type (meta_data_t *md, const char *key) /* {{{ */
+{
+ meta_entry_t *e;
+
+ if ((md == NULL) || (key == NULL))
+ return -EINVAL;
+
+ pthread_mutex_lock (&md->lock);
+
+ for (e = md->head; e != NULL; e = e->next)
+ {
+ if (strcasecmp (key, e->key) == 0)
+ {
+ pthread_mutex_unlock (&md->lock);
+ return e->type;
+ }
+ }
+
+ pthread_mutex_unlock (&md->lock);
+ return 0;
+} /* }}} int meta_data_type */
+
+int meta_data_toc (meta_data_t *md, char ***toc) /* {{{ */
+{
+ int i = 0, count = 0;
+ meta_entry_t *e;
+
+ if ((md == NULL) || (toc == NULL))
+ return -EINVAL;
+
+ pthread_mutex_lock (&md->lock);
+
+ for (e = md->head; e != NULL; e = e->next)
+ ++count;
+
+ *toc = malloc(count * sizeof(**toc));
+ for (e = md->head; e != NULL; e = e->next)
+ (*toc)[i++] = strdup(e->key);
+
+ pthread_mutex_unlock (&md->lock);
+ return count;
+} /* }}} int meta_data_toc */
+
int meta_data_delete (meta_data_t *md, const char *key) /* {{{ */
{
meta_entry_t *this;
#include "collectd.h"
+/*
+ * Defines
+ */
+#define MD_TYPE_STRING 1
+#define MD_TYPE_SIGNED_INT 2
+#define MD_TYPE_UNSIGNED_INT 3
+#define MD_TYPE_DOUBLE 4
+#define MD_TYPE_BOOLEAN 5
+
struct meta_data_s;
typedef struct meta_data_s meta_data_t;
void meta_data_destroy (meta_data_t *md);
int meta_data_exists (meta_data_t *md, const char *key);
+int meta_data_type (meta_data_t *md, const char *key);
+int meta_data_toc (meta_data_t *md, char ***toc);
int meta_data_delete (meta_data_t *md, const char *key);
int meta_data_add_string (meta_data_t *md,
Config *self = (Config *) s;
static char *kwlist[] = {"key", "parent", "values", "children", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "S|OOO", kwlist,
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO", kwlist,
&key, &parent, &values, &children))
return -1;
+ if (!IS_BYTES_OR_UNICODE(key)) {
+ PyErr_SetString(PyExc_TypeError, "argument 1 must be str");
+ Py_XDECREF(parent);
+ Py_XDECREF(values);
+ Py_XDECREF(children);
+ return -1;
+ }
if (values == NULL) {
values = PyTuple_New(0);
PyErr_Clear();
static PyObject *Config_repr(PyObject *s) {
Config *self = (Config *) s;
+ PyObject *ret = NULL;
+ static PyObject *node_prefix = NULL, *root_prefix = NULL, *ending = NULL;
+
+ /* This is ok because we have the GIL, so this is thread-save by default. */
+ if (node_prefix == NULL)
+ node_prefix = cpy_string_to_unicode_or_bytes("<collectd.Config node ");
+ if (root_prefix == NULL)
+ root_prefix = cpy_string_to_unicode_or_bytes("<collectd.Config root node ");
+ if (ending == NULL)
+ ending = cpy_string_to_unicode_or_bytes(">");
+ if (node_prefix == NULL || root_prefix == NULL || ending == NULL)
+ return NULL;
- return PyString_FromFormat("<collectd.Config %snode %s>", self->parent == Py_None ? "root " : "", PyString_AsString(PyObject_Str(self->key)));
+ ret = PyObject_Str(self->key);
+ CPY_SUBSTITUTE(PyObject_Repr, ret, ret);
+ if (self->parent == NULL || self->parent == Py_None)
+ CPY_STRCAT(&ret, root_prefix);
+ else
+ CPY_STRCAT(&ret, node_prefix);
+ CPY_STRCAT(&ret, ending);
+
+ return ret;
}
static int Config_traverse(PyObject *self, visitproc visit, void *arg) {
Py_VISIT(c->key);
Py_VISIT(c->values);
Py_VISIT(c->children);
- return 0;
-}
+ return 0;}
static int Config_clear(PyObject *self) {
Config *c = (Config *) self;
};
PyTypeObject ConfigType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* Always 0 */
+ CPY_INIT_TYPE
"collectd.Config", /* tp_name */
sizeof(Config), /* tp_basicsize */
0, /* Will be filled in later */
mod = PyObject_GetAttrString(callback, "__module__"); /* New reference. */
if (mod != NULL)
- module = PyString_AsString(mod);
+ module = cpy_unicode_or_bytes_to_string(&mod);
if (module != NULL) {
snprintf(buf, size, "python.%s", module);
PyErr_NormalizeException(&type, &value, &traceback);
if (type == NULL) return;
tn = PyObject_GetAttrString(type, "__name__"); /* New reference. */
- m = PyObject_GetAttrString(value, "message"); /* New reference. */
+ m = PyObject_Str(value); /* New reference. */
if (tn != NULL)
- typename = PyString_AsString(tn);
+ typename = cpy_unicode_or_bytes_to_string(&tn);
if (m != NULL)
- message = PyString_AsString(m);
+ message = cpy_unicode_or_bytes_to_string(&m);
if (typename == NULL)
typename = "NamelessException";
if (message == NULL)
PyObject *line;
line = PyList_GET_ITEM(list, i); /* Borrowed reference. */
- s = strdup(PyString_AsString(line));
+ Py_INCREF(line);
+ s = strdup(cpy_unicode_or_bytes_to_string(&line));
+ Py_DECREF(line);
if (s[strlen(s) - 1] == '\n')
s[strlen(s) - 1] = 0;
Py_BEGIN_ALLOW_THREADS
static int cpy_write_callback(const data_set_t *ds, const value_list_t *value_list, user_data_t *data) {
int i;
cpy_callback_t *c = data->data;
- PyObject *ret, *v, *list;
+ PyObject *ret, *list;
+ Values *v;
CPY_LOCK_THREADS
list = PyList_New(value_list->values_len); /* New reference. */
CPY_RETURN_FROM_THREADS 0;
}
}
- v = PyObject_CallFunction((void *) &ValuesType, "sOssssdi", value_list->type, list,
- value_list->plugin_instance, value_list->type_instance, value_list->plugin,
- value_list->host, (double) value_list->time, value_list->interval);
- Py_DECREF(list);
+ v = PyObject_New(Values, (void *) &ValuesType);
+ sstrncpy(v->data.host, value_list->host, sizeof(v->data.host));
+ sstrncpy(v->data.type, value_list->type, sizeof(v->data.type));
+ sstrncpy(v->data.type_instance, value_list->type_instance, sizeof(v->data.type_instance));
+ sstrncpy(v->data.plugin, value_list->plugin, sizeof(v->data.plugin));
+ sstrncpy(v->data.plugin_instance, value_list->plugin_instance, sizeof(v->data.plugin_instance));
+ v->data.time = value_list->time;
+ v->interval = value_list->interval;
+ v->values = list;
ret = PyObject_CallFunctionObjArgs(c->callback, v, c->data, (void *) 0); /* New reference. */
if (ret == NULL) {
cpy_log_exception("write callback");
static int cpy_notification_callback(const notification_t *notification, user_data_t *data) {
cpy_callback_t *c = data->data;
- PyObject *ret, *n;
+ PyObject *ret;
+ Notification *n;
CPY_LOCK_THREADS
- n = PyObject_CallFunction((void *) &NotificationType, "ssssssdi", notification->type, notification->message,
- notification->plugin_instance, notification->type_instance, notification->plugin,
- notification->host, (double) notification->time, notification->severity);
+ n = PyObject_New(Notification, (void *) &NotificationType);
+ sstrncpy(n->data.host, notification->host, sizeof(n->data.host));
+ sstrncpy(n->data.type, notification->type, sizeof(n->data.type));
+ sstrncpy(n->data.type_instance, notification->type_instance, sizeof(n->data.type_instance));
+ sstrncpy(n->data.plugin, notification->plugin, sizeof(n->data.plugin));
+ sstrncpy(n->data.plugin_instance, notification->plugin_instance, sizeof(n->data.plugin_instance));
+ n->data.time = notification->time;
+ sstrncpy(n->message, notification->message, sizeof(n->message));
+ n->severity = notification->severity;
ret = PyObject_CallFunctionObjArgs(c->callback, n, c->data, (void *) 0); /* New reference. */
if (ret == NULL) {
cpy_log_exception("notification callback");
static void cpy_log_callback(int severity, const char *message, user_data_t *data) {
cpy_callback_t * c = data->data;
- PyObject *ret;
+ PyObject *ret, *text;
CPY_LOCK_THREADS
+ text = cpy_string_to_unicode_or_bytes(message);
if (c->data == NULL)
- ret = PyObject_CallFunction(c->callback, "is", severity, message); /* New reference. */
+ ret = PyObject_CallFunction(c->callback, "iN", severity, text); /* New reference. */
else
- ret = PyObject_CallFunction(c->callback, "isO", severity, message, c->data); /* New reference. */
+ ret = PyObject_CallFunction(c->callback, "iNO", severity, text, c->data); /* New reference. */
if (ret == NULL) {
/* FIXME */
static void cpy_flush_callback(int timeout, const char *id, user_data_t *data) {
cpy_callback_t * c = data->data;
- PyObject *ret;
+ PyObject *ret, *text;
CPY_LOCK_THREADS
+ text = cpy_string_to_unicode_or_bytes(id);
if (c->data == NULL)
- ret = PyObject_CallFunction(c->callback, "is", timeout, id); /* New reference. */
+ ret = PyObject_CallFunction(c->callback, "iN", timeout, text); /* New reference. */
else
- ret = PyObject_CallFunction(c->callback, "isO", timeout, id, c->data); /* New reference. */
+ ret = PyObject_CallFunction(c->callback, "iNO", timeout, text, c->data); /* New reference. */
if (ret == NULL) {
cpy_log_exception("flush callback");
PyObject *callback = NULL, *data = NULL, *mod = NULL;
static char *kwlist[] = {"callback", "data", "name", NULL};
- if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oz", kwlist, &callback, &data, &name) == 0) return NULL;
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
if (PyCallable_Check(callback) == 0) {
PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
return NULL;
c->next = *list_head;
*list_head = c;
Py_XDECREF(mod);
- return PyString_FromString(buf);
+ return cpy_string_to_unicode_or_bytes(buf);
}
static PyObject *cpy_flush(cpy_callback_t **list_head, PyObject *args, PyObject *kwds) {
const char *plugin = NULL, *identifier = NULL;
static char *kwlist[] = {"plugin", "timeout", "identifier", NULL};
- if (PyArg_ParseTupleAndKeywords(args, kwds, "|ziz", kwlist, &plugin, &timeout, &identifier) == 0) return NULL;
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "|etiet", kwlist, NULL, &plugin, &timeout, NULL, &identifier) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_flush(plugin, timeout, identifier);
Py_END_ALLOW_THREADS
PyObject *callback = NULL, *data = NULL;
static char *kwlist[] = {"callback", "data", "name", NULL};
- if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oz", kwlist, &callback, &data, &name) == 0) return NULL;
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O|Oet", kwlist, &callback, &data, NULL, &name) == 0) return NULL;
if (PyCallable_Check(callback) == 0) {
PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
return NULL;
user_data->free_func = cpy_destroy_user_data;
user_data->data = c;
register_function(buf, handler, user_data);
- return PyString_FromString(buf);
+ return cpy_string_to_unicode_or_bytes(buf);
}
static PyObject *cpy_register_read(PyObject *self, PyObject *args, PyObject *kwds) {
struct timespec ts;
static char *kwlist[] = {"callback", "interval", "data", "name", NULL};
- if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOz", kwlist, &callback, &interval, &data, &name) == 0) return NULL;
+ if (PyArg_ParseTupleAndKeywords(args, kwds, "O|dOet", kwlist, &callback, &interval, &data, NULL, &name) == 0) return NULL;
if (PyCallable_Check(callback) == 0) {
PyErr_SetString(PyExc_TypeError, "callback needs a be a callable object.");
return NULL;
ts.tv_sec = interval;
ts.tv_nsec = (interval - ts.tv_sec) * 1000000000;
plugin_register_complex_read(buf, cpy_read_callback, &ts, user_data);
- return PyString_FromString(buf);
+ return cpy_string_to_unicode_or_bytes(buf);
}
static PyObject *cpy_register_log(PyObject *self, PyObject *args, PyObject *kwds) {
static PyObject *cpy_error(PyObject *self, PyObject *args) {
const char *text;
- if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
+ if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_log(LOG_ERR, "%s", text);
Py_END_ALLOW_THREADS
static PyObject *cpy_warning(PyObject *self, PyObject *args) {
const char *text;
- if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
+ if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_log(LOG_WARNING, "%s", text);
Py_END_ALLOW_THREADS
static PyObject *cpy_notice(PyObject *self, PyObject *args) {
const char *text;
- if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
+ if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_log(LOG_NOTICE, "%s", text);
Py_END_ALLOW_THREADS
static PyObject *cpy_info(PyObject *self, PyObject *args) {
const char *text;
- if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
+ if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_log(LOG_INFO, "%s", text);
Py_END_ALLOW_THREADS
static PyObject *cpy_debug(PyObject *self, PyObject *args) {
#ifdef COLLECT_DEBUG
const char *text;
- if (PyArg_ParseTuple(args, "s", &text) == 0) return NULL;
+ if (PyArg_ParseTuple(args, "et", NULL, &text) == 0) return NULL;
Py_BEGIN_ALLOW_THREADS
plugin_log(LOG_DEBUG, "%s", text);
Py_END_ALLOW_THREADS
const char *name;
cpy_callback_t *prev = NULL, *tmp;
- if (PyUnicode_Check(arg)) {
- arg = PyUnicode_AsEncodedString(arg, NULL, NULL);
- if (arg == NULL)
- return NULL;
- name = PyString_AsString(arg);
- Py_DECREF(arg);
- } else if (PyString_Check(arg)) {
- name = PyString_AsString(arg);
- } else {
+ Py_INCREF(arg);
+ name = cpy_unicode_or_bytes_to_string(&arg);
+ if (name == NULL) {
+ PyErr_Clear();
if (!PyCallable_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
+ Py_DECREF(arg);
return NULL;
}
cpy_build_name(buf, sizeof(buf), arg, NULL);
if (strcmp(name, tmp->name) == 0)
break;
+ Py_DECREF(arg);
if (tmp == NULL) {
PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
return NULL;
char buf[512];
const char *name;
- if (PyUnicode_Check(arg)) {
- arg = PyUnicode_AsEncodedString(arg, NULL, NULL);
- if (arg == NULL)
- return NULL;
- name = PyString_AsString(arg);
- Py_DECREF(arg);
- } else if (PyString_Check(arg)) {
- name = PyString_AsString(arg);
- } else {
+ Py_INCREF(arg);
+ name = cpy_unicode_or_bytes_to_string(&arg);
+ if (name == NULL) {
+ PyErr_Clear();
if (!PyCallable_Check(arg)) {
PyErr_SetString(PyExc_TypeError, "This function needs a string or a callable object as its only parameter.");
+ Py_DECREF(arg);
return NULL;
}
cpy_build_name(buf, sizeof(buf), arg, NULL);
name = buf;
}
- if (unreg(name) == 0)
+ if (unreg(name) == 0) {
+ Py_DECREF(arg);
Py_RETURN_NONE;
+ }
PyErr_Format(PyExc_RuntimeError, "Unable to unregister %s callback '%s'.", desc, name);
+ Py_DECREF(arg);
return NULL;
}
values = PyTuple_New(ci->values_num); /* New reference. */
for (i = 0; i < ci->values_num; ++i) {
if (ci->values[i].type == OCONFIG_TYPE_STRING) {
- PyTuple_SET_ITEM(values, i, PyString_FromString(ci->values[i].value.string));
+ PyTuple_SET_ITEM(values, i, cpy_string_to_unicode_or_bytes(ci->values[i].value.string));
} else if (ci->values[i].type == OCONFIG_TYPE_NUMBER) {
PyTuple_SET_ITEM(values, i, PyFloat_FromDouble(ci->values[i].value.number));
} else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN) {
}
}
- item = PyObject_CallFunction((void *) &ConfigType, "sONO", ci->key, parent, values, Py_None);
+ tmp = cpy_string_to_unicode_or_bytes(ci->key);
+ item = PyObject_CallFunction((void *) &ConfigType, "NONO", tmp, parent, values, Py_None);
if (item == NULL)
return NULL;
children = PyTuple_New(ci->children_num); /* New reference. */
return item;
}
+#ifdef IS_PY3K
+static struct PyModuleDef collectdmodule = {
+ PyModuleDef_HEAD_INIT,
+ "collectd", /* name of module */
+ "The python interface to collectd", /* module documentation, may be NULL */
+ -1,
+ cpy_methods
+};
+
+PyMODINIT_FUNC PyInit_collectd(void) {
+ return PyModule_Create(&collectdmodule);
+}
+#endif
+
static int cpy_config(oconfig_item_t *ci) {
int i;
PyObject *sys, *tb;
* python code during the config callback so we have to start
* the interpreter here. */
/* Do *not* use the python "thread" module at this point! */
+
+#ifdef IS_PY3K
+ /* Add a builtin module, before Py_Initialize */
+ PyImport_AppendInittab("collectd", PyInit_collectd);
+#endif
+
Py_Initialize();
PyType_Ready(&ConfigType);
cpy_log_exception("python initialization");
return 1;
}
+#ifdef IS_PY3K
+ module = PyImport_ImportModule("collectd");
+#else
module = Py_InitModule("collectd", cpy_methods); /* Borrowed reference. */
+#endif
PyModule_AddObject(module, "Config", (void *) &ConfigType); /* Steals a reference. */
PyModule_AddObject(module, "Values", (void *) &ValuesType); /* Steals a reference. */
PyModule_AddObject(module, "Notification", (void *) &NotificationType); /* Steals a reference. */
if (cf_util_get_string(item, &dir) != 0)
continue;
- dir_object = PyString_FromString(dir); /* New reference. */
+ dir_object = cpy_string_to_unicode_or_bytes(dir); /* New reference. */
if (dir_object == NULL) {
ERROR("python plugin: Unable to convert \"%s\" to "
"a python object.", dir);
if (module == NULL) {
ERROR("python plugin: Error importing module \"%s\".", module_name);
cpy_log_exception("importing module");
- PyErr_Print();
}
free(module_name);
Py_XDECREF(module);
#include "cpython.h"
+static PyObject *cpy_common_repr(PyObject *s) {
+ PyObject *ret, *tmp;
+ static PyObject *l_type = NULL, *l_type_instance = NULL, *l_plugin = NULL, *l_plugin_instance = NULL;
+ static PyObject *l_host = NULL, *l_time = NULL;
+ PluginData *self = (PluginData *) s;
+
+ if (l_type == NULL)
+ l_type = cpy_string_to_unicode_or_bytes("(type=");
+ if (l_type_instance == NULL)
+ l_type_instance = cpy_string_to_unicode_or_bytes(",type_instance=");
+ if (l_plugin == NULL)
+ l_plugin = cpy_string_to_unicode_or_bytes(",plugin=");
+ if (l_plugin_instance == NULL)
+ l_plugin_instance = cpy_string_to_unicode_or_bytes(",plugin_instance=");
+ if (l_host == NULL)
+ l_host = cpy_string_to_unicode_or_bytes(",host=");
+ if (l_time == NULL)
+ l_time = cpy_string_to_unicode_or_bytes(",time=");
+
+ if (!l_type || !l_type_instance || !l_plugin || !l_plugin_instance || !l_host || !l_time)
+ return NULL;
+
+ ret = cpy_string_to_unicode_or_bytes(s->ob_type->tp_name);
+
+ CPY_STRCAT(&ret, l_type);
+ tmp = cpy_string_to_unicode_or_bytes(self->type);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+
+ if (self->type_instance[0] != 0) {
+ CPY_STRCAT(&ret, l_type_instance);
+ tmp = cpy_string_to_unicode_or_bytes(self->type_instance);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+
+ if (self->plugin[0] != 0) {
+ CPY_STRCAT(&ret, l_plugin);
+ tmp = cpy_string_to_unicode_or_bytes(self->plugin);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+
+ if (self->plugin_instance[0] != 0) {
+ CPY_STRCAT(&ret, l_plugin_instance);
+ tmp = cpy_string_to_unicode_or_bytes(self->plugin_instance);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+
+ if (self->host[0] != 0) {
+ CPY_STRCAT(&ret, l_host);
+ tmp = cpy_string_to_unicode_or_bytes(self->host);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+
+ if (self->time != 0) {
+ CPY_STRCAT(&ret, l_time);
+ tmp = PyInt_FromLong(self->time);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+ return ret;
+}
+
static char time_doc[] = "This is the Unix timestap of the time this value was read.\n"
"For dispatching values this can be set to 0 which means \"now\".\n"
"This means the time the value is actually dispatched, not the time\n"
static char *kwlist[] = {"type", "plugin_instance", "type_instance",
"plugin", "host", "time", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sssssd", kwlist, &type,
- &plugin_instance, &type_instance, &plugin, &host, &time))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetd", kwlist, NULL, &type,
+ NULL, &plugin_instance, NULL, &type_instance, NULL, &plugin, NULL, &host, &time))
return -1;
if (type[0] != 0 && plugin_get_ds(type) == NULL) {
}
static PyObject *PluginData_repr(PyObject *s) {
- PluginData *self = (PluginData *) s;
+ PyObject *ret;
+ static PyObject *l_closing = NULL;
+
+ if (l_closing == NULL)
+ l_closing = cpy_string_to_unicode_or_bytes(")");
- return PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s',time=%lu)", self->type,
- *self->type_instance ? "',type_instance='" : "", self->type_instance,
- *self->plugin ? "',plugin='" : "", self->plugin,
- *self->plugin_instance ? "',plugin_instance='" : "", self->plugin_instance,
- *self->host ? "',host='" : "", self->host,
- (long unsigned) self->time);
+ if (l_closing == NULL)
+ return NULL;
+
+ ret = cpy_common_repr(s);
+ CPY_STRCAT(&ret, l_closing);
+ return ret;
}
static PyMemberDef PluginData_members[] = {
static PyObject *PluginData_getstring(PyObject *self, void *data) {
const char *value = ((char *) self) + (intptr_t) data;
- return PyString_FromString(value);
+ return cpy_string_to_unicode_or_bytes(value);
}
static int PluginData_setstring(PyObject *self, PyObject *value, void *data) {
PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
return -1;
}
- new = PyString_AsString(value);
- if (new == NULL) return -1;
+ Py_INCREF(value);
+ new = cpy_unicode_or_bytes_to_string(&value);
+ if (new == NULL) {
+ Py_DECREF(value);
+ return -1;
+ }
old = ((char *) self) + (intptr_t) data;
sstrncpy(old, new, DATA_MAX_NAME_LEN);
+ Py_DECREF(value);
return 0;
}
PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
return -1;
}
- new = PyString_AsString(value);
- if (new == NULL) return -1;
+ Py_INCREF(value);
+ new = cpy_unicode_or_bytes_to_string(&value);
+ if (new == NULL) {
+ Py_DECREF(value);
+ return -1;
+ }
if (plugin_get_ds(new) == NULL) {
PyErr_Format(PyExc_TypeError, "Dataset %s not found", new);
+ Py_DECREF(value);
return -1;
}
old = ((char *) self) + (intptr_t) data;
sstrncpy(old, new, DATA_MAX_NAME_LEN);
+ Py_DECREF(value);
return 0;
}
};
PyTypeObject PluginDataType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* Always 0 */
+ CPY_INIT_TYPE
"collectd.PluginData", /* tp_name */
sizeof(PluginData), /* tp_basicsize */
0, /* Will be filled in later */
static int Values_init(PyObject *s, PyObject *args, PyObject *kwds) {
Values *self = (Values *) s;
- int interval = 0, ret;
+ int interval = 0;
double time = 0;
PyObject *values = NULL, *tmp;
const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
"plugin", "host", "time", "interval", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
- &type, &values, &plugin_instance, &type_instance,
- &plugin, &host, &time, &interval))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdi", kwlist,
+ NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
+ NULL, &plugin, NULL, &host, &time, &interval))
return -1;
- tmp = Py_BuildValue("sssssd", type, plugin_instance, type_instance, plugin, host, time);
- if (tmp == NULL)
- return -1;
- ret = PluginDataType.tp_init(s, tmp, NULL);
- Py_DECREF(tmp);
- if (ret != 0)
+ if (type[0] != 0 && plugin_get_ds(type) == NULL) {
+ PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
return -1;
-
+ }
+
+ sstrncpy(self->data.host, host, sizeof(self->data.host));
+ sstrncpy(self->data.plugin, plugin, sizeof(self->data.plugin));
+ sstrncpy(self->data.plugin_instance, plugin_instance, sizeof(self->data.plugin_instance));
+ sstrncpy(self->data.type, type, sizeof(self->data.type));
+ sstrncpy(self->data.type_instance, type_instance, sizeof(self->data.type_instance));
+ self->data.time = time;
+
if (values == NULL) {
values = PyList_New(0);
PyErr_Clear();
static char *kwlist[] = {"type", "values", "plugin_instance", "type_instance",
"plugin", "host", "time", "interval", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
- &type, &values, &plugin_instance, &type_instance,
- &plugin, &host, &time, &interval))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdi", kwlist,
+ NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
+ NULL, &plugin, NULL, &host, &time, &interval))
return NULL;
if (type[0] == 0) {
static char *kwlist[] = {"destination", "type", "values", "plugin_instance", "type_instance",
"plugin", "host", "time", "interval", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|sOssssdi", kwlist,
- &type, &values, &plugin_instance, &type_instance,
- &plugin, &host, &time, &interval))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etOetetetetdi", kwlist,
+ NULL, &type, &values, NULL, &plugin_instance, NULL, &type_instance,
+ NULL, &plugin, NULL, &host, &time, &interval))
return NULL;
if (type[0] == 0) {
}
static PyObject *Values_repr(PyObject *s) {
- PyObject *ret, *valuestring = NULL;
+ PyObject *ret, *tmp;
+ static PyObject *l_interval = NULL, *l_values = NULL, *l_closing = NULL;
Values *self = (Values *) s;
- if (self->values != NULL)
- valuestring = PyObject_Repr(self->values);
- if (valuestring == NULL)
+ if (l_interval == NULL)
+ l_interval = cpy_string_to_unicode_or_bytes(",interval=");
+ if (l_values == NULL)
+ l_values = cpy_string_to_unicode_or_bytes(",values=");
+ if (l_closing == NULL)
+ l_closing = cpy_string_to_unicode_or_bytes(")");
+
+ if (l_interval == NULL || l_values == NULL || l_closing == NULL)
return NULL;
- ret = PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s',time=%lu,interval=%i,values=%s)", self->data.type,
- *self->data.type_instance ? "',type_instance='" : "", self->data.type_instance,
- *self->data.plugin ? "',plugin='" : "", self->data.plugin,
- *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
- *self->data.host ? "',host='" : "", self->data.host,
- (long unsigned) self->data.time, self->interval,
- valuestring ? PyString_AsString(valuestring) : "[]");
- Py_XDECREF(valuestring);
+ ret = cpy_common_repr(s);
+ if (self->interval != 0) {
+ CPY_STRCAT(&ret, l_interval);
+ tmp = PyInt_FromLong(self->interval);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+ if (self->values != NULL && PySequence_Length(self->values) > 0) {
+ CPY_STRCAT(&ret, l_values);
+ tmp = PyObject_Repr(self->values);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+ CPY_STRCAT(&ret, l_closing);
return ret;
}
};
PyTypeObject ValuesType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* Always 0 */
+ CPY_INIT_TYPE
"collectd.Values", /* tp_name */
sizeof(Values), /* tp_basicsize */
0, /* Will be filled in later */
static int Notification_init(PyObject *s, PyObject *args, PyObject *kwds) {
Notification *self = (Notification *) s;
- PyObject *tmp;
- int severity = 0, ret;
+ int severity = 0;
double time = 0;
const char *message = "";
const char *type = "", *plugin_instance = "", *type_instance = "", *plugin = "", *host = "";
static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
"plugin", "host", "time", "severity", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssdi", kwlist,
- &type, &message, &plugin_instance, &type_instance,
- &plugin, &host, &time, &severity))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
+ NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
+ NULL, &plugin, NULL, &host, &time, &severity))
return -1;
- tmp = Py_BuildValue("sssssd", type, plugin_instance, type_instance, plugin, host, time);
- if (tmp == NULL)
- return -1;
- ret = PluginDataType.tp_init(s, tmp, NULL);
- Py_DECREF(tmp);
- if (ret != 0)
+ if (type[0] != 0 && plugin_get_ds(type) == NULL) {
+ PyErr_Format(PyExc_TypeError, "Dataset %s not found", type);
return -1;
-
+ }
+
+ sstrncpy(self->data.host, host, sizeof(self->data.host));
+ sstrncpy(self->data.plugin, plugin, sizeof(self->data.plugin));
+ sstrncpy(self->data.plugin_instance, plugin_instance, sizeof(self->data.plugin_instance));
+ sstrncpy(self->data.type, type, sizeof(self->data.type));
+ sstrncpy(self->data.type_instance, type_instance, sizeof(self->data.type_instance));
+ self->data.time = time;
+
sstrncpy(self->message, message, sizeof(self->message));
self->severity = severity;
return 0;
static char *kwlist[] = {"type", "message", "plugin_instance", "type_instance",
"plugin", "host", "time", "severity", NULL};
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "|ssssssdi", kwlist,
- &type, &message, &plugin_instance, &type_instance,
- &plugin, &host, &t, &severity))
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "|etetetetetetdi", kwlist,
+ NULL, &type, NULL, &message, NULL, &plugin_instance, NULL, &type_instance,
+ NULL, &plugin, NULL, &host, &t, &severity))
return NULL;
if (type[0] == 0) {
PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute");
return -1;
}
- new = PyString_AsString(value);
- if (new == NULL) return -1;
+ Py_INCREF(value);
+ new = cpy_unicode_or_bytes_to_string(&value);
+ if (new == NULL) {
+ Py_DECREF(value);
+ return -1;
+ }
old = ((char *) self) + (intptr_t) data;
sstrncpy(old, new, NOTIF_MAX_MSG_LEN);
+ Py_DECREF(value);
return 0;
}
static PyObject *Notification_repr(PyObject *s) {
- PyObject *ret;
+ PyObject *ret, *tmp;
+ static PyObject *l_severity = NULL, *l_message = NULL, *l_closing = NULL;
Notification *self = (Notification *) s;
- ret = PyString_FromFormat("collectd.Values(type='%s%s%s%s%s%s%s%s%s%s%s',time=%lu,interval=%i)", self->data.type,
- *self->data.type_instance ? "',type_instance='" : "", self->data.type_instance,
- *self->data.plugin ? "',plugin='" : "", self->data.plugin,
- *self->data.plugin_instance ? "',plugin_instance='" : "", self->data.plugin_instance,
- *self->data.host ? "',host='" : "", self->data.host,
- *self->message ? "',message='" : "", self->message,
- (long unsigned) self->data.time, self->severity);
+ if (l_severity == NULL)
+ l_severity = cpy_string_to_unicode_or_bytes(",severity=");
+ if (l_message == NULL)
+ l_message = cpy_string_to_unicode_or_bytes(",message=");
+ if (l_closing == NULL)
+ l_closing = cpy_string_to_unicode_or_bytes(")");
+
+ if (l_severity == NULL || l_message == NULL || l_closing == NULL)
+ return NULL;
+
+ ret = cpy_common_repr(s);
+ if (self->severity != 0) {
+ CPY_STRCAT(&ret, l_severity);
+ tmp = PyInt_FromLong(self->severity);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+ if (self->message[0] != 0) {
+ CPY_STRCAT(&ret, l_message);
+ tmp = cpy_string_to_unicode_or_bytes(self->message);
+ CPY_SUBSTITUTE(PyObject_Repr, tmp, tmp);
+ CPY_STRCAT_AND_DEL(&ret, tmp);
+ }
+ CPY_STRCAT(&ret, l_closing);
return ret;
}
};
PyTypeObject NotificationType = {
- PyObject_HEAD_INIT(NULL)
- 0, /* Always 0 */
+ CPY_INIT_TYPE
"collectd.Notification", /* tp_name */
sizeof(Notification), /* tp_basicsize */
0, /* Will be filled in later */
_Bool collect_interface;
_Bool collect_regtable;
+ _Bool collect_cpu_load;
+ _Bool collect_memory;
+ _Bool collect_df;
+ _Bool collect_disk;
};
typedef struct cr_data_s cr_data_t;
plugin_dispatch_values (&vl);
} /* }}} void cr_submit_gauge */
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0)
+static void cr_submit_counter (cr_data_t *rd, const char *type, /* {{{ */
+ const char *type_instance, counter_t value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].counter = value;
+
+ vl.values = values;
+ vl.values_len = STATIC_ARRAY_SIZE (values);
+ sstrncpy (vl.host, rd->node, sizeof (vl.host)); /* FIXME */
+ sstrncpy (vl.plugin, "routeros", sizeof (vl.plugin));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+} /* }}} void cr_submit_gauge */
+#endif
+
static void submit_regtable (cr_data_t *rd, /* {{{ */
const ros_registration_table_t *r)
{
return (0);
} /* }}} int handle_regtable */
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0) /* FIXME */
+static int handle_system_resource (__attribute__((unused)) ros_connection_t *c, /* {{{ */
+ const ros_system_resource_t *r,
+ __attribute__((unused)) void *user_data)
+{
+ cr_data_t *rd;
+
+ if ((r == NULL) || (user_data == NULL))
+ return (EINVAL);
+ rd = user_data;
+
+ if (rd->collect_cpu_load)
+ cr_submit_gauge (rd, "gauge", "cpu_load", (gauge_t) r->cpu_load);
+
+ if (rd->collect_memory)
+ {
+ cr_submit_gauge (rd, "memory", "used",
+ (gauge_t) (r->total_memory - r->free_memory));
+ cr_submit_gauge (rd, "memory", "free", (gauge_t) r->free_memory);
+ }
+
+ if (rd->collect_df)
+ {
+ cr_submit_gauge (rd, "df_complex", "used",
+ (gauge_t) (r->total_memory - r->free_memory));
+ cr_submit_gauge (rd, "df_complex", "free", (gauge_t) r->free_memory);
+ }
+
+ if (rd->collect_disk)
+ {
+ cr_submit_counter (rd, "counter", "secors_written", (counter_t) r->write_sect_total);
+ cr_submit_gauge (rd, "gauge", "bad_blocks", (gauge_t) r->bad_blocks);
+ }
+
+ return (0);
+} /* }}} int handle_system_resource */
+#endif
+
static int cr_read (user_data_t *user_data) /* {{{ */
{
int status;
}
}
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0) /* FIXME */
+ if (rd->collect_cpu_load
+ || rd->collect_memory
+ || rd->collect_df
+ || rd->collect_disk)
+ {
+ status = ros_system_resource (rd->connection, handle_system_resource,
+ /* user data = */ rd);
+ if (status != 0)
+ {
+ char errbuf[128];
+ ERROR ("routeros plugin: ros_system_resource failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ ros_disconnect (rd->connection);
+ rd->connection = NULL;
+ return (-1);
+ }
+ }
+#endif
+
return (0);
} /* }}} int cr_read */
router_data->service = NULL;
router_data->username = NULL;
router_data->password = NULL;
- router_data->collect_interface = false;
- router_data->collect_regtable = false;
status = 0;
for (i = 0; i < ci->children_num; i++)
cf_util_get_boolean (child, &router_data->collect_interface);
else if (strcasecmp ("CollectRegistrationTable", child->key) == 0)
cf_util_get_boolean (child, &router_data->collect_regtable);
+#if ROS_VERSION >= ROS_VERSION_ENCODE(1, 1, 0) /* FIXME */
+ else if (strcasecmp ("CollectCPULoad", child->key) == 0)
+ cf_util_get_boolean (child, &router_data->collect_cpu_load);
+ else if (strcasecmp ("CollectMemory", child->key) == 0)
+ cf_util_get_boolean (child, &router_data->collect_memory);
+ else if (strcasecmp ("CollectDF", child->key) == 0)
+ cf_util_get_boolean (child, &router_data->collect_df);
+ else if (strcasecmp ("CollectDisk", child->key) == 0)
+ cf_util_get_boolean (child, &router_data->collect_disk);
+#endif
else
{
WARNING ("routeros plugin: Unknown config option `%s'.", child->key);
static int thermal_sysfs_read (void)
{
return walk_directory (dirname_sysfs, thermal_sysfs_device_read,
- /* user_data = */ NULL);
+ /* user_data = */ NULL, /* include hidden */ 0);
}
static int thermal_procfs_read (void)
{
return walk_directory (dirname_procfs, thermal_procfs_device_read,
- /* user_data = */ NULL);
+ /* user_data = */ NULL, /* include hidden */ 0);
}
static int thermal_init (void)