ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-SNMP/SNMP.pm
(Generate patch)

Comparing AnyEvent-SNMP/SNMP.pm (file contents):
Revision 1.4 by root, Sun Apr 19 11:06:21 2009 UTC vs.
Revision 1.7 by root, Sun Aug 2 14:24:23 2009 UTC

1=head1 NAME 1=head1 NAME
2 2
3AnyEvent::SNMP - adaptor to integrate Net::SNMP into Anyevent. 3AnyEvent::SNMP - adaptor to integrate Net::SNMP into AnyEvent.
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 use AnyEvent::SNMP; 7 use AnyEvent::SNMP;
8 use Net::SNMP; 8 use Net::SNMP;
49 49
50=over 4 50=over 4
51 51
52=item $AnyEvent::SNMP::MAX_OUTSTANDING (default: C<50>, dynamic) 52=item $AnyEvent::SNMP::MAX_OUTSTANDING (default: C<50>, dynamic)
53 53
54=item AnyEvent::SNMP::set_max_outstanding $new_value
55
54Use this package variable to restrict the number of outstanding SNMP 56Use this package variable to restrict the number of outstanding SNMP
55requests at any point in time. 57requests at any point in time.
56 58
57Net::SNMP is very fast at creating and sending SNMP requests, but much 59Net::SNMP is very fast at creating and sending SNMP requests, but much
58slower at parsing (big, bulk) responses. This makes it easy to request a 60slower at parsing (big, bulk) responses. This makes it easy to request a
61In the best case, this can lead to unnecessary delays (and even time-outs, 63In the best case, this can lead to unnecessary delays (and even time-outs,
62as the data has been received but not yet processed) and in the worst 64as the data has been received but not yet processed) and in the worst
63case, this can lead to packet loss, when the receive queue overflows and 65case, this can lead to packet loss, when the receive queue overflows and
64the kernel can no longer accept new packets. 66the kernel can no longer accept new packets.
65 67
66To avoid this, you can (and should) limit the number of outstanding requests 68To avoid this, you can (and should) limit the number of outstanding
67to a number low enough so that parsing time doesn't introduce noticable delays. 69requests to a number low enough so that parsing time doesn't introduce
70noticable delays.
68 71
69Unfortunately, this number depends not only on processing speed and load 72Unfortunately, this number depends not only on processing speed and load
70of the machine running Net::SNMP, but also on the network latency and the 73of the machine running Net::SNMP, but also on the network latency and the
71speed of your SNMP agents. 74speed of your SNMP agents.
72 75
73AnyEvent::SNMP tries to dynamically adjust this number dynamically upwards 76AnyEvent::SNMP tries to dynamically adjust this number dynamically upwards
74and downwards. 77and downwards.
75 78
79Increasing C<$MAX_OUTSTANDING> will not automatically use the
80C<extra request slots. To increase $MAX_OUTSTANDING> and make
81C<C<AnyEvent::SNMP> make use of the extra paralellity, call
82C<AnyEvent::SNMP::set_max_outstanding> with the new value, e.g.:
83
84 AnyEvent::SNMP::set_max_outstanding 500;
85
86Although due to the dynamic adjustment, this might have little lasting
87effect.
88
76Note that you can use L<Net::SNMP::XS> to speed up parsing of responses 89Note that you can use L<Net::SNMP::XS> to speed up parsing of responses
77considerably. 90considerably.
78 91
79=item $AnyEvent::SNMP::MIN_RECVQUEUE (default: C<4>) 92=item $AnyEvent::SNMP::MIN_RECVQUEUE (default: C<8>)
80 93
81=item $AnyEvent::SNMP::MAX_RECVQUEUE (default: C<64>) 94=item $AnyEvent::SNMP::MAX_RECVQUEUE (default: C<64>)
82 95
83These values specify the minimum and maximum receive queue length (in 96These values specify the minimum and maximum receive queue length (in
84units of one response packet). 97units of one response packet).
143# avoid the method call 156# avoid the method call
144my $timer = sub { shift->timer (@_) }; 157my $timer = sub { shift->timer (@_) };
145AnyEvent::post_detect { $timer = AnyEvent->can ("timer") }; 158AnyEvent::post_detect { $timer = AnyEvent->can ("timer") };
146 159
147our $BUSY; 160our $BUSY;
148our %TRANSPORT; # address => [count, watcher] 161our @TRANSPORT; # fileno => [count, watcher]
149our @QUEUE; 162our @QUEUE;
150our $MAX_OUTSTANDING = 50; 163our $MAX_OUTSTANDING = 50;
151our $MIN_RECVQUEUE = 4; 164our $MIN_RECVQUEUE = 8;
152our $MAX_RECVQUEUE = 64; 165our $MAX_RECVQUEUE = 64;
153 166
154sub kick_job; 167sub kick_job;
155 168
156sub _send_pdu { 169sub _send_pdu {
192 } 205 }
193 206
194 # Schedule the timeout handler if the message expects a response. 207 # Schedule the timeout handler if the message expects a response.
195 if ($pdu->expect_response) { 208 if ($pdu->expect_response) {
196 my $transport = $msg->transport; 209 my $transport = $msg->transport;
210 my $fileno = $transport->fileno;
197 211
198 # register the transport 212 # register the transport
199 unless ($TRANSPORT{$transport+0}[0]++) { 213 unless ($TRANSPORT[$fileno][0]++) {
200 $TRANSPORT{$transport+0}[1] = AnyEvent->io (fh => $transport->socket, poll => 'r', cb => sub { 214 $TRANSPORT[$fileno][1] = AnyEvent->io (fh => $transport->socket, poll => 'r', cb => sub {
201 for my $count (1..$MAX_RECVQUEUE) { # handle up to this many requests in one go 215 for my $count (1..$MAX_RECVQUEUE) { # handle up to this many requests in one go
202 # Create a new Message object to receive the response 216 # Create a new Message object to receive the response
203 my ($msg, $error) = Net::SNMP::Message->new (-transport => $transport); 217 my ($msg, $error) = Net::SNMP::Message->new (-transport => $transport);
204 218
205 if (!defined $msg) { 219 if (!defined $msg) {
215 ++$MAX_OUTSTANDING; 229 ++$MAX_OUTSTANDING;
216 kick_job; 230 kick_job;
217 } 231 }
218 } else { 232 } else {
219 # for some reason, connected-oriented transports seem to need this 233 # for some reason, connected-oriented transports seem to need this
220 delete $TRANSPORT{$transport+0} 234 delete $TRANSPORT[$fileno]
221 unless --$TRANSPORT{$transport+0}[0]; 235 unless --$TRANSPORT[$fileno][0];
222 } 236 }
223 237
224 $msg->error; 238 $msg->error;
225 return; 239 return;
226 } 240 }
249 undef $$rtimeout_w; 263 undef $$rtimeout_w;
250 264
251 --$BUSY; 265 --$BUSY;
252 kick_job; 266 kick_job;
253 267
254 unless (--$TRANSPORT{$transport+0}[0]) { 268 unless (--$TRANSPORT[$fileno][0]) {
255 delete $TRANSPORT{$transport+0}; 269 delete $TRANSPORT[$fileno];
256 return; 270 return;
257 } 271 }
258 } 272 }
259 } 273 }
260 274
261 # when we end up here, we successfully handled $MAX_RECVQUEUE 275 # when we end up here, we successfully handled $MAX_RECVQUEUE
262 # replies in one iteration, so assume we are overloaded 276 # replies in one iteration, so assume we are overloaded
263 # and reduce the amount of parallelity. 277 # and reduce the amount of parallelity.
264 $MAX_OUTSTANDING = (int $MAX_OUTSTANDING * 0.9) || 1; 278 $MAX_OUTSTANDING = (int $MAX_OUTSTANDING * 0.95) || 1;
265 }); 279 });
266 } 280 }
267 281
268 $msg->timeout_id (\(my $rtimeout_w = 282 $msg->timeout_id (\(my $rtimeout_w =
269 AnyEvent->$timer (after => $pdu->timeout, cb => sub { 283 AnyEvent->$timer (after => $pdu->timeout, cb => sub {
270 my $rtimeout_w = $msg->timeout_id; 284 my $rtimeout_w = $msg->timeout_id;
271 if ($$rtimeout_w) { 285 if ($$rtimeout_w) {
272 undef $$rtimeout_w; 286 undef $$rtimeout_w;
273 delete $TRANSPORT{$transport+0} 287 delete $TRANSPORT[$fileno]
274 unless --$TRANSPORT{$transport+0}[0]; 288 unless --$TRANSPORT[$fileno][0];
275 } 289 }
276 290
277 if ($retries--) { 291 if ($retries--) {
278 _send_pdu ($pdu, $retries); 292 _send_pdu ($pdu, $retries);
279 } else { 293 } else {
299 ++$BUSY; 313 ++$BUSY;
300 314
301 _send_pdu $pdu, $pdu->retries; 315 _send_pdu $pdu, $pdu->retries;
302 } 316 }
303} 317}
318
304sub send_pdu($$$) { 319sub send_pdu($$$) {
305 my (undef, $pdu, $delay) = @_; 320 my (undef, $pdu, $delay) = @_;
306 321
307 # $delay is not very sensibly implemented by AnyEvent::SNMP, 322 # $delay is not very sensibly implemented by AnyEvent::SNMP,
308 # but apparently it is not a very sensible feature. 323 # but apparently it is not a very sensible feature.
329 344
330sub one_event($) { 345sub one_event($) {
331 AnyEvent->one_event; 346 AnyEvent->one_event;
332} 347}
333 348
349sub set_max_outstanding($) {
350 $MAX_OUTSTANDING = $_[0];
351 kick_job;
352}
353
334=head1 SEE ALSO 354=head1 SEE ALSO
335 355
336L<AnyEvent>, L<Net::SNMP>, L<Net::SNMP::XS>, L<Net::SNMP::EV>. 356L<AnyEvent>, L<Net::SNMP>, L<Net::SNMP::XS>, L<Net::SNMP::EV>.
337 357
338=head1 AUTHOR 358=head1 AUTHOR

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines