Subversion Repositories DevTools

Rev

Blame | Last modification | View Log | RSS feed

########################################################################
# COPYRIGHT - VIX IP PTY LTD ("VIX"). ALL RIGHTS RESERVED.
#
# Module name   : rmMerge_suckRelease.pl
# Module type   : JATS Utility
# Compiler(s)   : Perl
# Environment(s): jats
#
# Description   : Extact package-version data from RM
#
# Usage         : See POD at the end of this file
#
#......................................................................#

require 5.008_002;
use strict;
use warnings;

use Pod::Usage;
use Getopt::Long;

use JatsError;
use JatsRmApi;
use JatsSystem;
use FileUtils;
use ConfigurationFile;
use File::Copy;
use DBI;
my $RM_DB;
my $VERSION = "1.0";
my $newRMCred = ['NEW', 'jdbc:oracle:thin:@auawsards002:1521:RELEASEM', 'RM_READONLY', 'Tp8WmmDKMq2Z'];

my $opt_reuse=1;
my $opt_help=0;
my $opt_verbose=0;
my $opt_debug=0;
my $opt_outfile;
my $opt_rtagId;

our %rmData;
my @keyFields = qw(PV_ID RTAG_ID PROJ_ID PKG_ID CREATOR_ID RELEASOR_ID PARENT_RTAG_ID OFFICIAL_ID BASE_VIEW_ID INSERTOR_ID RCON_ID BM_CON_ID ROOT_PV_ID VTREE_ID SDKTAG_ID GBE_ID BMCON_ID);

my %keyFields = map {$_ => 1} @keyFields;
my %keyFieldsData;


#-------------------------------------------------------------------------------
# Function        : Mainline Entry Point
#
# Description     :
#
# Inputs          :
#
my $result = GetOptions (
                "help:+"        => \$opt_help,
                "manual:3"      => \$opt_help,
                "verbose:+"     => \$opt_verbose,
                "debug:+"       => \$opt_debug,
                "reuse!"        => \$opt_reuse,
                "outfile:s"     => \$opt_outfile,
                "rtagid:i"      => \$opt_rtagId,
                );

                #
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
                #

#
#   Process help and manual options
#
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
pod2usage(-verbose => 1) if ( $opt_help == 2 );
pod2usage(-verbose => 2) if ( $opt_help > 2 );
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ( $#ARGV >= 0 );

#
#   Configure the error reporting rmMerge_process now that we have the user options
#
ErrorConfig( 'name'    =>'SUCKRELEASE',
             'verbose' => $opt_verbose,
             'debug' => $opt_debug,
            );

  
#   Generate the output filename
#
$opt_outfile = join('.', $opt_rtagId, 'releaseinfo', 'txt') unless ($opt_outfile);
my $localDataStore = $opt_outfile;
  
$ENV{GBE_RM_LOCATION} = $newRMCred->[1];
$ENV{GBE_RM_USERNAME} = $newRMCred->[2];
$ENV{GBE_RM_PASSWORD} = $newRMCred->[3];
connectRM(\$RM_DB) unless ( $RM_DB );

unless (GetRelease( $opt_rtagId)){
    Error ("Release not found for rtag_id: $opt_rtagId");
}
Message("Extacting: $opt_rtagId to $opt_outfile");

#
#   Insert some basic information
#   
$rmData{METADATA}{RTAG_ID} = $opt_rtagId;

GetTableData('RELEASE_TAGS');
GetTableData('RELEASE_CONTENT');
GetTableData('PEGGED_VERSIONS');
GetTableData('ADVISORY_RIPPLE');
GetTableData('RELEASE_CONFIG');

#
#   Have the basic data - don't know about blobs !!!!
#   Need to extract, as text, those fields that are used for linkage purposes
#   PV_IDs, PKG_IDS
#
GetXrefsUsers(qw(CREATOR_ID RELEASOR_ID OFFICIAL_ID INSERTOR_ID ));
GetXrefsPvid(qw(PV_ID ROOT_PV_ID));
#GetXrefsPkg(qw(PKG_ID));
GetXrefsRtagId(qw( RTAG_ID PARENT_RTAG_ID ));
GetXrefsProjId(qw( PROJ_ID ));
GetXrefsBaseViewId(qw( BASE_VIEW_ID ));
GetXrefsGbeId(qw(GBE_ID ));

GetXrefsIgnore(qw( RCON_ID BMCON_ID ));                 # Primary keys - ignore
GetXrefsIgnore(qw( VTREE_ID SDKTAG_ID));         # Assume these have not changed

disconnectRM(\$RM_DB);
ErrorDoExit();
saveLocalData();

my @unProcessed;
foreach my $tableName (keys %keyFieldsData) {
    foreach my $name ( keys %{$keyFieldsData{$tableName}}) {
        foreach my $key ( keys %{$keyFieldsData{$tableName}{$name}}) {
            push @unProcessed, "$tableName, $name, $key";
        }
    }
}

if (@unProcessed) {
    Error("Some the key fields have not been rmMerge_processed", @unProcessed )
}

exit 0;


#-------------------------------------------------------------------------------
# Function        : GetXrefsCommon 
#
# Description     : Common code for getting cross reference data 
#
# Inputs          : $refFields      - Ref to fields to rmMerge_process
#                   $tag           - Tag base name
#                   $sql            - Sql fragment 
#
# Returns         : 
#
sub GetXrefsCommon
{
    my ($refFields, $tag, $sql) = @_;
    my %idList;

    foreach my $name (@$refFields) {
        $rmData{XREF_MAP}{$name} = $tag;
    }

    foreach my $tableName (keys %keyFieldsData) {
        foreach my $name (@$refFields) {
            foreach my $key ( keys %{$keyFieldsData{$tableName}{$name}}) {
                $idList{ $key} = 1;
            }
        }
    }
    return unless %idList;

    #
    #   Get all the table data
    #
    my %xRef;   
    my $m_sqlstr = $sql . " in (". join(',',keys %idList) .")";
    my $data = getDataFromRm('GetXrefsCommon:'. $tag, $m_sqlstr, {dump => 0} );

    #
    #   Post rmMerge_process the data
    #
    foreach my $row ( @{$data} ){
        $xRef{$row->[0]} = $row->[1];
    }

    #
    #   Create data structures
    #
    foreach my $tableName (keys %keyFieldsData) {
        my $tName = $tableName . "_XREF";
        foreach my $name (@$refFields) {
            foreach my $key ( keys %{$keyFieldsData{$tableName}{$name}}) {
                DebugDumpData("Xref", \%xRef) unless exists $xRef{$key};
                ReportError("Cannot locate cross ref for $tableName, $name, $key") unless exists $xRef{$key} ;
                $rmData{$tName}{$tag}{$key} = $xRef{$key};
            }
            delete $keyFieldsData{$tableName}{$name};
        }
    }
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsBaseViewId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsBaseViewId
{
    GetXrefsCommon( \@_, 'VIEW_ID',"select view_id, view_name from views where view_id");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsGbeId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsGbeId
{
    GetXrefsCommon( \@_, 'GBE_ID',"select gbe_id, gbe_value from release_manager.gbe_machtype where gbe_id");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsProjId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsProjId
{
    GetXrefsCommon( \@_, 'PROJ_ID',"select proj_id, proj_name from projects where proj_id");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsRtagId 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsRtagId
{
    GetXrefsCommon( \@_, 'RTAG_ID',"select rtag_id, rtag_name from release_tags where rtag_id");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsIgnore 
#
# Description     : Ignore the cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsIgnore
{
    my (@refFields) = @_;
    foreach my $tableName (keys %keyFieldsData) {
        foreach my $name (@refFields) {
            delete $keyFieldsData{$tableName}{$name};
        }
    }
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsPkg 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsPkg
{
    GetXrefsCommon( \@_, 'PKG_ID',"select p.pkg_id, p.pkg_name from release_manager.packages p where pkg_id");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsPvid 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsPvid
{
    GetXrefsCommon( \@_, 'PV_ID',"select pv.pv_id, p.pkg_name ||'$;'|| pv.pkg_version from release_manager.packages p, release_manager.package_versions pv where p.pkg_id = pv.pkg_id and pv.pv_id");
}

#-------------------------------------------------------------------------------
# Function        : GetXrefsUsers 
#
# Description     : Get cross references to other entites     
#
# Inputs          : list of keyFieldData keys to rmMerge_process
#
# Returns         : 
#
sub GetXrefsUsers
{
    GetXrefsCommon( \@_, 'USER_ID',"select user_id, user_name from access_manager.users where user_id");
}

#-------------------------------------------------------------------------------
# Function        : GetRelease 
#
# Description     : Get Details of a Release
#
# Inputs          : rtagId
#
# Returns         : A hash of data
#
sub GetRelease
{
    my ($rtagId) = @_;

    my $m_sqlstr = "select rtag_id, rtag_name from release_tags where rtag_id = $rtagId";
    my $data = getDataFromRm('GetRelease', $m_sqlstr, {oneRow => 1});
    return $data;
}

#-------------------------------------------------------------------------------
# Function        : GetTableData 
#
# Description     : Get all data from a table for the package
#                   Its pretty dumb
#
# Inputs          : $tableName 
#
# Returns         : 
#
sub GetTableData
{
    my ($tableName) = @_;
    my (@row);
    my @names;
    Verbose ("GetTableData: $tableName");

    #
    #   Get the list of table names
    #
    my $names = GetColumnNames($tableName);
    $rmData{$tableName . '_NAMES'} = $names;

    #
    #   Scan the colums looking for key names
    #   
    my %xref;
    my $index = 0;
    foreach my $entry ( @{$names}) {
        my $fname = $entry->[0];
        if ( exists $keyFields{$fname}) {
            $xref{$index} = $fname;    
        } elsif ( $fname =~ m~_ID~ ) {
            Error("Consider $fname in $tableName");
        }
        $index++;
    }

    #
    #   Get all the table data
    #   
    my $m_sqlstr = "select * from release_manager.$tableName where rtag_id = $opt_rtagId";
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    my @data = @row;
                    escapeRowData(\@data);
                    push @{$rmData{$tableName . '_DATA'}}, \@data;

                    #
                    #   Extract key linkage fields as we go
                    #
                    while (my($index, $fname) = each %xref) {
                        my $data = $row[$index];
                        next unless defined $data;
                        next if length($data) == 0;
                        $keyFieldsData{$tableName}{$fname}{$row[$index]} = 1;
                    }
                }
            }
            $sth->finish();
        }
        else
        {
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
        }
    }
    else
    {
        Error("Prepare failure" );
    }
}

#-------------------------------------------------------------------------------
# Function        : GetColumnNames 
#
# Description     : Get Database information
#
# Inputs          : table to rmMerge_process 
#
# Returns         : Ref to an array of data
#
sub GetColumnNames
{
    my ($tableName) = @_;
    my (@row);
    my $found;
    my @names;
    Verbose ("GetColumnNames: $tableName");

    my $m_sqlstr = "select COLUMN_NAME, data_type, NULLABLE, COLUMN_ID from ALL_TAB_COLUMNS where TABLE_NAME='$tableName'";
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) )
        {
            if ( $sth->rows )
            {
                while ( @row = $sth->fetchrow_array )
                {
                    my @data = @row;
                    $names[$row[3]-1] = \@data;
#                    print join(' ', @row), "\n";
                    $found = 1;
                }
            }
            $sth->finish();
        }
        else
        {
            Error("Execute failure: $m_sqlstr", $sth->errstr() );
        }
    }
    else
    {
        Error("Prepare failure" );
    }

    Error("Internal. Table not found: $tableName") unless $found;
    return \@names;
}

#-------------------------------------------------------------------------------
# Function        : escapeRowData 
#
# Description     : Given an array of data items massage the data so that special characters
#                   can be serailaized and deserailised via perl
#                   
#                   Special chars include: tab,newline, return
#                   
#                   At the moment there is not cross ref to the type of field
#                   Assume that if it has narsy data init then its a string
#                   and we don't do much to those
#
# Inputs          : $row    - Ref to an array
#
# Returns         : Nothing. Data is rmMerge_processed in place 
#
sub escapeRowData
{
    my ($row) = @_;
    foreach my $value ( @$row) {

        $value =~ s/([\t\r\n%'])/"%" . uc(sprintf "%2.2x" , unpack("C", $1))/eg;
    }
}



#-------------------------------------------------------------------------------
# Function        : saveLocalData 
#
# Description     : Saves a hash of data to disk 
#
# Inputs          : 
#
# Returns         : 
#
sub saveLocalData
{
    #
    #   Dump out the configuration information
    #
    my $fh = ConfigurationFile::New( $localDataStore);

    $fh->DumpData( "\n# rmData\n#\n", "rmData", \%rmData );
    $fh->Close();

    #DebugDumpData("rmData", \%rmData);
}

#-------------------------------------------------------------------------------
# Function        : restoreLocalData 
#
# Description     : Read in the locally preserved data 
#
# Inputs          : 
#
# Returns         : 
#
sub restoreLocalData
{
    if (-f $localDataStore) {
        require ( $localDataStore );
    }
}

#-------------------------------------------------------------------------------
# Function        : getDataFromRm 
#
# Description     : Get an array of data from RM 
#
# Inputs          : $name           - Query Name
#                   $m_sqlstr       - Query
#                   $options        - Ref to a hash of options
#                                       sql     - show sql
#                                       data    - show data
#                                       dump    - show results
#                                       oneRow  - Only feth one row
#                                       error   - Must find data
#                                       
# Returns         : 
#
sub getDataFromRm
{
    my ($name,$m_sqlstr, $options ) = @_;
    my @row;
    my $data;

    if (ref $options ne 'HASH') {
        $options = {}; 
    }

    if ($options->{sql}) {
        Message("$name: $m_sqlstr")
    }
    my $sth = $RM_DB->prepare($m_sqlstr);
    if ( defined($sth) )
    {
        if ( $sth->execute( ) ) {
            if ( $sth->rows ) {
                while ( @row = $sth->fetchrow_array ) {
                    if ($options->{data}) {
                        Message ("$name: @row");
                    }
                    #Debug0("$name: @row");
                    push @{$data}, [@row];

                    last if $options->{oneRow};
                }
            }
            $sth->finish();
        } else {
            Error("Execute failure:$name: $m_sqlstr", $sth->errstr() );
        }
    } else {
        Error("Prepare failure:$name" );
    }

    if (!$data && $options->{error}) {
        Error( $options->{error} );
    }

    if ($data && $options->{oneRow}) {
        $data = $data->[0];
    }
 
    if ($options->{dump}) {
        DebugDumpData("$name", $data);
    }
    return $data;
}


#-------------------------------------------------------------------------------
#   Documentation
#

=pod

=for htmltoc    GENERAL::ClearCase::

=head1 NAME

rmMerge_suckRelease - Extract Release Information from RM

=head1 SYNOPSIS

jats rmMerge_suck [options] PackageName PackageVersion

 Options:
    -help              - brief help message
    -help -help        - Detailed help message
    -man               - Full documentation
    -outfile=name      - Name of the output file (optional)
    -rtagid=rtag       - Identify the release

=head1 OPTIONS

=over 8

=item B<-help>

Print a brief help message and exits.

=item B<-help -help>

Print a detailed help message with an explanation for each option.

=back

=head1 EXAMPLE

jats rmMerge_suckRelease -rtagId=xxxxx

=cut