diff options
Diffstat (limited to 'lib/App/Beam/History.pm')
-rw-r--r-- | lib/App/Beam/History.pm | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/lib/App/Beam/History.pm b/lib/App/Beam/History.pm new file mode 100644 index 0000000..0421c3e --- /dev/null +++ b/lib/App/Beam/History.pm @@ -0,0 +1,76 @@ +package App::Beam::History; + +use strict; +use Carp; +use App::Beam::History::Record; +use App::Beam::History::Entry qw(:state); + +require Exporter; +our @ISA = qw(Exporter); + +use Fcntl qw(:flock SEEK_SET); +use Storable qw(fd_retrieve nstore_fd); + +sub new { + my $class = shift; + my $filename = shift; + my $rounds = shift; + my $levels = shift; + + my $self = bless { filename => $filename }, $class; + + my $v; + local %_ = @_; + if (defined($v = delete($_{dry_run}))) { + $self->{dry_run} = $v; + } + + if (keys(%_)) { + croak "unknown or unhandled parameters: ".join(',', keys(%_)); + } + + unless (open($self->{filehandle}, '+>>', $filename)) { + croak "can't open file $filename: $!"; + } + unless (flock($self->{filehandle}, LOCK_EX | LOCK_NB)) { + croak "can't lock file $filename: $!"; + } + seek($self->{filehandle}, 0, SEEK_SET); + if ((stat($self->{filehandle}))[7] == 0) { + $self->{history} = []; + unshift @{$self->{history}}, new App::Beam::History::Record; + } else { + $self->{history} = fd_retrieve($self->{filehandle}) + or croak "can't retrieve status from $self->{filehandle}: $!"; + if (ref($self->{history}) ne 'ARRAY') { + croak "$self->{filename}: malformed status file"; + } + unshift @{$self->{history}}, + new App::Beam::History::Record(prev => $self->{history}[0], + rounds => $rounds, + levels => $levels); + } + return $self; +} + +sub records { + my $self = shift; + return @{$self->{history}}; +} + +sub top { + my ($self, $idx) = @_; + return $self->{history}[$idx]; +} + +sub save { + my $self = shift; + if (!$self->{dry_run} && $self->top->state != STATE_PENDING) { + seek($self->{filehandle}, 0, SEEK_SET); + truncate($self->{filehandle}, 0); + nstore_fd($self->{history}, $self->{filehandle}); + } + flock($self->{filehandle}, LOCK_UN); + close($self->{filehandle}); +} + |