| Net-Peep documentation | Contained in the Net-Peep distribution. |
Net::Peep::Scheduler - Perl extension for scheduling events for Peep, the Network Auralizer.
use Net::Peep::Scheduler;
my $scheduler = new Net::Peep::Scheduler;
$scheduler->schedulerAddEvent(
'test_program', 6, 0, 'test_event', \&handler, $data);
$scheduler->schedulerExplicitWakeUp();
Net::Peep::Scheduler provides methods for scheduling events to run concurrently, using sigalarm. The scheduler makes use of Time::HiRes to allow scheduling of events up to microsecond accuracy. Scheduled events will always be played in order of soonest scheduled time, regardless of the order the events were fed to the scheduler.
Note that this module also defines its own debugging level - 8. That's one notch below 'Whoa Nelly', so use with extreme prejudice.
None by default.
$VERSION - The CVS revision of this module.
new() - Net::Peep::Scheduler constructor.
schedulerAddEvent($app_name, $future_secs, $future_usecs,
$type, $handler_coderef, $handler_data)
Schedules an event for $future_secs seconds and
$future_usecs microseconds in the future. When the event
occurs, the $handler_coderef is executed and passed
whatever data is referenced by $handler_data. The
application should also identify itself via $app_name and
register the type of event with $type.
scheduleExplicitWakeUp() - Tells the scheduler explicitly
to wake up and execute the closest scheduled event.
Michael Gilfix <mgilfix@eecs.tufts.edu> Copyright (C) 2001
perl(1), peepd(1), Net::Peep::BC, Net::Peep::Client, Net::Peep::Log.
http://peep.sourceforge.net
$Log: Scheduler.pm,v $ Revision 1.2 2001/08/08 20:17:57 starky Check in of code for the 0.4.3 client release. Includes modifications to allow for backwards-compatibility to Perl 5.00503 and a critical bug fix to the 0.4.2 version of Net::Peep::Conf.
Revision 1.1 2001/06/04 06:53:09 starky A scheduler for events requiring the sigalrm signal for handling. See the PODs for more detail.
| Net-Peep documentation | Contained in the Net-Peep distribution. |
package Net::Peep::Scheduler; require 5.00503; use strict; # use warnings; # commented out for 5.005 compatibility use Carp; use Data::Dumper; use Time::HiRes qw{ tv_interval gettimeofday alarm }; use Net::Peep::Log; require Exporter; use vars qw{ @ISA %EXPORT_TAGS @EXPORT_OK @EXPORT $VERSION }; @ISA = qw(Exporter); %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); @EXPORT = qw( ); $VERSION = do { my @r = (q$Revision: 1.2 $ =~ /\d+/g); sprintf "%d."."%02d" x $#r, @r }; # structure of an event # $entry = { # 'application' => The application name # 'schedule_time' => the time for wakeup # 'type' => the type of event # 'data' => the data to pass to the handler # 'handler' => the handler to invoke # } # The scheduled event queue use vars qw( @scheduler_queue ); sub new { my $self = shift; my $class = ref($self) || $self; my $this = { }; bless $this, $class; # Init the scheduler $this->logger()->debug(8, "Registering scheduler and scheduling alarm ..."); $SIG{'ALRM'} = sub { $this->schedulerWakeUp }; return $this; } #end sub new # returns a logging object sub logger { my $self = shift; unless ( exists $self->{'__LOGGER'} ) { $self->{'__LOGGER'} = new Net::Peep::Log } return $self->{'__LOGGER'}; } #end sub logger sub schedulerAddEvent { my ($self, $app, $sleepsec, $sleepusec, $type, $handler, $data, $repeated) = @_; # Do some sanity checking confess "Error: No application name given to scheduler when adding event." unless $app; confess "Error: Wakeup given to scheduler is in the past." unless $sleepsec > 0.0 || $sleepusec > 0.0; confess "Error: No scheduled event type given to scheduler when adding event." unless $type; confess "Error: No handler given to scheduler when adding event." unless $handler; my ($s, $usec) = gettimeofday(); my $entry = { 'application' => $app, 'sleepsec' => $sleepsec, 'sleepusec' => $sleepusec, 'schedule_time' => [ $s + $sleepsec, $usec + $sleepusec ], 'type' => $type, 'data' => $data, 'handler' => $handler, 'repeated' => $repeated, }; # Add the entry into the scheduler queue and sort by time push @scheduler_queue, $entry; @scheduler_queue = sort { my ($asec, $ausec) = @{ $a->{'schedule_time'} }; my ($bsec, $busec) = @{ $b->{'schedule_time'} }; $asec + 0.000001 * $ausec <=> $bsec + 0.000001 * $busec; } @scheduler_queue; # Now sleep for the new time $self->schedulerSleep; } #end sub schedulerAddEvent sub schedulerRemoveEventsForApp { # Removes all entries in the scheduler queue for an application my $self = shift; my $app = shift || die "Application name not found!"; @scheduler_queue = grep ! $_->{'app'} eq $app, @scheduler_queue; } # end sub schedulerRemoveEventsForApp sub schedulerGetEvent { my $self = shift; return (shift @scheduler_queue); } #end sub schedulerGetEvent sub schedulerCalcSleepTime { my $self = shift; my $nextent = $scheduler_queue[0]; # Check if we have an empty queue unless ( $nextent ) { return undef; } my $sleeptime = tv_interval ( [ gettimeofday() ], $nextent->{'schedule_time'} ); return $sleeptime; } #end sub schedulerCalcSleepTime sub schedulerSleep { my ($self, $time) = @_; my $sleeptime = $time || $self->schedulerCalcSleepTime; # Check if there's no such sleep time at this moment unless ( $sleeptime ) { return undef; } $self->logger()->debug(8, "Scheduler will wake up in $sleeptime seconds."); alarm ( $sleeptime ); return $sleeptime; } #end sub schedulerSleep sub schedulerExplicitWakeUp { my $self = shift; $self->logger()->debug(8, "Scheduler received explicit wake up..."); $self->schedulerWakeUp; } #end sub schedulerExplicitWakeUp sub schedulerWakeUp { my $self = shift; $self->logger()->debug(8, "Scheduler woke up."); my $entry = $self->schedulerGetEvent; # Doesn't apply because a schedulerExplicitWakeUp call would violate this and # still be valid # # # Check that the time has past # unless ( &Time::HiRes::tv_interval ( [ &Time::HiRes::gettimeofday() ], $entry->{'schedule_time'}) < 0.0 ) { # $self->logger()->debug(8, "Scheduled event was premature - returned error."); # return "Error: Scheduler woke up prematurely."; # } # Check if this is an internal housekeeping entry # Otherwise, pass control and data to the handler if ($entry->{'application'} eq '__SCHEDULER') { # internal processing - reserved for future use $self->logger()->debug(8, "Processing internal event..."); } else { # Otherwise, call the handler with arguments of the type # of scheduled event and the data associated $self->logger()->debug(8, "Invoking event handler for ". $entry->{'application'}. " of type ". $entry->{'type'}. " ..."); &{ $entry->{'handler'} } ( $entry->{'type'}, $entry->{'data'} ); if ($entry->{'repeated'}) { # if it's a repeated event, it should # reschedule itself # note that repeated events don't happen # precisely every sleepsec + 0.000001 * # sleepusec because of a delay every cycle # imposed by the execution time of the handler $self->schedulerAddEvent( $entry->{'application'}, $entry->{'sleepsec'}, $entry->{'sleepusec'}, $entry->{'type'}, $entry->{'handler'}, $entry->{'data'}, $entry->{'repeated'} ); } } # Reassign ourselves before we exit $SIG{'ALRM'} = sub { $self->schedulerWakeUp }; $self->schedulerSleep; } #end sub schedulerWakeUp 1; __END__ # Below is stub documentation for your module. You better edit it!