add locking to Event moving and diskspace updating.

This commit is contained in:
Isaac Connor 2018-01-18 11:38:08 -05:00
parent 1fbb5bc0f8
commit 715adb5acb
3 changed files with 65 additions and 2 deletions

View File

@ -431,6 +431,14 @@ sub DiskSpace {
sub MoveTo {
my ( $self, $NewStorage ) = @_;
$ZoneMinder::Database::dbh->begin_work();
$self->lock_and_load();
# data is reloaded, so need to check that the move hasn't already happened.
if ( $$self{StorageId} == $$NewStorage{Id} ) {
$ZoneMinder::Database::dbh->commit();
return "Event has already been moved by someone else.";
}
my $OldStorage = $self->Storage();
my ( $OldPath ) = ( $self->Path() =~ /^(.*)$/ ); # De-taint
@ -438,16 +446,21 @@ sub MoveTo {
my ( $NewPath ) = ( $NewStorage->Path() =~ /^(.*)$/ ); # De-taint
if ( ! $$NewStorage{Id} ) {
$ZoneMinder::Database::dbh->commit();
return "New storage does not have an id. Moving will not happen.";
} elsif ( !$NewPath ) {
$ZoneMinder::Database::dbh->commit();
return "New path ($NewPath) is empty.";
} elsif ( ! -e $NewPath ) {
$ZoneMinder::Database::dbh->commit();
return "New path $NewPath does not exist.";
} elsif ( ! -e $OldPath ) {
$ZoneMinder::Database::dbh->commit();
return "Old path $OldPath does not exist.";
}
( $NewPath ) = ( $self->Path(undef) =~ /^(.*)$/ ); # De-taint
if ( $NewPath eq $OldPath ) {
$ZoneMinder::Database::dbh->commit();
return "New path and old path are the same! $NewPath";
}
Debug("Moving event $$self{Id} from $OldPath to $NewPath");
@ -476,14 +489,22 @@ sub MoveTo {
last;
}
} # end foreach file.
return $error if $error;
if ( $error ) {
$ZoneMinder::Database::dbh->commit();
return $error;
}
# Succeeded in copying all files, so we may now update the Event.
$$self{StorageId} = $$NewStorage{Id};
$$self{Storage} = $NewStorage;
$error .= $self->save();
return $error if $error;
if ( $error ) {
$ZoneMinder::Database::dbh->commit();
return $error;
}
$self->delete_files( $OldStorage );
$ZoneMinder::Database::dbh->commit();
return $error;
} # end sub MoveTo

View File

@ -105,6 +105,44 @@ sub load {
} # end if
} # end sub load
sub lock_and_load {
my ( $self ) = @_;
my $type = ref $self;
no strict 'refs';
my $table = ${$type.'::table'};
if ( ! $table ) {
Error( 'NO table for type ' . $type );
return;
} # end if
my $primary_key = ${$type.'::primary_key'};
if ( ! $primary_key ) {
Error( 'NO primary_key for type ' . $type );
return;
} # end if
if ( ! $$self{$primary_key} ) {
my ( $caller, undef, $line ) = caller;
Error( (ref $self) . "::lock_and_load called without $primary_key from $caller:$line");
return;
}
#$log->debug("Object::load Loading from db $type");
Debug("Loading $type from $table WHERE $primary_key = $$self{$primary_key}");
my $data = $ZoneMinder::Database::dbh->selectrow_hashref( "SELECT * FROM $table WHERE $primary_key=? FOR UPDATE", {}, $$self{$primary_key} );
if ( ! $data ) {
if ( $ZoneMinder::Database::dbh->errstr ) {
Error( "Failure to load Object record for $$self{$primary_key}: Reason: " . $ZoneMinder::Database::dbh->errstr );
} else {
Debug("No Results Loading $type from $table WHERE $primary_key = $$self{$primary_key}");
} # end if
} # end if
if ( $data and %$data ) {
@$self{keys %$data} = values %$data;
} # end if
} # end sub lock_and_load
sub AUTOLOAD {
my ( $self, $newvalue ) = @_;
my $type = ref($_[0]);

View File

@ -320,8 +320,12 @@ sub checkFilter {
if ( $filter->{UpdateDiskSpace} ) {
my $Event = new ZoneMinder::Event( $$event{Id}, $event );
$ZoneMinder::Database::dbh->begin_work();
$Event->lock_and_load();
$Event->DiskSpace(undef);
$Event->save();
$ZoneMinder::Database::dbh->commit();
} # end if UpdateDiskSpace
} # end foreach event
}