#!/usr/bin/perl
# 
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1
# 
# The contents of this file are subject to the Mozilla Public License
# Version 1.1 ("License"); you may not use this file except in
# compliance with the License. You may obtain a copy of the License at
# http://www.zimbra.com/license
# 
# Software distributed under the License is distributed on an "AS IS"
# basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
# the License for the specific language governing rights and limitations
# under the License.
# 
# The Original Code is: Zimbra Collaboration Suite Server.
# 
# The Initial Developer of the Original Code is Zimbra, Inc.
# Portions created by Zimbra are Copyright (C) 2005, 2006 Zimbra, Inc.
# All Rights Reserved.
# 
# Contributor(s):
# 
# ***** END LICENSE BLOCK *****
# 

use strict;

use lib "/opt/zimbra/zimbramon/lib";
use Zimbra::Util::Common;

use DBI;
use Time::Local;

my $baseDir = "/opt/zimbra";

my $data_source="dbi:mysql:database=zimbra_logger;mysql_read_default_file=/opt/zimbra/conf/my.logger.cnf;mysql_socket=/opt/zimbra/logger/db/mysql.sock";

my $username="zimbra";
my $password = `/opt/zimbra/bin/zmlocalconfig -s -m nokey zimbra_logger_mysql_password`;
chomp $password;

my $platform=`/opt/zimbra/libexec/get_plat_tag.sh`;
chomp $platform;
my $timeout=0;
while (! isSqlRunning() && ($timeout <= 120) ) {
  $timeout += sleep 5;
}
my $dbh = DBI->connect($data_source, $username, $password);

if (!$dbh) { 
	print STDERR "DB: Can't connect to $data_source: $DBI::errstr\n";
	exit 1;
}

my %MON = (
		'Jan' => '01',
		'Feb' => '02',
		'Mar' => '03',
		'Apr' => '04',
		'May' => '05',
		'Jun' => '06',
		'Jul' => '07',
		'Aug' => '08',
		'Sep' => '09',
		'Oct' => '10',
		'Nov' => '11',
		'Dec' => '12'
	);

sub logdate_to_sqldate {
	my $ts = shift;
	if ($ts eq "" || !defined($ts)) {
		return '';
	}
	# Sep 14 18:30:02

	my @p = split (' ', $ts);
	my @s= localtime();
	my $y = $s[5]+1900;
	my $m = $MON{$p[0]};

	my $dt = sprintf ("%4d-%02d-%02d %s",$y,$m,$p[1],$p[2]);
	return $dt;
}


sub get_last_timestamp {
	my $ts;

	my $statement = "select max(time) from server_stat";

	my $sth = $dbh->prepare($statement);

	if (!$sth->execute) {
		Zimbra::Logger::Log ("err", "DB: $sth->errstr");
		return undef;
	}

	my @ary = $sth->fetchrow_array;

	return (datetime_to_timestamp($ary[0]));
	
}

my $statement =
	"insert into raw_logs(log_date, loghost, app, pid, msg, postfix_qid) values (?,?,?,?,?,?)";

my $sth = $dbh->prepare($statement);

my $status_statement =
	"insert into service_status(server, service, time, status, loghostname) values (?,?,?,?,?)";

my $s_sth = $dbh->prepare($status_statement);

my $DEBUG = 0;

($DEBUG) && open FOO, ">/tmp/zmlogger.out";

($DEBUG) && print FOO localtime()," zmlogger starting up\n";

$SIG{QUIT} = \&bye;

my $logregex = qr/(^.{15}) ((\d+\.\d+\.\d+\.\d+) \S+|(\S+)) ([^[]+)\[(\d+)\]: (.*)$/o;

while (<>) {
	(/last message repeated/) && next;

	my ($log_date, $host, $ip, $name, $app, $pid, $msg) = ($_ =~ m/$logregex/);
  $host = (($ip ne "") ? $ip : $name);

	if ($app eq 'slapd' || $app eq 'master') {next;}

	if ($host eq "") { next;}
	my $qid = undef;

	if ($app =~ /^postfix/ && $msg =~ /^(\S{8,12}): /) {
		$qid = $1;
	} 

	if ($msg =~ /info: ([^,]+), STATUS: (\S+): (\S+): (Running|Stopped).*$/) {
		my $tm = $1;
		my $hostname = $2;
		my $service = $3;
		my $status = ($4 eq "Running")?1:0;
		my $statement = "delete from service_status ".
			"where server=\'".$hostname."\' and service=\'".$service."\'";

		my $dsth = $dbh->prepare($statement);

		#print "Executing $statement with @args\n\n";

		eval {
			if (!$dsth->execute() ) {
				warn $dsth->errstr;
				next;
			}
		};


		eval {
			$s_sth->execute($hostname, $service, $tm, $status, $host);
		};

		next;
	}

	eval {
		if (!$sth->execute(logdate_to_sqldate($log_date), $host, 
			$app, $pid, $msg, $qid) ) {
			($DEBUG) && print FOO localtime(),
				" zmlogger insert failed: ",$sth->errstr,"\n";
		} else {
            		#($DEBUG) && print FOO localtime(),
                	#" zmlogger insert completed: $host $app $pid $msg $qid\n";
        	}   

	};
	if ($@) {
		print "Error inserting $log_date, $host, $app, $pid, $msg\n";
		print "From $_\n";
		print $sth->errstr,"\n";
		print "$@\n";
	}

}
($DEBUG) && close FOO;

sub isSqlRunning {
  `logmysqladmin status > /dev/null 2>&1`;
  return(($? == 0) ? 1 : 0);
}

sub bye {
	($DEBUG) && close FOO;
	exit (0);
}

