Update: Small changes applied to the two examples.
Having each worker obtain the file handle will do the trick. The + is not necessary in this context but needed for LOCK_SH. Thus, I typically open flock handles in read and write mode.
open ($fh, '+>>', $file_out);
flock($fh, LOCK_EX) or die "cannnot lock file - $!\n";
print $fh @out;
#print $fh $out[0]; #Date
#print $fh $out[1]; #Site
#print $fh $out[2]; #CTR
#print $fh $out[3]; #IP
#print $fh $out[4]; #Temperature
flock($fh, LOCK_UN) or die "cannnot unlock file - $!\n";
close $fh;
Below is an example using MCE::Loop. Calling MCE->print passes data to the manager process to append to the file. Locking is handled automatically behind the scene.
use Net::SNMP;
use MCE::Loop;
# ... acquire devices and log handle
open ($fh, '>>', $file_out);
print $fh "$date;Site;CTR;IP;Temperature\n";
MCE::Loop::init( chunk_size => 1, max_workers => 50 );
mce_loop {
my $key_bgtr = $_;
my @out;
foreach my $key_ip (keys %{$devices{$key_bgtr}})
{
$out[0]=$date.';';
$out[1]=$devices{$key_bgtr}{$key_ip}.';';
$out[2]=$key_bgtr.';';
$out[3]=$key_ip.';';
for (my $k =2;$k<=3;$k++)
{
if (!defined $out[$k]) {$out[$k] = './.'}
}
$ss = Net::SNMP->session(Hostname=> $key_ip, Timeout => 1);
$out[4] = $ss->get_request(Varbindlist => [$oid]);
$out[4]= $out[4]->{$oid};
if (defined $out[4] && $out[4] !~ /^$|\s/ && $out[4] >=5)
{
$out[4] = "$out[4]\n";
}
else
{
$error = $ss->error();
if ($error =~ /.*noSuchName.*/)
{
$out[4]="no ALCplus2e\n";
}
else
{
$out[4]="OFFLINE\n";
}
MCE->print($log, "$key_bgtr: $error\n");
}
MCE->print($fh, @out);
$ss->close;
}
} keys %devices;
close $fh;
The following example outputs orderly if processing sorted keys is desired. Each worker must gather regardless if @out is empty or not. The manager process needs the $chunk_id value for ordered output.
use Net::SNMP;
use MCE::Loop;
use MCE::Candy;
# ... acquire devices
open ($fh, '>>', $file_out);
print $fh "$date;Site;CTR;IP;Temperature\n";
MCE::Loop::init(
chunk_size => 1, max_workers => 50,
gather => MCE::Candy::out_iter_fh($fh)
);
mce_loop {
my ($mce, $chunk_ref, $chunk_id) = @_;
my $key_bgtr = $chunk_ref->[0];
my @out;
foreach my $key_ip (keys %{$devices{$key_bgtr}})
{
$out[0]=$date.';';
$out[1]=$devices{$key_bgtr}{$key_ip}.';';
$out[2]=$key_bgtr.';';
$out[3]=$key_ip.';';
for (my $k =2;$k<=3;$k++)
{
if (!defined $out[$k]) {$out[$k] = './.'}
}
$ss = Net::SNMP->session(Hostname=> $key_ip, Timeout => 1);
$out[4] = $ss->get_request(Varbindlist => [$oid]);
$out[4]= $out[4]->{$oid};
if (defined $out[4] && $out[4] !~ /^$|\s/ && $out[4] >=5)
{
$out[4] = "$out[4]\n";
}
else
{
$error = $ss->error();
if ($error =~ /.*noSuchName.*/)
{
$out[4]="no ALCplus2e\n";
}
else
{
$out[4]="OFFLINE\n";
}
MCE->print($log, "$key_bgtr: $error\n");
}
$ss->close;
}
MCE->gather($chunk_id, join('', @out));
} sort keys %devices;
close $fh;
Kind regards, Mario |