#!/usr/bin/perl  -I/opt/ep2stable/perl_lib

######################################################################
#
#  This file is part of EPrints 2.
#  
#  Copyright (c) 2000,2001,2002 University of Southampton, UK. SO17 1BJ.
#  
#  EPrints 2 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.
#  
#  EPrints 2 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 EPrints 2; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
######################################################################


=pod

=head1 NAME

B<indexer> - ???

=head1 SYNOPSIS

B<indexer> start [B<options>] 

B<indexer> stop [B<options>] 

B<indexer> status [B<options>] 

=head1 DESCRIPTION

???

=over 8

=item B<archiveid> 

The ID of the eprint archive to rehash the documents of.

=back

=head1 OPTIONS

=over 8

=item B<--help>

Print a brief help message and exit.

=item B<--man>

Print the full manual page and then exit.

=item B<--quiet>

Be vewwy vewwy quiet. This option will supress all output unless an error occurs.

=item B<--force>

Start up, even if the PID file exists (implying another copy is running). This
is useful for starting after a crash, but be carefully not to run to copies at
once as BAD THINGS will happen.

=item B<--verbose>

Explain in detail what is going on.
May be repeated for greater effect.

=item B<--version>

Output version information and exit.

=back   

=head1 AUTHOR

This is part of this EPrints 2 system. EPrints 2 is developed by Christopher Gutteridge.

=head1 VERSION

EPrints Version: 2.3.2

=head1 CONTACT

For more information goto B<http://www.eprints.org/> which give information on mailing lists and the like.

Chris Gutteridge may be contacted at B<support@eprints.org>

Should you need a real world address for some reason, EPrints can be contacted in the real world at

 EPrints c/o Christopher Gutteridge
 Department of Electronics and Computer Science
 University of Southampton
 SO17 1BJ
 United Kingdom

=head1 COPYRIGHT

This file is part of EPrints 2.

Copyright (c) 2000,2001,2002 University of Southampton, UK. SO17 1BJ.

EPrints 2 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.

EPrints 2 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 EPrints 2; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

=cut

use EPrints::Session;
use EPrints::EPrint;
use EPrints::Config;
use EPrints::Index;

use strict;
use Getopt::Long;
use Pod::Usage;

my $version = 0;
my $verbose = 0;
my $quiet = 0;
my $help = 0;
my $man = 0;
my $force = 0;

GetOptions( 
	'help|?' => \$help,
	'man' => \$man,
	'version' => \$version,
	'verbose+' => \$verbose,
	'silent' => \$quiet,
	'force' => \$force,
	'quiet' => \$quiet
) || pod2usage( 2 );
EPrints::Utils::cmd_version( "indexer" ) if $version;
pod2usage( 1 ) if $help;
pod2usage( -exitstatus => 0, -verbose => 2 ) if $man;
pod2usage( 2 ) if( scalar @ARGV != 1 );
pod2usage( 2 ) if( $ARGV[0] ne "start" && $ARGV[0] ne "stop" && $ARGV[0] ne "status" );

our $noise = 1;
$noise = 0 if( $quiet );
$noise = 1+$verbose if( $verbose );

my $pidfile = EPrints::Config::get("var_path")."/indexer.pid";

if( $ARGV[0] eq "status" )
{
	if( !-e $pidfile )
	{
		print "Indexer is not running\n";
		exit;
	}


	my $pid = get_pid( $pidfile, $noise );
	print "Indexer appears to be running with PID $pid\n";
	exit;
}


if( $ARGV[0] eq "stop" )
{
	if( !-e $pidfile )
	{
		print <<END;
$pidfile does not appear to exist.

Maybe something bad happend? If indexer is still running you will have to
shut it down by hand.
END
		exit 1;
	}

	my $pid = get_pid( $pidfile, $noise );

	if( !defined $pid )
	{	
		die "Could not find PID in $pidfile.  Weird. Better kill it by hand.";
	}
	
	# if "kill" is not in bin then this will cause trouble. 
	print "Sending TERM signal to $pid\n" if( $noise > 1 );
	kill 15, $pid;


	# give it 10 seconds
	my $counter = 10;
	for( 1..$counter )
	{
		if( !-e $pidfile )
		{
			print "...Killed $pid\n" if( $noise > 1 );
			exit 0;
		}
		sleep 1;
		print "tick\n" if( $noise > 2 );
	}

	print <<END;
pidfile did not disappear within $counter seconds, so something didn't 
work somewhere. Try killing process number $pid (if it exists) and 
then removing $pidfile
END

	exit;
}


#foreach my $arc_id ( EPrints::Config::get_archive_ids() )
#{
#
#	my $session  = new EPrints::Session( 1 , $arc_id , $noise );
#	if( !defined $session ) 
#	{
#		print STDERR "Error opening session: $arc_id\n";
#		exit( 1 );
#	}
#	$session->terminate;
#}

$0 = "EPrints Indexer for ".$EPrints::SystemSettings::conf->{base_path}.": Parent Process";
if( !$force && -e $pidfile )
{
	my $pid = get_pid( $pidfile, $noise );
	print <<END;

EPrints indexer appears to be running with process ID $pid. 
It may have crashed. 

To check if the process is still running (on a linux system)
use:

ps auwwx | grep EPrints

Options to "ps" vary on other systems. You may also try:

ps -ef | grep EPrints

If indexer is not already running you may either:
 * delete the PID file: $pidfile 
 * run indexer with the --force option

END
	exit 1;
}


print "Becoming a daemon. Go me.\n" if( $noise > 1 );
close STDIN;
close STDOUT;
close STDERR;
exit if fork;
exit if fork;



my $kid;

$SIG{TERM} = sub { 
	print "Unlinking $pidfile\n" if( $noise > 1 );
	unlink( $pidfile ) || die( "Can't unlink $pidfile" );
	if( defined $kid )
	{
		print "Sending TERM signal to junior: $kid\n" if( $noise > 1 );
		kill 15, $kid;
	}
	
	print "indexer snr exiting $$\n" if( $noise > 1 );
	exit;
};


open( PID, ">$pidfile" ) || die "Can't open $pidfile for writing";
print PID <<END;
# This file is automatically generated to indicate what process ID
# indexer is running as. If this file exists then indexer is assumed
# to be running.
END
print PID $$."\n";
print PID EPrints::Utils::get_timestamp()."\n";
close PID;



while( 1 ) 
{
	my @arc_ids = EPrints::Config::get_archive_ids();
	foreach my $arc_id ( sort @arc_ids )
	{

		# nb. using load_archive_config not get_archive_config. This
		# reloads the XML file each time round.
        	my $archive_config = EPrints::Config::load_archive_config( $arc_id );

		# Don't index things which don't want to be index
		if( !$archive_config->{index} )
		{
			# sleep for a little while so we don't hammer the machine
			# if there are lots of non-indexing archives, or even
			# no indexing archives for a while.
			sleep 60;
			next;
		}

		print "\n.$$.. - START.outer\n" if( $noise > 1);
		$kid = fork();
		my $cmd = "/usr/bin/renice 8 $$";	
		`$cmd`;
		if( $kid == 0 )
		{
			my $index;
			my $session;
			$SIG{TERM} = sub { 
				print "indexer jnr exiting $$\n" if( $noise > 1 );
				$index->cleanup if( defined $index );
				$session->terminate if( defined $session );
				exit;
			};
			print "\n.$$.. - START.inner\n" if( $noise > 1);
			$session = new EPrints::Session( 1 , $arc_id , $noise );

			my @ds_ids = &EPrints::DataSet::get_sql_dataset_ids;
			foreach my $ds_id ( sort @ds_ids )
			{
				print "dataset: $arc_id .. $ds_id\n" if( $noise > 1);
				$0 = "EPrints Indexer for ".$EPrints::SystemSettings::conf->{base_path}.": $arc_id/$ds_id";
				if( !defined $session ) 
				{
					print STDERR "Error opening session: $arc_id\n";
					exit( 1 );
				}
				$index = new EPrints::Index( 
						$session, 
						$session->get_archive->get_dataset( $ds_id ) );
				$index->change_pname( 1 );
				$index->create;
				$index->build;
				$index->install;
				$index->cleanup;
				undef $index;
			}


			$session->terminate;
			print "\n.$$.. - END.inner\n" if( $noise > 1 );
			exit;
		}
		wait; 
		undef $kid;
		sleep 5;
		print "\n.$$.. - END.outer\n" if( $noise > 1 );
	}
}


sub get_pid
{
	my( $pidfile, $noise ) = @_;

	print "Reading $pidfile\n" if( $noise > 1 );
	open( PID, $pidfile ) || die( "Could not open $pidfile" );
	my $pid;
	while( <PID> )
	{
		chomp;
		if( m/^\d+$/ )
		{
			$pid = $_;
			last;
		}
	}
	close PID;

	return $pid;
}
