Util::ShortTermRepository (version 0.0)


package Util::ShortTermRepository;
##############################################################################
#
# DESCRIPTION: 
#
# HISTORY
# HISTORY: $Log: ShortTermRepository.pm,v $
# HISTORY: Revision 1.6  2007/11/30 16:34:22  apsop
# HISTORY: Check for existence of fetched repository file before using it.
# HISTORY:
# HISTORY: Revision 1.5  2007/06/29 15:25:21  apsop
# HISTORY: Set SEARCH_RANGE to 2.  Only wait if checksum is wrong, not if no file is found.
# HISTORY:
# HISTORY: Revision 1.4  2006/12/20 14:20:19  apsop
# HISTORY: Bug fix the previous changes.
# HISTORY:
# HISTORY: Revision 1.3  2006/12/19 15:23:37  apsop
# HISTORY: Use time indexed directories for storing repository files.
# HISTORY:
# HISTORY: Revision 1.2  2006/08/01 20:35:34  apsop
# HISTORY: Add in CVS history indicator.
# HISTORY:
# HISTORY:
#
# VERSION: 0.0
#
##############################################################################

use strict;

#########################
# constructor
#########################
sub new { #(directory)
    my $proto = shift;
    my $class = ref($proto) || $proto;

    #####################################
    # initialize some variables
    #####################################
    my $self={};
    $self->{DIR}=shift;
    $self->{FILENAME}=shift;
    $self->{FILES}={};
    $self->{WAIT}=60; 
    $self->{SEARCH_RANGE}=2;
    $self->{MAX_COUNT}=5;

    bless($self,$class);
    return $self;

} # end of constructor

#########################
# accessors
#########################

##############################################################################
#
##############################################################################
sub log {
    my $self = shift;
    return $self->{FILENAME}->log();
}

#########################
# methods
#########################

##############################################################################
#
##############################################################################
sub export {
    my $self = shift;
    my $type = shift;
    my $log = $self->log();

    my @files = @_;
    unless(@files) {
        #########################################
        # export all the files of the given type
        #########################################
        @files = $self->{FILENAME}->any($type);
    }

    ########################################
    # copy all the files to the repository
    ########################################
    my $file;
    foreach $file (@files) {
      $file =~ /_(\d+)\./;
      my $index = int($1/1000000)*1000000;
      my $dir = "$self->{DIR}/$type/$index";
      mkdir $dir;

      my $checksum = "$dir/.$file.sha1";
      unlink $checksum;
      system("sha1sum $file > $checksum");
      system("cp $file $dir");
    }

} # end of export method

##############################################################################
#
##############################################################################
sub fetch {
    my $self = shift;
    my $type = shift;
    my @args = @_;
    my $log = $self->log();

    my $filename = $self->{FILENAME};
    my $dir;

    my $file;
    my $okaysum = 0;
    my $count = 0;
    until($okaysum){
      ##############################################
      # locate the file in the repository directory
      ##############################################
      my $subdir  = int($args[2]/1000000)*1000000;
      for(my $idir = 0; $idir < $self->{SEARCH_RANGE}; $idir++){
        $dir = "$self->{DIR}/$type/" . ($subdir - 1000000*$idir);
	$filename->glob_dir($dir);
	$file = $filename->get($type, @args);

	################################################################
	# if we located the file, copy it into the working directory
	################################################################
	if($file && $self->{FILENAME}->fetch($file, $dir) && -f $file) {
      
	  my $checksum = "$dir/.$file.sha1";
	  if( -f $checksum){
	    open SUM, $checksum;
	    my $sum = (split ' ', <SUM>)[0];
	    close SUM;

	    open SUM, "sha1sum $file |";
	    my $check = (split ' ', <SUM>)[0];
	    close SUM;

	    $okaysum = 1 if $sum eq $check;
	    last;
	  }
	}
      }

      if($okaysum){
        ###########################################################
        # we got a file, so remember its name for cataloging later
        ###########################################################
        $self->remember($type, $file);
      }elsif(!$file){
	######################
	# no file, so give up
	######################
	return $file;
      }else{
	######################################################
	# Got a file, but bad checksum, so wait and try again
	######################################################
	unlink $file;
	unless($count){
	  $log->entry("Waiting for repository while fetching $file.");
	}
	last if $count++ > $self->{MAX_COUNT};
	sleep $self->{WAIT};
      }
    }

    unless($okaysum){
      $log->error(1, "Repository timeout while file fetching $file.");
    }
    return $file;
    
} # end of fetch method


##############################################################################
# store a file name and type internally so that it can be included in a catalog
# of all fetched files later.
##############################################################################
sub remember {
    my $self = shift;
    my $type = shift;
    my $file = shift;

    unless($self->{FILES}->{$type}) {
        $self->{FILES}->{$type} = {};
    }

    $self->{FILES}->{$type}->{$file} =1;

} # end of remember method


1;