my $queue = new Thread::Queue;
$queue->enqueue( @ips[ 0 .. $howmany ] );
####
while( my $string = $queue->dequeue_nb ) {
####
#! perl -slw
use strict;
use threads;
use Thread::Queue;
use Storable qw[ freeze thaw ];
use constant {
ipCidrRouteProto => "1.3.6.1.2.1.4.24.4.1.7",
ipCidrRouteIfIndex => "1.3.6.1.2.1.4.24.4.1.5",
ipCidrRouteType => "1.3.6.1.2.1.4.24.4.1.6",
ipRouteMask => "1.3.6.1.2.1.4.21.1.11",
ipRouteIfIndex => "1.3.6.1.2.1.4.21.1.2",
ipRouteType => "1.3.6.1.2.1.4.21.1.8",
ipRouteNextHop => "1.3.6.1.2.1.4.21.1.7",
ipRouteProto => "1.3.6.1.2.1.4.21.1.9",
};
sub warnf{ warn sprintf $_[0], @_ }
my $THREADS = $ARGV[ 0 ] || 100;
my $Q = new Thread::Queue;
## The main processing goes here
sub processResults{
my( $host, $commstr, $result ) = @_;
## do your heavy stuff here
}
## simple worker thread
sub worker {
while( my $result = $Q->dequeue ) {
my $result = thaw $result;
my $host = delete $result->{ _my_private_host_key };
my $commstr = delete $result->{ _my_private_commstr_key };
processResult( $host, $commstr, $result );
}
}
## Callback
sub enqueue {
## First arg is the seesion handle--the rest whatever we asked for
my( $session, $host, $commstr ) = @_;
my $result = $session->var_bind_list(); ## Get the results hash
$result->{ _my_private_host_key } = $host; ## Tack on some extras
$result->{ _my_private_commstr_key } = $commstr;
$Q->enqueue( freeze $result ); ## And serialise it for queuing
$session->close;
}
my @workers = map{
threads->create( \&worker );
} 1 .. $THREADS;
## Avoid loading the heavy stuff until after we've spawned out threads;
require Net::SNMP;
open my $ipsFH, '<', 'allips.txt' or die $!;
while( my( $host, $commstr ) = split ' ', <$ipsFH> ) {
my( $session, $error ) = Net::SNMP->session(
-hostname => $host, -community => $commstr, -port => 161,
-version => 'SNMPv1', -translate => 1, -debug => 0x00,
-nonblocking => 1, -timeout => 30, -retries => 3,
);
unless( defined $session ) {
warn "Couldn't create session for $host/$commstr: reason: $error\n";
next;
}
my $success = $session->get_entries(
-columns => [
ipCidrRouteIfIndex,
ipCidrRouteProto,
ipCidrRouteType
],
## Have host and commstr passed back to the callback
-callback => [ \&enqueue, $host, $commstr ],
) and next;
$success = $session->get_entries(
-columns => [
ipRouteNextHop,
ipRouteIfIndex,
ipRouteMask,
ipRouteProto,
ipRouteType
]
## Have host and commstr passed back to the callback
-callback => [ \&enqueue, $host, $commstr ],
) or warnf "Failed to get_entries for $host/$commstr: reason %s\n",
$session->error();
}
close $ipsFH;
## Run the event loop
Net::SNMP->snmp_dispatcher();
## Wait for the work to be done
sleep 1 while $Q->pending;
## signal workers to die
$Q->enqueue( ( undef ) x $THREADS );
## And bury them
$_->join for @workers;