From cf4ac74d02beeae8104159862371811ca1d6ead0 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 24 Jan 2018 10:45:42 -0500 Subject: [PATCH 1/2] If failed to delete from Frames or Stats, return instead of deleting the event. --- scripts/ZoneMinder/lib/ZoneMinder/Event.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 43bff549e..530aa4f5c 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -357,6 +357,9 @@ sub delete { my $res = $sth->execute( $event->{Id} ) or Error( "Can't execute '$sql': ".$sth->errstr() ); $sth->finish(); + if ( $ZoneMinder::Database::dbh->errstr() ) { + return; + } $sql = 'DELETE FROM Stats WHERE EventId=?'; $sth = $ZoneMinder::Database::dbh->prepare_cached( $sql ) @@ -364,6 +367,9 @@ sub delete { $res = $sth->execute( $event->{Id} ) or Error( "Can't execute '$sql': ".$sth->errstr() ); $sth->finish(); + if ( $ZoneMinder::Database::dbh->errstr() ) { + return; + } $event->delete_files( ); } else { From 50fc4a2d94c2ed5e9406105b0673e1dd3dfbd554 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Wed, 24 Jan 2018 11:51:11 -0500 Subject: [PATCH 2/2] Use a memory table called Monitor_Status to store FPS and Status info for Monitors. This is to reduce locking and updates on the main Monitors table. --- db/zm_create.sql.in | 11 ++-- db/zm_update-1.31.28.sql | 57 ++++++++++++++++++++ src/zm_ffmpeg_camera.cpp | 7 +-- src/zm_monitor.cpp | 4 +- src/zmc.cpp | 2 +- version | 2 +- web/skins/classic/views/_monitor_filters.php | 2 +- web/skins/classic/views/console.php | 13 ++++- 8 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 db/zm_update-1.31.28.sql diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 92d133e0f..2ff2de208 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -608,9 +608,6 @@ CREATE TABLE `Monitors` ( `WebColour` varchar(32) NOT NULL default 'red', `Exif` tinyint(1) unsigned NOT NULL default '0', `Sequence` smallint(5) unsigned default NULL, - `Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown', - `CaptureFPS` DECIMAL(10,2) NOT NULL default 0, - `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, `TotalEvents` int(10) unsigned, `TotalEventDiskSpace` bigint unsigned, `HourEvents` int(10) unsigned, @@ -629,6 +626,14 @@ CREATE TABLE `Monitors` ( CREATE INDEX `Monitors_ServerId_idx` ON `Monitors` (`ServerId`); +DROP TABLE IF EXISTS `Monitor_Status`; +CREATE TABLE `Monitor_Status` ( + `Id` int(10) unsigned NOT NULL, + `Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown', + `CaptureFPS` DECIMAL(10,2) NOT NULL default 0, + `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, + PRIMARY KEY (`Id`) +) ENGINE=MEMORY; -- -- Table structure for table `States` -- PP - Added IsActive to track custom run states diff --git a/db/zm_update-1.31.28.sql b/db/zm_update-1.31.28.sql new file mode 100644 index 000000000..ce540b545 --- /dev/null +++ b/db/zm_update-1.31.28.sql @@ -0,0 +1,57 @@ +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitor_Status' + ) > 0 + , + "SELECT 'Monitor_Status Already exists'", + " +CREATE TABLE `Monitor_Status` ( + `Id` int(10) unsigned NOT NULL, + `Status` enum('Unknown','NotRunning','Running','NoSignal','Signal') NOT NULL default 'Unknown', + `CaptureFPS` DECIMAL(10,2) NOT NULL default 0, + `AnalysisFPS` DECIMAL(5,2) NOT NULL default 0, + PRIMARY KEY (`Id`) +) ENGINE=MEMORY" + )); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'Status' + ) > 0 + , + "ALTER TABLE Monitors DROP COLUMN Status" + "SELECT 'Monitor Status already removed.'", + )); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'CaptureFPS' + ) > 0 + , + "ALTER TABLE Monitors DROP COLUMN CaptureFPS" + "SELECT 'Monitor CaptureFPS already removed.'", + )); + +PREPARE stmt FROM @s; +EXECUTE stmt; + +SET @s = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE() + AND table_name = 'Monitors' + AND column_name = 'AnalysisFPS' + ) > 0 + , + "ALTER TABLE Monitors DROP COLUMN AnalysisFPS" + "SELECT 'Monitor AnalysisFPS already removed.'", + )); + +PREPARE stmt FROM @s; +EXECUTE stmt; diff --git a/src/zm_ffmpeg_camera.cpp b/src/zm_ffmpeg_camera.cpp index 25e96e5a7..069d68b63 100644 --- a/src/zm_ffmpeg_camera.cpp +++ b/src/zm_ffmpeg_camera.cpp @@ -738,7 +738,8 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event int ret; static char errbuf[AV_ERROR_MAX_STRING_SIZE]; - // If the reopen thread has a value, but mCanCapture != 0, then we have just reopened the connection to the ffmpeg device, and we can clean up the thread. + // If the reopen thread has a value, but mCanCapture != 0, then we have just reopened + // the connection to the ffmpeg device, and we can clean up the thread. if ( mReopenThread != 0 ) { void *retval = 0; @@ -751,7 +752,6 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event mReopenThread = 0; } - int frameComplete = false; while ( ! frameComplete ) { av_init_packet( &packet ); @@ -774,7 +774,7 @@ int FfmpegCamera::CaptureAndRecord( Image &image, timeval recording, char* event } int keyframe = packet.flags & AV_PKT_FLAG_KEY; -dumpPacket(&packet); + dumpPacket(&packet); //Video recording if ( recording.tv_sec ) { @@ -836,6 +836,7 @@ dumpPacket(&packet); startTime, this->getMonitor()); } // end if record_audio + if ( ! videoStore->open() ) { delete videoStore; videoStore = NULL; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index dc097d1ab..980a41645 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1205,7 +1205,7 @@ bool Monitor::Analyse() { fps = double(fps_report_interval)/(now.tv_sec - last_fps_time); Info( "%s: %d - Analysing at %.2f fps", name, image_count, fps ); static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "UPDATE Monitors SET AnalysisFPS = '%.2lf' WHERE Id = '%d'", fps, id ); + snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (Id,AnalysisFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE AnalysisFPS = %.2lf", id, fps, fps ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); } @@ -3022,7 +3022,7 @@ Debug(4, "Return from Capture (%d)", captureResult); Info( "%s: images:%d - Capturing at %.2lf fps", name, image_count, fps ); last_fps_time = now; static char sql[ZM_SQL_SML_BUFSIZ]; - snprintf( sql, sizeof(sql), "UPDATE Monitors SET CaptureFPS='%.2lf' WHERE Id=%d", fps, id ); + snprintf( sql, sizeof(sql), "INSERT INTO Monitor_Status (Id,CaptureFPS) VALUES (%d, %.2lf) ON DUPLICATE KEY UPDATE CaptureFPS = %.2lf", id, fps, fps ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); } diff --git a/src/zmc.cpp b/src/zmc.cpp index a58e04a86..5169b0699 100644 --- a/src/zmc.cpp +++ b/src/zmc.cpp @@ -223,7 +223,7 @@ int main(int argc, char *argv[]) { Info("Starting Capture version %s", ZM_VERSION); static char sql[ZM_SQL_SML_BUFSIZ]; for ( int i = 0; i < n_monitors; i ++ ) { - snprintf( sql, sizeof(sql), "UPDATE Monitors SET Status = 'Running' WHERE Id = '%d'", monitors[i]->Id() ); + snprintf( sql, sizeof(sql), "REPLACE INTO Monitor_Status (Id, Status ) VALUES ('%d','Running')", monitors[i]->Id() ); if ( mysql_query( &dbconn, sql ) ) { Error( "Can't run query: %s", mysql_error( &dbconn ) ); } diff --git a/version b/version index 060b0a197..9e60186a4 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.27 +1.31.28 diff --git a/web/skins/classic/views/_monitor_filters.php b/web/skins/classic/views/_monitor_filters.php index d2564f7a5..7633200ea 100644 --- a/web/skins/classic/views/_monitor_filters.php +++ b/web/skins/classic/views/_monitor_filters.php @@ -89,7 +89,7 @@ if ( ! is_array( $selected_monitor_ids ) ) { $values += $ids; } - $sql = 'SELECT * FROM Monitors' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC'; + $sql = 'SELECT *,S.Status AS Status, S.CaptureFPS AS CaptureFPS FROM Monitors AS M LEFT JOIN Monitor_Status AS S ON S.Id=M.Id ' . ( count($conditions) ? ' WHERE ' . implode(' AND ', $conditions ) : '' ).' ORDER BY Sequence ASC'; $monitors = dbFetchAll( $sql, null, $values ); $displayMonitors = array(); $monitors_dropdown = array(); diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index a4731d649..d3350ff96 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -215,7 +215,18 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) { ' : '>') . $monitor['Name'] ?> '.translate('Fn'.$monitor['Function']).( empty($monitor['Enabled']) ? ', disabled' : '' ) .'', canEdit( 'Monitors' ) ) ?>
- +