2010-09-17 Ramon Novoa <rnovoa@artica.es>

* pandora_agent: Added multi-thread support.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@3252 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
ramonn 2010-09-17 13:03:24 +00:00
parent 4f7fb22103
commit bbe506edd1
2 changed files with 134 additions and 42 deletions

View File

@ -1,3 +1,7 @@
2010-09-17 Ramon Novoa <rnovoa@artica.es>
* pandora_agent: Added multi-thread support.
2010-09-17 Junichi Satoh <junichi@rworks.jp> 2010-09-17 Junichi Satoh <junichi@rworks.jp>
* SunOS/make_solaris_package/README, * SunOS/make_solaris_package/README,

View File

@ -29,6 +29,31 @@ use Sys::Hostname;
use File::Basename; use File::Basename;
use File::Copy; use File::Copy;
# Agent XML data
my $Xml;
# Semaphore used to acces $Xml
my $Sem = undef;
# Semaphore used to control the number of threads
my $ThreadSem = undef;
# Thread list
my @Threads;
# Load thread support
eval {
local $SIG{__DIE__};
require threads;
require threads::shared;
require Thread::Semaphore;
};
if (!$@) {
threads::shared::share (\$Xml);
threads::shared::share (\$Sem);
$Sem = Thread::Semaphore->new;
}
use constant AGENT_VERSION => '3.1'; use constant AGENT_VERSION => '3.1';
use constant AGENT_BUILD => '100608'; use constant AGENT_BUILD => '100608';
@ -115,7 +140,8 @@ my %Conf = (
'secondary_server_opts' => '', 'secondary_server_opts' => '',
'autotime' => 0, 'autotime' => 0,
'timezone_offset' => 0, 'timezone_offset' => 0,
'pandora_exec' => 'pandora_exec' 'pandora_exec' => 'pandora_exec',
'agent_threads' => 1
); );
# Modules # Modules
@ -378,6 +404,9 @@ sub read_config (;$) {
$AgentMD5 = md5 ($Conf{'agent_name'}) unless (defined ($token)); $AgentMD5 = md5 ($Conf{'agent_name'}) unless (defined ($token));
$RemoteConfFile = "$AgentMD5.conf"; $RemoteConfFile = "$AgentMD5.conf";
$RemoteMD5File = "$AgentMD5.md5"; $RemoteMD5File = "$AgentMD5.md5";
# Set the maximun number of threads
$ThreadSem = Thread::Semaphore->new ($Conf{'agent_threads'}) if defined ($Sem);
close (CONF_FILE); close (CONF_FILE);
return ''; return '';
@ -755,10 +784,10 @@ sub exec_module ($) {
my $module = shift; my $module = shift;
# Need something to execute # Need something to execute
return () unless ($module->{'func'} != 0); return unless ($module->{'func'} != 0);
# Check module interval # Check module interval
return undef unless (++($module->{'counter'}) >= $module->{'interval'}); return unless (++($module->{'counter'}) >= $module->{'interval'});
# Check module cron # Check module cron
return unless (check_module_cron ($module) == 1); return unless (check_module_cron ($module) == 1);
@ -781,7 +810,9 @@ sub exec_module ($) {
} }
} }
return @value; write_module_xml ($module, @value);
$ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1);
} }
################################################################################ ################################################################################
@ -1123,6 +1154,60 @@ sub check_module_cron ($) {
return 1; return 1;
} }
################################################################################
# Write module data in XML format.
################################################################################
sub write_module_xml ($@) {
my ($module, @data) = @_;
# No data
return unless (defined $data[0]);
# Critical section
$Sem->down () if (defined ($Sem));
$Xml .= " <module>\n" .
" <name><![CDATA[" . $module->{'name'} . "]]></name>\n" .
" <description><![CDATA[" . $module->{'description'} . "]]></description>\n" .
" <type>" . $module->{'type'} . "</type>\n";
# Data list
if ($#data > 0) {
$Xml .= " <datalist>\n";
foreach my $data_item (@data) {
chomp ($data_item);
$Xml .= " <data><value><![CDATA[$data_item]]></value></data>\n";
}
$Xml .= " </datalist>\n";
# Single data
} else {
chomp ($data[0]);
$Xml .= " <data><![CDATA[$data[0]]]></data>\n";
}
$Xml .= " </module>\n";
$Sem->up () if (defined ($Sem));
}
################################################################################
# Execute the given plugin.
################################################################################
sub exec_plugin ($) {
my $plugin = shift;
my $output = `$plugin 2>/dev/null`;
# Do not save the output if there was an error
return unless ($? eq 0);
# Critical section
$Sem->down () if (defined ($Sem));
$Xml .= $output;
$Sem->up () if (defined ($Sem));
$ThreadSem->up () if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1);
}
################################################################################ ################################################################################
# Main. # Main.
################################################################################ ################################################################################
@ -1170,71 +1255,74 @@ while (1) {
# Check file collections # Check file collections
check_collections () unless ($Conf{'debug'} eq '1'); check_collections () unless ($Conf{'debug'} eq '1');
my $xml = "<?xml version='1.0' encoding='" . $Conf{'encoding'} . "'?>\n" . $Xml = "<?xml version='1.0' encoding='" . $Conf{'encoding'} . "'?>\n" .
"<agent_data description='" . $Conf{'description'} ."' group='" . $Conf{'group'} . "<agent_data description='" . $Conf{'description'} ."' group='" . $Conf{'group'} .
"' os_name='$OS' os_version='$OS_VERSION' interval='" . $Conf{'interval'} . "' os_name='$OS' os_version='$OS_VERSION' interval='" . $Conf{'interval'} .
"' version='" . AGENT_VERSION . '(Build ' . AGENT_BUILD . ')' . ($Conf{'autotime'} eq '1' ? '' : "' timestamp='" . strftime ('%Y/%m/%d %H:%M:%S', localtime ())) . "' version='" . AGENT_VERSION . '(Build ' . AGENT_BUILD . ')' . ($Conf{'autotime'} eq '1' ? '' : "' timestamp='" . strftime ('%Y/%m/%d %H:%M:%S', localtime ())) .
"' agent_name='" . $Conf{'agent_name'} . "' timezone_offset='". $Conf{'timezone_offset'}; "' agent_name='" . $Conf{'agent_name'} . "' timezone_offset='". $Conf{'timezone_offset'};
if (defined ($Conf{'parent_agent_name'})) { if (defined ($Conf{'parent_agent_name'})) {
$xml .= "' parent_agent_name='" .$Conf{'parent_agent_name'}; $Xml .= "' parent_agent_name='" .$Conf{'parent_agent_name'};
} }
if (defined ($Conf{'longitude'}) && defined ($Conf{'latitude'})) { if (defined ($Conf{'longitude'}) && defined ($Conf{'latitude'})) {
$xml .= "' longitude='" .$Conf{'longitude'} . "' latitude='" .$Conf{'latitude'}; $Xml .= "' longitude='" .$Conf{'longitude'} . "' latitude='" .$Conf{'latitude'};
if (defined ($Conf{'altitude'})) { if (defined ($Conf{'altitude'})) {
$xml .= "' altitude='" .$Conf{'altitude'}; $Xml .= "' altitude='" .$Conf{'altitude'};
} }
if (defined ($Conf{'position_description'})) { if (defined ($Conf{'position_description'})) {
$xml .= "' position_description='" .$Conf{'position_description'}; $Xml .= "' position_description='" .$Conf{'position_description'};
} }
} }
$xml .= "'>\n"; $Xml .= "'>\n";
# Execute modules # Execute modules
foreach my $module (@Modules) { foreach my $module (@Modules) {
# Execute the module and generate the XML # Execute the module in a separate thread
my @data = exec_module ($module); if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1) {
next unless (defined $data[0]); $ThreadSem->down ();
my $thr = threads->create (\&exec_module, $module);
$xml .= " <module>\n" . if (! defined ($thr)) {
" <name><![CDATA[$module->{'name'}]]></name>\n" . $ThreadSem->up ();
" <description><![CDATA[$module->{'description'}]]></description>\n" . } else {
" <type>$module->{'type'}</type>\n"; push (@Threads, $thr);
# Data list
if ($#data > 0) {
$xml .= " <datalist>\n";
foreach my $data_item (@data) {
chomp ($data_item);
$xml .= " <data><value><![CDATA[$data_item]]></value></data>\n";
} }
$xml .= " </datalist>\n"; # Execute the module
# Single data
} else { } else {
chomp ($data[0]); exec_module ($module);
$xml .= " <data><![CDATA[$data[0]]]></data>\n";
} }
$xml .= " </module>\n";
} }
# Execute plugins # Execute plugins
foreach my $plugin (@Plugins) { foreach my $plugin (@Plugins) {
my $output = `$plugin 2>/dev/null`; # Execute the plugin in a separate thread
if (defined ($ThreadSem) && $Conf{'agent_threads'} > 1) {
# Do not save the output if there was an error $ThreadSem->down ();
next unless ($? eq 0); my $thr = threads->create (\&exec_plugin, $plugin);
if (! defined ($thr)) {
$xml .= $output; $ThreadSem->up ();
} else {
push (@Threads, $thr);
}
# Execute the plugin
} else {
exec_plugin ($plugin);
}
} }
$xml .= "</agent_data>"; # Wait for all the threads
foreach my $thread (@Threads) {
$thread->join ();
}
@Threads = ();
$Xml .= "</agent_data>";
# Save XML data file # Save XML data file
my $temp_file = $Conf{'temporal'} . '/' . $Conf{'agent_name'} . '.' . time () . '.data'; my $temp_file = $Conf{'temporal'} . '/' . $Conf{'agent_name'} . '.' . time () . '.data';
open (TEMP_FILE, "> $temp_file") || error ("Could not write XML data file: $!"); open (TEMP_FILE, "> $temp_file") || error ("Could not write XML data file: $!");
print TEMP_FILE $xml; print TEMP_FILE $Xml;
close (TEMP_FILE); close (TEMP_FILE);
# Debug mode # Debug mode