diff --git a/db/zm_create.sql.in b/db/zm_create.sql.in
index bf598b646..fbc7cad3c 100644
--- a/db/zm_create.sql.in
+++ b/db/zm_create.sql.in
@@ -283,6 +283,7 @@ CREATE TABLE `Filters` (
`Id` int(10) unsigned NOT NULL auto_increment,
`Name` varchar(64) NOT NULL default '',
`UserId` int(10) unsigned,
+ `ExecuteInterval` int(10) unsigned NOT NULL default '60',
`Query_json` text NOT NULL,
`AutoArchive` tinyint(3) unsigned NOT NULL default '0',
`AutoUnarchive` tinyint(3) unsigned NOT NULL default '0',
diff --git a/db/zm_update-1.35.25.sql b/db/zm_update-1.35.25.sql
index 387ef09b0..16df91d74 100644
--- a/db/zm_update-1.35.25.sql
+++ b/db/zm_update-1.35.25.sql
@@ -56,7 +56,7 @@ EXECUTE stmt;
SET @s = (SELECT IF(
(SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS WHERE table_schema = DATABASE()
AND table_name = 'Monitor_Status'
- AND column_name = 'DayEvents'
+ AND column_name = 'DayEventDiskSpace'
) > 0,
"ALTER TABLE `Monitor_Status` DROP `DayEventDiskSpace`",
"SELECT 'Column DayEventDiskSpace already removed from Monitor_Status'"
diff --git a/db/zm_update-1.37.6.sql b/db/zm_update-1.37.6.sql
new file mode 100644
index 000000000..7c79886ad
--- /dev/null
+++ b/db/zm_update-1.37.6.sql
@@ -0,0 +1,18 @@
+--
+-- Update Filters table to have a ExecuteInterval Column
+--
+
+SELECT 'Checking for ExecuteInterval in Filters';
+SET @s = (SELECT IF(
+ (SELECT COUNT(*)
+ FROM INFORMATION_SCHEMA.COLUMNS
+ WHERE table_name = 'Filters'
+ AND table_schema = DATABASE()
+ AND column_name = 'ExecuteInterval'
+ ) > 0,
+"SELECT 'Column ExecuteInterval already exists in Filters'",
+"ALTER TABLE Filters ADD COLUMN `ExecuteInterval` int(10) unsigned NOT NULL default '60' AFTER `UserId`"
+));
+
+PREPARE stmt FROM @s;
+EXECUTE stmt;
diff --git a/distros/redhat/zoneminder.spec b/distros/redhat/zoneminder.spec
index 8d49c0d7f..f5aeebf2d 100644
--- a/distros/redhat/zoneminder.spec
+++ b/distros/redhat/zoneminder.spec
@@ -36,7 +36,7 @@
%global _hardened_build 1
Name: zoneminder
-Version: 1.37.5
+Version: 1.37.6
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm
index 0db46ff0d..7b3efad46 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Filter.pm
@@ -56,6 +56,7 @@ $primary_key = 'Id';
%fields = map { $_ => $_ } qw(
Id
Name
+ExecuteInterval
Query_json
AutoArchive
AutoUnarchive
@@ -106,7 +107,6 @@ sub Execute {
$sql =~ s/zmSystemLoad/$load/g;
}
- $sql .= ' FOR UPDATE' if $$self{LockRows};
Debug("Filter::Execute SQL ($sql)");
my $sth = $ZoneMinder::Database::dbh->prepare_cached($sql)
@@ -371,10 +371,7 @@ sub Sql {
if ( @auto_terms ) {
$sql .= ' AND ( '.join(' or ', @auto_terms).' )';
}
- if ( !$filter_expr->{sort_field} ) {
- $filter_expr->{sort_field} = 'StartDateTime';
- $filter_expr->{sort_asc} = 0;
- }
+
my $sort_column = '';
if ( $filter_expr->{sort_field} eq 'Id' ) {
$sort_column = 'E.Id';
@@ -406,14 +403,23 @@ sub Sql {
$sort_column = 'E.MaxScore';
} elsif ( $filter_expr->{sort_field} eq 'DiskSpace' ) {
$sort_column = 'E.DiskSpace';
- } else {
- $sort_column = 'E.StartDateTime';
+ } elsif ( $filter_expr->{sort_field} ne '' ) {
+ $sort_column = 'E.'.$filter_expr->{sort_field};
}
- my $sort_order = $filter_expr->{sort_asc} ? 'ASC' : 'DESC';
- $sql .= ' ORDER BY '.$sort_column.' '.$sort_order;
- if ( $filter_expr->{limit} ) {
+ if ( $sort_column ne '' ) {
+ $sql .= ' ORDER BY '.$sort_column.' '.($filter_expr->{sort_asc} ? 'ASC' : 'DESC');
+ }
+ if ($filter_expr->{limit}) {
$sql .= ' LIMIT 0,'.$filter_expr->{limit};
}
+ if ($$self{LockRows}) {
+ $sql .= ' FOR UPDATE OF E'
+ } else {
+ $sql .= ' FOR SHARE OF E'
+ }
+ if ($filter_expr->{skip_locked}) {
+ $sql .= ' SKIP LOCKED';
+ }
$self->{Sql} = $sql;
} # end if has Sql
return $self->{Sql};
diff --git a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in
index e7fdcd35f..e0c9bf971 100644
--- a/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in
+++ b/scripts/ZoneMinder/lib/ZoneMinder/Memory.pm.in
@@ -42,6 +42,7 @@ our @ISA = qw(Exporter ZoneMinder::Base);
# will save memory.
our %EXPORT_TAGS = (
constants => [ qw(
+ STATE_UNKNOWN
STATE_IDLE
STATE_PREALARM
STATE_ALARM
@@ -98,11 +99,12 @@ our $VERSION = $ZoneMinder::Base::VERSION;
use ZoneMinder::Config qw(:all);
use ZoneMinder::Logger qw(:all);
-use constant STATE_IDLE => 0;
-use constant STATE_PREALARM => 1;
-use constant STATE_ALARM => 2;
-use constant STATE_ALERT => 3;
-use constant STATE_TAPE => 4;
+use constant STATE_UNKNOWN => 0;
+use constant STATE_IDLE => 1;
+use constant STATE_PREALARM => 2;
+use constant STATE_ALARM => 3;
+use constant STATE_ALERT => 4;
+use constant STATE_TAPE => 5;
use constant ACTION_GET => 1;
use constant ACTION_SET => 2;
diff --git a/scripts/zmfilter.pl.in b/scripts/zmfilter.pl.in
index 08ae4abf2..fd927020f 100644
--- a/scripts/zmfilter.pl.in
+++ b/scripts/zmfilter.pl.in
@@ -138,7 +138,6 @@ $ENV{PATH} = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
-my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL};
my $event_id = 0;
if (!EVENT_PATH) {
@@ -174,6 +173,7 @@ my @filters;
my $last_action = 0;
while (!$zm_terminate) {
+ my $delay = $Config{ZM_FILTER_EXECUTE_INTERVAL};
my $now = time;
if (($now - $last_action) > $Config{ZM_FILTER_RELOAD_DELAY}) {
Debug('Reloading filters');
@@ -183,6 +183,15 @@ while (!$zm_terminate) {
foreach my $filter (@filters) {
last if $zm_terminate;
+
+ my $elapsed = ($now - $$filter{last_ran});
+ if ($$filter{last_ran} and ($elapsed < $$filter{ExecuteInterval})) {
+ my $filter_delay = $$filter{ExecuteInterval} - ($now - $$filter{last_ran});
+ $delay = $filter_delay if $filter_delay < $delay;
+ Debug("Setting delay to $delay because ExecuteInterval=$$filter{ExecuteInterval} and $elapsed have elapsed");
+ next;
+ }
+
if ($$filter{Concurrent} and !($filter_id or $filter_name)) {
my ( $proc ) = $0 =~ /(\S+)/;
my ( $id ) = $$filter{Id} =~ /(\d+)/;
@@ -191,8 +200,9 @@ while (!$zm_terminate) {
system(qq`$proc --filter_id $id &`);
} else {
checkFilter($filter);
+ $$filter{last_ran} = $now;
}
- }
+ } # end foreach filter
last if (!$daemon and ($filter_name or $filter_id)) or $zm_terminate;
@@ -362,11 +372,6 @@ sub checkFilter {
} # end if AutoCopy
if ( $filter->{UpdateDiskSpace} ) {
- if ( $$filter{LockRows} ) {
- $ZoneMinder::Database::dbh->begin_work();
- $Event->lock_and_load();
- }
-
my $old_diskspace = $$Event{DiskSpace};
my $new_diskspace = $Event->DiskSpace(undef);
diff --git a/scripts/zmtrigger.pl.in b/scripts/zmtrigger.pl.in
index 041d1c449..83fcf29f5 100644
--- a/scripts/zmtrigger.pl.in
+++ b/scripts/zmtrigger.pl.in
@@ -166,13 +166,9 @@ while (!$zm_terminate) {
foreach my $connection ( values(%spawned_connections) ) {
if ( vec($rout, $connection->fileno(), 1) ) {
Debug('Got input from spawned connection '
- .$connection->name()
- .' ('
- .$connection->fileno()
- .')'
- );
+ .$connection->name().' ('.$connection->fileno().')');
my $messages = $connection->getMessages();
- if ( defined($messages) ) {
+ if (defined($messages)) {
foreach my $message ( @$messages ) {
handleMessage($connection, $message);
}
@@ -199,34 +195,32 @@ while (!$zm_terminate) {
# Check polled connections
foreach my $connection ( @in_poll_connections ) {
my $messages = $connection->getMessages();
- if ( defined($messages) ) {
- foreach my $message ( @$messages ) {
- handleMessage($connection, $message);
- }
+ if (defined($messages)) {
+ foreach my $message (@$messages) { handleMessage($connection, $message) };
}
}
# Check for alarms that might have happened
my @out_messages;
foreach my $monitor ( values %monitors ) {
+ if ($$monitor{Function} eq 'None') {
+ $monitor_reload_time = 0;
+ next;
+ }
- if ( ! zmMemVerify($monitor) ) {
+ if (!zmMemVerify($monitor)) {
# Our attempt to verify the memory handle failed. We should reload the monitors.
# Don't need to zmMemInvalidate because the monitor reload will do it.
push @needsReload, $monitor;
next;
}
- my ( $state, $last_event ) = zmMemRead( $monitor,
- [
+ my ($state, $last_event) = zmMemRead($monitor, [
'shared_data:state',
'shared_data:last_event'
- ]
- );
+ ]);
-#print( "$monitor->{Id}: S:$state, LE:$last_event" );
-#print( "$monitor->{Id}: mS:$monitor->{LastState}, mLE:$monitor->{LastEvent}" );
- if ( $state == STATE_ALARM or $state == STATE_ALERT ) {
+ if ($state == STATE_ALARM or $state == STATE_ALERT) {
# In alarm state
if ( !defined($monitor->{LastEvent})
or ($last_event != $monitor->{LastEvent})
diff --git a/src/zm_buffer.cpp b/src/zm_buffer.cpp
index 4cb580aa4..c65d8b24a 100644
--- a/src/zm_buffer.cpp
+++ b/src/zm_buffer.cpp
@@ -65,7 +65,7 @@ unsigned int Buffer::expand(unsigned int count) {
int Buffer::read_into(int sd, unsigned int bytes) {
// Make sure there is enough space
this->expand(bytes);
- Debug(3, "Reading %u btes", bytes);
+ Debug(3, "Reading %u bytes", bytes);
int bytes_read = ::read(sd, mTail, bytes);
if (bytes_read > 0) {
mTail += bytes_read;
diff --git a/src/zm_rgb.h b/src/zm_rgb.h
index 58ad9bfae..ef1d46ce3 100644
--- a/src/zm_rgb.h
+++ b/src/zm_rgb.h
@@ -118,41 +118,34 @@ constexpr Rgb kRGBTransparent = 0x01000000;
/* Convert RGB colour value into BGR\ARGB\ABGR */
inline Rgb rgb_convert(Rgb p_col, int p_subpixorder) {
- Rgb result;
+ Rgb result = 0;
- switch(p_subpixorder) {
-
+ switch (p_subpixorder) {
case ZM_SUBPIX_ORDER_BGR:
case ZM_SUBPIX_ORDER_BGRA:
- {
- BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col);
- GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col);
- RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col);
- }
- break;
+ BLUE_PTR_BGRA(&result) = BLUE_VAL_RGBA(p_col);
+ GREEN_PTR_BGRA(&result) = GREEN_VAL_RGBA(p_col);
+ RED_PTR_BGRA(&result) = RED_VAL_RGBA(p_col);
+ break;
case ZM_SUBPIX_ORDER_ARGB:
- {
- BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col);
- GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col);
- RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col);
- }
- break;
+ BLUE_PTR_ARGB(&result) = BLUE_VAL_RGBA(p_col);
+ GREEN_PTR_ARGB(&result) = GREEN_VAL_RGBA(p_col);
+ RED_PTR_ARGB(&result) = RED_VAL_RGBA(p_col);
+ break;
case ZM_SUBPIX_ORDER_ABGR:
- {
- BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col);
- GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col);
- RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col);
- }
- break;
- /* Grayscale */
+ BLUE_PTR_ABGR(&result) = BLUE_VAL_RGBA(p_col);
+ GREEN_PTR_ABGR(&result) = GREEN_VAL_RGBA(p_col);
+ RED_PTR_ABGR(&result) = RED_VAL_RGBA(p_col);
+ break;
+ /* Grayscale */
case ZM_SUBPIX_ORDER_NONE:
- result = p_col & 0xff;
- break;
+ result = p_col & 0xff;
+ break;
default:
- return p_col;
- break;
+ result = p_col;
+ break;
}
-
+
return result;
}
diff --git a/src/zmc.cpp b/src/zmc.cpp
index c2f14e254..29e9886fd 100644
--- a/src/zmc.cpp
+++ b/src/zmc.cpp
@@ -365,6 +365,7 @@ int main(int argc, char *argv[]) {
monitor->Id());
zmDbDo(sql);
}
+ monitors.clear();
Image::Deinitialise();
Debug(1, "terminating");
diff --git a/utils/do_debian_package.sh b/utils/do_debian_package.sh
index 29ebdc0ef..00dcd44e9 100755
--- a/utils/do_debian_package.sh
+++ b/utils/do_debian_package.sh
@@ -218,8 +218,8 @@ rm .gitignore
cd ../
-if [ ! -e "$DIRECTORY.orig.tar.gz" ]; then
- read -p "$DIRECTORY.orig.tar.gz does not exist, create it? [Y/n]"
+if [ -e "$DIRECTORY.orig.tar.gz" ]; then
+ read -p "$DIRECTORY.orig.tar.gz exists, overwrite it? [Y/n]"
if [[ "$REPLY" == "" || "$REPLY" == [yY] ]]; then
tar zcf $DIRECTORY.orig.tar.gz $DIRECTORY.orig
fi;
diff --git a/version b/version
index e2ba07049..e22b12fd6 100644
--- a/version
+++ b/version
@@ -1 +1 @@
-1.37.5
+1.37.6
diff --git a/web/ajax/events.php b/web/ajax/events.php
index 090fe476e..4db6b99cc 100644
--- a/web/ajax/events.php
+++ b/web/ajax/events.php
@@ -48,7 +48,7 @@ if (isset($_REQUEST['order'])) {
} else if (strtolower($_REQUEST['order']) == 'desc') {
$order = 'DESC';
} else {
- Warning("Invalid value for order " . $_REQUEST['order']);
+ Warning('Invalid value for order ' . $_REQUEST['order']);
}
}
@@ -170,18 +170,23 @@ function queryRequest($filter, $search, $advsearch, $sort, $offset, $order, $lim
// The names of columns shown in the event view that are NOT dB columns in the database
$col_alt = array('Monitor', 'Storage');
- if (!in_array($sort, array_merge($columns, $col_alt))) {
- ZM\Error('Invalid sort field: ' . $sort);
- $sort = 'Id';
+ if ( $sort != '' ) {
+ if (!in_array($sort, array_merge($columns, $col_alt))) {
+ ZM\Error('Invalid sort field: ' . $sort);
+ $sort = '';
+ } else if ( $sort == 'Monitor' ) {
+ $sort = 'M.Name';
+ } else {
+ $sort = 'E.'.$sort;
+ }
}
$values = array();
$likes = array();
$where = $filter->sql()?' WHERE ('.$filter->sql().')' : '';
- $sort = $sort == 'Monitor' ? 'M.Name' : 'E.'.$sort;
$col_str = 'E.*, M.Name AS Monitor';
- $sql = 'SELECT ' .$col_str. ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.' ORDER BY '.$sort.' '.$order;
+ $sql = 'SELECT ' .$col_str. ' FROM `Events` AS E INNER JOIN Monitors AS M ON E.MonitorId = M.Id'.$where.($sort?' ORDER BY '.$sort.' '.$order:'');
$storage_areas = ZM\Storage::find();
$StorageById = array();
diff --git a/web/ajax/modals/filterdebug.php b/web/ajax/modals/filterdebug.php
index 725539a99..f3a961874 100644
--- a/web/ajax/modals/filterdebug.php
+++ b/web/ajax/modals/filterdebug.php
@@ -9,13 +9,13 @@
No filter id specified.
';
} else {
$filter = new ZM\Filter($_REQUEST['fid']);
- if ( ! $filter->Id() ) {
+ if (!$filter->Id()) {
echo '
Filter not found for id '.$_REQUEST['fid'].'
';
}
}
@@ -25,7 +25,16 @@
// We have to manually insert the csrf key into the form when using a modal generated via ajax call
echo getCSRFinputHTML();
?>
-
sql() ?>
+
+FROM Monitors AS M INNER JOIN Events AS E ON (M.Id = E.MonitorId) WHERE ';
+ $sql .= $filter->sql();
+ $sql .= $filter->sort_field() ? ' ORDER BY '.$filter->sort_field(). ' ' .($filter->sort_asc() ? 'ASC' : 'DESC') : '';
+ $sql .= $filter->limit() ? ' LIMIT '.$filter->limit() : '';
+ $sql .= $filter->skip_locked() ? ' SKIP LOCKED' : '';
+
+ echo $sql;
+?>