diff --git a/lib/Simba/CA.pm b/lib/Simba/CA.pm index e3ac2b1..3405c96 100644 --- a/lib/Simba/CA.pm +++ b/lib/Simba/CA.pm @@ -153,13 +153,7 @@ sub run { sub backup2disk { my ($self, $target) = @_; - # XXX - lock fileset here, we don't want to backup the same fileset twice concurrently. - # theoretically something like - $self->{dbh}->selectall_arrayref(q{select * from filesets where id = ? for update}, {}, $target->{id}); - # should suffice, but I'm not sure if that blocks too much (does that block reads? block the whole table?) - # Just try it and we will see ... - # According to the manual this only works if autocommit is off, so it probably doesn't work on MyISAM - # anyway. + $self->reserve_fileset($target); $self->log(3, "starting backup for target host " . $target->{host} . " dir " . $target->{dir}); $self->{target} = $target; @@ -215,10 +209,36 @@ sub backup2disk { } $self->flush_insert_instances(); $self->close_session(); + $self->reserve_fileset($target); $self->log(3, "finished backup for target host " . $target->{host} . " dir " . $target->{dir} . ": $count files"); $self->{counts}{objects} += $count; } +sub reserve_fileset { + my ($self, $target) = @_; + + for (;;) { + my $rows = $self->{dbh}->do(q{update filesets set pid=? where id = ? and pid is null}, {}, $$, $target->{id}); + return if $rows == 1; + my $pid = $self->{dbh}->selectrow_array(q{select pid from filesets where id = ?}, {}, $target->{id}); + $self->log(3, "fileset $target->{id} appears to be in use by my pid $pid"); + if (!kill(0, $pid) && $!{ESRCH}) { + $self->log(3, "pid $pid doesn't exist, trying to release fileset $target->{id}"); + $self->{dbh}->do(q{update filesets set pid=null where id = ? and pid=?}, {}, $target->{id}, $pid); + } + sleep 60; + } +} + + +sub release_fileset { + my ($self, $target) = @_; + + $self->log(3, "releasing fileset $target->{id}"); + $self->{dbh}->do(q{update filesets set pid=null where id=? and pid=?}, {}, $target->{id}, $$); +} + + sub parse { my ($self, $s) = @_;