# Copyright 1999-2016. Parallels IP Holdings GmbH. All Rights Reserved.
package Storage::FileStorage;

use strict;
use bigint;

use Storage::Storage;
use Logging;
use AgentConfig;
use HelpFuncs;

use POSIX;
use IPC::Run;
use Symbol;
use File::Copy;

use Storage::Splitter;
use Storage::Counter;

use vars qw|@ISA|;

@ISA = qw|Storage::Storage|;

sub _init {
  my ($self, %options) = @_;

  $self->SUPER::_init(%options);
  $self->{split_size} = $options{split_size};
  $self->{gzip_bundle} = $options{gzip_bundle};
  $self->{output_dir} = $options{output_dir};
  $self->{space_reserved} = $options{space_reserved} if $options{space_reserved};
  $self->{sign} = 1 if $options{sign};

  $self->{last_used_id} = 0;

  $self->{unpacked_size} = 0;
  $self->{packed_size} = 0;

  Logging::debug("-" x 60);
  Logging::debug("FILE storage initialized.");
  Logging::debug("Base directory: $self->{output_dir}");
  Logging::debug("Space reserved: $self->{space_reserved}");
  Logging::debug("Gzip bundles: " . ($self->{gzip_bundle} ? "yes" : "no"));
  Logging::debug("Bundle split size: " . ($self->{split_size} || "do not split"));
  Logging::debug("-" x 60);
  $self->reserveSpace();
}

sub getFullOutputPath{
 my $self = shift;
 return "$self->{output_dir}";
}

sub createRepositoryIndex{
  my ( $self, $index ) = @_;
  if( $index ){
    Logging::debug("Create repository index: $index");
    my $destDir = "$self->{output_dir}/.discovered";
    system("mkdir", "-p", "$destDir") if not -e $destDir;
    open INDEXFILE, "> $destDir/$index";
    close INDEXFILE;
  }
}

sub writeDiscovered{
  my $self = shift;

  $self->_writeDiscovered(@_);
}

sub moveFileToDiscovered {
  my ($self, $srcPath, $newName, $dumpDirPath, $dumpXmlName) = @_;
  
  my $destDir = $self->getFullOutputPath();
  $destDir .= "/".$dumpDirPath if ($dumpDirPath);
  $destDir .= "/.discovered/$dumpXmlName";
  
  if (not -e $destDir) {
    Logging::debug("Create discovered: $destDir");
    system("mkdir", "-p", "$destDir");
  }
  
  my $destPath = $destDir."/".$newName;
  
  move($srcPath, $destPath);
}

sub addTar {
  my ($self, $proposedId, %options) = @_;

  return unless -d $options{'directory'};

  if (defined $options{'checkEmptyDir'} ||
     !exists $options{'include'} && !exists $options{'add_file'} && !exists $options{'include_hidden_files'} # don`t run tar ... * in empty dir
  ) {
    return unless $self->checkDirForArchive($options{'directory'}, $options{'exclude'}, $options{'include_hidden_files'});
  }

  if ($self->{collectStatistics})
  {
    $self->{stopWatch}->createMarker("pack");
  }

  my ($destDir, $destFile, $id) = $self->getFileNameIdFromId( $proposedId, $self->getDefExtension(), 1 );
  Logging::debug("Tar bundle. id=$id, destFile=$destDir/$destFile");

  my $bundle = Storage::Bundle::createTarBundle(%options, 'gzip' => $self->{gzip_bundle});

  unless ($bundle)
  {
    if ($self->{collectStatistics})
    {
      $self->{statistics}->{packTime} += $self->{stopWatch}->getDiff("pack");
      $self->{stopWatch}->releaseMarker("pack");
    }
    return;
  }
  my $size = 0;
  my $files = $self->executeAndSave($destDir, $destFile, $self->getDefExtension(), $bundle, \$size);
  my $ret =  $self->regIdFiles( $id, $destDir, $size, $files );
  if ($self->{collectStatistics})
  {
    $self->{statistics}->{packTime} += $self->{stopWatch}->getDiff("pack");
    $self->{stopWatch}->releaseMarker("pack");
  }

  return $ret;
}

sub CleanupFiles()
{
  my $self = shift;
  my $pid;
  while( ( $pid = wait() ) !=-1 ){
    Logging::debug("The child process '$pid' has been terminated" );
  }
  my $path = $self->getFullOutputPath();
  my @files = $self->getDumpFiles();
  foreach my $file(@files ){
     Logging::debug("Remove file '$file' from repository '$path' ");
     unlink "$path/$file" or Logging::debug("Cannot remove file '$path/$file'");
  }
  if( exists $self->{discovered} ){
    foreach my $discovered(@{$self->{discovered}} ){
       Logging::debug("Remove discovered '$discovered'");
       opendir DIR, $discovered;
       my @dirfiles = readdir( DIR );
       closedir DIR;
       foreach my $file(@dirfiles){
         if( $file ne '.' and $file ne '..' ){
           unlink "$discovered/$file" or Logging::debug("Cannot remove file '$discovered/$file'");
         }
       }
       rmdir( $discovered ) or Logging::debug("Cannot remove discovered '$discovered'");
    }
  }
}

1;

# Local Variables:
# mode: cperl
# cperl-indent-level: 2
# indent-tabs-mode: nil
# tab-width: 4
# End:
