~ubuntu-branches/ubuntu/edgy/smokeping/edgy-proposed

« back to all changes in this revision

Viewing changes to lib/probes/basefork.pm

  • Committer: Bazaar Package Importer
  • Author(s): Jose Carlos Garcia Sogo
  • Date: 2002-04-02 15:02:08 UTC
  • Revision ID: james.westby@ubuntu.com-20020402150208-8eycqntc07q6gig5
Tags: upstream-1.6
ImportĀ upstreamĀ versionĀ 1.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package probes::basefork;
 
2
 
 
3
my $DEFAULTFORKS = 5;
 
4
 
 
5
=head1 NAME
 
6
 
 
7
probes::basefork - Yet Another Base Class for implementing SmokePing Probes
 
8
 
 
9
=head1 OVERVIEW
 
10
 
 
11
Like probes::basevars, but supports the probe-specific property `forks'
 
12
to determine how many processes should be run concurrently.
 
13
 
 
14
=head1 SYNOPSYS
 
15
 
 
16
 *** Probes ***
 
17
 
 
18
 + MyForkingProbe
 
19
 # run this many concurrent processes
 
20
 forks = 10 
 
21
 
 
22
 + MyOtherForkingProbe
 
23
 # we don't want any concurrent processes at all for some reason.
 
24
 forks = 1 
 
25
 
 
26
=head1 DESCRIPTION
 
27
 
 
28
Not all pinger programs support testing multiple hosts in a single go like
 
29
fping(1). If the measurement takes long enough, there may be not enough time 
 
30
perform all the tests in the time available. For example, if the test takes
 
31
30 seconds, measuring ten hosts already fills up the SmokePing default 
 
32
five minute step.
 
33
 
 
34
Thus, it may be necessary to do some of the tests concurrently. This module
 
35
defines the B<ping> method that forks the requested number of concurrent 
 
36
processes and calls the B<pingone> method that derived classes must provide.
 
37
 
 
38
The B<pingone> method is called with one argument: a hash containing
 
39
the target that is to be measured. The contents of the hash are
 
40
described in I<probes::basevars>(3pm).
 
41
 
 
42
The number of concurrent processes is determined by the probe-specific 
 
43
variable `forks' and is 5 by default. If there are more 
 
44
targets than this value, another round of forks is done after the first 
 
45
processes are finished. This continues until all the targets have been
 
46
tested.
 
47
 
 
48
=head1 AUTHOR
 
49
 
 
50
Niko Tyni E<lt>ntyni@iki.fiE<gt>
 
51
 
 
52
=head1 BUGS
 
53
 
 
54
Doesn't signal failures in child processes, partly because SmokePing 
 
55
hasn't any logging features after daemonization.
 
56
 
 
57
=head1 SEE ALSO
 
58
 
 
59
probes::basevars(3pm), probes::EchoPing(3pm)
 
60
 
 
61
=cut
 
62
 
 
63
use strict;
 
64
use base qw(probes::basevars);
 
65
use Symbol;
 
66
use Carp;
 
67
use IO::Select;
 
68
 
 
69
sub ping_one {
 
70
        croak "ping_one: this must be overridden by the subclass";
 
71
}
 
72
 
 
73
sub ping {
 
74
        my $self = shift;
 
75
        my $forks = $self->{properties}{forks};
 
76
        $forks = $DEFAULTFORKS unless defined $forks;
 
77
        $forks = $DEFAULTFORKS if $forks !~ /^\d+$/ or $forks < 1;
 
78
 
 
79
        my @targets = @{$self->targets};
 
80
 
 
81
        while (@targets) {
 
82
                my %targetlookup;
 
83
                my $s = IO::Select->new();
 
84
                for (1..$forks) {
 
85
                        last unless @targets;
 
86
                        my $t = pop @targets;
 
87
                        my $pid;
 
88
                        my $handle = gensym;
 
89
                        do {
 
90
                                $pid = open($handle, "-|");
 
91
                                my $sleep_count = 0;
 
92
 
 
93
                                unless (defined $pid) {
 
94
                                        carp("cannot fork: $!");
 
95
                                        croak("bailing out") 
 
96
                                                if $sleep_count++ > 6;
 
97
                                        sleep 10;
 
98
                                }
 
99
                        } until defined $pid;
 
100
                        if ($pid) { #parent
 
101
                                $s->add($handle);
 
102
                                $targetlookup{$handle} = $t;
 
103
                        } else { #child
 
104
                                my @times = $self->pingone($t);
 
105
                                print join(" ", @times), "\n";
 
106
                                exit;
 
107
                        }
 
108
                }
 
109
                my $step = $self->{cfg}{Database}{step};
 
110
                my $starttime = time();
 
111
                while ($s->handles and time() - $starttime < $step) {
 
112
                        if( $s->can('has_exception') ) {
 
113
                                $s->remove($s->has_exception(0)); # should we carp?
 
114
                        } elsif( $s->can('has_error') ) {
 
115
                                $s->remove($s->has_error(0));
 
116
                        } else {
 
117
                                croak 'IO::Select neither knows has_exception() nor has_error()';
 
118
                        };
 
119
                        for my $ready ($s->can_read($step / 2)) {
 
120
                                $s->remove($ready);
 
121
                                my $response = <$ready>;
 
122
                                close $ready;
 
123
 
 
124
                                chomp $response;
 
125
                                my @times = split(/ /, $response);
 
126
                                my $target = $targetlookup{$ready};
 
127
                                my $tree = $target->{tree};
 
128
                                $self->{rtts}{$tree} = \@times;
 
129
                        }
 
130
                }
 
131
        }
 
132
}
 
133
 
 
134
sub ProbeDesc {
 
135
        return "Probe that can fork and doesn't override the ProbeDesc method";
 
136
}
 
137
 
 
138
1;