# Buildd common base functionality
# Copyright © 1998 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
# Copyright © 2009 Roger Leigh <rleigh@debian.org>
#
# 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, see
# <http://www.gnu.org/licenses/>.
#
#######################################################################

package Buildd::Base;

use strict;
use warnings;

use IO::File;
use Buildd         qw(lock_file unlock_file);
use Buildd::Client qw();

use Sbuild::Base;
use Sbuild qw($devnull);

BEGIN {
	use Exporter ();
	our (@ISA, @EXPORT);

	@ISA = qw(Exporter Sbuild::Base);

	@EXPORT = qw();
}

sub new {
	my $class = shift;
	my $conf  = shift;

	my $self = $class->SUPER::new($conf);
	bless($self, $class);

	$self->set('PID', $$);

	$self->open_log();

	return $self;
}

sub open_log ($) {
	my $self = shift;

	my $logfile = $self->get_conf('DAEMON_LOG_FILE');

	my $log = IO::File->new("$logfile", O_CREAT | O_WRONLY | O_APPEND, 0640)
	  or die "$0: Cannot open logfile $logfile: $!\n";
	$log->autoflush(1);

	# Since we are a daemon, fully detach from terminal by reopening
	# stdout and stderr to redirect to the log file.  Note messages
	# should be printed using log(), not printing directly to the
	# filehandle.  This is a fallback only.
	open(STDOUT, '>&', $log) or warn "Can't redirect stderr\n";
	open(STDERR, '>&', $log) or warn "Can't redirect stderr\n";

	$self->set('Log Stream', $log);

	return $log;
}

sub close_log ($) {
	my $self = shift;

	# We can't close stdout and stderr, so redirect to /dev/null.
	open(STDOUT, '>&', $devnull) or warn "Can't redirect stderr\n";
	open(STDERR, '>&', $devnull) or warn "Can't redirect stderr\n";

	my $log = $self->get('Log Stream');
	$self->set('Log Stream', undef);

	return $log->close();
}

sub reopen_log ($) {
	my $self = shift;

	my $log = $self->get('Log Stream');

	if ($self->close_log()) {
		$log = $self->open_log();
	}

	return $log;
}

sub write_stats ($$$) {
	my $self = shift;
	my ($cat, $val) = @_;

	local (*F);

	my $home = $self->get_conf('HOME');

	lock_file("$home/stats");
	open(F, ">>$home/stats/$cat");
	print F "$val\n";
	close(F);
	unlock_file("$home/stats");
}

sub get_db_handle ($$) {
	my $self        = shift;
	my $dist_config = shift;

	my $db = Buildd::Client->new($dist_config);
	$db->set('Log Stream', $self->get('Log Stream'));
	return $db;
}

sub get_dist_config_by_name ($$) {
	my $self      = shift;
	my $dist_name = shift;

	my $dist_config;
	for my $dist_config_entry (@{ $self->get_conf('DISTRIBUTIONS') }) {
		if ($dist_config_entry->get('DIST_NAME') eq $dist_name) {
			$dist_config = $dist_config_entry;
		}
	}

	if (!$dist_config) {
		$self->set(
			'Mail Short Error',
			$self->get('Mail Short Error')
			  . "No configuration found for dist $dist_name\n"
		);
		$self->set(
			'Mail Error',
			$self->get('Mail Error')
			  . "Answer could not be processed, as dist=$dist_name does not match any of\n"
			  . "the entries in the buildd configuration.\n"
		);
	}

	return $dist_config;
}

sub get_arch_dist_config_by_name ($$) {
	my $self      = shift;
	my $arch_name = shift;
	my $dist_name = shift;

	my $arch_config, my $dist_config;
	for my $dist_config_entry (@{ $self->get_conf('DISTRIBUTIONS') }) {
		if (   $dist_config_entry->get('BUILT_ARCHITECTURE') eq $arch_name
			&& $dist_config_entry->get('DIST_NAME') eq $dist_name) {
			$dist_config = $dist_config_entry;
		}
	}

	if (!$dist_config) {
		$self->set(
			'Mail Short Error',
			$self->get('Mail Short Error')
			  . "No configuration found for arch=$arch_name, dist=$dist_name\n"
		);
		$self->set(
			'Mail Error',
			$self->get('Mail Error')
			  . "Answer could not be processed, as arch=$arch_name, dist=$dist_name"
			  . "does not match any of the entries in the buildd configuration.\n"
		);
	}

	return $dist_config;
}

sub log {
	my $self = shift;

	my $timestamp = localtime;
	# omit weekday and year for brevity
	$timestamp =~ s/^\w+\s(.*)\s\d+$/$1/;
	my $prefix = "$timestamp $Buildd::progname\[" . $self->get('PID') . "\]: ";

	for my $line (split(/\n/, join("", @_))) {
		Sbuild::Base::log($self, $prefix, $line, "\n");
	}
}

1;
