/[echolot]/trunk/Echolot/Scheduler.pm
ViewVC logotype

Contents of /trunk/Echolot/Scheduler.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 51 - (show annotations) (download)
Thu Jun 20 04:28:13 2002 UTC (10 years, 11 months ago) by weasel
File size: 3345 byte(s)
Change some things so that signal handlers may queue tasks more easily
1 package Echolot::Scheduler;
2
3 # (c) 2002 Peter Palfrader <peter@palfrader.org>
4 # $Id: Scheduler.pm,v 1.5 2002/06/20 04:28:13 weasel Exp $
5 #
6
7 =pod
8
9 =head1 Name
10
11 Echolot::Scheduler - Task selector/scheduler for echolot
12
13 =head1 DESCRIPTION
14
15 This package provides several functions for scheduling tasks within
16 the ping daemon.
17
18 =over
19
20 =cut
21
22 use strict;
23 use warnings;
24 use Carp qw{cluck};
25
26 my $ORDER = 1;
27
28 =item B<new> ()
29
30 Creates a new scheduler object.
31
32 =cut
33 sub new {
34 my ($class, %params) = @_;
35 my $self = {};
36 bless $self, $class;
37 return $self;
38 };
39
40 =item B<add> (I<name>, I<interval>, I<offset>, I<what>)
41
42 Adds a task with I<name> to the list of tasks. Every I<interval> seconds
43 I<what> is called. If for example I<interval> is 3600 - meaning I<what>
44 should be executed hourly - setting I<offset> to 600 would mean that
45 it get's called 10 minutes after the hour.
46
47 =cut
48 sub add($$$$$) {
49 my ($self, $name, $interval, $offset, $what) = @_;
50
51 if (defined $self->{'tasks'}->{$name}) {
52 @{ $self->{'schedule'} } = grep { $_->{'name'} ne $name } @{ $self->{'schedule'} };
53 };
54
55 $self->{'tasks'}->{$name} =
56 {
57 interval => $interval,
58 offset => $offset,
59 what => $what,
60 order => $ORDER++
61 };
62
63 $self->schedule($name);
64
65 return 1;
66 };
67
68 =item B<schedule> (I<name>, I<for>)
69
70 Schedule execution of I<name> for I<for>. If I<for> is not given it is calculated
71 from I<interval> and I<offset> passed to B<new>.
72
73 =cut
74 sub schedule($$;$) {
75 my ($self, $name, $for) = @_;
76
77 (defined $self->{'tasks'}->{$name}) or
78 cluck("Task $name is not defined"),
79 return 0;
80
81 my $interval = $self->{'tasks'}->{$name}->{'interval'};
82 my $offset = $self->{'tasks'}->{$name}->{'offset'};
83
84
85 unless (defined $for) {
86 ($interval < 0) and
87 return 1;
88 my $now = time();
89 $for = $now - $now % $interval + $offset;
90 ($for <= $now) and $for += $interval;
91 };
92
93 push @{ $self->{'schedule'} },
94 {
95 start => $for,
96 order => $self->{'tasks'}->{$name}->{'order'},
97 name => $name
98 };
99
100 @{ $self->{'schedule'} } = sort { $a->{'start'} <=> $b->{'start'} or $a->{'order'} <=> $b->{'order'} }
101 @{ $self->{'schedule'} };
102
103 return 1;
104 };
105
106 =item B<run> ()
107
108 Start the scheduling run.
109
110 It will run forever or until a task with I<what> == 'exit' is executed.
111
112 =cut
113 sub run($) {
114 my ($self) = @_;
115
116 (defined $self->{'schedule'}->[0]) or
117 croak("Scheduler is empty"),
118 return 0;
119
120 while(1) {
121 my $now = time();
122 my $task = $self->{'schedule'}->[0];
123 if ($task->{'start'} < $now) {
124 warn("Task $task->{'name'} could not be started on time\n");
125 } else {
126 print "zZzZZzz at $now\n";
127 sleep ($task->{'start'} - $now);
128 };
129
130 (time() < $task->{'start'}) and
131 next;
132
133 $now = $task->{'start'};
134 do {
135 $task = shift @{ $self->{'schedule'} };
136 my $name = $task->{'name'};
137 (defined $self->{'tasks'}->{$name}) or
138 warn("Task $task->{'name'} is not defined\n");
139
140 my $what = $self->{'tasks'}->{$name}->{'what'};
141 print "Running $name at ".(time())." (scheduled for $now)\n";
142 last if ($what eq 'exit');
143 &$what();
144 $self->schedule($name, $now + $self->{'tasks'}->{$name}->{'interval'}) if
145 ($self->{'tasks'}->{$name}->{'interval'} > 0);
146
147 (defined $self->{'schedule'}->[0]) or
148 croak("Scheduler is empty"),
149 return 0;
150 } while ($now >= $self->{'schedule'}->[0]->{'start'});
151 };
152
153 return 1;
154 };
155
156 # vim: set ts=4 shiftwidth=4:

  ViewVC Help
Powered by ViewVC 1.1.5