#!/usr/bin/perl
#  Copyright (C) 2002  Stanislav Sinyagin
#
#  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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.

# Stanislav Sinyagin <ssinyagin@k-open.com>

# we cannot report a failure of STDERR reopening, as we are already a
# forked child, so this Perl::Critic warning is disabled.
## no critic (InputOutput::RequireCheckedOpen)

use strict;
use warnings;
BEGIN { require '/usr/share/torrus/conf_defaults/torrus-config.pl'; }

use IO::File;
use Proc::Daemon;
use Getopt::Long;

use Torrus::Log;
use Torrus::Monitor;
use Torrus::MonitorScheduler;
use Torrus::SiteConfig;

exit(1) unless Torrus::SiteConfig::verify();

my $tree;
my $nodaemon;
my $runonce;
my $runalways;
my $delay = 0;
my $debug;
my $verbose;
my $help_needed;

# Derive the process name from the command line
my $process_name = $0;
$process_name =~ s/^.*\/([^\/]+)$/$1/;
$process_name .= ' ' . join(' ', @ARGV);


my $ok = GetOptions ('tree=s'   => \$tree,
                     'nodaemon' => \$nodaemon,
                     'runonce'  => \$runonce,
                     'runalways' => \$runalways,
                     'delay=i'  => \$delay,
                     'debug'    => \$debug,
                     'verbose'  => \$verbose,
                     'help'     => \$help_needed);

if( not $ok or not $tree or $help_needed or scalar(@ARGV) > 0 )
{
    print STDERR "Usage: $0 --tree=NAME [options...]\n",
    "Options:\n",
    "  --tree=NAME     tree name\n",
    "  --nodaemon      do not fork daemon and log to STDERR\n",
    "  --runonce       run one time and exit. Implies --nodaemon\n",
    "  --runalways     continue running if no monitors defined\n",
    "  --delay         delay the start of the first cycle, minutes\n",
    "  --debug         set the log level to debug\n",
    "  --verbose       set the log level to info\n",
    "  --help          this help message\n";
    exit 1;
}

if( not Torrus::SiteConfig::mayRunMonitor( $tree ) )
{
    Error('Tree ' . $tree . ' is not configured to run monitor');
    exit 1;
}


if( $debug )
{
    Torrus::Log::setLevel('debug');
}
elsif( $verbose )
{
    Torrus::Log::setLevel('verbose');
}


my $pidfile;

if( not $nodaemon and not $runonce )
{
    my $pidfilename =
        $Torrus::Global::pidDir . '/monitor.' . $tree . '.pid';
    
    if( -r $pidfilename )
    {
        my $oldpid;
        my $fh = IO::File->new($pidfilename, 'r');
        if( defined($fh) )
        {
            $oldpid = $fh->getline();
        }
        $fh->close();
        
        $oldpid = 'unknown' unless defined($oldpid);
        
        Error('Another monitor daemon is running, pid=', $oldpid);
        exit 1;
    }

    &Proc::Daemon::Init();
    umask 0017; # Proc::Daemon::Init sets the mask to all-writable

    # now we're forked, save the PID file for the END block
    $pidfile = $pidfilename;
    
    if( $Torrus::Monitor::useSyslog )
    {
        Torrus::Log::enableSyslog('torrus/monitor_' . $tree);
    }
    else
    {
        my $logfile = $Torrus::Global::logDir . '/monitor.' . $tree . '.log';
        
        # At this point, we cannot tell anyone if "open" fails
        open(STDERR, '>>', $logfile);
        *STDERR->autoflush();
    }

    my $fh = IO::File->new($pidfile, 'w');
    if( defined($fh) )
    {
        $fh->printf('%d', $$);
        $fh->close();
    }
    else
    {
        Error("Cannot open $pidfile for writing: $!");
    }
}

Info(sprintf("Torrus version %s", '2.09'));
Info(sprintf("%s started for tree %s", $0, $tree));
Info(sprintf("Process ID %d", $$));

$SIG{'HUP'} = sub {
    Warn('Received SIGHUP. Stopping the process.');
    exit(1);
};

if( $delay > 0 )
{
    Info(sprintf('Delaying for %d minutes', $delay));
    sleep($delay * 60);
}

&Torrus::DB::setSafeSignalHandlers();

my %options =
    (
     '-ProcessName' => $process_name,
     '-Tree'      => $tree,
     );
if( $runonce )
{
    $options{'-RunOnce'} = 1;
}
if( $runalways or $Torrus::Monitor::runAlways )
{
    $options{'-RunAlways'} = 1;
}

my $scheduler = new Torrus::MonitorScheduler( %options );
$scheduler->run();

if( not $options{'-RunOnce'} )
{
    Error('Monitor process exited: ' .
          'there is no datasource where monitoring is enabled');
}

exit;


END
{
    if( defined($pidfile) and -r $pidfile )
    {
        unlink $pidfile;
    }
}


# Local Variables:
# mode: perl
# indent-tabs-mode: nil
# perl-indent-level: 4
# End:
