PageRenderTime 34ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/SNMP/Effective/Dispatch.pm

https://github.com/arcanez/snmp-effective
Perl | 262 lines | 207 code | 51 blank | 4 comment | 20 complexity | 405466d381995e83b11892054e902bcf MD5 | raw file
  1. package SNMP::Effective::Dispatch;
  2. use strict;
  3. use warnings;
  4. our $VERSION = '1.05';
  5. our %METHOD = (
  6. get => 'get',
  7. getnext => 'getnext',
  8. walk => 'getnext',
  9. set => 'set',
  10. bulkwalk => 'bulkwalk',
  11. );
  12. sub _set {
  13. my $self = shift;
  14. my $host = shift;
  15. my $request = shift;
  16. my $response = shift;
  17. return $self->_end($host, 'Timeout') unless(ref $response);
  18. for my $r (grep { ref $_ } @$response) {
  19. my $cur_oid = SNMP::Effective::make_numeric_oid($r->name);
  20. $host->data($r, $cur_oid);
  21. }
  22. return $self->_end($host);
  23. }
  24. sub _get {
  25. my $self = shift;
  26. my $host = shift;
  27. my $request = shift;
  28. my $response = shift;
  29. return $self->_end($host, 'Timeout') unless(ref $response);
  30. for my $r (grep { ref $_ } @$response) {
  31. my $cur_oid = SNMP::Effective::make_numeric_oid($r->name);
  32. $host->data($r, $cur_oid);
  33. }
  34. return $self->_end($host);
  35. }
  36. sub _getnext {
  37. my $self = shift;
  38. my $host = shift;
  39. my $request = shift;
  40. my $response = shift;
  41. return $self->_end($host, 'Timeout') unless(ref $response);
  42. for my $r (grep { ref $_ } @$response) {
  43. my $cur_oid = SNMP::Effective::make_numeric_oid($r->name);
  44. $host->data($r, $cur_oid);
  45. }
  46. return $self->_end($host);
  47. }
  48. sub _walk {
  49. my $self = shift;
  50. my $host = shift;
  51. my $request = shift;
  52. my $response = shift;
  53. my $i = 0;
  54. return $self->_end($host, 'Timeout') unless(ref $response);
  55. while($i < @$response) {
  56. my $splice = 2;
  57. if(my $r = $response->[$i]) {
  58. my($cur_oid, $ref_oid) = SNMP::Effective::make_numeric_oid(
  59. $r->name, $request->[$i]->name
  60. );
  61. $r->[0] = $cur_oid;
  62. $splice--;
  63. ### valid oid
  64. if(defined SNMP::Effective::match_oid($cur_oid, $ref_oid)) {
  65. $host->data($r, $ref_oid);
  66. $splice--;
  67. $i++;
  68. }
  69. }
  70. if($splice) {
  71. splice @$request, $i, 1;
  72. splice @$response, $i, 1;
  73. }
  74. }
  75. if(@$response) {
  76. $$host->getnext($response, [ \&_walk, $self, $host, $request ]);
  77. return;
  78. }
  79. else {
  80. return $self->_end($host);
  81. }
  82. }
  83. sub _bulkwalk {
  84. my $self = shift;
  85. my $host = shift;
  86. my $request = shift;
  87. my $responses = shift;
  88. return $self->_end($host, 'Timeout') unless(ref $responses);
  89. for my $response (@$responses) {
  90. for my $r (@$response) {
  91. my $cur_oid = SNMP::Effective::make_numeric_oid($r->tag);
  92. $host->data($r, $cur_oid);
  93. }
  94. }
  95. return $self->_end($host);
  96. }
  97. sub _end {
  98. my $self = shift;
  99. my $host = shift;
  100. my $error = shift;
  101. $self->log->debug("Calling callback for $host...");
  102. $host->callback->($host, $error);
  103. $host->clear_data;
  104. return $self->dispatch($host)
  105. }
  106. sub dispatch {
  107. my $self = shift;
  108. my $host = shift;
  109. my $hostlist = $self->hostlist;
  110. my $log = $self->log;
  111. my $request;
  112. my $req_id;
  113. $self->_wait_for_lock;
  114. HOST:
  115. while($self->{'_sessions'} < $self->max_sessions or $host) {
  116. $host ||= shift @$hostlist or last HOST;
  117. $request = shift @$host or next HOST;
  118. $req_id = undef;
  119. my $snmp_method = $METHOD{ $request->[0] };
  120. ### fetch or create snmp session
  121. unless($$host) {
  122. unless($$host = $self->_create_session($host)) {
  123. next HOST;
  124. }
  125. $self->{'_sessions'}++;
  126. }
  127. ### ready request
  128. if($$host->can($snmp_method) and $self->can("_$request->[0]")) {
  129. if ($snmp_method eq 'bulkwalk') {
  130. $req_id = $$host->$snmp_method(
  131. $self->{nonrepeaters}, $self->{maxrepetitions}, $request->[1], [ "_$request->[0]", $self, $host, $request->[1] ]
  132. );
  133. } else {
  134. $req_id = $$host->$snmp_method(
  135. $request->[1],
  136. [ "_$request->[0]", $self, $host, $request->[1] ]
  137. );
  138. }
  139. $log->debug(
  140. "\$self->_$request->[0]( ${host}->$snmp_method(...) )"
  141. );
  142. }
  143. ### something went wrong
  144. unless($req_id) {
  145. $log->info("Method $request->[0] failed \@ $host");
  146. next HOST;
  147. }
  148. }
  149. continue {
  150. if(ref $$host and !ref $request) {
  151. $self->{'_sessions'}--;
  152. $log->info("Completed $host");
  153. }
  154. if($req_id or !@$host) {
  155. $host = undef;
  156. }
  157. }
  158. $log->debug(sprintf "Sessions/max-sessions: %i<%i",
  159. $self->{'_sessions'}, $self->max_sessions
  160. );
  161. unless(@$hostlist or $self->{'_sessions'}) {
  162. $log->info("SNMP::finish() is next up");
  163. SNMP::finish();
  164. }
  165. $self->_unlock;
  166. return @$hostlist || $self->{'_sessions'};
  167. }
  168. 1;
  169. __END__
  170. =head1 NAME
  171. SNMP::Effective::Dispatch - Helper module for SNMP::Effective
  172. =head1 VERSION
  173. This document refers to version 1.05 of SNMP::Effective::Dispatch.
  174. =head1 DESCRIPTION
  175. This is a helper module for SNMP::Effective
  176. =head1 METHODS
  177. =head2 C<dispatch>
  178. This method does the actual fetching, and is called by
  179. SNMP::Effective::execute
  180. =head1 DEBUGGING
  181. Debugging is enabled through Log::Log4perl. If nothing else is spesified,
  182. it will default to "error" level, and print to STDERR. The component-name
  183. you want to change is "SNMP::Effective", inless this module ins inherited.
  184. =head1 NOTES
  185. =head2 %SNMP::Effective::Dispatch::METHOD
  186. This hash contains a mapping between $effective->add($key => []),
  187. SNMP::Effective::Dispatch::_$key() and SNMP.pm's $value method. This means
  188. that you can actually add your custom method if you like.
  189. The SNMP::Effective::Dispatch::_walk() method, is a working example on this,
  190. since it's actually a series of getnext, seen from SNMP.pm's perspective.
  191. =head1 TODO
  192. =head1 AUTHOR
  193. Jan Henning Thorsen, C<< <pm at flodhest.net> >>
  194. =head1 ACKNOWLEDGEMENTS
  195. Various contributions by Oliver Gorwits.
  196. =head1 COPYRIGHT & LICENSE
  197. Copyright 2007 Jan Henning Thorsen, all rights reserved.
  198. This program is free software; you can redistribute it and/or modify it
  199. under the same terms as Perl itself.
  200. =cut