package CFDB; use Carp; use POSIX qw/strftime/; sub write_file { my ($file, $cont) = @_; open my $f, ">", "$file.tmp" or die "Couldn't open file for writing $file.tmp: $!"; print $f $cont or die "Couldn't write to file $file.tmp: $!";; close $f or die "Couldn't close written file $file.tmp: $!"; rename "$file.tmp", $file; } sub read_file { my ($file) = @_; open my $f, "<", "$file" or die "Couldn't open file $file: $!"; return join '', <$f>; } sub new { my ($class, %arg) = @_; my $self = bless { %arg, }, $class; $self->{last_check} = (-M $self->{db_file}) + 1; unless (-e $self->{db_file}) { write_file ($self->{db_file}, cf::to_json ({})); } $self->check_maildb (); $self; } sub check_maildb { my ($self) = @_; if ($self->{last_check} > (-M $self->{db_file})) { $self->{last_check} = -M $self->{db_file}; my $maildb = eval { my $m = cf::from_json read_file $self->{db_file}; return $m }; if ($@) { warn "ERROR when reading mail database $self->{db_file}: $@\n"; $self->{db_file} = $self->{db_file} . ".after_failure"; } else { $self->{maildb} = $maildb; } } } # This is not thread or multiprocess safe! # XXX: A second process will (of course) terribly damage the maildatabase # but i assume there wont be any second process. sub sync_maildb { my ($self) = @_; write_file ($self->{db_file}, cf::to_json ($self->{maildb})); $self->{last_check} = -M $self->{db_file}; } sub get { my ($self, $key) = @_; $self->check_maildb; $self->{maildb}->{$key}; } sub clear { my ($self, $key) = @_; $self->check_maildb; delete $self->{maildb}->{$key}; $self->sync_maildb; } sub set { my ($self, $key, $value) = @_; $self->check_maildb; $self->{maildb}->{$key} = $value; $self->sync_maildb; } 1