diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in index 9071cdfd8..d0a063642 100644 --- a/db/zm_create.sql.in +++ b/db/zm_create.sql.in @@ -209,6 +209,7 @@ CREATE TABLE `Events` ( `StateId` int(10) unsigned NOT NULL, `Orientation` enum('0','90','180','270','hori','vert') NOT NULL default '0', `DiskSpace` bigint unsigned default NULL, + `Scheme` enum('Deep','Medium','Shallow') NOT NULL default 'Medium', PRIMARY KEY (`Id`), KEY `Events_MonitorId_idx` (`MonitorId`), KEY `Events_StorageId_idx` (`StorageId`), @@ -267,6 +268,110 @@ CREATE TABLE `Events_Archived` ( KEY `Events_Month_MonitorId_idx` (`MonitorId`) ) ENGINE=@ZM_MYSQL_ENGINE@; + +drop trigger if exists event_update_trigger; + +delimiter // + +CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events +FOR EACH ROW +BEGIN + declare diff BIGINT default 0; + + set diff = NEW.DiskSpace - OLD.DiskSpace; + IF ( NEW.StorageId = OLD.StorageID ) THEN + IF ( diff ) THEN + call update_storage_stats(OLD.StorageId, diff); + END IF; + ELSE + IF ( NEW.DiskSpace ) THEN + call update_storage_stats(NEW.StorageId, NEW.DiskSpace); + END IF; + IF ( OLD.DiskSpace ) THEN + call update_storage_stats(OLD.StorageId, -OLD.DiskSpace); + END IF; + END IF; + + UPDATE Events_Hour SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Day SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Week SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Month SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + IF ( NEW.Archived != OLD.Archived ) THEN + IF ( NEW.Archived ) THEN + INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace); + UPDATE Monitors SET ArchivedEvents = ArchivedEvents+1, ArchivedEventDiskSpace = ArchivedEventDiskSpace + NEW.DiskSpace WHERE Id=NEW.MonitorId; + ELSEIF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitors SET ArchivedEvents =ArchivedEvents-1, ArchivedEventDiskSpace = ArchivedEventDiskSpace - OLD.DiskSpace WHERE Id=OLD.MonitorId; + ELSE + IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN + UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Monitors SET + ArchivedEventDiskSpace = ArchivedEventDiskSpace - OLD.DiskSpace + NEW.DiskSpace + WHERE Id=OLD.MonitorId; + END IF; + END IF; + END IF; + + IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN + UPDATE Monitors SET TotalEventDiskSpace = TotalEventDiskSpace - OLD.DiskSpace + NEW.DiskSpace WHERE Id=OLD.MonitorId; + END IF; + +END; + +// + +delimiter ; + +DROP TRIGGER IF EXISTS event_insert_trigger; + +delimiter // +create trigger event_insert_trigger after insert on Events +for each row + begin + + INSERT INTO Events_Hour (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Day (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Week (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Month (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); +end; +// + +delimiter ; + + +drop trigger if exists event_delete_trigger; + +delimiter // + +CREATE TRIGGER event_delete_trigger BEFORE DELETe on Events + +FOR EACH ROW +BEGIN + call update_storage_stats(OLD.StorageId, -OLD.DiskSpace); + DELETE FROM Events_Hour WHERE EventId=OLD.Id; + DELETE FROM Events_Day WHERE EventId=OLD.Id; + DELETE FROM Events_Week WHERE EventId=OLD.Id; + DELETE FROM Events_Month WHERE EventId=OLD.Id; + IF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitors SET + ArchivedEvents = ArchivedEvents - 1, + ArchivedEventDiskSpace = ArchivedEventDiskSpace - OLD.DiskSpace, + TotalEvents = TotalEvents - 1, + TotalEventDiskSpace = TotalEventDiskSpace - OLD.DiskSpace + WHERE Id=OLD.MonitorId; + ELSE + UPDATE Monitors SET + TotalEvents = TotalEvents-1, + TotalEventDiskSpace=TotalEventDiskSpace-OLD.DiskSpace + WHERE Id=OLD.MonitorId; + END IF; +END; + +// + +delimiter ; -- -- Table structure for table `Filters` -- @@ -686,6 +791,24 @@ CREATE TABLE `Zones` ( KEY `MonitorId` (`MonitorId`) ) ENGINE=@ZM_MYSQL_ENGINE@; +DELIMITER // +DROP TRIGGER IF EXISTS Zone_Insert_Trigger// +CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID; + END +// +DROP TRIGGER IF EXISTS Zone_Delete_Trigger// +CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID; + END +// + +DELIMITER ; + DROP TABLE IF EXISTS `Storage`; CREATE TABLE `Storage` ( `Id` smallint(5) unsigned NOT NULL auto_increment, diff --git a/db/zm_update-1.31.21.sql b/db/zm_update-1.31.21.sql new file mode 100644 index 000000000..a50fafac5 --- /dev/null +++ b/db/zm_update-1.31.21.sql @@ -0,0 +1,150 @@ +delimiter // +DROP TRIGGER IF EXISTS Zone_Insert_Trigger// +CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID; + END +// + +DROP TRIGGER IF EXISTS Zone_Delete_Trigger// +CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID; + END +// + +UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id)// + +drop trigger if exists event_update_trigger// + +CREATE TRIGGER event_update_trigger AFTER UPDATE ON Events +FOR EACH ROW +BEGIN + declare diff BIGINT default 0; + + set diff = NEW.DiskSpace - OLD.DiskSpace; + IF ( NEW.StorageId = OLD.StorageID ) THEN + IF ( diff ) THEN + call update_storage_stats(OLD.StorageId, diff); + END IF; + ELSE + IF ( NEW.DiskSpace ) THEN + call update_storage_stats(NEW.StorageId, NEW.DiskSpace); + END IF; + IF ( OLD.DiskSpace ) THEN + call update_storage_stats(OLD.StorageId, -OLD.DiskSpace); + END IF; + END IF; + + UPDATE Events_Hour SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Day SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Week SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Events_Month SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + IF ( NEW.Archived != OLD.Archived ) THEN + IF ( NEW.Archived ) THEN + INSERT INTO Events_Archived (EventId,MonitorId,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.DiskSpace); + UPDATE Monitors SET ArchivedEvents = ArchivedEvents+1, ArchivedEventDiskSpace = ArchivedEventDiskSpace + NEW.DiskSpace WHERE Id=NEW.MonitorId; + ELSEIF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitors SET ArchivedEvents =ArchivedEvents-1, ArchivedEventDiskSpace = ArchivedEventDiskSpace - OLD.DiskSpace WHERE Id=OLD.MonitorId; + ELSE + IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN + UPDATE Events_Archived SET DiskSpace=NEW.DiskSpace WHERE EventId=NEW.Id; + UPDATE Monitors SET + ArchivedEventDiskSpace = ArchivedEventDiskSpace - OLD.DiskSpace + NEW.DiskSpace + WHERE Id=OLD.MonitorId; + END IF; + END IF; + END IF; + + IF ( OLD.DiskSpace != NEW.DiskSpace ) THEN + UPDATE Monitors SET TotalEventDiskSpace = TotalEventDiskSpace - OLD.DiskSpace + NEW.DiskSpace WHERE Id=OLD.MonitorId; + END IF; + +END; + +// + +delimiter ; + +DROP TRIGGER IF EXISTS event_insert_trigger; + +delimiter // +create trigger event_insert_trigger after insert on Events +for each row + begin + + INSERT INTO Events_Hour (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Day (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Week (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); + INSERT INTO Events_Month (EventId,MonitorId,StartTime,DiskSpace) VALUES (NEW.Id,NEW.MonitorId,NEW.StartTime,0); +end; +// + +delimiter ; + + +drop trigger if exists event_delete_trigger; + +delimiter // + +CREATE TRIGGER event_delete_trigger BEFORE DELETe on Events + +FOR EACH ROW +BEGIN + call update_storage_stats(OLD.StorageId, -OLD.DiskSpace); + DELETE FROM Events_Hour WHERE EventId=OLD.Id; + DELETE FROM Events_Day WHERE EventId=OLD.Id; + DELETE FROM Events_Week WHERE EventId=OLD.Id; + DELETE FROM Events_Month WHERE EventId=OLD.Id; + IF ( OLD.Archived ) THEN + DELETE FROM Events_Archived WHERE EventId=OLD.Id; + UPDATE Monitors SET + ArchivedEvents = ArchivedEvents - 1, + ArchivedEventDiskSpace = ArchivedEventDiskSpace - OLD.DiskSpace, + TotalEvents = TotalEvents - 1, + TotalEventDiskSpace = TotalEventDiskSpace - OLD.DiskSpace + WHERE Id=OLD.MonitorId; + ELSE + UPDATE Monitors SET + TotalEvents = TotalEvents-1, + TotalEventDiskSpace=TotalEventDiskSpace-OLD.DiskSpace + WHERE Id=OLD.MonitorId; + END IF; +END; + +// + +delimiter ; + +UPDATE Monitors INNER JOIN ( + SELECT MonitorId, + COUNT(Id) AS TotalEvents, + SUM(DiskSpace) AS TotalEventDiskSpace, + SUM(IF(Archived,1,0)) AS ArchivedEvents, + SUM(IF(Archived,DiskSpace,0)) AS ArchivedEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),1,0)) AS HourEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 hour),DiskSpace,0)) AS HourEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),1,0)) AS DayEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 day),DiskSpace,0)) AS DayEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),1,0)) AS WeekEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 week),DiskSpace,0)) AS WeekEventDiskSpace, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),1,0)) AS MonthEvents, + SUM(IF(StartTime > DATE_SUB(NOW(), INTERVAL 1 month),DiskSpace,0)) AS MonthEventDiskSpace + FROM Events GROUP BY MonitorId + ) AS E ON E.MonitorId=Monitors.Id SET + Monitors.TotalEvents = E.TotalEvents, + Monitors.TotalEventDiskSpace = E.TotalEventDiskSpace, + Monitors.ArchivedEvents = E.ArchivedEvents, + Monitors.ArchivedEventDiskSpace = E.ArchivedEventDiskSpace, + Monitors.HourEvents = E.HourEvents, + Monitors.HourEventDiskSpace = E.HourEventDiskSpace, + Monitors.DayEvents = E.DayEvents, + Monitors.DayEventDiskSpace = E.DayEventDiskSpace, + Monitors.WeekEvents = E.WeekEvents, + Monitors.WeekEventDiskSpace = E.WeekEventDiskSpace, + Monitors.MonthEvents = E.MonthEvents, + Monitors.MonthEventDiskSpace = E.MonthEventDiskSpace; + diff --git a/db/zm_update-1.31.22.sql b/db/zm_update-1.31.22.sql new file mode 100644 index 000000000..04533b7f4 --- /dev/null +++ b/db/zm_update-1.31.22.sql @@ -0,0 +1,19 @@ +delimiter // +DROP TRIGGER IF EXISTS Zone_Insert_Trigger// +CREATE TRIGGER Zone_Insert_Trigger AFTER INSERT ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=NEW.MonitorId) WHERE Id=NEW.MonitorID; + END +// + +DROP TRIGGER IF EXISTS Zone_Delete_Trigger// +CREATE TRIGGER Zone_Delete_Trigger AFTER DELETE ON Zones +FOR EACH ROW + BEGIN + UPDATE Monitors SET ZoneCount=(SELECT COUNT(*) FROM Zones WHERE MonitorId=OLD.MonitorId) WHERE Id=OLD.MonitorID; + END +// + +UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id)// +UPDATE Storage SET DiskSpace=(SELECT SUM(DiskSpace) FROM Events WHERE StorageId=Storage.Id); diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm index 52a25ad17..134cfa794 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/Event.pm +++ b/scripts/ZoneMinder/lib/ZoneMinder/Event.pm @@ -359,7 +359,7 @@ sub delete_files { my $storage_path = $Storage->Path(); if ( ! $storage_path ) { - Fatal("Empty storage path when deleting files for event $$event{Id} with storage id $$event{StorageId} "); + Error("Empty storage path when deleting files for event $$event{Id} with storage id $$event{StorageId} "); return; } diff --git a/scripts/zmdc.pl.in b/scripts/zmdc.pl.in index 0dab0cb82..ce95058e6 100644 --- a/scripts/zmdc.pl.in +++ b/scripts/zmdc.pl.in @@ -297,7 +297,7 @@ sub run { while( 1 ) { if ( $Config{ZM_SERVER_ID} ) { - if ( $secs_count % 60 ) { + if ( ! ( $secs_count % 60 ) ) { $dbh = zmDbConnect() if ! $dbh->ping(); my @cpuload = Sys::CpuLoad::load(); dPrint( ZoneMinder::Logger::INFO, 'Updating Server record' ); diff --git a/scripts/zmpkg.pl.in b/scripts/zmpkg.pl.in index ab9f938cb..f7184affd 100644 --- a/scripts/zmpkg.pl.in +++ b/scripts/zmpkg.pl.in @@ -191,16 +191,23 @@ if ( $command =~ /^(?:start|restart)$/ ) { zmMemTidy(); runCommand('zmdc.pl startup'); + my $Server = undef; + my $sql; + my @values; if ( $Config{ZM_SERVER_ID} ) { + require ZoneMinder::Server; Info("Multi-server configuration detected. Starting up services for server $Config{ZM_SERVER_ID}\n"); + $Server = new ZoneMinder::Server( $Config{ZM_SERVER_ID} ); + $sql = 'SELECT * FROM Monitors WHERE ServerId=?'; + @values = ( $Config{ZM_SERVER_ID} ); } else { Info('Single server configuration detected. Starting up services.'); + $sql = 'SELECT * FROM Monitors'; } - my $sql = $Config{ZM_SERVER_ID} ? 'SELECT * FROM Monitors WHERE ServerId=?' : 'SELECT * FROM Monitors'; my $sth = $dbh->prepare_cached( $sql ) or Fatal( "Can't prepare '$sql': ".$dbh->errstr() ); - my $res = $sth->execute( $Config{ZM_SERVER_ID} ? $Config{ZM_SERVER_ID} : () ) + my $res = $sth->execute( @values ) or Fatal( "Can't execute: ".$sth->errstr() ); while( my $monitor = $sth->fetchrow_hashref() ) { if ( $monitor->{Function} ne 'None' ) { @@ -223,10 +230,18 @@ if ( $command =~ /^(?:start|restart)$/ ) { # This is now started unconditionally runCommand('zmdc.pl start zmfilter.pl'); if ( $Config{ZM_RUN_AUDIT} ) { - runCommand('zmdc.pl start zmaudit.pl -c'); + if ( $Server and exists $$Server{'zmaudit.pl'} and ! $$Server{'zmaudit.pl'} ) { + Debug("Not running zmaudit.pl because it is turned off for this server."); + } else { + runCommand('zmdc.pl start zmaudit.pl -c'); + } } if ( $Config{ZM_OPT_TRIGGERS} ) { - runCommand('zmdc.pl start zmtrigger.pl'); + if ( $Server and exists $$Server{'zmtrigger.pl'} and ! $$Server{'zmtrigger.pl'} ) { + Debug("Not running zmtrigger.pl because it is turned off for this server."); + } else { + runCommand('zmdc.pl start zmtrigger.pl'); + } } if ( $Config{ZM_OPT_X10} ) { runCommand('zmdc.pl start zmx10.pl -c start'); @@ -238,6 +253,11 @@ if ( $command =~ /^(?:start|restart)$/ ) { if ( $Config{ZM_TELEMETRY_DATA} ) { runCommand('zmdc.pl start zmtelemetry.pl'); } + if ( $Server and exists $$Server{'zmstats.pl'} and ! $$Server{'zmstats.pl'} ) { + Debug("Not running zmstats.pl because it is turned off for this server."); + } else { + runCommand('zmdc.pl start zmstats.pl'); + } } else { $retval = 1; } diff --git a/scripts/zmstats.pl.in b/scripts/zmstats.pl.in index ae58b6fb9..dd3750906 100644 --- a/scripts/zmstats.pl.in +++ b/scripts/zmstats.pl.in @@ -164,7 +164,7 @@ while( 1 ) { $eventcounts_week_sth->execute( ) or Error( "Can't execute: ".$eventcounts_sth->errstr() ); $eventcounts_month_sth->execute( ) or Error( "Can't execute: ".$eventcounts_sth->errstr() ); - sleep( $Config{ZM_STATS_CHECK_INTERVAL} ); + sleep( $Config{ZM_STATS_UPDATE_INTERVAL} ); } # end while (1) Info( "Stats Daemon exiting\n" ); diff --git a/src/zm_event.cpp b/src/zm_event.cpp index c72383a30..03d1047ae 100644 --- a/src/zm_event.cpp +++ b/src/zm_event.cpp @@ -399,7 +399,10 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st static char event_file[PATH_MAX]; snprintf( event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames ); - if ( ! ( monitor->GetOptSaveJPEGs() & 3 ) ) { + if ( monitor->GetOptSaveJPEGs() & 1 ) { + Debug( 1, "Writing pre-capture frame %d", frames ); + WriteFrameImage( images[i], *(timestamps[i]), event_file ); + } else { //If this is the first frame, we should add a thumbnail to the event directory // ICON: We are working through the pre-event frames so this snapshot won't // neccessarily be of the motion. But some events are less than 10 frames, @@ -409,9 +412,8 @@ void Event::AddFramesInternal( int n_frames, int start_frame, Image **images, st WriteFrameImage( images[i], *(timestamps[i]), snapshot_file.c_str() ); } } - if ( monitor->GetOptSaveJPEGs() & 1 ) { - Debug( 1, "Writing pre-capture frame %d", frames ); - WriteFrameImage( images[i], *(timestamps[i]), event_file ); + if ( videowriter != NULL ) { + WriteFrameVideo( images[i], *(timestamps[i]), videowriter ); } struct DeltaTimeval delta_time; @@ -466,20 +468,18 @@ void Event::AddFrame( Image *image, struct timeval timestamp, int score, Image * static char event_file[PATH_MAX]; snprintf( event_file, sizeof(event_file), staticConfig.capture_file_format, path, frames ); - if ( ! ( monitor->GetOptSaveJPEGs() & 3 ) ) { - //if ( monitor->GetOptSaveJPEGs() & 4 ) { - // Only snapshots - //If this is the first frame, we should add a thumbnail to the event directory - if ( frames == 10 || frames == 1 ) { - std::string snapshot_file = std::string(path) + "/snapshot.jpg"; - WriteFrameImage( image, timestamp, snapshot_file.c_str() ); - } - } if ( monitor->GetOptSaveJPEGs() & 1 ) { Debug( 1, "Writing capture frame %d to %s", frames, event_file ); if ( ! WriteFrameImage( image, timestamp, event_file ) ) { Error("Failed to write frame image"); } + } else { + //If this is the first frame, we should add a thumbnail to the event directory + if ( frames == 1 ) { + char snapshot_file[PATH_MAX]; + snprintf( snapshot_file, sizeof(snapshot_file), "%s/snapshot.jpg", path ); + WriteFrameImage( image, timestamp, snapshot_file ); + } } struct DeltaTimeval delta_time; diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 4698813b1..38057d7e5 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -1588,8 +1588,20 @@ void Monitor::Reload() { function = (Function)atoi(dbrow[index++]); enabled = atoi(dbrow[index++]); const char *p_linked_monitors = dbrow[index++]; - strncpy( event_prefix, dbrow[index++], sizeof(event_prefix)-1 ); - strncpy( label_format, dbrow[index++], sizeof(label_format)-1 ); + + if ( dbrow[index] ) { + strncpy( event_prefix, dbrow[index++], sizeof(event_prefix)-1 ); + } else { + event_prefix[0] = 0; + index++; + } + if ( dbrow[index] ) { + strncpy( label_format, dbrow[index++], sizeof(label_format)-1 ); + } else { + label_format[0] = 0; + index++; + } + label_coord = Coord( atoi(dbrow[index]), atoi(dbrow[index+1]) ); index += 2; label_size = atoi(dbrow[index++]); warmup_count = atoi(dbrow[index++]); diff --git a/version b/version index b4202e9fd..f6cb7f351 100644 --- a/version +++ b/version @@ -1 +1 @@ -1.31.20 +1.31.22 diff --git a/web/includes/Group.php b/web/includes/Group.php index 9d6d058bb..543665655 100644 --- a/web/includes/Group.php +++ b/web/includes/Group.php @@ -135,6 +135,61 @@ public $defaults = array( return $this->{'MonitorIds'}; } + public static function get_group_dropdown() { + + session_start(); + $selected_group_id = 0; + if ( isset($_REQUEST['groups']) ) { + $selected_group_id = $group_id = $_SESSION['groups'] = $_REQUEST['groups']; + } else if ( isset( $_SESSION['groups'] ) ) { + $selected_group_id = $group_id = $_SESSION['groups']; + } else if ( isset($_REQUEST['filtering']) ) { + unset($_SESSION['groups']); + } + session_write_close(); + + $Groups = array(); + foreach ( Group::find_all( ) as $Group ) { + $Groups[$Group->Id()] = $Group; + } + +# This array is indexed by parent_id +global $children; + $children = array(); + + foreach ( $Groups as $id=>$Group ) { + if ( $Group->ParentId() != null ) { + if ( ! isset( $children[$Group->ParentId()] ) ) + $children[$Group->ParentId()] = array(); + $children[$Group->ParentId()][] = $Group; + } + } + + function get_options( $Group ) { + global $children; + $options = array( $Group->Id() => str_repeat('   ', $Group->depth() ) . $Group->Name() ); + if ( isset($children[$Group->Id()]) ) { + foreach ( $children[$Group->Id()] as $child ) { + $options += get_options( $child ); + } + } + return $options; + } + $group_options = array(); + foreach ( $Groups as $id=>$Group ) { + if ( ! $Group->ParentId() ) { + $group_options += get_options( $Group ); + } + } + return htmlSelect( 'Group[]', $group_options, isset($_SESSION['Group'])?$_SESSION['Group']:null, array( + 'onchange' => 'this.form.submit();', + 'class'=>'chosen', + 'multiple'=>'multiple', + 'data-placeholder'=>'All', + ) ); + + } # end public static function get_group_dropdown + public static function get_group_dropdowns() { # This will end up with the group_id of the deepest selection $group_id = 0; @@ -142,6 +197,8 @@ public $defaults = array( $groups = array(); $parent_group_ids = null; session_start(); + + $group_options = array(0=>'All'); while(1) { $Groups = Group::find_all( array('ParentId'=>$parent_group_ids) ); if ( ! count( $Groups ) ) @@ -161,15 +218,17 @@ public $defaults = array( if ( ! isset( $groups[$depth] ) ) { $groups[$depth] = array(0=>'All'); } +$group_options[$Group->Id()] = str_repeat( ' ', $depth ) . $Group->Name(); $groups[$depth][$Group->Id()] = $Group->Name(); if ( $selected_group_id and ( $selected_group_id == $Group->Id() ) ) $parent_group_ids[] = $Group->Id(); } - echo htmlSelect( 'group'.$depth, $groups[$depth], $selected_group_id, "this.form.submit();" ); + //echo htmlSelect( 'group'.$depth, $groups[$depth], $selected_group_id, "this.form.submit();" ); if ( ! count($parent_group_ids) ) break; $depth += 1; } + echo htmlSelect( 'groups', $group_options, $selected_group_id, 'this.form.submit();' ); session_write_close(); return $group_id; @@ -179,9 +238,17 @@ public $defaults = array( public static function get_group_sql( $group_id ) { $groupSql = ''; if ( $group_id ) { - $MonitorIds = dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($group_id) ); + if ( is_array( $group_id ) ) { + $group_id_sql_part = ' IN ('.implode(',', array_map(function(){return '?';}, $group_id ) ).')'; - $MonitorIds = array_merge( $MonitorIds, dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId IN (SELECT Id FROM Groups WHERE ParentId = ?)', 'MonitorId', array($group_id) ) ); + $MonitorIds = dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId'.$group_id_sql_part, 'MonitorId', $group_id ); + + $MonitorIds = array_merge( $MonitorIds, dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId IN (SELECT Id FROM Groups WHERE ParentId'.$group_id_sql_part.')', 'MonitorId', $group_id ) ); + } else { + $MonitorIds = dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId=?', 'MonitorId', array($group_id) ); + + $MonitorIds = array_merge( $MonitorIds, dbFetchAll( 'SELECT MonitorId FROM Groups_Monitors WHERE GroupId IN (SELECT Id FROM Groups WHERE ParentId = ?)', 'MonitorId', array($group_id) ) ); + } $groupSql = " find_in_set( Id, '".implode( ',', $MonitorIds )."' )"; } return $groupSql; diff --git a/web/includes/Server.php b/web/includes/Server.php index fa892f8d9..a6d2b06a5 100644 --- a/web/includes/Server.php +++ b/web/includes/Server.php @@ -23,15 +23,39 @@ class Server { $this->{'Hostname'} = ''; } } - public static function find_all() { - $servers = array(); - $result = dbQuery( 'SELECT * FROM Servers ORDER BY Name'); - $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server' ); - foreach ( $results as $row => $server_obj ) { - $servers[] = $server_obj; - } - return $servers; - } + public static function find_all( $parameters = null, $options = null ) { + $filters = array(); + $sql = 'SELECT * FROM Servers '; + $values = array(); + + if ( $parameters ) { + $fields = array(); + $sql .= 'WHERE '; + foreach ( $parameters as $field => $value ) { + if ( $value == null ) { + $fields[] = $field.' IS NULL'; + } else if ( is_array( $value ) ) { + $func = function(){return '?';}; + $fields[] = $field.' IN ('.implode(',', array_map( $func, $value ) ). ')'; + $values += $value; + + } else { + $fields[] = $field.'=?'; + $values[] = $value; + } + } + $sql .= implode(' AND ', $fields ); + } + if ( $options and isset($options['order']) ) { + $sql .= ' ORDER BY ' . $options['order']; + } + $result = dbQuery($sql, $values); + $results = $result->fetchALL(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'Server'); + foreach ( $results as $row => $obj ) { + $filters[] = $obj; + } + return $filters; + } public function Url() { if ( $this->Id() ) { diff --git a/web/includes/Storage.php b/web/includes/Storage.php index 945b8a464..070e03102 100644 --- a/web/includes/Storage.php +++ b/web/includes/Storage.php @@ -120,6 +120,7 @@ public static function find_all( $parameters = null, $options = null ) { } $used = $this->disk_used_space(); $usage = round( ($used / $total) * 100); + Warning("Used $usage = round( ( $used / $total ) * 100 )"); return $usage; } public function disk_total_space() { @@ -130,7 +131,7 @@ public static function find_all( $parameters = null, $options = null ) { } public function disk_used_space() { # This isn't a function like this in php, so we have to add up the space used in each event. - if ( ! array_key_exists( 'DiskSpace', $this ) ) { + if ( (! array_key_exists( 'DiskSpace', $this )) or (!$this->{'DiskSpace'}) ) { $used = 0; if ( $this->{'Type'} == 's3fs' ) { $used = dbFetchOne('SELECT SUM(DiskSpace) AS DiskSpace FROM Events WHERE StorageId=? AND DiskSpace IS NOT NULL', 'DiskSpace', array($this->Id()) ); diff --git a/web/includes/actions.php b/web/includes/actions.php index c9ccb9157..36cfee616 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -379,7 +379,6 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) { dbQuery( 'UPDATE Zones SET '.implode( ', ', $changes ).' WHERE MonitorId=? AND Id=?', array( $mid, $zid) ); } else { dbQuery( 'INSERT INTO Zones SET MonitorId=?, '.implode( ', ', $changes ), array( $mid ) ); - dbQuery( 'UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id) WHERE Id=?', array($mid)); } //if ( $cookies ) session_write_close(); if ( daemonCheck() ) { @@ -432,7 +431,6 @@ if ( !empty($_REQUEST['mid']) && canEdit( 'Monitors', $_REQUEST['mid'] ) ) { foreach( $_REQUEST['markZids'] as $markZid ) { $zone = dbFetchOne( 'select * from Zones where Id=?', NULL, array($markZid) ); dbQuery( 'delete from Zones WHERE MonitorId=? AND Id=?', array( $mid, $markZid) ); - dbQuery( 'UPDATE Monitors SET ZoneCount=(SELECT COUNT(Id) FROM Zones WHERE MonitorId=Monitors.Id) WHERE Id=?', array($mid)); $deletedZid = 1; } if ( $deletedZid ) { diff --git a/web/includes/functions.php b/web/includes/functions.php index 87771396b..ed9c91834 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -636,10 +636,10 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) { { if ( is_array( $newValues[$key] ) ) { if ( join(',',$newValues[$key]) != $values[$key] ) { - $changes[$key] = "$key = ".dbEscape(join(',',$newValues[$key])); + $changes[$key] = "`$key` = ".dbEscape(join(',',$newValues[$key])); } } elseif ( $values[$key] ) { - $changes[$key] = "$key = ''"; + $changes[$key] = "`$key` = ''"; } break; } @@ -696,9 +696,9 @@ function getFormChanges( $values, $newValues, $types=false, $columns=false ) { { if ( !isset($values[$key]) || ($values[$key] != $value) ) { if ( ! isset($value) || $value == '' ) { - $changes[$key] = "$key = NULL"; + $changes[$key] = "`$key` = NULL"; } else { - $changes[$key] = $key . ' = '.dbEscape(trim($value)); + $changes[$key] = "`$key` = ".dbEscape(trim($value)); } } break; diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index b6f0e7455..993441cdf 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -82,9 +82,11 @@ echo output_link_if_exists( array( '/js/dateTimePicker/jquery-ui-timepicker-addon.css', '/js/jquery-ui-structure.css', '/css/'.$css.'/jquery-ui-theme.css', - '/js/chosen/chosen.min.css', ) ); +?> + +'lower(Name)')); $ServersById = array(); foreach ( $servers as $S ) { $ServersById[$S->Id()] = $S; } session_start(); -foreach ( array('ServerId','StorageId','Status','MonitorId') as $var ) { +foreach ( array('Group', 'ServerId','StorageId','Status','MonitorId') as $var ) { if ( isset( $_REQUEST[$var] ) ) { if ( $_REQUEST[$var] != '' ) { $_SESSION[$var] = $_REQUEST[$var]; @@ -49,7 +49,8 @@ foreach ( $storage_areas as $S ) { diff --git a/web/skins/classic/views/group.php b/web/skins/classic/views/group.php index 11ea093ed..df9ea36d4 100644 --- a/web/skins/classic/views/group.php +++ b/web/skins/classic/views/group.php @@ -92,7 +92,8 @@ if ( $newGroup->Id() ) $sql = 'SELECT Id,Name from Groups'.(count($kids)?' WHERE Id NOT IN ('.implode(',',array_map(function(){return '?';}, $kids )).')' : '').' ORDER BY Name'; $options = array(''=>'None'); foreach ( dbFetchAll( $sql, null, $kids ) as $option ) { - $options[$option['Id']] = $option['Name']; + + $options[$option['Id']] = str_repeat('  ', $Groups[$option['Id']]->depth() ) . $option['Name']; } echo htmlSelect( 'newGroup[ParentId]', $options, $newGroup->ParentId(), array('onchange'=>'configureButtons(this);' )); ?> diff --git a/web/skins/classic/views/groups.php b/web/skins/classic/views/groups.php index 7301020b9..f3ea754e2 100644 --- a/web/skins/classic/views/groups.php +++ b/web/skins/classic/views/groups.php @@ -18,7 +18,7 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !canView( 'Groups' ) ) { +if ( !canView('Groups') ) { $view = 'error'; return; } @@ -64,8 +64,7 @@ function group_line( $Group ) { global $children; global $max_depth; $html = ''; - for ( $i = 1; $i<$Group->depth(); $i+=1 ) - $html .= ' '; + $html .= str_repeat( ' ', $Group->depth() ); $html .= ''; if ( canEdit('Groups') ) { $html .= ''. validHtmlStr($Group->Id() . ' ' . $Group->Name()).''; diff --git a/web/skins/classic/views/js/montagereview.js b/web/skins/classic/views/js/montagereview.js index e1f854f66..7a180c9ef 100644 --- a/web/skins/classic/views/js/montagereview.js +++ b/web/skins/classic/views/js/montagereview.js @@ -526,7 +526,7 @@ function clicknav(minSecs,maxSecs,live) {// we use the current time if we can if ( monitorZoomScale[monitorPtr[i]] < 0.99 || monitorZoomScale[monitorPtr[i]] > 1.01 ) // allow for some up/down changes and just treat as 1 of almost 1 zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2); - var uri = "?view=" + currentView + '&fit='+(fitMode==1?'1':'0') + groupStr + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value]; + var uri = "?view=" + currentView + '&fit='+(fitMode==1?'1':'0') + minStr + maxStr + currentStr + intervalStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value]; window.location = uri; } // end function clicknav @@ -745,7 +745,7 @@ function changeDateTime(e) { if ( monitorZoomScale[monitorPtr[i]] < 0.99 || monitorZoomScale[monitorPtr[i]] > 1.01 ) // allow for some up/down changes and just treat as 1 of almost 1 zoomStr += "&z" + monitorPtr[i].toString() + "=" + monitorZoomScale[monitorPtr[i]].toFixed(2); - var uri = "?view=" + currentView + fitStr + groupStr + minStr + maxStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value]; + var uri = "?view=" + currentView + fitStr + minStr + maxStr + liveStr + zoomStr + "&scale=" + $j("#scaleslider")[0].value + "&speed=" + speeds[$j("#speedslider")[0].value]; window.location = uri; } diff --git a/web/skins/classic/views/js/montagereview.js.php b/web/skins/classic/views/js/montagereview.js.php index 19089a315..981724a57 100644 --- a/web/skins/classic/views/js/montagereview.js.php +++ b/web/skins/classic/views/js/montagereview.js.php @@ -27,7 +27,6 @@ var eStorageId = []; var eStartSecs = []; var eEndSecs = []; var eventFrames = []; // this is going to presume all frames equal durationlength -var groupStr=; 1, 'Analysis images only (if available)' => 2, 'Frames + Analysis images (if available)' => 3, - 'Snapshot Only' => 4 ); $videowriteropts = array( diff --git a/web/skins/classic/views/storage.php b/web/skins/classic/views/storage.php index c5962ba01..8768e445c 100644 --- a/web/skins/classic/views/storage.php +++ b/web/skins/classic/views/storage.php @@ -19,20 +19,20 @@ // if ( !canEdit( 'System' ) ) { - $view = 'error'; - return; + $view = 'error'; + return; } if ( $_REQUEST['id'] ) { - if ( !($newStorage = dbFetchOne('SELECT * FROM Storage WHERE Id=?', NULL, ARRAY($_REQUEST['id'])) ) ) { - $view = 'error'; - return; + if ( !($newStorage = dbFetchOne('SELECT * FROM Storage WHERE Id=?', NULL, ARRAY($_REQUEST['id'])) ) ) { + $view = 'error'; + return; $newStorage['ServerId'] = ''; - } + } } else { - $newStorage = array(); - $newStorage['Name'] = translate('NewStorage'); - $newStorage['Path'] = ''; + $newStorage = array(); + $newStorage['Name'] = translate('NewStorage'); + $newStorage['Path'] = ''; $newStorage['Type'] = 'local'; $newStorage['Scheme'] = 'Medium'; } @@ -44,7 +44,7 @@ $scheme_options = array( 'Shallow' => translate('Shallow'), ); -$servers = Server::find_all(); +$servers = Server::find_all( null, array('order'=>'lower(Name)') ); $ServersById = array(); foreach ( $servers as $S ) { $ServersById[$S->Id()] = $S; @@ -75,7 +75,7 @@ xhtmlHeaders(__FILE__, translate('Storage')." - ".$newStorage['Name'] ); - + 'Remote / No Specific Server') + $ServersById, $newStorage['ServerId'] ); ?>