ESPPlus::Storage - An interface to ESP+ Storage repository files


ESPPlus-Storage documentation Contained in the ESPPlus-Storage distribution.

Index


Code Index:

NAME

Top

ESPPlus::Storage - An interface to ESP+ Storage repository files

SYNOPSIS

Top

  use ESPPlus::Storage;
  my $st = ESPPlus::Storage->new
      ( { filename => $Repository,
          uncompress_function => \&uncompress } );

DESCRIPTION

Top

This module provides an interface to the ESP+ Storage repository files. It allows you to read a .REP file as a series of original records. See ESPPlus::Storage::Reader::Tie for an especially easy interface for reading databases.

For an even easier interface, see ESPPlus::Storage::Reader::Tie. It wraps the interface described below and in ESPPlus::Storage::Reader and ESPPlus::Storage::Record.

CONSTRUCTOR

Top

new
 $db = ESPPlus::Storage->new( { compress_function   => \ &compress,
                                uncompress_function => \ &uncompress,
                                ( $handle ? ( handle   => $handle ) :
                                            ( filename => $filename ) )
                            } )

This is the class constructor and it takes four optional arguments, two of them contradictory. It returns a new ESPPlus::Storage object. All of the arguments are passed in data in a hash reference.

The compress_function and uncompress_function parameters both expect code references. uncompress_function is expected to accept a reference to a .Z compressed string and is expected to return a reference to an uncompressed string. This is required for reading .REP repository records.

compress_function is the exact opposite, it is needed for writing to .REP repositories, accepts a reference to uncompressed data and returns a reference to .Z compressed data.

Currently there is no LZW implementation on www.cpan.org so the current expectation is that you will write a wrapper over /usr/bin/uncompress. A sample wrapper is included farther down in the documentation.

The two parameters filename and handle are complementary. If you supply only a filename then it will be opened for you otherwise pass in an already opened handle to a .REP file via handle.

METHODS / PROPERTIES

Top

compress_function

When called without arguments it returns the ESPPlus::Storage object's stored compress_function code reference. When called with a value, it saves that as the new value.

 my $c = $db->compress_function;
 $db->compress_function( $new_c );

uncompress_function

When called without arguments it returns the ESPPlus::Storage object's stored uncompress_function code reference. When called with a value, it saves that as the new value.

 my $c = $db->uncompress_function;
 $db->uncompress_function( $new_c );

filename

When called without arguments it returns the ESPPlus::Storage object's stored filename. When called with a value, it saves that as the new value.

 my $f = $db->filename;
 $db->filename( $new_f );

handle

When called without arguments it returns a stored IO::File object if there is one. If there isn't then it attempts to open one by using filename. When called with a value it saves that as the new value.

 my $h = $db->handle;
 $db->handle( $h );

reader

This returns a ESPPlus::Storage::Reader object. This is what reads a .REP database file.

writer

This returns a ESPPlus::Storage::Writer object. This creates .REP database files.

UNCOMPRESS WRAPPER

 The following function is a sample implementation of a function suitable
 for passing into <uncompress_function>.

 our $TempFile = `mktemp /tmp/esp.XXX`;
 our $Uncompress = "/usr/bin/uncompress";
 sub uncompress {
     my $compressed = shift;

     {
         my $out = IO::File->new;
         sysopen $out, $TempFile, O_WRONLY
             or die "Couldn't open $TempFile: $!";
         flock $out, LOCK_EX
             or die "Couldn't get an exclusive lock on $TempFile: $!";
         truncate $out, 0
             or die "Couldn't truncate $TempFile: $!";
         binmode $out
             or die "Could binmode $TempFile: $!";
         print $out $$compressed
             or die "Couldnt write to $TempFile: $!";
         close $out
             or die "Couldn't close $TempFile: $!";
     }

     # add error processing as above
     my $in = IO::Handle->new;
     {
         my $sleep_count = 0;
         my $pid = open $in, "-|", $Uncompress, '-c', $TempFile
             or die "Can't exec $Uncompress: $!";
         unless (defined $pid) {
             warn "Cannot fork: $!";
             die "Bailing out" if $sleep_count++ > 6;
             sleep 10;
             redo;
         }
     }

     local $/;
     binmode $in or die "Couldn't binmode \$in: $!";
     my $uncompressed = <$in>;
     close $in or warn "$Uncompress exited $?";

     return \ $uncompressed;
 }

COPYRIGHT AND LICENSE

Top

SEE ALSO

Top

ESPPlus::Storage::Reader ESPPlus::Storage::Reader::Tie ESPPlus::Storage::Writer ESPPlus::Storage::Record


ESPPlus-Storage documentation Contained in the ESPPlus-Storage distribution.

package ESPPlus::Storage;
use 5.006;
use strict;
use warnings;
use Carp 'confess';
use IO::File ();
use ESPPlus::Storage::Util;
use ESPPlus::Storage::Record;
use ESPPlus::Storage::Reader;
use ESPPlus::Storage::Writer;

use vars qw($VERSION);

$VERSION = '0.01';

BEGIN {
    for (qw(compress_function
	    uncompress_function
	    filename)) {
	attribute_builder( $_ );
    }
}

sub new {
    my $class = shift;
    my $p = shift;
    
    my $self = bless {}, $class;
    
    for my $param (qw(compress_function
		      uncompress_function
		      filename
		      handle)) {
	next unless exists $p->{$param};
	$self->{$param} = delete $p->{$param};
    }
    
    if (%$p) {
	confess "Invalid parameters " . join(', ', sort keys %$p)
	    . " to $class->new";
    }
    
    unless ($self->{'filename'} or $self->{'handle'}) {
	confess "You must provide either a filename or filehandle to "
	    . "$class->new";
    }
    
    # Be sure to kick off the file open if necessary
    $self->handle;

    return $self;
}

sub handle {
    my $self = shift;
    
    if (@_) {
	$self->{'handle'} = shift;
    }

    unless (exists $self->{'handle'}) {
	$self->{'handle'} = IO::File->new( $self->filename, 'r' );
    }
    
    return $self->{'handle'};
}

sub reader {
    my $self = shift;
    
    my $class = "${\ref $self}::Reader";
    
    return $class->new( { uncompress_function => $self->{'uncompress_function'},
			  handle => $self->handle } );
}

sub writer {
    my $self = shift;
    my $class = "${\ref $self}::Writer";
    
    return $class->new( { compress_function => $self->{'compress_function'},
			  handle => $self->handle } );
}


1;

__END__