#!/usr/bin/perl -w
use Date::Calc qw/ Week_of_Year /;
use File::Path;
use File::Copy;
use Time::Local;
use Storable;
use Data::Dumper;

# Initialize ---------------------------------------------------------

# Target FlyBack Directory
my $target_base		= "/storage/flyback/flyback";
# Cache Directory
my $cachedir            = "./flyback_clean_cache";

# Concatination Policy(per Day)
my $rp_pd_doUntilStoragePercent	= 70;	# unit: percent
                                        # このパーセンテージを下回るまで日単位の統合を行う
my $rp_pd_After			= 7;	# unit: day
                                        # この日にち以前のバックアップを対象とする
# Concatination Policy(per Week)
my $rp_pw_doUntilStoragePercent	= 80;	# unit: percent
                                        # このパーセンテージを下回るまで週単位の統合を行う
my $rp_pw_After			= 8;	# unit: week
                                        # この週以前のバックアップを対象とする
# Concatination Policy(per Month)
my $rp_pm_doUntilStoragePercent	= 90;	# unit: percent
                                        # このパーセンテージを下回るまで月単位の統合を行う
my $rp_pm_After			= 8;	# unit: month
                                        # この月以前のバックアップを対象とする

my $starttime = time;
my $lockfile = "$target_base/indexing_lock.txt";

my $debug = 1;			# Debug Option(Verbose Output)
				# True : 1
my %dirinfo;
my %fileinfo;
# Main ---------------------------------------------------------------

   #
   # Initiation
   #
   if($debug) {
      my $now = localtime;
      logger("Start time :\t$now\n");
      logger("Target Directory :\t$target_base\n");
   }

   if(-e $lockfile) {
      logger("Another cleaning operation is in progress.\n");
      logger("Exitting.\n");
      exit;
   }else{
      system("touch $lockfile");
   }

   #
   # Stage 1
   #
   my $storage_percent = `df -h $target_base | tail -1 | awk '{print \$5}'`; chomp($storage_percent);
   $storage_percent =~ s/\%//;
   if($storage_percent > $rp_pd_doUntilStoragePercent) {
      logger("Current Remaining capacity[" . $storage_percent . "\%] is higher than threshold[" . $rp_pd_doUntilStoragePercent . "\%] for Stage 1 concatination\n");
      logger("Do Stage 1 Concatination until threshold[$rp_pd_doUntilStoragePercent\%]\n");
      do_stage1($target_base, $cachedir, $rp_pd_doUntilStoragePercent);
   }else{
      my $str = "Current Remaining capacity[" . $storage_percent . "\%] is lower than threshold[" . $rp_pd_doUntilStoragePercent . "\%] for Stage 1 concatination\n";
      logger($str);
      unlink($lockfile);
      logger("Exitting.\n");
      exit;
   }

   #
   # Stage 2
   #
   if($storage_percent > $rp_pw_doUntilStoragePercent) {
      logger("Current Remaining capacity[" . $storage_percent . "\%] is higher than threshold[" . $rp_pw_doUntilStoragePercent . "\%] for Stage 2 concatination\n");
      logger("Do Stage 2 Concatination until threshold[$rp_pw_doUntilStoragePercent\%]\n");
      do_stage2($target_base, $cachedir, $rp_pw_doUntilStoragePercent);
   }else{
      my $str = "Current Remaining capacity[" . $storage_percent . "\%] is lower than threshold[" . $rp_pw_doUntilStoragePercent . "\%] for Stage 2 concatination\n";
      logger($str);
      logger("Exitting.\n");
      unlink($lockfile);
      exit;
   }

   #
   # Stage 3
   #
   if($storage_percent > $rp_pm_doUntilStoragePercent) {
      logger("Current Remaining capacity[" . $storage_percent . "\%] is higher than threshold[" . $rp_pm_doUntilStoragePercent . "\%] for Stage 3 concatination\n");
      logger("Do Stage 3 Concatination until threshold[$rp_pm_doUntilStoragePercent\%]\n");
      do_stage3($target_base, $cachedir, $rp_pm_doUntilStoragePercent);
   }else{
      my $str = "Current Remaining capacity[" . $storage_percent . "\%] is lower than threshold[" . $rp_pm_doUntilStoragePercent . "\%] for Stage 3 concatination\n";
      logger($str);
      logger("Exitting.\n");
      unlink($lockfile);
      exit;
   }

   #
   # Warning
   #


sub do_stage1 {
   my $target_base = $_[0];
   my $cachedir = $_[1];
   my $target_percent = $_[2];
   my @dirlist = <$target_base/*.backup>;
   @dirlist = sort(@dirlist);
   my %tgt;
   my @ar = ();
   my $dnameold = "";
   foreach my $var (@dirlist) {
      my $dname = $var;
      if($dname =~ m/\d+_\d+\.backup/) {
         $dname = $&;
	 $dname = substr($dname, 0, 8);
      }else{ print "no match\n"; }
      if($dname ne $dnameold) {
         if($dnameold ne "") {
	    @ar = ();
	 }
	 $dnameold = $dname;
      }
      push(@ar, $var);
      $tgt{$dname} = [ @ar ];
   }
   foreach my $day (sort(keys(%tgt))) {
      my $ref = $tgt{$day};
      my @rmdirs = sort(@$ref);
      my $remain = pop(@rmdirs);
      my $numrmdirs = @rmdirs;
      if($numrmdirs == 0) { next; }
      foreach my $dir(@rmdirs) {
         {
	    local $SIG{__WARN__} = sub{
              my $msg = shift;
	       unlink($lockfile);
	       die "$msg";
	    };
	    if(-d $dir) {
               rmtree($dir);
	    }
	 }
      }
      logger("   concatinate $day to $remain. removed $numrmdirs directory.\n");   
      my $storage_percent = `df -h $target_base | tail -1 | awk '{print \$5}'`; chomp($storage_percent);
      $storage_percent =~ s/\%//;
      if($storage_percent < $rp_pd_doUntilStoragePercent) {
         return;
      }

   }

   logger("Stage 1 completed.\n");

}

sub do_stage2 {
   my $target_base = $_[0];
   my $cachedir = $_[1];
   my $target_percent = $_[2];
   my @dirlist = <$target_base/*.backup>;
   @dirlist = sort(@dirlist);
   my %tgt;
   my @ar = ();
   my $dnameold = "";
   foreach my $var (@dirlist) {
      my $dname = $var;
      if($dname =~ m/\d+_\d+\.backup/) {
         $dname = $&;
         my $year =  substr($dname, 0, 4);
         my $month = substr($dname, 4, 2);
         my $day =   substr($dname, 6, 2);
         my ($w,$y) = Week_of_Year($year, $month, $day);
	 $dname = "$y$w";
      }else{ print "no match\n"; }
      if($dname ne $dnameold) {
         if($dnameold ne "") {
            @ar = ();
         }
         $dnameold = $dname;
      }
      push(@ar, $var);
      $tgt{$dname} = [ @ar ];
   }
   foreach my $week (sort(keys(%tgt))) {
      my $ref = $tgt{$week};
      my @rmdirs = sort(@$ref);
      my $remain = pop(@rmdirs);
      my $numrmdirs = @rmdirs;
      if($numrmdirs == 0) { next; }
      foreach my $dir(@rmdirs) {
         {
            local $SIG{__WARN__} = sub{
               my $msg = shift;
               die "$msg";
            };
            if(-d $dir) {
               rmtree($dir);
            }
         }
      }
      logger("   concatinate $week to $remain\. removed $numrmdirs directory.\n");   
      my $storage_percent = `df -h $target_base | tail -1 | awk '{print \$5}'`; chomp($storage_percent);
      $storage_percent =~ s/\%//;
      if($storage_percent < $rp_pw_doUntilStoragePercent) {
         return;
      }
   }
   logger("Stage 2 completed.\n");
}

sub do_stage3 {
   my $target_base = $_[0];
   my $cachedir = $_[1];
   my $target_percent = $_[2];
   my @dirlist = <$target_base/*.backup>;
   @dirlist = sort(@dirlist);
   my %tgt;
   my @ar = ();
   my $dnameold = "";
   foreach my $var (@dirlist) {
      my $dname = $var;
      if($dname =~ m/\d+_\d+\.backup/) {
         $dname = $&;
         $dname =  substr($dname, 0, 6);
      }else{ print "no match\n"; }
      if($dname ne $dnameold) {
         if($dnameold ne "") {
            @ar = ();
         }
         $dnameold = $dname;
      }
      push(@ar, $var);
      $tgt{$dname} = [ @ar ];
   }
   foreach my $month (sort(keys(%tgt))) {
      my $ref = $tgt{$month};
      my @rmdirs = sort(@$ref);
      my $remain = pop(@rmdirs);
      my $numrmdirs = @rmdirs;
      if($numrmdirs == 0) { next; }
      foreach my $dir(@rmdirs) {
         {
            local $SIG{__WARN__} = sub{
               my $msg = shift;
               die "$msg";
            };
            if(-d $dir) {
               rmtree($dir);
            }
         }
      }
      logger("   concatinate $month to $remain\. removed $numrmdirs directory.\n");   
      my $storage_percent = `df -h $target_base | tail -1 | awk '{print \$5}'`; chomp($storage_percent);
      $storage_percent =~ s/\%//;
      if($storage_percent < $rp_pm_doUntilStoragePercent) {
         return;
      }

   }
   logger("Stage 3 completed.\n");
}

sub logger {
   my $str1 = shift;
   my $pid = $$;
   my $pname = $0;
   my $now = time;
   my $elapsed = $now - $starttime;
   my $str = $pname . "[" . $pid . ", " . $elapsed . "]: " . $str1;
   system("/bin/logger $str");
   print STDOUT $str;
}
