line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package SNMP::Class::ResultSet; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
=head1 SNMP::Class::ResultSet |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
SNMP::Class::ResultSet - A list of L objects. |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
=head1 VERSION |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
Version 0.12 |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
=cut |
12
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
3302
|
use version; our $VERSION = qv("0.11"); |
|
1
|
|
|
|
|
2859
|
|
|
1
|
|
|
|
|
7
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
=head1 SYNOPSIS |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
use SNMP::Class::ResultSet; |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
my $foo = SNMP::Class::ResultSet->new; |
20
|
|
|
|
|
|
|
$foo->push($vb1); |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
... |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
#later: |
25
|
|
|
|
|
|
|
... |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=cut |
28
|
|
|
|
|
|
|
|
29
|
1
|
|
|
1
|
|
91
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
30
|
|
30
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
28
|
|
31
|
1
|
|
|
1
|
|
6
|
use Carp; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
79
|
|
32
|
1
|
|
|
1
|
|
559
|
use SNMP; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
use SNMP::Class; |
34
|
|
|
|
|
|
|
use Data::Dumper; |
35
|
|
|
|
|
|
|
use UNIVERSAL qw(isa); |
36
|
|
|
|
|
|
|
use Class::Std; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
use Log::Log4perl qw(:easy); |
39
|
|
|
|
|
|
|
my $logger = get_logger(); |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
use overload |
42
|
|
|
|
|
|
|
'@{}' => \&varbinds, |
43
|
|
|
|
|
|
|
'.' => \&dot, |
44
|
|
|
|
|
|
|
'+' => \&plus, |
45
|
|
|
|
|
|
|
fallback => 1; |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
#class fields |
48
|
|
|
|
|
|
|
my (%varbinds,%index_object,%index_instance,%index_value,%index_oid) : ATTRS(); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
=head1 METHODS |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
B All the methods that are returning a ResultSet will only do so when called in scalar context. They alternatively return the list of varbinds in list context. |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=head2 new |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
Constructor. Just issue it without arguments. Creates an empty ResultSet. SNMP::Class::Varbind objects can later be stored in there using the push method. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=cut |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub BUILD { |
62
|
|
|
|
|
|
|
my ($self, $id, $arg_ref) = @_; |
63
|
|
|
|
|
|
|
$varbinds{$id} = []; |
64
|
|
|
|
|
|
|
$index_oid{$id} = {}; |
65
|
|
|
|
|
|
|
$index_object{$id} = {}; |
66
|
|
|
|
|
|
|
$index_instance{$id} = {}; |
67
|
|
|
|
|
|
|
$index_value{$id} = {}; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head2 smart_return |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
In scalar context, this method returns the object itself, while in list context returns the list of the varbinds. In null context, it will croak. This method is mainly used for internal purposes. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=cut |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub smart_return { |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
defined(my $self = shift(@_)) or croak "Incorrect call to smart_return"; |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
defined(my $context = wantarray) or croak "ResultSet used in null context"; |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
if ($context) { |
83
|
|
|
|
|
|
|
DEBUG "List context detected"; |
84
|
|
|
|
|
|
|
return @{$self->varbinds}; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
return $self; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
=head2 varbinds |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
Returns a reference to a list containing all the stored varbinds. Modifying the list alters the object. |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
=cut |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
sub varbinds { |
97
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to varbind"; |
98
|
|
|
|
|
|
|
my $id = ident $self; |
99
|
|
|
|
|
|
|
return $varbinds{$id}; |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
sub index_oid { |
105
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to index_oid"; |
106
|
|
|
|
|
|
|
my $id = ident $self; |
107
|
|
|
|
|
|
|
return $index_oid{$id}; |
108
|
|
|
|
|
|
|
} |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub index_object { |
111
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to index_object"; |
112
|
|
|
|
|
|
|
my $id = ident $self; |
113
|
|
|
|
|
|
|
return $index_object{$id}; |
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
sub index_instance { |
117
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to index_instance"; |
118
|
|
|
|
|
|
|
my $id = ident $self; |
119
|
|
|
|
|
|
|
return $index_instance{$id}; |
120
|
|
|
|
|
|
|
} |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub index_value { |
123
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to index_value"; |
124
|
|
|
|
|
|
|
my $id = ident $self; |
125
|
|
|
|
|
|
|
return $index_value{$id}; |
126
|
|
|
|
|
|
|
} |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
=head2 dump |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
Returns a string representation of the entire ResultSet. Mainly used for debugging purposes. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=cut |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
sub dump { |
136
|
|
|
|
|
|
|
my $self = shift(@_); |
137
|
|
|
|
|
|
|
croak "Incorrect call to dump" unless defined($self); |
138
|
|
|
|
|
|
|
return join("\n",($self->map(sub {$_->dump}))); |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
=head2 push |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
Takes one argument, which must be an L or a descendant of that class. Inserts it into the ResultSet. |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=cut |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
sub push { |
148
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to push"; |
149
|
|
|
|
|
|
|
my $id = ident $self; |
150
|
|
|
|
|
|
|
my $payload = shift(@_); |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
#make sure that this is of the correct class |
153
|
|
|
|
|
|
|
if (! eval $payload->isa('SNMP::Class::Varbind')) { |
154
|
|
|
|
|
|
|
confess "Payload is not an SNMP::Class::Varbind"; |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
push @{$self->varbinds},($payload); |
157
|
|
|
|
|
|
|
$self->index_oid->{$payload->numeric} = \$payload; |
158
|
|
|
|
|
|
|
#@#push @{$self->index_object->{$payload->object->numeric}},(\$payload); |
159
|
|
|
|
|
|
|
#@#push @{$self->index_instance->{$payload->instance->numeric}},(\$payload); |
160
|
|
|
|
|
|
|
#@#push @{$self->index_value->{$payload->raw_value}},(\$payload); |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
#using the get_oid inside a hash key will force it to use the overloaded '""' quote_oid subroutine |
163
|
|
|
|
|
|
|
###$self->{oid_index}->{$payload->get_oid}->{$payload->get_instance_numeric} = \$payload; |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
} |
166
|
|
|
|
|
|
|
|
167
|
|
|
|
|
|
|
=head2 pop |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
Pops a varbind out of the Set. Takes no arguments. |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
=cut |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
sub pop { |
174
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call"; |
175
|
|
|
|
|
|
|
return pop @{$self->varbinds}; |
176
|
|
|
|
|
|
|
} |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
#take a list with possible duplicate elements |
181
|
|
|
|
|
|
|
#return a list with each element unique |
182
|
|
|
|
|
|
|
#sub unique { |
183
|
|
|
|
|
|
|
# my @ret; |
184
|
|
|
|
|
|
|
# for my $elem (@_) { |
185
|
|
|
|
|
|
|
# next unless defined($elem); |
186
|
|
|
|
|
|
|
# CORE::push @ret,($elem) if(!(grep {$elem == $_} @ret));#make sure the the == operator does what you expect |
187
|
|
|
|
|
|
|
# } |
188
|
|
|
|
|
|
|
# return @ret; |
189
|
|
|
|
|
|
|
#} |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
#this function (this is not a method) takes an assorted list of SNMP::Class::OIDs, SNMP::Class::ResultSets and even strings |
193
|
|
|
|
|
|
|
#and returns a proper list of SNMP::Class::OIDs. Used for internal purposes. |
194
|
|
|
|
|
|
|
sub construct_matchlist { |
195
|
|
|
|
|
|
|
my @matchlist; |
196
|
|
|
|
|
|
|
for my $item (@_) { |
197
|
|
|
|
|
|
|
if(ref($item)) { |
198
|
|
|
|
|
|
|
if ( eval $item->isa("SNMP::Class::OID") ) { |
199
|
|
|
|
|
|
|
CORE::push @matchlist,($item); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
elsif (eval $item->isa('SNMP::Class::ResultSet')) { |
202
|
|
|
|
|
|
|
CORE::push @matchlist,(@{$item->varbinds}); |
203
|
|
|
|
|
|
|
} |
204
|
|
|
|
|
|
|
else { |
205
|
|
|
|
|
|
|
croak "I don't know how to handle a ".ref($item); |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
else { |
209
|
|
|
|
|
|
|
CORE::push @matchlist,(SNMP::Class::OID->new($item)); |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
} |
212
|
|
|
|
|
|
|
return @matchlist; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
#4 little handly subroutines to use for matching using various ways |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
sub match_label { |
219
|
|
|
|
|
|
|
my($x,$y) = @_; |
220
|
|
|
|
|
|
|
return unless defined($x->get_label_oid); |
221
|
|
|
|
|
|
|
return unless defined($y->get_label_oid); |
222
|
|
|
|
|
|
|
return $x->get_label_oid->oid_is_equal( $y->get_label_oid ); |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
sub match_instance { |
226
|
|
|
|
|
|
|
my($x,$y) = @_; |
227
|
|
|
|
|
|
|
return unless defined($x->get_label_oid); |
228
|
|
|
|
|
|
|
return unless defined($y->get_label_oid); |
229
|
|
|
|
|
|
|
return $x->get_instance_oid->oid_is_equal( $y->get_instance_oid ); |
230
|
|
|
|
|
|
|
} |
231
|
|
|
|
|
|
|
|
232
|
|
|
|
|
|
|
sub match_fulloid { |
233
|
|
|
|
|
|
|
my($x,$y) = @_; |
234
|
|
|
|
|
|
|
return $x->oid_is_equal( $y ); |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub match_value { |
238
|
|
|
|
|
|
|
my($x,$y) = @_; |
239
|
|
|
|
|
|
|
return $x->value eq $y; |
240
|
|
|
|
|
|
|
} |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
#this is the core of the filtering mechanism |
243
|
|
|
|
|
|
|
#the match_callback method may be used as an argument to the filter method |
244
|
|
|
|
|
|
|
#takes 2 arguments: |
245
|
|
|
|
|
|
|
#1)a reference to a comparing subref which returns true or false (see 4 ready match_* subrefs above) |
246
|
|
|
|
|
|
|
#2)a list of items to match against. |
247
|
|
|
|
|
|
|
#produces a closure that matches $_ against any of those items (grep-style) using the comparing subref |
248
|
|
|
|
|
|
|
sub match_callback { |
249
|
|
|
|
|
|
|
my $match_sub_ref = shift(@_); |
250
|
|
|
|
|
|
|
my @matchlist = (@_); |
251
|
|
|
|
|
|
|
confess "Please do not supply empty matchlists in your filters -- completely pointless" unless @matchlist; |
252
|
|
|
|
|
|
|
return sub { |
253
|
|
|
|
|
|
|
for my $match_item (@matchlist) { |
254
|
|
|
|
|
|
|
if ($match_sub_ref->($_,$match_item)) { |
255
|
|
|
|
|
|
|
DEBUG "Item ".$_->to_string." matches"; |
256
|
|
|
|
|
|
|
return 1; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
} |
259
|
|
|
|
|
|
|
return; |
260
|
|
|
|
|
|
|
}; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub filter_label { |
265
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to label"; |
266
|
|
|
|
|
|
|
return $self->filter(match_callback(\&match_label,construct_matchlist(@_))); |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
sub filter_instance { |
269
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to label"; |
270
|
|
|
|
|
|
|
return $self->filter(match_callback(\&match_instance,construct_matchlist(@_))); |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
sub filter_fulloid { |
273
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to label"; |
274
|
|
|
|
|
|
|
return $self->filter(match_callback(\&match_fulloid,construct_matchlist(@_))); |
275
|
|
|
|
|
|
|
} |
276
|
|
|
|
|
|
|
sub filter_value { |
277
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to label"; |
278
|
|
|
|
|
|
|
return $self->filter(match_callback(\&match_value,@_)); |
279
|
|
|
|
|
|
|
} |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
=head2 filter |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
filter can be used when there is the need to filter the varbinds inside the resultset using arbitrary rules. Takes one argument, which is a reference to a subroutine which will be doing the filtering. The subroutine must return an appropriate true or false value just like in L. The value of each L item in the ResultSet gets assigned to the $_ global variable. For example: |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
print $rs->filter(sub {$_->get_label_oid == 'sysName'}); |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
If used in a scalar context, a reference to a new ResultSet containing the filter results will be returned. If used in a list context, a simple array containing the varbinds of the result will be returned. Please do note that in the previous example, the print function always forces list context, so we get what we want. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
=cut |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
sub filter { |
292
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call"; |
293
|
|
|
|
|
|
|
my $coderef = shift(@_); |
294
|
|
|
|
|
|
|
if(ref($coderef) ne 'CODE') { |
295
|
|
|
|
|
|
|
confess "First argument must be always a reference to a sub"; |
296
|
|
|
|
|
|
|
} |
297
|
|
|
|
|
|
|
my $ret_set = SNMP::Class::ResultSet->new; |
298
|
|
|
|
|
|
|
map { $ret_set->push($_); } ( grep { &$coderef; } @{$self->varbinds} ); |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
$ret_set->smart_return; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head2 find |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
Filters based on key-value pairs that are labels and values. For example: |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
$rs->find('ifDescr' => 'eth0', ifDescr => 'eth1'); |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
will find which are the instance oids of the row that has ifDescr equal to 'eth0' B 'eth1' (if any), and filter using that instances. |
310
|
|
|
|
|
|
|
|
311
|
|
|
|
|
|
|
This means that to get the ifSpeed of eth0, one can simply issue: |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
my $speed = $rs->find('ifDescr' => 'eth0')->ifSpeed->value; |
314
|
|
|
|
|
|
|
|
315
|
|
|
|
|
|
|
=cut |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
sub find { |
318
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to find"; |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
my @matchlist = (); |
321
|
|
|
|
|
|
|
###print Dumper(@_); |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
while(1) { |
324
|
|
|
|
|
|
|
my $object = shift(@_); |
325
|
|
|
|
|
|
|
last unless defined($object); |
326
|
|
|
|
|
|
|
my $value = shift(@_); |
327
|
|
|
|
|
|
|
last unless defined($value); |
328
|
|
|
|
|
|
|
DEBUG "Searching for instances with $object == $value"; |
329
|
|
|
|
|
|
|
CORE::push @matchlist,(@{$self->filter_label($object)->filter_value($value)}); |
330
|
|
|
|
|
|
|
} |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
#be careful. The matchlist which we have may very well be empty! |
333
|
|
|
|
|
|
|
#we should not be filtering against an empty matchlist |
334
|
|
|
|
|
|
|
#note that the filter_instance will croak in such a case. |
335
|
|
|
|
|
|
|
return $self->filter_instance(@matchlist); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
=head2 number_of_items |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
Returns the number of items present inside the ResultSet |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
=cut |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
sub number_of_items { |
346
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to number_of_items"; |
347
|
|
|
|
|
|
|
return scalar @{$self->varbinds}; |
348
|
|
|
|
|
|
|
} |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
=head2 is_empty |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
Reveals whether the ResultSet is empty or not. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=cut |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
sub is_empty { |
357
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to is_empty"; |
358
|
|
|
|
|
|
|
return ($self->number_of_items == 0); |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head2 dot |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
The dot method overloads the '.' operator, returns L. Use it to get a single L out of a ResultSet as a final instance filter. For example, if $rs contains ifSpeed.1, ifSpeed.2 and ifSpeed.3, then this call: |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
$rs.3 |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
returns the ifSpeed.3 L. |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
B |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
=cut |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub dot { |
375
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to dot"; |
376
|
|
|
|
|
|
|
my $str = shift(@_); #we won't test because it could be false, e.g. ifName.0 |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
$logger->debug("dot called with $str as argument"); |
379
|
|
|
|
|
|
|
|
380
|
|
|
|
|
|
|
#we force scalar context |
381
|
|
|
|
|
|
|
my $ret = scalar $self->filter_instance($str); |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
if ($ret->is_empty) { |
384
|
|
|
|
|
|
|
confess "empty resultset"; |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
if ($ret->number_of_items > 1) { |
387
|
|
|
|
|
|
|
carp "Warning: resultset with more than 1 items"; |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
return $ret->item(0); |
390
|
|
|
|
|
|
|
} |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
=head2 item |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
Returns the item of the ResultSet with index same as the first argument. No argument yields the first item (index 0) in the ResultSet. |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=cut |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub item { |
399
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call"; |
400
|
|
|
|
|
|
|
my $index = shift(@_) || 0; |
401
|
|
|
|
|
|
|
return $self->varbinds->[$index]; |
402
|
|
|
|
|
|
|
} |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
#calls named method $method on the and hopefully only existing item. Should not be used by the user. |
405
|
|
|
|
|
|
|
#This is an internal shortcut to simplify method creation that applies to SNMP::Class::OID single members of a ResultSet |
406
|
|
|
|
|
|
|
sub item_method :RESTRICTED() { |
407
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call"; |
408
|
|
|
|
|
|
|
my $method = shift(@_) or croak "missing method name"; |
409
|
|
|
|
|
|
|
my @rest = (@_); |
410
|
|
|
|
|
|
|
if($self->is_empty) { |
411
|
|
|
|
|
|
|
croak "$method cannot be called on an empty result set"; |
412
|
|
|
|
|
|
|
} |
413
|
|
|
|
|
|
|
if ($self->number_of_items > 1) { |
414
|
|
|
|
|
|
|
WARN "Warning: Calling $method on a result set that has more than one item"; |
415
|
|
|
|
|
|
|
} |
416
|
|
|
|
|
|
|
return $self->item(0)->$method(@rest); |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
#warning: plus will not protect you from duplicates |
420
|
|
|
|
|
|
|
#plus will return a new object |
421
|
|
|
|
|
|
|
sub plus { |
422
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to plus"; |
423
|
|
|
|
|
|
|
my $item = shift(@_) or croak "Argument to add(+) missing"; |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
#check that this object is an SNMP::Class::Varbind |
426
|
|
|
|
|
|
|
confess "item to add is not an SNMP::Class::ResultSet!" unless (ref($item)&&(eval $item->isa("SNMP::Class::ResultSet"))); |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
my $ret = SNMP::Class::ResultSet->new(); |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
map { $ret->push($_) } (@{$self->varbinds}); |
431
|
|
|
|
|
|
|
map { $ret->push($_) } (@{$item->varbinds}); |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
return $ret; |
434
|
|
|
|
|
|
|
} |
435
|
|
|
|
|
|
|
|
436
|
|
|
|
|
|
|
#append act on $self |
437
|
|
|
|
|
|
|
sub append { |
438
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call to append"; |
439
|
|
|
|
|
|
|
my $item = shift(@_) or croak "Argument to append missing"; |
440
|
|
|
|
|
|
|
#check that this object is an SNMP::Class::Varbind |
441
|
|
|
|
|
|
|
confess "item to add is not an SNMP::Class::ResultSet!" unless (ref($item)&&(eval $item->isa("SNMP::Class::ResultSet"))); |
442
|
|
|
|
|
|
|
map { $self->push($_) } (@{$item->varbinds}); |
443
|
|
|
|
|
|
|
return; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
sub map { |
447
|
|
|
|
|
|
|
my $self = shift(@_) or croak "Incorrect call"; |
448
|
|
|
|
|
|
|
my $func = shift(@_) or croak "missing sub"; |
449
|
|
|
|
|
|
|
croak "argument should be code reference" unless (ref $func eq 'CODE'); |
450
|
|
|
|
|
|
|
#$logger->debug("mapping...."); |
451
|
|
|
|
|
|
|
my @result; |
452
|
|
|
|
|
|
|
for(@{$self->varbinds}) { |
453
|
|
|
|
|
|
|
#$logger->debug("executing sub with ".$_->dump); |
454
|
|
|
|
|
|
|
CORE::push @result,($func->()); |
455
|
|
|
|
|
|
|
} |
456
|
|
|
|
|
|
|
return @result; |
457
|
|
|
|
|
|
|
} |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub AUTOMETHOD { |
461
|
|
|
|
|
|
|
my $self = shift(@_) or confess("Incorrect call to AUTOMETHOD"); |
462
|
|
|
|
|
|
|
my $id = shift(@_) or confess("Second argument (id) to AUTOMETHOD missing"); |
463
|
|
|
|
|
|
|
my $subname = $_; # Requested subroutine name is passed via $_; |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
if (SNMP::Class::Utils::is_valid_oid($subname)) { |
466
|
|
|
|
|
|
|
$logger->debug("ResultSet: $subname seems like a valid OID "); |
467
|
|
|
|
|
|
|
return sub { |
468
|
|
|
|
|
|
|
# if(wantarray) { |
469
|
|
|
|
|
|
|
# $logger->debug("$subname called in list context"); |
470
|
|
|
|
|
|
|
# return @{$self->filter_label($subname)->varbinds}; |
471
|
|
|
|
|
|
|
# } |
472
|
|
|
|
|
|
|
DEBUG "Returning the resultset"; |
473
|
|
|
|
|
|
|
return $self->filter_label($subname); |
474
|
|
|
|
|
|
|
}; |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
} |
477
|
|
|
|
|
|
|
elsif (SNMP::Class::Varbind->can($subname)) { |
478
|
|
|
|
|
|
|
DEBUG "$subname method call was refering to the contained varbind. Will delegate to the first item. Resultset is ".$self->dump; |
479
|
|
|
|
|
|
|
return sub { return $self->item_method($subname,@_) }; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
else { |
482
|
|
|
|
|
|
|
$logger->debug("$subname doesn't seem like something I can actually make sense of. ."); |
483
|
|
|
|
|
|
|
return; |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
|
|
|
|
|
|
#we'll just have to create this little closure and return it to the Class::Std module |
487
|
|
|
|
|
|
|
#remember: this closure will run in the place of the method that was called by the invoker |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
} |
490
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
=head1 AUTHOR |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
Athanasios Douitsis, C<< >> |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
=head1 BUGS |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
501
|
|
|
|
|
|
|
C, or through the web interface at |
502
|
|
|
|
|
|
|
L. |
503
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
504
|
|
|
|
|
|
|
your bug as I make changes. |
505
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
=head1 SUPPORT |
507
|
|
|
|
|
|
|
|
508
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
perldoc SNMP::Class |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
You can also look for information at: |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
=over 4 |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
L |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
=item * CPAN Ratings |
521
|
|
|
|
|
|
|
|
522
|
|
|
|
|
|
|
L |
523
|
|
|
|
|
|
|
|
524
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
L |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
=item * Search CPAN |
529
|
|
|
|
|
|
|
|
530
|
|
|
|
|
|
|
L |
531
|
|
|
|
|
|
|
|
532
|
|
|
|
|
|
|
=back |
533
|
|
|
|
|
|
|
|
534
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
535
|
|
|
|
|
|
|
|
536
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
537
|
|
|
|
|
|
|
|
538
|
|
|
|
|
|
|
Copyright 2007 Athanasios Douitsis, all rights reserved. |
539
|
|
|
|
|
|
|
|
540
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
541
|
|
|
|
|
|
|
under the same terms as Perl itself. |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
=cut |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
1; # End of SNMP::Class::ResultSet |