#!/usr/bin/perl -w

# Copyright 2008-2014 Cumulus Systems Incorporated.
# All Rights Reserved.

# This script delete files from /usr/local/megha/db/probe/<site name>/<probe id>/work/backup directory which are older than 7 days.
# This script called by CRON job at a regular interval of 4 hours.
#
# @param : Property File Path
#
# @return : In case of success, returns 0. In case of failure, returns 1.
#
# Sample command: perl cleanupRawData.pl <Property File Path>

# It is used to use find files.
use File::Find;

# It is used to get the current date and time.
use Time::HiRes qw(gettimeofday);
use POSIX "strftime";

# It is used to indicate the path where common module is placed.
use lib "/usr/local/megha/lib/common/perl";

# It is required for logging information.
use commonLogModule;

# This variable stores the probe type.
my $probeType = "Linux";

# This variable stores commonLogModule instance.
my $logObj = "";

# Application Home directory.
my $HOME_FOLDER = "/usr/local/megha";

# This variable stores property file path.
my $propFileName = "";

# This variable stores status of function call.
my $status = 0;

# This variable stores log file path.
my $logFile = "";

# This variable stores log file handle.
my $LOG_HANDLE;

# This variable stores db/probe directory path.
my $probeDir = "";

# This variable stores path of directory from which files will be deleted.
my $backupDir = "";

# This variable stores probe unique ID.
my $probeId = "";

# Initialize the environment.
$status = init();
if (0 != $status)
{
    $logObj->error("Call to init() failed.");
    goto EXIT;
}

# Delete old files.
$status = deleteOlderFiles();
if (0 != $status)
{
    $logObj->error("Call to deleteOlderFiles() failed.");
    goto EXIT;
}

EXIT:

exit;

# This function is used to initialize the environment to run the Perl script correctly.
#
# @affected global variables :
#   $propFileName
#   $logFile
#   $probeDir
#   $backupDir
#
# @return :
#   0 if Success
#   1 if Error
sub init
{
    # This variable is used to store the return value of function calls.
    my $retVal = 0;
    
    # This variable stores Log folder path.
    my $logFolder = $baseFolder."/logs";

    # If log folder does not exist then create it.
    if (! (-e $logFolder))
    {
        mkpath($logFolder);
    }

    # Get commonLogModule instance.
    $logObj = commonLogModule->getInstance($logFolder, $probeType, $probeId);
    
    # If number of command line arguments are not correct then quit.
    if (1 != ($#ARGV + 1))
    {
        $logObj->error("Number of arguments to cleanupRawData.pl are not correct. Input argument count: [".($#ARGV + 1)."].");
        print("Example: perl cleanupRawData.pl <Property File Path>.");

        $retVal = 1;
        goto EXIT;
    }

    # Get the property file name from command line argument.
    $propFileName = $ARGV[0];

    # Read the .properties file corresponding to Linux Probe.
    $status = readPropertyFile();
    if (0 != $status)
    {
        $logObj->error("Call to readPropertyFile() failed.");

        $retVal = 1;
        goto EXIT;
    }
    
    # Update the final log message information with populated Linux probe id.
    $logObj->setProbeId($probeId);

    # Probe workspace.
    $probeDir = "$HOME_FOLDER/db/probe/$siteName/Linux_$probeId";

    # Check probe directory exist or not.
    if (! (-d $probeDir))
    {
        $logObj->error("Directory does not exist [$probeDir].");

        $retVal = 1;
        goto EXIT;
    }

    # Raw data directory.
    $backupDir = "$probeDir/backup";

    # Check backup directory exist or not.
    if (! (-d $backupDir))
    {
        $logObj->error("Directory does not exist [$backupDir].");

        $retVal = 1;
        goto EXIT;
    }

EXIT:

    return $retVal;
}

# This function is used delete the files which are older than 7 days.
#
# @affected global variables :
#    Nothing
#
# @return :
#   0 if Success
#   1 if Error
sub deleteOlderFiles
{
    # This variable is used to store the return value of function calls.
    my $retVal = 0;

    # Store file names which need to be deleted.
    my @file_list = ();

    # Number of files which should be deleted.
    my $totalFilesToDelete = 0;

    # Number of files deleted successfully.
    my $totalDeletedFiles = 0;

    # Directories to search.
    my @find_dirs = ($backupDir);

    # Get current time.
    my $now = time();

    # Days to preserve files.
    my $DAYS_FOR_PRESERVE_FILES = 7;

    # Seconds in a day.
    my $SECONDS_PER_DAY = 60 * 60 * 24;

    # Files with age greater than this age should be deleted.
    my $MIN_AGE_FOR_DELETION = $DAYS_FOR_PRESERVE_FILES * $SECONDS_PER_DAY;

    # Get the list of files to delete.
    find ( sub
    {
        my $file = $File::Find::name;

        if (-f $file)
        {
            push(@file_list, $file);
        }
    }, @find_dirs);

    # Adding 1 as $#file_list returns -1 if @file_list is empty and one less count if @file_list is not empty.
    $totalFilesToDelete = $#file_list + 1;

    # If there are no files to delete then return.
    if ($totalFilesToDelete == 0)
    {
        $logObj->info("No files to delete.");

        $retVal = 0;
        goto EXIT;
    }

    $logObj->info("Total count of files which should be deleted [$totalFilesToDelete].");

    for my $file (@file_list)
    {
        # Get statistic of the file.
        my @stats = stat($file);

        # Check modified time of each file and if it is more than 7 days then delete it.
        # $stats[9] gives last modify time in seconds since the epoch.
        if (($now - $stats[9]) > $MIN_AGE_FOR_DELETION)
        {
            if (unlink $file)
            {
                $totalDeletedFiles++;
            }
            else
            {
                $logObj->warn("Failed to delete file [$file].");
            }
        }
    }

    $logObj->info("Total files older than [$DAYS_FOR_PRESERVE_FILES] days are [$totalFilesToDelete]. Total deleted file count: [$totalDeletedFiles].");

EXIT:

    return $retVal;
}

# This function is used to read input .properties file.
#
# @affected global variables :
#   $probeId
#   $siteName
#
# @return :
#   0 if Success
#   1 if Error
sub readPropertyFile
{
    # This variable is used to store the return code for this function.
    my $retVal = 0;

    # Store Probe name.
    my $probeName = "";

    $logObj->info("Reading file: [$propFileName].");

    open(PROP_FILE, $propFileName) or die $logObj->error("Not able to open the file: [$propFileName].");

    # Loop through the content of .properties file.
    while (<PROP_FILE>)
    {
        # Remove the new line character.
        $_ =~ s/\r\n//g;
        $_ =~ s/\n//g;

        # Look for Probe name.
        if ($_ =~ /^ProbeName=(\S+)(\s*)$/)
        {
            $probeName = $1;
        }
        # Look for Site name.
        elsif ($_ =~ /^SiteName=(.+)(\s*)$/)
        {
            $siteName = $1;
        }
        else
        {
            # Current line is of no use. So ignore it.
        }
    }

    if ("" eq $probeName)
    {
        $logObj->error("Probe name is not present in the properties file.");

        $retVal = 1;
        goto EXIT;
    }

    if ("" eq $siteName)
    {
        $logObj->error("Site name is not present in the properties file.");

        $retVal = 1;
        goto EXIT;
    }

    $probeId = $probeName;

EXIT:

    close(PROP_FILE);

    return $retVal;
}