1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
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});
}
|