#!/usr/bin/perl

use strict;
use DBI;
use Getopt::Std;
#use Fcntl;

my $check_prg = 'zebraidx';
if (`ps -ef | grep -e zebra-index.tbz -e $check_prg | grep -v grep`) {
    print "[WARN] $check_prg is running.\n";
    exit 1;
}

my $scriptname = `basename $0`;
chomp $scriptname;
my $isRunning = `ps -ef | grep $scriptname | grep perl | grep -v grep | wc -l`;
chomp($isRunning);
if ($isRunning > 1) {
    print "is running...\n";
    exit 1;
}
#sleep 5;

# Fix z-index if it is bad
#system "/root/bin/zindex_fix";

# Check user
if ($ENV{'LOGNAME'} ne 'root') {
    print STDERR "$scriptname: run by $ENV{'LOGNAME'}\n";
    exit 2;
}
#/Check user

my %options = ();
getopts("s:e:m:",\%options);

my $start = $options{'s'};
my $end = $options{'e'};
my $max = $options{'m'};

#my ($start, $end) = ($ARGV[0], $ARGV[1]);
(defined $start) || ($start = -1);
(defined $end) || ($end = -1);
(defined $max) || ($max = 0);

#isWorkingHour($start, $end);

my $OPALS_CONF_DIR  = '/etc/opals/conf';

my ($code, $config, $zDir, $dir, $path, $max_rid, 
    $dbh, $sth_dir, $sth_update, $sth_max_rid, $sth_rcount);

END {
    if ($dbh) {
        $dbh->disconnect();
    }
}

my @values;
open SITECODE, "ls $OPALS_CONF_DIR | ";
while (<SITECODE>) {
    $code = $_;
    chomp $code;
    $config = loadConfig("$OPALS_CONF_DIR/$code");
    $dbh = makeConnection($config);

    $zDir = 
        $config->{'zRoot'}.'/'.
        $config->{'zPort'}.
        '/record/'.
        $config->{'zDatabase'};

    if (!$config->{'zindex'} || 
        $config->{'zindex'} !~ m/^on$/i ||
        ! -d $zDir || 
        !$dbh) {
        next;
    }

    # Z-indexing records
    print "Z-indexing database $config->{'zDatabase'}:\n";

    ($sth_dir, $sth_update, $sth_max_rid, $sth_rcount) = prepare_sth($dbh);
    $sth_dir->execute();
    my $rcount;
    while (($dir) = $sth_dir->fetchrow_array) {
        #isWorkingHour($start, $end);
        $sth_rcount->execute();
        ($rcount) = $sth_rcount->fetchrow_array;
        if ($rcount > $max && isWorkingHour($start, $end) == 1) {
            print "There are more than $max records to be indexed during working hours.\n";
            last;
        }

        $sth_max_rid->execute($dir);
        ($max_rid) = $sth_max_rid->fetchrow_array();

        zindex($config, $dir);
        $sth_update->execute($dir, $max_rid);
    }
    $sth_rcount->finish;
    $sth_dir->finish;
    $sth_update->finish;
    $sth_max_rid->finish;
    print "Done.\n";

    # Update import status
    updateImportStatus($dbh);

    $dbh->disconnect();
    $dbh = undef;
}
close SITECODE;

## Remove lock file
#close LOCK;
##unlink $lockFile;
#system("/bin/rm -f $lockFile");
##/Remove lock file

exit 0;
################################################################################


sub makeConnection {
    my ($config) = @_;
    if (!$config) {
        return;
    }
    my ($db_driver, $db_name, $db_host, $db_port, $db_user, $db_password);

    $db_driver   = $config->{'db_driver'} || 'mysql';
    $db_name     = $config->{'db_name'};
    $db_host     = $config->{'db_host'};
    $db_port     = $config->{'db_port'}   || '3306';
    $db_user     = $config->{'db_user'};
    $db_password = $config->{'db_password'};

    my $dsn = "dbi:$db_driver:$db_name:$db_host:$db_port";

    return DBI->connect($dsn, $db_user, $db_password);
}
############################################################


sub loadConfig {
    my ($configFile) = @_;
#    print "Enter the config filename of Opals: ";
#    $configFile = <STDIN>;
    my $config = {};

    open CONF, $configFile || die "Cannot open file $configFile";
    while (<CONF>) {
        chomp;
        s/#.*//;                # remove comments
        next if /^\s*$/;        # ignore blank lines

        if (/^\s*(\w+)\s*=\s*(.*?)\s*$/) {
            $config->{$1} = $2;
        }
    }
    close CONF;
    
    return $config;
}
############################################################


sub prepare_sth {
    my ($dbh) = @_;
    my $sth_dir = $dbh->prepare(<<_SQL_);
select  ceil(rid/1000) as dir
from    opl_marcRecord
where   zIndexed = 0
group by dir
_SQL_
    my $sth_update = $dbh->prepare(<<_SQL_);
update  opl_marcRecord
set     zIndexed = 1
where   ceil(rid/1000) = ?
     && rid <= ?
_SQL_
    my $sth_max_rid = $dbh->prepare(<<_SQL_);
select  max(rid) as max_rid
from    opl_marcRecord
where   zIndexed = 0
     && ceil(rid/1000) = ?
_SQL_
    my $sth_rcount = $dbh->prepare(<<_SQL_);
select  count(distinct rid) as rcount
from    opl_marcRecord
where   zIndexed = 0
_SQL_

    return ($sth_dir, $sth_update, $sth_max_rid, $sth_rcount);
}
############################################################


sub zindex {
    my ($config, $dir) = @_;
    my ($zebraidx, $zRoot, $zPort, $zDatabase, $path);
    $zebraidx  = $config->{'zebraidx'};
    $zRoot     = $config->{'zRoot'};
    $zPort     = $config->{'zPort'};
    $zDatabase = $config->{'zDatabase'};

    $zebraidx = "LANG=en_US.UTF-8 $zebraidx -c $zRoot/$zPort/zebra.cfg";
    my $zLog = "$zRoot/$zPort/log/zebraidx.log";

    $path = "$zRoot/$zPort/record/$zDatabase/$dir";
    print "\t$path\n";

    system("chown -R apache.apache $path");
    system("$zebraidx -d $zDatabase update $path >> $zLog 2>&1");
    system("$zebraidx commit >> $zLog 2>&1");
    system("find $zRoot/$zPort/register/ -type f -exec chmod 644 {} \\;");
}
############################################################


sub updateImportStatus {
    my ($dbh) = @_;

    my $sth_indexing = $dbh->prepare(<<_SQL_);
select  iid
from    opl_marcImport
where   status = 'indexing'
order by iid
_SQL_
    my $sth_checkIndex = $dbh->prepare(<<_SQL_);
select  count(*) as isIndexing
from    opl_item as i, opl_marcRecord as r
where   i.importId = ?
     && i.rid      = r.rid
     && r.zIndexed = 0
_SQL_
    my $sth_updateStatus = $dbh->prepare(<<_SQL_);
update  opl_marcImport
set     status = 'done'
where   iid = ?
_SQL_

    $sth_indexing->execute();
    my ($iid, $isIndexing);
    while (($iid) = $sth_indexing->fetchrow_array) {
        $sth_checkIndex->execute($iid);
        ($isIndexing) = $sth_checkIndex->fetchrow_array;
        if (!$isIndexing) {
            $sth_updateStatus->execute($iid);
        }
    }
    $sth_updateStatus->finish;
    $sth_checkIndex->finish;
    $sth_indexing->finish;
}
############################################################

sub isWorkingHour {
    my ($start, $end) = @_;

    my $cur_time=`date +%H`;
    if ($start && $cur_time >= $start && $cur_time < $end) {
        #print "zindex is temorarily disabled from $end:00 to $start:00", ".\n";
        #exit 1;
        return 1;
    }

    return 0;
}
