#! /usr/bin/perl -w

use strict;

use lib '/usr/share/perl5';

use Locale::TextDomain qw/lire/;

use Lire::Program;
use Lire::Logger;
use Lire::DlfStore;
use Lire::DlfSchema;
use Lire::DlfConverterProcess;
use Lire::DlfConverterManager;
use Lire::ImportJob;
use Lire::Config::Build qw/ac_info/;
use File::Path 'rmtree';
use File::Copy;

sub lr_store_create {
    my $store_path = $_[0];

    lr_err( __( "missing 'store' argument\n" ),
            __( "Usage: lr_store create <store>\n" ) )
      unless defined $store_path;

    lr_err( __x( "directory {store_path} already exists",
                 'store_path' => $store_path ) )
      if -d $store_path;

    eval {
        my $store = Lire::DlfStore->open( $store_path, 1 );
        $store->close();
    };
    lr_err( $@ ) if $@;
}

sub lr_store_delete {
    my $store_path = $_[0];

    lr_err( __( "missing 'store' argument\n" ),
            __( "Usage: lr_store delete <store>\n" ) )
      unless defined $store_path;

    lr_err( __x( 'No such store: {store_path}',
                 'store_path' => $store_path ) )
      unless -d $store_path;

    rmtree( [ $store_path ], 0, 0 );
}

sub lr_store_help {
    lr_notice( __x( "Usage: {prog} <command> <arguments>
Available commands:

   --version or -v
       print version of Lire.

   --help or -h
      this help message.

   create <store>
      create a new empty DLF store.

   delete <store>
      delete a DLF store.

   list_dlf <store>
      list the available DLF streams in the DLF store.

   export_dlf <store> <dlf_stream>
      export the DLF stream <dlf_stream> in Lire 1.2.1 DLF format on STDOUT.

   import_log <store> <converter> [<logfile]
      import logfile in the DLF store using <converter> as DLF converter.
      This also outputs the conversion stats as shell variables.

", 'prog' => $Lire::Program::PROG ) );
}

sub lr_store_version {
    lr_notice( __x( "{prog} shipped with Lire {version}",
                    'prog' => $Lire::Program::PROG,
                    'version' => ac_info( 'VERSION') ) );
    exit 0;
}

sub lr_store_import_log {
    my ( $store_path, $converter, $log_file) = @_;

    lr_err( __( "missing 'store' argument\n" ),
            __("Usage: lr_store import_log <store> <converter> [<logfile>]\n"))
      unless defined $store_path;

    lr_err( __( "missing 'converter' argument\n" ),
            __("Usage: lr_store import_log <store> <converter> [<logfile>]\n"))
      unless defined $converter;

    $log_file = "-" unless defined $log_file;

    eval {
        Lire::DlfConverterManager->instance->register_default_converters();
        die( __x( "There is no DLF converter registered under the name '{converter}'
Use lr_check_service -l to obtain the list of registered DLF converters",
                  'converter' => $converter ) )
          unless defined Lire::DlfConverterManager->instance->get_converter( $converter );

        my $src = new Lire::ImportJob( "lr_store",
                                       pattern => $log_file,
                                       period => 'unique',
                                       converter => $converter );
        my $store = Lire::DlfStore->open( $store_path, 0 );
        my $process = new Lire::DlfConverterProcess( $src, $store );
        $process->run_import_job();
        print "lr_import_line_count=", $process->line_count(), "\n",
              "lr_import_dlf_count=", $process->dlf_count(), "\n",
              "lr_import_error_count=", $process->error_count(), "\n",
              "lr_import_saved_count=", $process->saved_count(), "\n",
              "lr_import_ignored_count=", $process->ignored_count(), "\n";
        $store->close();
    };
    lr_err( $@ ) if $@;
}

sub lr_store_list_dlf {
    my $store_path = $_[0];

    lr_err( __( "missing 'store' argument\n" ),
            __( "Usage: lr_store list_dlf <store>\n" ) )
      unless defined $store_path;

    eval {
        my $store = Lire::DlfStore->open( $store_path );
        print join( "\n", $store->dlf_streams ), "\n";
        $store->close();
    };
    lr_err( $@ ) if $@;
}

sub lr_store_export_dlf {
    my ( $store_path, $dlf_stream ) = @_;

    lr_err( __( "missing 'store' argument\n" ),
            __( "Usage: lr_store export_dlf <store> <dlf_stream>" ) )
      unless defined $store_path;

    lr_err( __( "missing 'dlf_stream' argument\n" ),
            __( "Usage: lr_store export_dlf <store> <dlf_stream>" ) )
      unless defined $dlf_stream;

    my $store = eval { Lire::DlfStore->open( $store_path ) };
    lr_err( $@ ) if $@;
    unless ( $store->has_dlf_stream( $dlf_stream ) ) {
        $store->close();
        lr_err( __x( 
"no DLF stream '{dlf_stream}' in the store.
Use lr_store list_dlf to find the available DLF streams.\n",
                    'dlf_stream' => $dlf_stream ) );
    }

    eval {
        my $stream = $store->open_dlf_stream( $dlf_stream, "r" );
        while (my $dlf = $stream->read_dlf_aref ) {
            print aref2old_dlf( $dlf ), "\n";
        }
        $stream->close();
        $store->close();
    };
    lr_err( $@ ) if $@;
}

sub aref2old_dlf {
    my $aref_dlf = $_[0];
    my @dlf = ();
    foreach my $field ( @$aref_dlf ) {
        if ( defined $field ) {
            Lire::DlfSchema::ascii_dlf_escape_field( $field );
        } else {
            $field = "LIRE_NOTAVAIL";
        }
        push @dlf, $field;
    }

    return join( " ", @dlf );
}

sub lr_unknown  {
    my $cmd = $_[0];

    lr_err( __x( "Unknown command: '{cmd}'.\n", 'cmd' => $cmd ),
            __( "Use lr_store --help for the list of known commands.\n" ) );
}

if ( @ARGV < 1 ) {
    lr_err( __( "Missing 'command' argument.\n" ),
            __( "Use lr_store --help for the list of known commands.\n" ) );
}

my $cmd = shift @ARGV;
my %commands =
  (
   "--help" => \&lr_store_help,
   "--version" => \&lr_store_version,
   "-h" => \&lr_store_help,
   "-v" => \&lr_store_version,
   "create" => \&lr_store_create,
   "delete" => \&lr_store_delete,
   "export_dlf" => \&lr_store_export_dlf,
   "import_log" => \&lr_store_import_log,
   "list_dlf" => \&lr_store_list_dlf,
  );

if ( exists $commands{$cmd} ) {
    $commands{$cmd}->( @ARGV );
} else {
    lr_unknown( $cmd );
}

exit 0;

__END__

=pod

=head1 NAME

lr_store - Command line interface to Lire DLF stores.

=head1 SYNOPSIS

B<lr_store> B<--version>|B<-v>

B<lr_store> B<--help>|B<-h>

B<lr_store> B<create> I<store>

B<lr_store> B<delete> I<store>

B<lr_store> B<export_dlf> I<store> I<dlf_stream>

B<lr_store> B<list_dlf> I<store>

B<lr_store> B<import_log> I<store> I<converter> [I<logfile>]

=head1 DESCRIPTION

B<lr_store> operates on Lire DLF stores. A DLF store is a directory
which is used to archive log data in the DLF format as well as acting
as a general-purpose storage area for everything related to the log
analysis process.

A I<store> C</path/to/store/> could look like e.g.

 /path/to/store/continuation/lr_store
 /path/to/store/ignored/lr_store
 /path/to/store/errors/lr_store
 /path/to/store/dlf.db

.  The C<lr_store> files are typically plain ascii files.  The file C<dlf.db>
typically is a DBD::SQLite database file.

The general syntax of the command is:

B<lr_store> <command> <argument>

When a I<store> argument is needed, this is always the path to the
directory which contains the archive.

=head2 --version

B<lr_store> B<--version>
B<lr_store> B<-v>

This will log the version of Lire along which this command was
shipped.

=head2 --help

B<lr_store> B<--help>
B<lr_store> B<-h>

This will log an help message describing the various subcommands
usage.

=head2 create

B<lr_store> B<create> I<store>

This will create a new empty DLF store in directory F<store>.

=head2 delete

B<lr_store> B<delete> I<store>

This will delete the DLF store F<store>. (For the moment, this is the
equivalent of B<rm> B<-fr> B<store>.

=head2 export_dlf

B<lr_store> B<export_dlf> I<store> I<dlf_stream>

This will export on STDOUT the DLF stream I<dlf_stream> in the DLF
format used by Lire 1.2.1 and older.

=head2 list_dlf

B<lr_store> B<list_dlf> I<store>

This will print on STDOUT the names of the DLF streams available in
that store.

=head2 import_log

B<lr_store> B<import_log> I<store> I<converter> [I<logfile>]

This will import the F<logfile> in F<store> using the DLF converter named
I<converter>.

To find the list of available converters, you can use

B<lr_check_service> B<-l>

The log file will be read from STDIN when '-' is given as a filename
or when the I<logfile> argument is omitted.

After the conversion is complete, the conversion stats will output on STDOUT
as shell assigments:

  lr_import_line_count=10
  lr_import_dlf_count=10
  lr_import_ignored_count=0
  lr_import_error_count=0
  lr_import_saved_count=0

=head1 SEE ALSO

lr_log2report(1), lr_log2xml(1)

=head1 AUTHOR

Francis J. Lacoste <flacoste@logreport.org>

=head1 VERSION

$Id: lr_store.in,v 1.9 2004/03/21 17:16:51 vanbaal Exp $

=head1 COPYRIGHT

Copyright (C) 2003 Stichting LogReport Foundation LogReport@LogReport.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 (see COPYING); if not, check with
http://www.gnu.org/copyleft/gpl.html or write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.

=cut

Local Variables:
mode: cperl
End:

