[collectd] [PATCH 4/6] Collectd.pm: Use threads::shared to share @plugins between threads.

Sebastian Harl sh at tokkee.org
Sat Nov 17 18:43:19 CET 2007


The list of plugins has to be common to all threads to be able to (un)register
callbacks after initialization. As threads::shared is not able to share
references to subroutines the callbacks now have to be identified by their
name. Collectd::call_by_name() is used to execute the callbacks.

Signed-off-by: Sebastian Harl <sh at tokkee.org>
---
 bindings/perl/Collectd.pm |   49 ++++++++++++++++++++++++++++++++++++--------
 1 files changed, 40 insertions(+), 9 deletions(-)

diff --git a/bindings/perl/Collectd.pm b/bindings/perl/Collectd.pm
index 1f9c61e..8c3159c 100644
--- a/bindings/perl/Collectd.pm
+++ b/bindings/perl/Collectd.pm
@@ -24,6 +24,9 @@ use warnings;
 
 use Config;
 
+use threads;
+use threads::shared;
+
 BEGIN {
 	if (! $Config{'useithreads'}) {
 		die "Perl does not support ithreads!";
@@ -75,7 +78,7 @@ our %EXPORT_TAGS = (
 
 Exporter::export_ok_tags ('all');
 
-my @plugins  = ();
+my @plugins : shared = ();
 
 my %types = (
 	TYPE_INIT,     "init",
@@ -86,7 +89,7 @@ my %types = (
 );
 
 foreach my $type (keys %types) {
-	$plugins[$type] = {};
+	$plugins[$type] = &share ({});
 }
 
 sub _log {
@@ -109,6 +112,8 @@ sub DEBUG   { _log (scalar caller, LOG_DEBUG,   shift); }
 sub plugin_call_all {
 	my $type = shift;
 
+	our $cb_name = undef;
+
 	if (! defined $type) {
 		return;
 	}
@@ -122,9 +127,12 @@ sub plugin_call_all {
 		return;
 	}
 
+	lock @plugins;
 	foreach my $plugin (keys %{$plugins[$type]}) {
 		my $p = $plugins[$type]->{$plugin};
 
+		my $status = 0;
+
 		if ($p->{'wait_left'} > 0) {
 			# TODO: use interval_g
 			$p->{'wait_left'} -= 10;
@@ -132,7 +140,18 @@ sub plugin_call_all {
 
 		next if ($p->{'wait_left'} > 0);
 
-		if (my $status = $p->{'code'}->(@_)) {
+		$cb_name = $p->{'cb_name'};
+		$status = call_by_name (@_);
+
+		if (! defined $status) {
+			if (TYPE_LOG != $type) {
+				ERROR ("Could not execute callback \"$cb_name\": $@");
+			}
+
+			next;
+		}
+
+		if ($status) {
 			$p->{'wait_left'} = 0;
 			$p->{'wait_time'} = 10;
 		}
@@ -194,13 +213,24 @@ sub plugin_register {
 	if ((TYPE_DATASET == $type) && ("ARRAY" eq ref $data)) {
 		return plugin_register_data_set ($name, $data);
 	}
-	elsif ("CODE" eq ref $data) {
+	elsif ((TYPE_DATASET != $type) && (! ref $data)) {
+		my $pkg = scalar caller;
+
+		my %p : shared;
+
+		if ($data !~ m/^$pkg/) {
+			$data = $pkg . "::" . $data;
+		}
+
 		# TODO: make interval_g available at configuration time
-		$plugins[$type]->{$name} = {
-				wait_time => 10,
-				wait_left => 0,
-				code      => $data,
-		};
+		%p = (
+			wait_time => 10,
+			wait_left => 0,
+			cb_name   => $data,
+		);
+
+		lock @plugins;
+		$plugins[$type]->{$name} = \%p;
 	}
 	else {
 		ERROR ("Collectd::plugin_register: Invalid data.");
@@ -224,6 +254,7 @@ sub plugin_unregister {
 		return plugin_unregister_data_set ($name);
 	}
 	elsif (defined $plugins[$type]) {
+		lock @plugins;
 		delete $plugins[$type]->{$name};
 	}
 	else {
-- 
1.5.3.4

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
Url : http://mailman.verplant.org/pipermail/collectd/attachments/20071117/27c0d4b4/attachment.pgp 


More information about the collectd mailing list