#!@PERL_EXECUTABLE@ -wT
use strict;
use warnings;
use bytes;

# ==========================================================================
#
# These are the elements you can edit to suit your installation
#
# ==========================================================================

use constant START_DELAY => 30; # To give everything else time to start

# ==========================================================================
#
# Don't change anything below here
#
# ==========================================================================

@EXTRA_PERL_LIB@
use ZoneMinder;
use DBI;
use Sys::MemInfo qw(totalmem freemem totalswap freeswap);
use ZoneMinder::Server;

$| = 1;

$ENV{PATH}  = '/bin:/usr/bin:/usr/local/bin';
$ENV{SHELL} = '/bin/sh' if exists $ENV{SHELL};
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};

logInit();
logSetSignal();
my $zm_terminate = 0;
sub TermHandler {
  Info('Received TERM, exiting');
  $zm_terminate = 1;
}
$SIG{TERM} = \&TermHandler;
$SIG{INT} = \&TermHandler;

Info('Stats Daemon starting in '.START_DELAY.' seconds');
sleep(START_DELAY);

my $dbh = zmDbConnect();
my $server = new ZoneMinder::Server($Config{ZM_SERVER_ID});

while (!$zm_terminate) {
  while ( ! ( $dbh and $dbh->ping() ) ) {
    Info('Reconnecting to db');
    if ( !($dbh = zmDbConnect()) ) {
      #What we do here is not that important, so just skip this interval
      sleep($Config{ZM_STATS_UPDATE_INTERVAL});
    }
  }

  my @cpuload = $server->CpuLoad();

  my  ($user_percent, $nice_percent, $sys_percent, $idle_percent, $usage_percent) = $server->CpuUsage();
  zmDbDo('INSERT INTO Server_Stats (ServerId, TimeStamp, CpuLoad, CpuUserPercent, CpuNicePercent, CpuSystemPercent, CpuIdlePercent, CpuUsagePercent, TotalMem, FreeMem, TotalSwap, FreeSwap) VALUES (?,NOW(),?,?,?,?,?,?,?,?,?,?)',
    $Config{ZM_SERVER_ID},
    $cpuload[0], $user_percent, $nice_percent, $sys_percent, $idle_percent, $usage_percent,
    &totalmem, &freemem, &totalswap, &freeswap);

  {
    my $rows = zmDbDo('DELETE FROM `Server_Stats` WHERE `TimeStamp` < now() - interval 1 DAY LIMIT 100');
    Debug("Deleted $rows Server Stats table entries by time");
  }

  # Clear out statuses for Monitors that have been set to None but for some reason didn't update the db
  zmDbDo('DELETE FROM Monitor_Status WHERE MonitorId IN (SELECT Id FROM Monitors WHERE Capturing=\'None\')');

  zmDbDo('DELETE FROM Events_Hour WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 hour)');
  zmDbDo('DELETE FROM Events_Day WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 day)');
  zmDbDo('DELETE FROM Events_Week WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 week)');
  zmDbDo('DELETE FROM Events_Month WHERE StartDateTime < DATE_SUB(NOW(), INTERVAL 1 month)');

  # Prune the Logs table if required
  if ( $Config{ZM_LOG_DATABASE_LIMIT} ) {
    if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^\d+$/ ) {
      # Number of rows
      my $selectLogRowCountSql = 'SELECT count(*) AS `Rows` FROM `Logs`';
      my $selectLogRowCountSth = $dbh->prepare_cached( $selectLogRowCountSql )
        or Fatal("Can't prepare '$selectLogRowCountSql': ".$dbh->errstr());
      my $res = $selectLogRowCountSth->execute()
        or Fatal("Can't execute: ".$selectLogRowCountSth->errstr());
      my $row = $selectLogRowCountSth->fetchrow_hashref();
      my $logRows = $row->{Rows};
      if ( $logRows > $Config{ZM_LOG_DATABASE_LIMIT} ) {
        my $rows = zmDbDo('DELETE low_priority FROM `Logs` ORDER BY `TimeKey` ASC LIMIT ?', $logRows - $Config{ZM_LOG_DATABASE_LIMIT});
        Debug('Deleted '.$rows.' log table entries by count') if defined $rows;
      }
    } else {
      # Time of record

      # 7 days is invalid.  We need to remove the s
      if ( $Config{ZM_LOG_DATABASE_LIMIT} =~ /^(.*)s$/ ) {
        $Config{ZM_LOG_DATABASE_LIMIT} = $1;
      }
      my $rows;
      do {
        $rows = zmDbDo('DELETE low_priority FROM `Logs` WHERE `TimeKey` < unix_timestamp(now() - interval '.$Config{ZM_LOG_DATABASE_LIMIT}.') LIMIT 100');
        Debug("Deleted $rows log table entries by time") if $rows;
      } while ($rows and ($rows == 100) and !$zm_terminate);
    }
  } # end if ZM_LOG_DATABASE_LIMIT

  {
    my $rows;
    do {
      # Delete any sessions that are more than a week old. Limiting to 100 because mysql sucks
      $rows = zmDbDo('DELETE FROM Sessions WHERE access < ? LIMIT 100', time - $Config{ZM_COOKIE_LIFETIME});
      Debug("Deleted $rows sessions") if $rows;
    } while ($rows and ($rows == 100) and !$zm_terminate);
  }

  sleep($Config{ZM_STATS_UPDATE_INTERVAL});
} # end while (!$zm_terminate)

Info('Stats Daemon exiting');
exit();
1;
__END__

#
# ==========================================================================
#
# ZoneMinder WatchDog Script, $Date$, $Revision$
# Copyright (C) 2001-2008 Philip Coombes
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# ==========================================================================

=head1 NAME

zmstats.pl - ZoneMinder Stats Updating Script

=head1 SYNOPSIS

zmstats.pl

=head1 DESCRIPTION

This does background updating various stats in the db like event counts, diskspace, etc.

=cut