don't do updates in a transaction so we don't hold locks

This commit is contained in:
Isaac Connor 2018-01-22 14:06:52 -05:00
parent e59ade5391
commit d63594b5fa
1 changed files with 48 additions and 30 deletions

View File

@ -159,7 +159,7 @@ if ( $check && $Config{ZM_CHECK_FOR_UPDATES} ) {
my $ua = LWP::UserAgent->new; my $ua = LWP::UserAgent->new;
$ua->agent( "ZoneMinder Update Agent/".ZM_VERSION ); $ua->agent( "ZoneMinder Update Agent/".ZM_VERSION );
if ( $Config{ZM_UPDATE_CHECK_PROXY} ) { if ( $Config{ZM_UPDATE_CHECK_PROXY} ) {
$ua->proxy( "http", $Config{ZM_UPDATE_CHECK_PROXY} ); $ua->proxy( 'http', $Config{ZM_UPDATE_CHECK_PROXY} );
} }
my $req = HTTP::Request->new( GET=>'https://update.zoneminder.com/version.txt' ); my $req = HTTP::Request->new( GET=>'https://update.zoneminder.com/version.txt' );
my $res = $ua->request($req); my $res = $ua->request($req);
@ -224,7 +224,7 @@ if ( $zoneFix ) {
} }
$sth->finish(); $sth->finish();
$sql = "update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?"; $sql = 'update Zones set MinAlarmPixels = ?, MaxAlarmPixels = ?, MinFilterPixels = ?, MaxFilterPixels = ?, MinBlobPixels = ?, MaxBlobPixels = ? where Id = ?';
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
foreach my $zone ( @zones ) { foreach my $zone ( @zones ) {
my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100; my $zone_width = (($zone->{HiX}*$zone->{MonitorWidth})-($zone->{LoX}*$zone->{MonitorWidth}))/100;
@ -378,7 +378,7 @@ if ( $version ) {
if ( $response =~ /^[yY]$/ ) { if ( $response =~ /^[yY]$/ ) {
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
my $command = "mysqldump"; my $command = 'mysqldump';
if ( defined($portOrSocket) ) { if ( defined($portOrSocket) ) {
if ( $portOrSocket =~ /^\// ) { if ( $portOrSocket =~ /^\// ) {
$command .= " -S".$portOrSocket; $command .= " -S".$portOrSocket;
@ -503,7 +503,7 @@ if ( $version ) {
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
while( my $monitor = $sth->fetchrow_hashref() ) { while( my $monitor = $sth->fetchrow_hashref() ) {
my $sql = "update Events set Width = ?, Height = ? where MonitorId = ?"; my $sql = 'update Events set Width = ?, Height = ? where MonitorId = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $monitor->{Width}, $monitor->{Height}, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( $monitor->{Width}, $monitor->{Height}, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() );
} }
@ -518,7 +518,7 @@ if ( $version ) {
my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute() or die( "Can't execute: ".$sth->errstr() );
my $sequence = 1; my $sequence = 1;
while( my $monitor = $sth->fetchrow_hashref() ) { while( my $monitor = $sth->fetchrow_hashref() ) {
my $sql = "update Monitors set Sequence = ? where Id = ?"; my $sql = 'update Monitors set Sequence = ? where Id = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $sequence++, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( $sequence++, $monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() );
} }
@ -536,7 +536,7 @@ if ( $version ) {
push( @filters, $filter ); push( @filters, $filter );
} }
$sth->finish(); $sth->finish();
$sql = "update Filters set Query = ? where Name = ?"; $sql = 'update Filters set Query = ? where Name = ?';
$sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
foreach my $filter ( @filters ) { foreach my $filter ( @filters ) {
if ( $filter->{Query} =~ /op\d=&/ ) { if ( $filter->{Query} =~ /op\d=&/ ) {
@ -569,7 +569,7 @@ if ( $version ) {
no strict 'refs'; no strict 'refs';
foreach my $zone ( @zones ) { foreach my $zone ( @zones ) {
# Create the coordinate strings # Create the coordinate strings
if ( $zone->{Units} eq "Pixels" ) { if ( $zone->{Units} eq 'Pixels' ) {
my $sql = "update Zones set NumCoords = 4, Coords = concat( LoX,',',LoY,' ',HiX,',',LoY,' ',HiX,',',HiY,' ',LoX,',',HiY ), Area = round( ((HiX-LoX)+1)*((HiY-LoY)+1) ) where Id = ?"; my $sql = "update Zones set NumCoords = 4, Coords = concat( LoX,',',LoY,' ',HiX,',',LoY,' ',HiX,',',HiY,' ',LoX,',',HiY ), Area = round( ((HiX-LoX)+1)*((HiY-LoY)+1) ) where Id = ?";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( $zone->{Id} ) or die( "Can't execute: ".$sth->errstr() );
@ -604,7 +604,7 @@ if ( $version ) {
foreach my $defn ( split( /,/, $state->{Definition} ) ) { foreach my $defn ( split( /,/, $state->{Definition} ) ) {
push( @new_defns, $defn.":1" ); push( @new_defns, $defn.":1" );
} }
my $sql = "update States set Definition = ? where Name = ?"; my $sql = 'update States set Definition = ? where Name = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( join( ',', @new_defns ), $state->{Name} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( join( ',', @new_defns ), $state->{Name} ) or die( "Can't execute: ".$sth->errstr() );
} }
@ -684,7 +684,7 @@ if ( $version ) {
$db_monitor->{LabelFormat} =~ s/\%\%s/%N/; $db_monitor->{LabelFormat} =~ s/\%\%s/%N/;
$db_monitor->{LabelFormat} =~ s/\%\%s/%Q/; $db_monitor->{LabelFormat} =~ s/\%\%s/%Q/;
my $sql = "update Monitors set LabelFormat = ? where Id = ?"; my $sql = 'update Monitors set LabelFormat = ? where Id = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $db_monitor->{LabelFormat}, $db_monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( $db_monitor->{LabelFormat}, $db_monitor->{Id} ) or die( "Can't execute: ".$sth->errstr() );
} }
@ -743,7 +743,7 @@ if ( $version ) {
$i++; $i++;
} }
$newQuery .= '}'; $newQuery .= '}';
foreach my $field ( "sort_field", "sort_asc", "limit" ) { foreach my $field ( 'sort_field', 'sort_asc', 'limit' ) {
if ( defined($filter->{$field}) ) { if ( defined($filter->{$field}) ) {
$newQuery .= 's:'.length($field).':"'.$field.'";'; $newQuery .= 's:'.length($field).':"'.$field.'";';
$newQuery .= 's:'.length($filter->{$field}).':"'.$filter->{$field}.'";'; $newQuery .= 's:'.length($filter->{$field}).':"'.$filter->{$field}.'";';
@ -751,7 +751,7 @@ if ( $version ) {
} }
$newQuery .= '}'; $newQuery .= '}';
my $sql = "update Filters set Query = ? where Name = ?"; my $sql = 'update Filters set Query = ? where Name = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $newQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( $newQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() );
} }
@ -829,7 +829,7 @@ if ( $version ) {
my $phpQuery = $dbFilter->{Query}; my $phpQuery = $dbFilter->{Query};
my $query = PHP::Serialization::unserialize( $phpQuery ); my $query = PHP::Serialization::unserialize( $phpQuery );
my $jsonQuery = jsonEncode( $query ); my $jsonQuery = jsonEncode( $query );
my $sql = "update Filters set Query = ? where Name = ?"; my $sql = 'update Filters set Query = ? where Name = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $jsonQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( $jsonQuery, $dbFilter->{Name} ) or die( "Can't execute: ".$sth->errstr() );
}; };
@ -851,7 +851,7 @@ if ( $version ) {
# Copy the FTP specific values to the new general config # Copy the FTP specific values to the new general config
my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'"; my $fetchSql = "select * from Config where Name like 'ZM_UPLOAD_FTP_%'";
my $fetchSth = $dbh->prepare_cached( $fetchSql ) or die( "Can't prepare '$fetchSql': ".$dbh->errstr() ); my $fetchSth = $dbh->prepare_cached( $fetchSql ) or die( "Can't prepare '$fetchSql': ".$dbh->errstr() );
my $updateSql = "update Config set Value = ? where Name = ?"; my $updateSql = 'update Config set Value = ? where Name = ?';
my $updateSth = $dbh->prepare_cached( $updateSql ) or die( "Can't prepare '$updateSql': ".$dbh->errstr() ); my $updateSth = $dbh->prepare_cached( $updateSql ) or die( "Can't prepare '$updateSql': ".$dbh->errstr() );
my $fetchRes = $fetchSth->execute() or die( "Can't execute: ".$fetchSth->errstr() ); my $fetchRes = $fetchSth->execute() or die( "Can't execute: ".$fetchSth->errstr() );
while( my $config = $fetchSth->fetchrow_hashref() ) { while( my $config = $fetchSth->fetchrow_hashref() ) {
@ -881,7 +881,7 @@ if ( $version ) {
if ( $version ge '1.26.0' ) { if ( $version ge '1.26.0' ) {
my @files; my @files;
$updateDir = $Config{ZM_PATH_DATA}."/db" if ! $updateDir; $updateDir = $Config{ZM_PATH_DATA}.'/db' if ! $updateDir;
opendir( my $dh, $updateDir ) || die "Can't open updateDir $!"; opendir( my $dh, $updateDir ) || die "Can't open updateDir $!";
#@files = sort grep { (!/^\./) && /^zm_update\-[\d\.]+\.sql$/ && -f "$updateDir/$_" } readdir($dh); #@files = sort grep { (!/^\./) && /^zm_update\-[\d\.]+\.sql$/ && -f "$updateDir/$_" } readdir($dh);
#PP - use perl version sort #PP - use perl version sort
@ -895,29 +895,28 @@ if ( $version ) {
die "Should have found upgrade scripts at $updateDir\n"; die "Should have found upgrade scripts at $updateDir\n";
} # end if } # end if
$dbh->{'AutoCommit'} = 0;
foreach my $patch ( @files ) { foreach my $patch ( @files ) {
my ( $v ) = $patch =~ /^zm_update\-([\d\.]+)\.sql$/; my ( $v ) = $patch =~ /^zm_update\-([\d\.]+)\.sql$/;
#PP make sure we use version compare #PP make sure we use version compare
if ( version->parse('v' . $v) > version->parse('v' . $version) ) { if ( version->parse('v' . $v) > version->parse('v' . $version) ) {
print( "Upgrading DB to $v from $version\n" ); print( "Upgrading DB to $v from $version\n" );
patchDB( $dbh, $v ); patchDB( $dbh, $v );
if ( $dbh->errstr() ) { my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
$dbh->rollback(); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
die "Error: " . $dbh->errstr(). ". Rolled back.\n"; my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
} # end if error $sth->finish();
} # end if #patchDB_using_do( $dbh, $version, $updateDir.'/'.$patch );
} # end if newer version
} # end foreach patchfile } # end foreach patchfile
$dbh->{'AutoCommit'} = 1;
$cascade = !undef; $cascade = !undef;
} # end if } # end if
if ( $cascade ) { if ( $cascade ) {
my $installed_version = ZM_VERSION; my $installed_version = ZM_VERSION;
my $sql = "update Config set Value = ? where Name = ?"; my $sql = 'update Config set Value = ? where Name = ?';
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() ); my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( "$installed_version", "ZM_DYN_DB_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); my $res = $sth->execute( "$installed_version", 'ZM_DYN_DB_VERSION' ) or die( "Can't execute: ".$sth->errstr() );
$res = $sth->execute( "$installed_version", "ZM_DYN_CURR_VERSION" ) or die( "Can't execute: ".$sth->errstr() ); $res = $sth->execute( "$installed_version", 'ZM_DYN_CURR_VERSION' ) or die( "Can't execute: ".$sth->errstr() );
$sth->finish(); $sth->finish();
} else { } else {
zmDbDisconnect(); zmDbDisconnect();
@ -928,11 +927,35 @@ if ( $version ) {
zmDbDisconnect(); zmDbDisconnect();
exit( 0 ); exit( 0 );
sub patchDB_using_do {
my ( $dbh, $version, $file ) = @_;
open( my $fh, '<', $file ) or die "Unable to open $file $!";
$/ = undef;
my $sql = <$fh>;
close $fh;
if ( $sql ) {
$dbh->{'AutoCommit'} = 0;
$dbh->do($sql);
if ( $dbh->errstr() ) {
$dbh->rollback();
die "Error: " . $dbh->errstr(). ". Rolled back.\n";
} # end if error
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
$dbh->{'AutoCommit'} = 1;
} else {
Warning("Empty db update file at $file");
}
}
sub patchDB { sub patchDB {
my $dbh = shift; my $dbh = shift;
my $version = shift; my $version = shift;
zmDbDisconnect();
my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ ); my ( $host, $portOrSocket ) = ( $Config{ZM_DB_HOST} =~ /^([^:]+)(?::(.+))?$/ );
my $command = 'mysql'; my $command = 'mysql';
@ -969,11 +992,6 @@ sub patchDB {
} }
print( "\nDatabase successfully upgraded to version $version.\n" ); print( "\nDatabase successfully upgraded to version $version.\n" );
$dbh = zmDbConnect();
my $sql = "update Config set Value = ? where Name = 'ZM_DYN_DB_VERSION'";
my $sth = $dbh->prepare_cached( $sql ) or die( "Can't prepare '$sql': ".$dbh->errstr() );
my $res = $sth->execute( $version ) or die( "Can't execute: ".$sth->errstr() );
$sth->finish();
} }
sub migratePaths { sub migratePaths {