1 # collectd - Collectd.pm
2 # Copyright (C) 2007, 2008 Sebastian Harl
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License as published by the
6 # Free Software Foundation; only version 2 of the License is applicable.
8 # This program is distributed in the hope that it will be useful, but
9 # WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 # General Public License for more details.
13 # You should have received a copy of the GNU General Public License along
14 # with this program; if not, write to the Free Software Foundation, Inc.,
15 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 # Sebastian Harl <sh at tokkee.org>
31 if (! $Config{'useithreads'}) {
32 die "Perl does not support ithreads!";
38 our @ISA = qw( Exporter );
44 plugin_dispatch_values
49 plugin_dispatch_notification
92 push @{$EXPORT_TAGS{'all'}}, grep {! $seen{$_}++ } @{$EXPORT_TAGS{$_}}
93 foreach keys %EXPORT_TAGS;
100 Exporter::export_ok_tags ('all');
102 my @plugins : shared = ();
103 my %cf_callbacks : shared = ();
109 TYPE_SHUTDOWN, "shutdown",
111 TYPE_NOTIF, "notify",
115 foreach my $type (keys %types) {
116 $plugins[$type] = &share ({});
124 if ("Collectd" eq $caller) {
127 return plugin_log ($lvl, $msg);
130 sub ERROR { _log (scalar caller, LOG_ERR, shift); }
131 sub WARNING { _log (scalar caller, LOG_WARNING, shift); }
132 sub NOTICE { _log (scalar caller, LOG_NOTICE, shift); }
133 sub INFO { _log (scalar caller, LOG_INFO, shift); }
134 sub DEBUG { _log (scalar caller, LOG_DEBUG, shift); }
136 sub plugin_call_all {
141 our $cb_name = undef;
143 if (! defined $type) {
147 if (TYPE_LOG != $type) {
148 DEBUG ("Collectd::plugin_call: type = \"$type\", args=\"@_\"");
151 if (! defined $plugins[$type]) {
152 ERROR ("Collectd::plugin_call: unknown type \"$type\"");
157 lock %{$plugins[$type]};
158 %plugins = %{$plugins[$type]};
161 foreach my $plugin (keys %plugins) {
162 my $p = $plugins{$plugin};
166 if ($p->{'wait_left'} > 0) {
167 $p->{'wait_left'} -= $interval_g;
170 next if ($p->{'wait_left'} > 0);
172 $cb_name = $p->{'cb_name'};
173 $status = call_by_name (@_);
182 $err = "callback returned false";
185 if (TYPE_LOG != $type) {
186 ERROR ("Execution of callback \"$cb_name\" failed: $err");
193 $p->{'wait_left'} = 0;
194 $p->{'wait_time'} = $interval_g;
196 elsif (TYPE_READ == $type) {
197 if ($p->{'wait_time'} < $interval_g) {
198 $p->{'wait_time'} = $interval_g;
201 $p->{'wait_left'} = $p->{'wait_time'};
202 $p->{'wait_time'} *= 2;
204 if ($p->{'wait_time'} > 86400) {
205 $p->{'wait_time'} = 86400;
208 WARNING ("${plugin}->read() failed with status $status. "
209 . "Will suspend it for $p->{'wait_left'} seconds.");
211 elsif (TYPE_INIT == $type) {
212 ERROR ("${plugin}->init() failed with status $status. "
213 . "Plugin will be disabled.");
215 foreach my $type (keys %types) {
216 plugin_unregister ($type, $plugin);
219 elsif (TYPE_LOG != $type) {
220 WARNING ("${plugin}->$types{$type}() failed with status $status.");
226 # Collectd::plugin_register (type, name, data).
229 # init, read, write, shutdown, data set
235 # reference to the plugin's subroutine that does the work or the data set
237 sub plugin_register {
242 DEBUG ("Collectd::plugin_register: "
243 . "type = \"$type\", name = \"$name\", data = \"$data\"");
245 if (! ((defined $type) && (defined $name) && (defined $data))) {
246 ERROR ("Usage: Collectd::plugin_register (type, name, data)");
250 if ((! defined $plugins[$type]) && (TYPE_DATASET != $type)
251 && (TYPE_CONFIG != $type)) {
252 ERROR ("Collectd::plugin_register: Invalid type \"$type\"");
256 if ((TYPE_DATASET == $type) && ("ARRAY" eq ref $data)) {
257 return plugin_register_data_set ($name, $data);
259 elsif ((TYPE_CONFIG == $type) && (! ref $data)) {
260 my $pkg = scalar caller;
262 if ($data !~ m/^$pkg\:\:/) {
263 $data = $pkg . "::" . $data;
267 $cf_callbacks{$name} = $data;
269 elsif ((TYPE_DATASET != $type) && (! ref $data)) {
270 my $pkg = scalar caller;
274 if ($data !~ m/^$pkg\:\:/) {
275 $data = $pkg . "::" . $data;
279 wait_time => $interval_g,
284 lock %{$plugins[$type]};
285 $plugins[$type]->{$name} = \%p;
288 ERROR ("Collectd::plugin_register: Invalid data.");
294 sub plugin_unregister {
298 DEBUG ("Collectd::plugin_unregister: type = \"$type\", name = \"$name\"");
300 if (! ((defined $type) && (defined $name))) {
301 ERROR ("Usage: Collectd::plugin_unregister (type, name)");
305 if (TYPE_DATASET == $type) {
306 return plugin_unregister_data_set ($name);
308 elsif (TYPE_CONFIG == $type) {
310 delete $cf_callbacks{$name};
312 elsif (defined $plugins[$type]) {
313 lock %{$plugins[$type]};
314 delete $plugins[$type]->{$name};
317 ERROR ("Collectd::plugin_unregister: Invalid type.");
329 if (! defined $args{'valuelists'}) {
330 ERROR ("Collectd::plugin_write: Missing 'valuelists' argument.");
334 DEBUG ("Collectd::plugin_write:"
335 . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
336 . (defined ($args{'datasets'}) ? " datasets = $args{'datasets'}" : "")
337 . " valueslists = $args{'valuelists'}");
339 if (defined ($args{'plugins'})) {
340 if ("ARRAY" eq ref ($args{'plugins'})) {
341 @plugins = @{$args{'plugins'}};
344 @plugins = ($args{'plugins'});
351 if ("ARRAY" eq ref ($args{'valuelists'})) {
352 @valuelists = @{$args{'valuelists'}};
355 @valuelists = ($args{'valuelists'});
358 if (defined ($args{'datasets'})) {
359 if ("ARRAY" eq ref ($args{'datasets'})) {
360 @datasets = @{$args{'datasets'}};
363 @datasets = ($args{'datasets'});
367 @datasets = (undef) x scalar (@valuelists);
370 if ($#datasets != $#valuelists) {
371 ERROR ("Collectd::plugin_write: Invalid number of datasets.");
375 foreach my $plugin (@plugins) {
376 for (my $i = 0; $i < scalar (@valuelists); ++$i) {
377 _plugin_write ($plugin, $datasets[$i], $valuelists[$i]);
389 DEBUG ("Collectd::plugin_flush:"
390 . (defined ($args{'timeout'}) ? " timeout = $args{'timeout'}" : "")
391 . (defined ($args{'plugins'}) ? " plugins = $args{'plugins'}" : "")
392 . (defined ($args{'identifiers'})
393 ? " identifiers = $args{'identifiers'}" : ""));
395 if (defined ($args{'timeout'}) && ($args{'timeout'} > 0)) {
396 $timeout = $args{'timeout'};
399 if (defined ($args{'plugins'})) {
400 if ("ARRAY" eq ref ($args{'plugins'})) {
401 @plugins = @{$args{'plugins'}};
404 @plugins = ($args{'plugins'});
411 if (defined ($args{'identifiers'})) {
412 if ("ARRAY" eq ref ($args{'identifiers'})) {
413 @ids = @{$args{'identifiers'}};
416 @ids = ($args{'identifiers'});
423 foreach my $plugin (@plugins) {
424 foreach my $id (@ids) {
425 _plugin_flush($plugin, $timeout, $id);
430 sub plugin_flush_one {
434 WARNING ("Collectd::plugin_flush_one is deprecated - "
435 . "use Collectd::plugin_flush instead.");
437 if (! (defined ($timeout) && defined ($name))) {
438 ERROR ("Usage: Collectd::plugin_flush_one(timeout, name)");
442 plugin_flush (plugins => $name, timeout => $timeout);
445 sub plugin_flush_all {
448 WARNING ("Collectd::plugin_flush_all is deprecated - "
449 . "use Collectd::plugin_flush instead.");
451 if (! defined ($timeout)) {
452 ERROR ("Usage: Collectd::plugin_flush_all(timeout)");
456 plugin_flush (timeout => $timeout);
459 sub _plugin_dispatch_config {
463 our $cb_name = undef;
465 if (! (defined ($plugin) && defined ($config))) {
469 if (! defined $cf_callbacks{$plugin}) {
470 WARNING ("Found a configuration for the \"$plugin\" plugin, but "
471 . "the plugin isn't loaded or didn't register "
472 . "a configuration callback.");
478 $cb_name = $cf_callbacks{$plugin};
480 call_by_name ($config);
485 # vim: set sw=4 ts=4 tw=78 noexpandtab :