aboutsummaryrefslogtreecommitdiff
path: root/lib/App/Beam.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/App/Beam.pm')
-rw-r--r--lib/App/Beam.pm166
1 files changed, 39 insertions, 127 deletions
diff --git a/lib/App/Beam.pm b/lib/App/Beam.pm
index b7e004e..3bee8b9 100644
--- a/lib/App/Beam.pm
+++ b/lib/App/Beam.pm
@@ -5,16 +5,12 @@ use Carp;
use File::Basename;
use Sys::Syslog;
use Unix::Sysexits;
-use Fcntl qw(:flock SEEK_SET);
-use Storable qw(fd_retrieve nstore_fd);
use POSIX qw(strftime floor);
require App::Beam::Config;
our @ISA = qw(App::Beam::Config);
-our @EXPORT_OK = qw(RESULT_PENDING RESULT_SUCCESS RESULT_FAILURE);
-our %EXPORT_TAGS = (
- result => [ qw(RESULT_PENDING RESULT_SUCCESS RESULT_FAILURE) ]
-);
+
+use App::Beam::History;
my $default_config_file = '/etc/beam.conf';
@@ -255,130 +251,16 @@ sub abend {
exit($code);
}
-use constant {
- RESULT_PENDING => 0,
- RESULT_SUCCESS => 1,
- RESULT_FAILURE => 2
-};
-
-# Locks the statfile and retrieves data from it into {status}
-sub lock {
- my $self = shift;
- my $file = $self->get('core.statfile');
- unless (open($self->{statfd}, '+>>', $file)) {
- $self->abend(EX_CANTCREAT, "can't open file $file: $!");
- }
- unless (flock($self->{statfd}, LOCK_EX | LOCK_NB)) {
- $self->abend(EX_TEMPFAIL, "can't lock file $file: $!");
- }
- seek($self->{statfd}, 0, SEEK_SET);
- if ((stat($self->{statfd}))[7] == 0) {
- $self->{status} = [];
- } else {
- $self->{status} = fd_retrieve($self->{statfd})
- or $self->abend(EX_UNAVAILABLE, "can't retrieve status from $file: $!");
- if (ref($self->{status}) ne 'ARRAY') {
- $self->abend(EX_DATAERR, "$file: malformed status file");
- }
- }
- my ($cycle, $round, $level) = $self->compute_triplet(1);
- unshift @{$self->{status}}, { timestamp => time(),
- result => RESULT_PENDING,
- cycle => $cycle,
- round => $round,
- level => $level };
-}
-
-# Saves the current status and unlocks the status file.
-sub unlock {
- my ($self) = @_;
- croak "unlock without lock" unless defined $self->{statfd};
- $self->debug(1, "saving state: ".$self->status('result'));
- if (!$self->{dry_run} && $self->status('result') != RESULT_PENDING) {
- seek($self->{statfd}, 0, SEEK_SET);
- truncate($self->{statfd}, 0);
- nstore_fd($self->{status}, $self->{statfd});
- }
- flock($self->{statfd}, LOCK_UN);
- close($self->{statfd});
-}
-
-sub compute_triplet {
- my ($self, $off, $base) = @_;
-
- $base = 0 unless defined $base;
- if ($#{$self->{status}} == -1) {
- return (0, 0, 0);
- }
- croak "invalid base" unless $base <= $#{$self->{status}};
-
- my ($cycle, $round, $level) =
- (${$self->{status}}[$base]{cycle},
- ${$self->{status}}[$base]{round},
- ${$self->{status}}[$base]{level});
-
- my ($maxround, $maxlevel) =
- ($self->get('schedule', 'rounds'),
- $self->get('schedule', 'levels'));
- if ($off == 1) {
- $level++;
- if ($level > $maxlevel) {
- $round++;
- $level = 0;
- if ($round > $maxround) {
- $cycle++;
- $round = 0;
- }
- }
- } elsif ($off == -1) {
- $level--;
- if ($level < 0) {
- $level += $maxlevel + 1;
- $round--;
- }
- if ($round < 0) {
- $round += $maxround + 1;
- $cycle--;
- if ($cycle == 0) {
- $round = $level = 0;
- last;
- }
- }
- } elsif ($off) {
- croak "invalid offset";
- }
- return ($cycle, $round, $level);
-}
-
-sub status {
- my ($self,$item,$base) = @_;
- $base = 0 unless defined $base;
- return undef unless $base <= $#{$self->{status}};
- return $self->{status}[$base]{$item};
-}
-
-sub result {
- my ($self) = @_;
- return $self->{status}[0]{result};
-}
-
-sub set_result {
- my ($self, $item, $result) = @_;
- $self->{status}[0]{detail}{$item} = $result;
- $self->{status}[0]{result} = $result
- unless $self->{status}[0]{result} == RESULT_FAILURE;
-}
-
sub format_name {
- my ($self, $name, $base) = @_;
- $base = 0 unless defined $base;
- return undef unless $base <= $#{$self->{status}};
+ my ($self, $name, $idx) = @_;
+ my $rec = $self->{history}->top($idx);
+ return undef unless defined $rec;
$name .= '-'
- . $self->status('cycle', $base)
+ . $rec->cycle
. '-'
- . $self->status('round', $base)
+ . $rec->round
. '-'
- . $self->status('level', $base);
+ . $rec->level;
return $name;
}
@@ -458,11 +340,27 @@ sub begin {
}
$self->logger('info', 'startup');
- $self->load_backends;
+ $self->load_backends;
+
+ eval {
+ my %args;
+ $args{dry_run} = $self->{dry_run};
+ $self->{history} =
+ new App::Beam::History($self->get('core.statfile'),
+ $self->get('schedule', 'rounds'),
+ $self->get('schedule', 'levels'),
+ %args);
+ };
+ if ($@) {
+ $self->logger('crit', $@);
+ exit(EX_CANTCREAT);
+ }
}
sub end {
my $self = shift;
+ $self->{history}->top->finish;
+ $self->{history}->save;
$self->logger('info', 'shutdown');
if ($self->get('logger.channel') eq 'syslog') {
closelog();
@@ -474,4 +372,18 @@ sub run {
$self->abend(EX_SOFTWARE, "unsupported command $_[0]");
}
+sub check_items {
+ my $self = shift;
+ my @items = split /\s+/, $self->get('core.items');
+ if (@_) {
+ push @items, $self->names_of('item');
+ foreach my $item (@_) {
+ $self->abend(EX_USAGE, "$item: no such item defined")
+ unless grep { $item eq $_ } @items;
+ }
+ @items = @_;
+ }
+ return @items;
+}
+
1;

Return to:

Send suggestions and report system problems to the System administrator.