#!/usr/bin/perl

use strict;
use warnings;

=head1 NAME

ubic-watchdog - watchdog which checks all ubic services.

=head1 VERSION

version 1.08

=head1 SYNOPSIS

    ubic-watchdog [-v]

=cut

use Getopt::Long 2.33;
use Pod::Usage;

use Ubic::Logger;
use Ubic;
use Try::Tiny;

return 1 if caller();

my $verbose;
GetOptions(
    'v|verbose' => \$verbose,
) or pod2usage(2);

if ($<) {
    die "ubic-watchdog requires root access";
}

sub check($);

sub check_all {
    my @services = @_;
    for my $service (@services) {
        my $child = fork;
        unless (defined $child) {
            die "fork failed";
        }
        unless ($child) {
            check($service);
            exit;
        }
    }
    1 while wait() > 0;
    return;
}

sub check($) {
    my $service = shift;
    my $name = $service->full_name;
    if ($verbose) {
        INFO("Checking $name");
    }

    try {
        my $lock = Ubic->lock($name);
        if ($service->isa('Ubic::Multiservice')) {
            INFO("$name is multiservice, checking subservices") if $verbose;
            check_all($service->services);
            return;
        }
        unless (Ubic->is_enabled($name)) {
            INFO("$name disabled") if $verbose;
            return;
        }
        # TODO - alarm?
        my $status = Ubic->status($name);
        unless ($status eq 'running') {
            Ubic->set_cached_status($name, $status->status); # following start can throw exception
            ERROR("$name is broken, restarting");
            Ubic->start($name);
        }
        $status = $service->status;
        if ($status ne 'running') {
            INFO("$name started, but status is still '$status'");
        }
        Ubic->set_cached_status($name, $status); # if service's start implementation is invalid, ubic-watchdog will restart it every minute, so be careful
    }
    catch {
        ERROR("Failed to check $name: $_");
    };

    INFO("$name checked") if $verbose;
}

my @services = Ubic->services;
check_all(@services);