auto_adjust_mem.pm 15.3 KB
#!/usr/bin/perl
#
#  Copyright Statement:
#  --------------------
#  This software is protected by Copyright and the information contained
#  herein is confidential. The software may not be copied and the information
#  contained herein may not be used or disclosed except with the written
#  permission of MediaTek Inc. (C) 2006
#
#  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
#  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
#  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
#  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
#  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
#  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
#  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
#  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
#  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
#  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
#
#  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
#  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
#  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
#  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
#  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
#
#  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
#  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
#  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
#  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
#  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
#
#*****************************************************************************
#*
#* Filename:
#* ---------
#*   auto_adjust_mem.pm
#*
#* Project:
#* --------
#*
#*
#* Description:
#* ------------
#*   This module collects the subroutines for common utility. 
#*       
#*
#* Author:
#* -------
#*   Qmei Yang (mtk03726)
#*
#****************************************************************************/

#****************************************************************************
# Included Modules
#****************************************************************************
use strict;
#****************************************************************************
# Constants
#****************************************************************************
my $AAPMC_VERNO  = " V0.05";
                  #  v0.05, 20130206 by Carina, add one error code to support FS AAPMC
                  #  v0.04, 20120521 by mei, add one error code to support BL AAPMC
                  #  v0.02, 20120425 by mei, add one error code
                  #  v0.01, initial version

return 1;

#****************************************************************************
# Package :  ERR
#****************************************************************************
package ERR;
use constant NO_MODIFY        => 0;
use constant MODIFY_SUCCESS   => 1;
use constant CANNOT_ADJUST    => 2;
use constant AAPMCLOG_SUCCESS => 3;
use constant AUTOCONFIG_SELF_MODIFY_SUCCESS => 4;
use constant NO_NEED_TO_UPDATE => 5;
use constant NO_MORE_SPACE => 6;

use constant ERR_MODIFYFAIL   => 101;
use constant ERR_UNEXPECTED   => 102; #default exit
use constant ERR_MODIFYDUPLICATED => 103;


#****************************************************************************
# Package :  AUTO_ADJUST
#****************************************************************************
package AUTO_ADJUST;
#****************************************************************************
# subroutine:  AUTO_ADJUST::ChangeDefineValue
#              aim to change #define value
# input:       $strFilePath: file path
#              %ChangeListHash={$strName, $strValue}
#              After changing, it should look like: #define $strName $strValue
# output:      $bModified: ERR::NO_MODIFY= no change, ERR::MODIFY_SUCCESS=modified
# SampleCode: 
#    my %ChangeList;
#    $ChangeList{'name1'} = "value1";
#    $ChangeList{'name2'} = "value2";
#    &AUTO_ADJUST::ChangeDefineValue($CUSTOM_FEATURE_CONFIG_H, \%ChangeList);
# or &AUTO_ADJUST::ChangeDefineValue($CUSTOM_FEATURE_CONFIG_H, {'name1'=>'value1',});
#****************************************************************************
sub ChangeDefineValue
{
    my ($strFilePath, $ChangeListHash_href) = @_;
    open (FILE_HANDLE, $strFilePath) or &autoadjust_die("Cannot open $strFilePath\n", __FILE__, __LINE__);
    my $reading = "";
    my $bModified = ERR::ERR_MODIFYFAIL;
    
    while (<FILE_HANDLE>) 
    {
        my $strLine = $_;
        foreach my $strName (keys %$ChangeListHash_href)
        {
            my $strValue = $ChangeListHash_href->{$strName};
            if($strLine =~ /^#define\s+($strName)\s+(\S+)/ or 
               $strLine =~ /\/\/\s*#define\s+($strName)\s+/ or 
               $strLine =~ /\/\/\s*#define\s+($strName)$/)
            {
              next if(hex($strValue) == hex($2));
              $strLine = "#define $strName $strValue\n";
              $bModified = ERR::MODIFY_SUCCESS;
            }
        }
        $reading .= $strLine;
    }
    close FILE_HANDLE;
    
    open (FILE_HANDLE, ">$strFilePath") or &autoadjust_die("Cannot open $strFilePath\n", __FILE__, __LINE__);
    print FILE_HANDLE $reading;
    close FILE_HANDLE;
    #print $bModified == 0 ? "No change\n" : "Modified\n";
    return $bModified;
}


#****************************************************************************
# subroutine:  AUTO_ADJUST::ModifyByChangeRecord
# input:       $strFolderPath: folder path before mcu\
#              Reference of @ChangeRecord = [$strFilePath, %ChangeListHash, %P4Info]
#              $bNeedBackup: 0=no need backup, 1=need backup
# output:      $err: ERR::NO_MODIFY= no change, ERR::MODIFY_SUCCESS=modified
# Note:        Backup the file before modifying. If no change, delete backup file.
#              Backup file name=File.beforeAutoAdj.timestamp.[rand=3 digits]
#              eg. ABC.h.beforeAutoAdj.1322408801.282
#****************************************************************************
use File::Copy;
sub ModifyByChangeRecord
{
    my ($strFolderPath, $ChangeRecord_ref, $bNeedBackup) = @_;
    $strFolderPath.= "\\" if($strFolderPath !~ /\\$/);
    my $filepath = $strFolderPath . $ChangeRecord_ref->[0];
    my $BackupPath = $filepath.".beforeAutoAdj".&AAPMCLogParser::GetTimeStamp();
    copy($filepath, $BackupPath) if ($bNeedBackup ==1);
    my $err = &ChangeDefineValue($filepath, $ChangeRecord_ref->[1]);
    unlink $BackupPath if($bNeedBackup ==1 and $err == ERR::NO_MODIFY);
    return $err;
}

#****************************************************************************
# subroutine:  AUTO_ADJUST::CreateP4InfoTemplate
# input:       $strOwner_ID: P4 ID
#              $strProject:  Project Name
#              $strPurpose:  CR Purpose
#              $strAdjustmentResult: Change List
# output:      Reference of %P4Info
#****************************************************************************
sub CreateP4InfoTemplate
{
    my ($strOwner_ID, $strProject, $strPurpose, $strAdjustmentResult) = @_;
    my %P4Info = ( "OWNER_ID" => $strOwner_ID,
                   "CR_DESCRIPTION" => "[$strProject]$strPurpose\n$strAdjustmentResult" );
    return \%P4Info;
}
#****************************************************************************
# subroutine:  AUTO_ADJUST::GetP4Info
# input:       Reference of %P4Info
# output:      $strOwner_ID: P4 Owner ID
#              $strCR_Description: CR description for 1 modification
#****************************************************************************
sub GetP4Info
{
    my ($P4Info_ref) = @_;
    my ($strOwner_ID, $strCR_Description);
    if($P4Info_ref)
    {
        $strOwner_ID       = $P4Info_ref->{OWNER_ID};
        $strCR_Description = $P4Info_ref->{CR_DESCRIPTION};
    }
    return ($strOwner_ID, $strCR_Description);
}

#****************************************************************************
# subroutine:  error_handler
# input:       $error_msg:     error message
#****************************************************************************
sub error_handler
{
    my ($error_msg, $file, $line_no, $strTitle) = @_;
       
    my $final_error_msg = "$strTitle ERROR: $error_msg at $file line $line_no : $!\n";
    print $final_error_msg;
    die $final_error_msg;
}
sub autoadjust_die
{
    my ($error_msg, $file, $line_no) = @_;
    &error_handler($error_msg, $file, $line_no, 'AUTO ADJUST MEM');
}


#****************************************************************************
# Package :  AAPMCLogParser
#****************************************************************************
package AAPMCLogParser;
use Storable qw/lock_retrieve lock_nstore/;

my $g_FileArchieve = undef;
my $g_DBInfo_ref   = undef; # %DBInfoTable

#****************************************************************************
# subroutine:  AAPMCLogParser::Open
# input:       $strLogPath: AAPMC.log's path
# output:      $err: ERR::ERR_UNEXPECTED=  Load failed
#                    ERR::AAPMCLOG_SUCCESS=Load successfully
#****************************************************************************
sub Open
{
    my ($strLogPath) = @_;
    my $err = ERR::ERR_UNEXPECTED;
    if(!-e $strLogPath)
    {
        my %Empty = ('AAPMCLog' => ());
        lock_nstore \%Empty, $strLogPath;
    }
    my $g_FileArchieve = lock_retrieve $strLogPath;
    if($g_FileArchieve)
    {
        $g_DBInfo_ref = $g_FileArchieve->{'AAPMCLog'};
        $err = ERR::AAPMCLOG_SUCCESS;
    }
    return $err;
}
#****************************************************************************
# subroutine:  AAPMCLogParser::Close
# input:       $strLogPath: AAPMC.log's path
# output:      $err: ERR::ERR_UNEXPECTED=  Load failed
#                    ERR::AAPMCLOG_SUCCESS=Load successfully
#****************************************************************************
sub Close
{
    my ($strLogPath) = @_;
    my $err = ERR::ERR_UNEXPECTED;
    if(-e $strLogPath)
    {
        my %Temp = ('AAPMCLog' => $g_DBInfo_ref);
        lock_nstore \%Temp, $strLogPath;
        $err = ERR::AAPMCLOG_SUCCESS;
    }
    return $err;
}
#****************************************************************************
# subroutine:  AAPMCLogParser::AddOneChangeRecord
# input:       $ChangeFilePath: The file is going to be modified. (store its path by mcu\... without folder information)
#              $ChangeList_ref: Reference of %ChangeListHash={$strName, $strValue}
#              $P4Info_ref: Reference of %P4Info = {$OwnerID, $CR_Description} => You can create by &AUTO_ADJUST::CreateP4InfoTemplate
# output:      $err: ERR::ERR_MODIFYDUPLICATED : Can't add the same key ChangeList more than twice
#                    ERR::AAPMCLOG_SUCCESS     : Add successfully
#****************************************************************************
sub AddOneChangeRecord
{
    my ($ChangeFilePath, $ChangeList_ref, $P4Info_ref) = @_;
    my $err = ERR::ERR_UNEXPECTED;
    #Trim the string before mcu\ in which mcu should be the last mcu
    if($ChangeFilePath =~ /\S+(mcu\S+)/)
    {
        $ChangeFilePath = $1;
    }
    if(0 == &isModified($ChangeFilePath, $ChangeList_ref))
    {
        #Key=TimeStamp, Value=0: $ChangeFilePath
        #                     1: %ChangeList
        #                     2: %P4Info
        $g_DBInfo_ref->{&GetTimeStamp()} = [ $ChangeFilePath, $ChangeList_ref, \%$P4Info_ref ];
        $err = ERR::AAPMCLOG_SUCCESS;
    }
    else
    {
        $err = ERR::ERR_MODIFYDUPLICATED;
    }
    return $err;
}
#****************************************************************************
# subroutine: AAPMCLogParser::isModified : Called by AddOneChangeRecord()
# input:      $strChangeFilePath: The file is going to be modified. (store its path by mcu\... without folder information)
#             $ChangeList_ref: Reference of %ChangeListHash={$strName, $strValue}
# output:     $isModified: 0=never modified before, 1= it has been modified
# comment: in the same file, if ChangeList's option existed, then return duplicated modification.
#****************************************************************************
sub isModified
{
    my ($strChangeFilePath, $ChangeList_ref) = @_;
    my $isModified = 0; # 0=no, 1=yes;
    if($g_DBInfo_ref)
    {
        while (my ($timestamp, $aChange) = each (%$g_DBInfo_ref))
        {
            if(($aChange->[0] eq $strChangeFilePath))
            {
                foreach my $option (keys %$ChangeList_ref)
                {
                    if(exists $aChange->[1]{$option})
                    {
                        $isModified = 1;
                        last;
                    }
                }
            }
        }
    }
    #print $isModified==0 ? "never modified\n" : "has been modified\n";
    return $isModified;
}
#****************************************************************************
# subroutine:  AAPMCLogParser::GetAllRecordsIndex
# input:       x
# output:      $err: ERR::ERR_UNEXPECTED: no records in DBInfo.
#                    ERR::AAPMCLOG_SUCCESS
#              Reference of @ChangeRecords: an array of all timestamps 
#****************************************************************************
sub GetAllRecordsIndex
{
    my @ChangeRecords;
    my $err = ERR::ERR_UNEXPECTED;
    if($g_DBInfo_ref)
    {
       map {push (@ChangeRecords, $_);} keys %$g_DBInfo_ref;
       $err = ERR::AAPMCLOG_SUCCESS;
    }
    return ($err, \@ChangeRecords);
}


#****************************************************************************
# subroutine:  AAPMCLogParser::GetByIndex
# input:       $Index: timestamp
#              $Type: AAPMCLogParser::FILEPATH
#                     AAPMCLogParser::CHANGELIST
#                     AAPMCLogParser::P4Info
#                     AAPMCLogParser::RECORD 
# output:   1. $err=ERR::ERR_UNEXPECTED=no data in DBInfo
#                   ERR::AAPMCLOG_SUCCESS
#           2. if $Type=AAPMCLogParser::FILEPATH,   return strChangeFilePath
#                 $Type=AAPMCLogParser::CHANGELIST, return Reference of %ChangeList
#                 $Type=AAPMCLogParser::P4INFO,     return Reference of %P4Info, 
#                                                   you may use AUTO_ADJUST::GetP4Info to get P4Info
#                 $Type=AAPMCLogParser::RECORD,     return Reference of %ChangeRecord
#                 else, return undef with ERR::ERR_UNEXPECTED
#****************************************************************************
use constant FILEPATH      => 0;
use constant CHANGELIST    => 1;
use constant P4INFO        => 2;
use constant RECORD        => 3;
sub GetByIndex
{
    my ($Index, $Type) = @_;
    if($g_DBInfo_ref)
    {
        if($Type < RECORD)
        {
            return ($g_DBInfo_ref->{$Index}[$Type]); 
        }
        elsif($Type == RECORD)
        {
            return ($g_DBInfo_ref->{$Index}); # @ChangeRecord
        }
    }
    return undef;
}

#****************************************************************************
# subroutine:  AAPMCLogParser::GetTimeStamp
# input:       x
# output:      string of timestamp with rand(1000)
#              eg. 1322408801.282
#****************************************************************************
sub GetTimeStamp
{
    return time().".".int(rand(1000));
}