# $Header: emdb/sysman/admin/scripts/db/convert/convert.pl /st_emdbsa_11.2/3 2009/02/06 23:27:15 hasriniv Exp $
#
# convert.pl
# 
# Copyright (c) 2004, 2009, Oracle and/or its affiliates.All rights reserved. 
#
#    NAME
#      convert.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    hasriniv    01/29/09 - Code sync
#    hasriniv    07/16/08 - Fix for bug 7171390
#    nachen      06/19/08 - XbranchMerge nachen_bug-7144603 from st_emdbsa_11.1
#    nachen      06/06/08 - fix internal references security issue
#    sxzhu       01/23/07 - Enable public for RAC
#    sxzhu       06/07/05 - Remove version check 
#    sxzhu       04/15/05 - Specify recovery area size by MB 
#    sxzhu       04/07/05 - Handle large plsql output 
#    sxzhu       04/04/05 - Fix migrating online logs for RAC 
#    sxzhu       03/02/05 - Workaround 10.1.0.4 ASM DB 
#    sxzhu       02/18/05 - Handle no row return from query
#    sxzhu       02/11/05 - Handle generating revert script on NT 
#    sxzhu       01/14/05 - More migrate logs
#    sxzhu       11/13/04 - Keep temp dir if asmTest set 
#    sxzhu       10/28/04 - Add single quote around tablespace 
#    sxzhu       10/14/04 - Support multiple channels and customizing tbs
#    sxzhu       09/27/04 - Migrate spfile between disk groups 
#    sxzhu       09/17/04 - Do not copy online logs if on diskgroup 
#    sxzhu       08/25/04 - Checkpoint after switching log 
#    sxzhu       07/20/04 - Do not reset UserID 
#    sxzhu       07/07/04 - Use singel rman command to backup datafiles 
#    szhu        06/15/04 - Not create recovery script if not migrate db files 
#    szhu        06/03/04 - Generate script to recover the original database 
#    szhu        06/02/04 - Crosscheck before migrating archivelogs and others 
#    szhu        05/13/04 - Migrate spfile
#    szhu        05/07/04 - Support hot migration 
#    szhu        05/05/04 - Crosscheck copy and others 
#    szhu        04/30/04 - Remove new logs before copy original ones 
#    szhu        04/28/04 - Rebounce db after migrating online logs 
#    szhu        04/13/04 - szhu_convert_0412 
#    szhu        03/30/04 - Creation
# 

require "$ENV{EMDROOT}/sysman/admin/scripts/db/convert/convert_common.pl";

use strict;
use warnings;

use File::Temp qw/ tempfile tempdir /;
use File::Spec;
use vars qw/ $userID $OS $NT $S $TEMP $DELIMITER $DEFER_OUTPUT 
             $OUTPUT_LOC $INDEX $CUSTOMIZE_LEVEL/;

# Global variables
#$userID = "";
$CUSTOMIZE_LEVEL = "tablespace"; #could also be datafile

#$ENV{EMAGENT_PERL_TRACE_LEVEL} = 0;  #DEBUG level.

# Set environment variables
# Call sub set_env_var() in emd_common.pl
# set_env(oracleHome, oracleSid)
sub set_env
{
  EMD_PERL_DEBUG("convert.set_env(): *** START ***");
  &set_env_var($_[0], $_[1]);
  EMD_PERL_DEBUG("convert.set_env(): *** END ***");
}

# Set the source DB credential
# setSrcDBCredential(userName, password)
sub setSrcDBCredential
{
  EMD_PERL_DEBUG("convert.setSrcDBCredential(): *** START ***");
  my ($userName, $password, $tns) = @_;
	if(!$tns){
			$userID = $userName."/".$password;
	}
	else{
			$userID = $userName."/".$password."\@${tns}";
	}
  EMD_PERL_DEBUG("convert.setSrcDBCredential(): User Name: $userName");
  EMD_PERL_DEBUG("convert.setSrcDBCredential(): *** END ***");
}

# Filter out DB credential from rman script, which is written to trace file
# filterDBCredentialFromRmanScript(rmanScript)
sub filterDBCredentialFromRmanScript
{
  my ($rmanScript) = @_;

  my $position1 = index($rmanScript, "TARGET");
  my $position2 = index($rmanScript, ";");
  my $replacedLength = $position2 - $position1 - 7;
  substr($rmanScript, $position1 + 7, $replacedLength) = "username/password(Hiden intentionally)";

  return $rmanScript;
}

# Parse the output string to detect ORA- errors
# parseOutput(output)
sub parseOutput
{
  EMD_PERL_DEBUG("convert_common.parseOutput(): *** START ***");

  my ($output) = @_;
  
  if ($output eq "")
  {
    EMD_PERL_ERROR("convert_common.parseOutput(): Output file is empty!");
  }
  
  if($output !~ /RMAN-[0-9]/)
  {
    EMD_PERL_DEBUG("convert_common.parseOutput(): No Error found.");
  }
  else
  {
    EMD_PERL_ERROR("convert_common.parseOutput(): RMAN- ERROR! Exit! See output log.");
    exit(1);
  }
  
  EMD_PERL_DEBUG("convert_common.parseOutput(): *** END ***");
}

# Run given rman script on DB
# The caller is responsible to close the returned fileHandle
# runRman(rmanScript, hideOutput) will hide standard output for any
# defined parameter "hideOutput"
# runRman(rmanScript) will print standard output
sub runRman
{
  EMD_PERL_DEBUG("convert.runRman(): *** START ***");
  
  my ($rman_string) = $_[0];
  my $rman_string_debug = &filterDBCredentialFromRmanScript($rman_string);
  EMD_PERL_DEBUG("convert.runRman(): RMAN Script:\n$rman_string_debug");

  (my $fh, my $filename) = &create_temp_file();

  if($NT)
  {
    $filename = "$TEMP\\"."convert.$$";
    EMD_PERL_DEBUG("convert.runRman(): temp file: $filename");
    open(RMAN_SCRIPT, "|$ENV{ORACLE_HOME}/bin/rman >$filename")
      || die "Cannot open pipe for RMAN_SCRIPT";
    print RMAN_SCRIPT $rman_string;
    #close RMAN_SCRIPT || die "Bad RMAN_SCRIPT";
    close RMAN_SCRIPT || print "Could not close pipe for RMAN_SCRIPT";
  }
  else
  {
    open(RMAN_SCRIPT, "|$ENV{ORACLE_HOME}/bin/rman >$filename")
      || die "Cannot open pipe for RMAN_SCRIPT";
    print RMAN_SCRIPT $rman_string;
    #close RMAN_SCRIPT || die "Bad RMAN_SCRIPT";
    close RMAN_SCRIPT || print "Could not close pipe for RMAN_SCRIPT";
  }

  #Open the temp file to print output to standard output and debug trace file
  open (OUT_PUT, "$filename") || die "Unable to open tempfile for OUT_PUT\n";
  my @output_content = <OUT_PUT>;
  my $output_string = "@output_content";
  close OUT_PUT;
  
  if(!defined($_[1]))
  {
    if(defined($DEFER_OUTPUT) && ($DEFER_OUTPUT eq 'Y'))
    {
      &deferOutput($output_string);
    }
    else
    {
      print STDOUT $output_string;
    }
  }
  
  EMD_PERL_DEBUG("convert.runRman(): OUT_PUT:\n$output_string");
  &parseOutput($output_string);
  
  EMD_PERL_DEBUG("convert.runRman(): *** END ***");

  return ($fh, $filename);
}

# Run srvctl utility with given command
# runSrvctl(command)
sub runSrvctl
{
  EMD_PERL_DEBUG("convert.runSrvctl(): *** START ***");
  
  my ($command) = @_;
  EMD_PERL_DEBUG("convert.runSrvctl(): Command:\n$command");

  (my $fh, my $filename) = &create_temp_file();
  
  if($NT)
  {
    $filename = "$TEMP\\"."convert.$$";
    EMD_PERL_DEBUG("convert.runSrvctl(): temp file: $filename");
  }
  
  # Do NOT check the return value of this command
  $command = "$ENV{ORACLE_HOME}${S}bin${S}srvctl ".${command};
	my(@res) = `$command >$filename 2>&1`;
  
  my $mesg = getOutputFromFile($filename);
  
  if(defined($DEFER_OUTPUT) && ($DEFER_OUTPUT eq 'Y'))
  {
    &deferOutput($mesg);
  }
  else
  {
    print STDOUT $mesg;
  }
  
	if($?)
  {
		my($err) = "@res";
    EMD_PERL_ERROR("convert.runSrvctl(): $command: $err");
    exit(1);
  }
  
  close $fh;
  if($NT)
  {
     &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.runSrvctl(): *** END ***");
}

# Check if an spfile is used 
# return spfile name: if empty, no spfile is being used.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# spfileUsed()
sub spfileUsed
{
  EMD_PERL_DEBUG("convert.spfileUsed(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 512;\n";
  $sql_string .= "variable rowcount number;\n";
  $sql_string .= "variable spfile_val varchar2(256);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select count(*) INTO :rowcount from v\$parameter where name = 'spfile';\n";
  $sql_string .= "  dbms_output.put_line('Row count: '||:rowcount);\n";
  $sql_string .= "  IF (:rowcount > 0) then\n";
  $sql_string .= "    select value INTO :spfile_val from v\$parameter where name = 'spfile';\n";
  $sql_string .= "    IF NOT (:spfile_val IS NULL) then\n";
  $sql_string .= "      dbms_output.put_line('Start printing spfile value: ');\n";
  $sql_string .= "      dbms_output.put_line('spfile# '||:spfile_val);\n";
  $sql_string .= "    end if;\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $spfileName = "";
  open (SPFILE, "$filename") || die "Unable to open tempfile for SPFILE\n";
  while (<SPFILE>)
  {
    if ($_=~/\bspfile#/)
    {
      chomp($_); 
      $spfileName = substr $_, 8; #spfile name starts from position 8
    }
  }

  close SPFILE;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.spfileUsed(): spfile name: $spfileName");
  EMD_PERL_DEBUG("convert.spfileUsed(): *** END ***");

  return $spfileName;
}

# Check if the target is a cluster database, get the db name 
# return israc (Y/N) and dbname
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getIsRacDbName()
sub getIsRacDbName
{
  EMD_PERL_DEBUG("convert.getIsRacDbName(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 512;\n";
  $sql_string .= "variable is_rac varchar2(20);\n";
  $sql_string .= "variable db_unique_name varchar2(256);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select value INTO :is_rac from v\$parameter where name = 'cluster_database';\n";
  $sql_string .= "  dbms_output.put_line('Start printing RAC flag and unique db name: ');\n";
  $sql_string .= "  dbms_output.put_line('rac# '||:is_rac);\n";
  $sql_string .= "  select value INTO :db_unique_name from v\$parameter where name = 'db_unique_name';\n";
  $sql_string .= "  IF NOT (:db_unique_name IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('dbname# '||:db_unique_name);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $israc = "";
  my $dbname = "";
  open (DBNAME, "$filename") || die "Unable to open tempfile for DBNAME\n";
  while (<DBNAME>)
  {
    if ($_=~/\brac#/)
    {
      chomp($_); 
      $israc = substr $_, 5; #rac flag starts from position 5
      if($israc eq "TRUE"){
        $israc = "Y";
      }
      else{
        $israc = "N";
      }
    }
    if ($_=~/\bdbname#/)
    {
      chomp($_); 
      $dbname = substr $_, 8; #dbname starts from position 8
    }
  }

  close DBNAME;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.spfileUsed(): getIsRacDbName israc: $israc; dbname: $dbname");
  EMD_PERL_DEBUG("convert.getIsRacDbName(): *** END ***");

  return ($israc, $dbname);
}

# Check the DB block change tracking mode.  If enabled, disable it.
# Retrun tracking filename if enabled, otherwise, return empty.
# Call &set_env(oracleHome, oracleSid) before calling this method.
# checkAndDisableChangeTracking()
sub checkAndDisableChangeTracking
{
  EMD_PERL_DEBUG("convert.checkAndDisableChangeTracking(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\n";
  $sql_string .= "variable status varchar2(20);\n";
  $sql_string .= "variable filename varchar2(256);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select STATUS, FILENAME INTO :status, :filename from V\$BLOCK_CHANGE_TRACKING;\n";
  $sql_string .= "  IF NOT (:status IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing status value: ');\n";
  $sql_string .= "    dbms_output.put_line('status# '||:status);\n";
  $sql_string .= "    IF (:status = 'ENABLED') then\n";
  $sql_string .= "      execute immediate 'ALTER DATABASE DISABLE BLOCK CHANGE TRACKING';\n";
  $sql_string .= "      IF NOT (:filename IS NULL) then\n";
  $sql_string .= "        dbms_output.put_line('Start printing filename value: ');\n";
  $sql_string .= "        dbms_output.put_line('filename# '||:filename);\n";
  $sql_string .= "      end if;\n";
  $sql_string .= "    end if;\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $status = "";
  my $trackingFile = "";
  open (CHANGE_TRACKING, "$filename") || die "Unable to open tempfile for CHANGE_TRACKING\n";
  while (<CHANGE_TRACKING>)
  {
    if ($_=~/\bstatus#/)
    {
      chomp($_); 
      $status = substr $_, 8; #status name starts from position 8
    }
    if ($_=~/\bfilename#/)
    {
      chomp($_); 
      $trackingFile = substr $_, 10; #trackingFile name starts from position 10
    }
  }

  close CHANGE_TRACKING;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.checkAndDisableChangeTracking(): Change tracking status: $status");
  EMD_PERL_DEBUG("convert.checkAndDisableChangeTracking(): Change tracking filename: $trackingFile");
  EMD_PERL_DEBUG("convert.checkAndDisableChangeTracking(): *** END ***");

  return $trackingFile;
}

# Enable the DB block change tracking mode.
# Call &set_env(oracleHome, oracleSid) before calling this method.
# enableChangeTracking(tracking_file)
sub enableChangeTracking
{
  EMD_PERL_DEBUG("convert.enableChangeTracking(): *** START ***");
  
  my ($tracking_file) = $_[0];
  
  if(defined($tracking_file))
  {
    EMD_PERL_DEBUG("convert.enableChangeTracking(): Change tracking file: $tracking_file");
  }
  else
  {
    EMD_PERL_DEBUG("convert.enableChangeTracking(): Change tracking file: NOT DEFINED");
  }

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\n";
  $sql_string .= "variable status varchar2(20);\n";
  $sql_string .= "variable filename varchar2(256);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";
  $sql_string .= "  select STATUS INTO :status from V\$BLOCK_CHANGE_TRACKING;\n";
  $sql_string .= "  IF NOT (:status IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Block change tracking status: '||:status);\n";
  $sql_string .= "    IF (:status = 'DISABLED') then\n";
  
  if(defined($tracking_file))
  {
    $sql_string .= "      execute immediate 'ALTER DATABASE ENABLE BLOCK CHANGE TRACKING USING FILE \'\'"."$tracking_file"."\'\' REUSE';\n";
  }
  else
  {
    $sql_string .= "      execute immediate 'ALTER DATABASE ENABLE BLOCK CHANGE TRACKING';\n";
  }
  
  $sql_string .= "    end if;\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "  select STATUS, FILENAME INTO :status, :filename from V\$BLOCK_CHANGE_TRACKING;\n";
  $sql_string .= "  IF NOT (:status IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing status value: ');\n";
  $sql_string .= "    dbms_output.put_line('status# '||:status);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "  IF NOT (:filename IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing filename value: ');\n";
  $sql_string .= "    dbms_output.put_line('filename# '||:filename);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $status = "";
  my $trackingFile = "";
  open (CHANGE_TRACKING, "$filename") || die "Unable to open tempfile for CHANGE_TRACKING\n";
  while (<CHANGE_TRACKING>)
  {
    if ($_=~/\bstatus#/)
    {
      chomp($_); 
      $status = substr $_, 8; #status name starts from position 8
    }
    if ($_=~/\bfilename#/)
    {
      chomp($_); 
      $trackingFile = substr $_, 10; #trackingFile name starts from position 10
    }
  }

  close CHANGE_TRACKING;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.enableChangeTracking(): Change tracking status: $status");
  EMD_PERL_DEBUG("convert.enableChangeTracking(): Change tracking filename: $trackingFile");
  EMD_PERL_DEBUG("convert.enableChangeTracking(): *** END ***");
}

# Get valid log file names (separated by delimiters)
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getLogFiles()
sub getLogFiles
{
  EMD_PERL_DEBUG("convert.getLogFiles(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\n";
  $sql_string .= "variable status varchar2(7);\n";
  $sql_string .= "variable filename varchar2(256);\n";
  $sql_string .= "declare\n";
  $sql_string .= "  i    binary_integer := 1;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";
  $sql_string .= "  FOR cfrec IN (SELECT status, member FROM v\$logfile WHERE status is NULL or status='STALE')\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('filename# '||cfrec.member);\n";
  $sql_string .= "    i := i + 1;\n";
  $sql_string .= "  END LOOP;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  my $logFile = "";
  my $logFiles = "";
  open (LOG_FILE, "$filename") || die "Unable to open tempfile for LOG_FILE\n";
  while (<LOG_FILE>)
  {
    if ($_=~/\bfilename#/)
    {
      chomp($_); 
      $logFile = substr $_, 10; #logFile name starts from position 10
      $logFiles .= ${logFile}.${DELIMITER};
      EMD_PERL_DEBUG("convert.getLogFiles(): Filename: $logFile");
    }
  }

  close LOG_FILE;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.getLogFiles(): *** END ***");
  
  return $logFiles;
}

# Get tempfile attributes (separated by delimiters)
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getTempFiles()
sub getTempFiles
{
  EMD_PERL_DEBUG("convert.getTempFiles(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\n";
  $sql_string .= "variable filename varchar2(513);\n";
  $sql_string .= "variable fileId number;\n";
  $sql_string .= "variable size number;\n";
  $sql_string .= "variable tablespace varchar2(30);\n";
  $sql_string .= "variable autoextensible varchar2(3);\n";
  $sql_string .= "variable nextsize number;\n";
  $sql_string .= "variable maxsize number;\n";
  $sql_string .= "declare\n";
  $sql_string .= "  i    binary_integer := 1;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";
  $sql_string .= "  FOR tfrec IN (SELECT v.name AS filename, v.file# as fileId, (d.bytes/1024) AS filesize, d.tablespace_name AS tbs, d.autoextensible AS autoexend, (d.increment_by * v.block_size/1024 ) AS nextsize, (d.maxblocks * v.block_size/1024) AS maxsize\n";
  $sql_string .= "                FROM v\$tempfile v, sys.dba_temp_files d \n";
  $sql_string .= "                WHERE v.file# = d.file_id and v.status='ONLINE' \n";
  $sql_string .= "                ORDER BY v.file#)\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('filename# '||tfrec.filename);\n";
  $sql_string .= "    dbms_output.put_line('fileId# '||tfrec.fileId);\n";
  $sql_string .= "    dbms_output.put_line('size# '||tfrec.filesize);\n";
  $sql_string .= "    dbms_output.put_line('tablespace# '||tfrec.tbs);\n";
  $sql_string .= "    dbms_output.put_line('autoextend# '||tfrec.autoexend);\n";
  $sql_string .= "    dbms_output.put_line('nextsize# '||tfrec.nextsize);\n";
  $sql_string .= "    dbms_output.put_line('maxsize# '||tfrec.maxsize);\n";
  $sql_string .= "    i := i + 1;\n";
  $sql_string .= "  END LOOP;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  my $tempFile = "";
  my $tempFiles = "";
  my $fileId = "";
  my $fileIds = "";
  my $size = "";
  my $sizes = "";
  my $tablespace = "";
  my $tablespaces = "";
  my $autoextend = "";
  my $autoextends = "";
  my $nextsize = "";
  my $nextsizes = "";
  my $maxsize = "";
  my $maxsizes = "";
  
  open (TEMP_FILE, "$filename") || die "Unable to open tempfile for TEMP_FILE\n";
  while (<TEMP_FILE>)
  {
    if ($_=~/\bfilename#/)
    {
      chomp($_); 
      $tempFile = substr $_, 10; #file name starts from position 10
      $tempFiles .= ${tempFile}.${DELIMITER};
    }
    if ($_=~/\bfileId#/)
    {
      chomp($_); 
      $fileId = substr $_, 8; #fileId starts from position 8
      $fileIds .= ${fileId}.${DELIMITER};
    }
    if ($_=~/\bsize#/)
    {
      chomp($_); 
      $size = substr $_, 6; #size starts from position 6
      $sizes .= ${size}."K".${DELIMITER};
    }
    if ($_=~/\btablespace#/)
    {
      chomp($_); 
      $tablespace = substr $_, 12; #tablespace starts from position 12
      $tablespaces .= ${tablespace}.${DELIMITER};
    }
    if ($_=~/\bautoextend#/)
    {
      chomp($_); 
      $autoextend = substr $_, 12; #autoextend starts from position 12
      $autoextends .= ${autoextend}.${DELIMITER};
    }
    if ($_=~/\bnextsize#/)
    {
      chomp($_); 
      $nextsize = substr $_, 10; #nextsize starts from position 10
      $nextsizes .= ${nextsize}."K".${DELIMITER};
    }
    if ($_=~/\bmaxsize#/)
    {
      chomp($_); 
      $maxsize = substr $_, 9; #maxsize starts from position 9
      $maxsizes .= ${maxsize}."K".${DELIMITER};
    }
  }

  close TEMP_FILE;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  my @tempAutoextends = split /$DELIMITER/, $autoextends;
  my @tempNextsizes = split /$DELIMITER/, $nextsizes;
  my @tempMaxsizes = split /$DELIMITER/, $maxsizes;
  my $tempAutoextend = "";
  my $autoextendClause = "";
  my $autoextendClauses = "";
  my $index = 0;
  foreach $tempAutoextend (@tempAutoextends)
  {
    if($tempAutoextend eq "YES")
    {
      $autoextendClause = "AUTOEXTEND ON NEXT ".$tempNextsizes[$index]." MAXSIZE ".$tempMaxsizes[$index];
    }
    else
    {
      $autoextendClause = " ";
    }
    $autoextendClauses .= ${autoextendClause}.${DELIMITER};
    $index ++;
  }
  
  EMD_PERL_DEBUG("convert.getTempFiles(): Filenames: $tempFiles");
  EMD_PERL_DEBUG("convert.getTempFiles(): FileIds: $fileIds");
  EMD_PERL_DEBUG("convert.getTempFiles(): Sizes: $sizes");
  EMD_PERL_DEBUG("convert.getTempFiles(): Tablespaces: $tablespaces");
  EMD_PERL_DEBUG("convert.getTempFiles(): Autoextend Clauses: $autoextendClauses");
  
  EMD_PERL_DEBUG("convert.getTempFiles(): *** END ***");
  
  return ($tempFiles, $fileIds, $sizes, $tablespaces, $autoextendClauses);
}

# Associate front end tempDGs with the backend temp ids 
# if could not match ids for any reason, just use DB area
# getToLocationsForTempfiles(ids, tempIDs, tempDGs, dbFilesLoc)
sub getToLocationsForTempfiles
{
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): *** START ***");
  
  my ($ids, $tempIDs, $tempDGs, $dbFilesLoc) = @_;
  
  my @backIds = split /$DELIMITER/, $ids;
  my @frontIds = split /$DELIMITER/, $tempIDs;
  my @frontDgs = split /$DELIMITER/, $tempDGs;
  
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): backIds: @backIds");
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): frontIds: @frontIds");
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): frontDgs: @frontDgs");
  
  my $id1;
  my $id2;
  my $index = 0;
  my $toLocations = "";
  foreach $id1 (@backIds)
  {
    $id2 = $frontIds[$index];
    if($id1 eq $id2)
    {
      $toLocations .= $frontDgs[$index].${DELIMITER};
    }
    else
    {
      $toLocations .= ${dbFilesLoc}.${DELIMITER};
    }
    $index = $index + 1;
  }
  
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): toLocations: $toLocations");
  EMD_PERL_DEBUG("convert.getToLocationsForTempfiles(): *** END ***");
  
  return $toLocations;
}

# Drop tempfiles
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# dropTempfiles(fileNames)
sub dropTempfiles
{
  EMD_PERL_DEBUG("convert.dropTempfiles(): *** START ***");

  my ($fileNames) = @_;

  my @tempFileNames = split /$DELIMITER/, $fileNames;
  
  EMD_PERL_DEBUG("convert.dropTempfiles(): Files to be dropped: @tempFileNames");

  #drop multiple tempfiles
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";

  my $tempFileName;
  foreach $tempFileName (@tempFileNames)
  {
    $sql_string .= "ALTER DATABASE TEMPFILE '$tempFileName' drop;\n"; 
  }
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.dropTempfiles(): *** END ***");
}

# Add tempfiles after opening the database
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# addTempfilesConvert(toLocations, sizes, tablespaces, autoextends)
sub addTempfilesConvert
{
  EMD_PERL_DEBUG("convert.addTempfilesConvert(): *** START ***");

  my ($toLocations, $sizes, $tablespaces, $autoextends) = @_;

  my @tempLocs = split /$DELIMITER/, $toLocations;
  my @tempSizes = split /$DELIMITER/, $sizes;
  my @tempTablespaces = split /$DELIMITER/, $tablespaces;
  my @tempAutoextends = split /$DELIMITER/, $autoextends;
  
  EMD_PERL_DEBUG("convert.addTempfilesConvert(): Temp files will be added to: @tempLocs");

  #add multiple tempfiles
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";

  my $tempSize;
  my $index = 0;
  foreach $tempSize (@tempSizes)
  {
    $sql_string .= "ALTER TABLESPACE \"$tempTablespaces[$index]\" "; 
    $sql_string .= "ADD TEMPFILE '$tempLocs[$index]' ";
    $sql_string .= "SIZE $tempSize REUSE $tempAutoextends[$index];\n";
    $index ++;
  }
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.addTempfilesConvert(): *** END ***");
}

# Backup a given file at the same location 
# Generate a unique name for the new file and return the new name
# backupFile(srcfile)
sub backupFile
{
  EMD_PERL_DEBUG("convert.backupFile(): *** START ***");
  
  my($srcfile) = @_;
  
  EMD_PERL_DEBUG("convert.backupFile(): Source File: $srcfile");
  
  if(! -e $srcfile)
  {
    EMD_PERL_DEBUG("convert.backupFile(): File $srcfile does not exist!");
    return "";
  }
  
  my $destfile = ${srcfile}.".saved";
  while(-e "$destfile")
  {
    EMD_PERL_DEBUG("convert.backupFile(): $destfile already exist");
    $destfile .= "_1";
  }
  
  EMD_PERL_DEBUG("convert.backupFile(): Destination File: $destfile");
  
  !copyFile($srcfile, $destfile) || (EMD_PERL_DEBUG("convert.backupFile(): Error copying $srcfile to $destfile") && (die "convert.backupFile(): Error copying $srcfile to $destfile"));  
		
  EMD_PERL_DEBUG("convert.backupFile(): *** END ***");
  
  return $destfile;
}

# Retrun the space_used value.
# Call &set_env(oracleHome, oracleSid) before calling this method.
# getSpaceUsedInRecoveryArea()
sub getSpaceUsedInRecoveryArea
{
  EMD_PERL_DEBUG("convert.getSpaceUsedInRecoveryArea(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "variable rowcount number;\n";
  $sql_string .= "variable used_space number;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select count(*) INTO :rowcount from v\$recovery_file_dest;\n";
  $sql_string .= "  IF (:rowcount > 0) then\n";
  $sql_string .= "    select NVL(space_used/1024/1024 + 10 - MOD(space_used/1024/1024,10), 0) as space_used_mb INTO :used_space from v\$recovery_file_dest;\n";
  $sql_string .= "    IF NOT (:used_space IS NULL) then\n";
  $sql_string .= "      dbms_output.put_line('Start printing used space value: ');\n";
  $sql_string .= "      dbms_output.put_line('space# '||:used_space);\n";
  $sql_string .= "    end if;\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $space = 0;
  open (USED_SPACE, "$filename") || die "Unable to open tempfile for USED_SPACE\n";
  while (<USED_SPACE>)
  {
    if ($_=~/\bspace#/)
    {
      chomp($_); 
      $space = substr $_, 7; #space name starts from position 7
    }
  }

  close USED_SPACE;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.getSpaceUsedInRecoveryArea(): Used space in recovery area: $space");
  EMD_PERL_DEBUG("convert.getSpaceUsedInRecoveryArea(): *** END ***");

  return $space;
}

# Construct init parameters based on user selections
# constructInitParameters(isMigrateDBFiles, isMigrateRecoveryFiles, isSetupRecoveryAreaOnly,
#                         dbFilesLoc, recoveryFilesLoc, recoveryFilesSize, 
#                         multiplexLocsArray, recoverySpace)
sub constructInitParameters
{
  EMD_PERL_DEBUG("convert.constructInitParameters(): *** START ***");
  
  my ($isMigrateDBFiles, $isMigrateRecoveryFiles, $isSetupRecoveryAreaOnly,
      $dbFilesLoc, $recoveryFilesLoc, $recoveryFilesSize, $multiplexLocsArray, $recoverySpace) = @_;
      
  EMD_PERL_DEBUG("convert.constructInitParameters(): isMigrateDBFiles: $isMigrateDBFiles");
  EMD_PERL_DEBUG("convert.constructInitParameters(): isMigrateRecoveryFiles: $isMigrateRecoveryFiles");
  EMD_PERL_DEBUG("convert.constructInitParameters(): isSetupRecoveryAreaOnly: $isSetupRecoveryAreaOnly");
  EMD_PERL_DEBUG("convert.constructInitParameters(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.constructInitParameters(): recoveryFilesLoc: $recoveryFilesLoc");
  EMD_PERL_DEBUG("convert.constructInitParameters(): recoveryFilesSize: $recoveryFilesSize");
  EMD_PERL_DEBUG("convert.constructInitParameters(): multiplexLocsArray: $multiplexLocsArray");
  EMD_PERL_DEBUG("convert.constructInitParameters(): recoverySpace: $recoverySpace");
      
  my $SINGLEQUOTE = "'";
  
  my $modifiedInitNames = "";
  my $modifiedInitValues = "";
  
  if($isMigrateDBFiles eq "Y")
  {
    $modifiedInitNames .= "DB_CREATE_FILE_DEST".${DELIMITER};
    $modifiedInitValues .= ${SINGLEQUOTE}.$dbFilesLoc.${SINGLEQUOTE}.${DELIMITER};
  }
  
  if($isMigrateRecoveryFiles eq "Y")
  {
    $modifiedInitNames .= "DB_RECOVERY_FILE_DEST_SIZE".${DELIMITER};
    if($isSetupRecoveryAreaOnly eq "Y")
    {
      $modifiedInitValues .= ${recoveryFilesSize}."M".${DELIMITER};
    }
    else
    {
      my $space = $recoverySpace + $recoveryFilesSize;
      
      #make sure the size is within limit
      if($space >= 2**44)
      {
        $space = 2**44 - 1;
      }
      
      $modifiedInitValues .= ${space}."M".${DELIMITER};
    }
    $modifiedInitNames .= "DB_RECOVERY_FILE_DEST".${DELIMITER};
    $modifiedInitValues .= ${SINGLEQUOTE}.${recoveryFilesLoc}.${SINGLEQUOTE}.${DELIMITER};
  }

  my($multiplexInitNames, $multiplexInitValues) = getSimpleMultiplexParameters($multiplexLocsArray);
  
  $modifiedInitNames .= $multiplexInitNames;
  $modifiedInitValues .= $multiplexInitValues;
  
  #my($largePoolSizeName, $largePoolSizeValue) = getLargePoolSizeParameter();
  #$modifiedInitNames .= $largePoolSizeName;
  #$modifiedInitValues .= $largePoolSizeValue;
    
  EMD_PERL_DEBUG("convert.constructInitParameters(): modifiedInitNames: $modifiedInitNames");
  EMD_PERL_DEBUG("convert.constructInitParameters(): modifiedInitValues: $modifiedInitValues");

  EMD_PERL_DEBUG("convert.constructInitParameters(): *** END ***");
  
  return ($modifiedInitNames, $modifiedInitValues);
}

# Get multiplex parameters based on user selections and some complex algorithm
# This method is not being used.
# getMultiplexParameters(isMigrateRecoveryFiles, dbFilesLoc, 
#                        recoveryFilesLoc, multiplexLocsArray)
sub getMultiplexParameters
{
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): *** START ***");
  
  my ($isMigrateRecoveryFiles, $dbFilesLoc, $recoveryFilesLoc, $multiplexLocsArray) = @_;
      
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): isMigrateRecoveryFiles: $isMigrateRecoveryFiles");
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): recoveryFilesLoc: $recoveryFilesLoc");
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): multiplexLocsArray: $multiplexLocsArray");
      
  my $SINGLEQUOTE = "'";
  
  my $modifiedInitNames = "";
  my $modifiedInitValues = "";
  
  my @multiplexLocs = split /$DELIMITER/, $multiplexLocsArray;
  
  #one multiplexing location is specified
  #the location is set the same as DB_CREATE_FILE_DEST
  if($#multiplexLocs == 0)
  {
    $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_1".${DELIMITER};
    $modifiedInitValues .= ${SINGLEQUOTE}.$dbFilesLoc.${SINGLEQUOTE}.${DELIMITER};
  }
  
  #two multiplexing locations are specified
  #no need to set DB_CREATE_ONLINE_LOG_DEST_n if the 
  #DB_CREATE_FILE_DEST and DB_RECOVERY_FILE_DEST are set
  
  #two multiplexing locations are specified
  #if only DB_CREATE_FILE_DEST is set
  #the first location is set the same as DB_CREATE_FILE_DEST
  #the second one is set as the second specified by user
  if($#multiplexLocs == 1)
  {
    $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_1".${DELIMITER};
    $modifiedInitValues .= ${SINGLEQUOTE}.$dbFilesLoc.${SINGLEQUOTE}.${DELIMITER};
    if($isMigrateRecoveryFiles ne "Y")
    {
      $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_2".${DELIMITER};
      $modifiedInitValues .= ${SINGLEQUOTE}.$multiplexLocs[1].${SINGLEQUOTE}.${DELIMITER};
    }
  }
  
  #three or more multiplexing locations are specified
  #the locations are set the same as DB_CREATE_FILE_DEST and DB_RECOVERY_FILE_DEST,
  #and other specified
  if($#multiplexLocs > 1)
  {
    my $index = "";
    $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_1".${DELIMITER};
    $modifiedInitValues .= ${SINGLEQUOTE}.$dbFilesLoc.${SINGLEQUOTE}.${DELIMITER};
    if($isMigrateRecoveryFiles eq "Y")
    {
      $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_2".${DELIMITER};
      $modifiedInitValues .= ${SINGLEQUOTE}.${recoveryFilesLoc}.${SINGLEQUOTE}.${DELIMITER};
      foreach (2 .. ($#multiplexLocs))
      {
        $index = $_ + 1;
        $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_"."$index".${DELIMITER};
        $modifiedInitValues .= ${SINGLEQUOTE}.$multiplexLocs[$_].${SINGLEQUOTE}.${DELIMITER};
      }
    }
    else
    {
      foreach (1 .. ($#multiplexLocs))
      {
        $index = $_ + 1;
        $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_"."$index".${DELIMITER};
        $modifiedInitValues .= ${SINGLEQUOTE}.$multiplexLocs[$_].${SINGLEQUOTE}.${DELIMITER};
      }
    }
  }
  
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): modifiedInitNames: $modifiedInitNames");
  EMD_PERL_DEBUG("convert.getMultiplexParameters(): modifiedInitValues: $modifiedInitValues");

  EMD_PERL_DEBUG("convert.getMultiplexParameters(): *** END ***");
  
  return ($modifiedInitNames, $modifiedInitValues);
}

# Get multiplex parameters based on user selections and simple algorithm
# Just set all user specifications as init parameters
# getSimpleMultiplexParameters(multiplexLocsArray)
sub getSimpleMultiplexParameters
{
  EMD_PERL_DEBUG("convert.getSimpleMultiplexParameters(): *** START ***");
  
  my ($multiplexLocsArray) = @_;

  EMD_PERL_DEBUG("convert.getSimpleMultiplexParameters(): multiplexLocsArray: $multiplexLocsArray");
      
  my $SINGLEQUOTE = "'";
  
  my $modifiedInitNames = "";
  my $modifiedInitValues = "";
  
  my @multiplexLocs = split /$DELIMITER/, $multiplexLocsArray;
  my $index = 0;
  foreach (0 .. ($#multiplexLocs))
  {
    $index = $_ + 1;
    $modifiedInitNames .= "DB_CREATE_ONLINE_LOG_DEST_"."$index".${DELIMITER};
    $modifiedInitValues .= ${SINGLEQUOTE}.$multiplexLocs[$_].${SINGLEQUOTE}.${DELIMITER};
  }
  
  EMD_PERL_DEBUG("convert.getSimpleMultiplexParameters(): modifiedInitNames: $modifiedInitNames");
  EMD_PERL_DEBUG("convert.getSimpleMultiplexParameters(): modifiedInitValues: $modifiedInitValues");

  EMD_PERL_DEBUG("convert.getSimpleMultiplexParameters(): *** END ***");
  
  return ($modifiedInitNames, $modifiedInitValues);
}

# Add 1MB if not an ASM DB
# getLargePoolSizeParameter()
sub getLargePoolSizeParameter
{
  EMD_PERL_DEBUG("convert.getLargePoolSizeParameter(): *** START ***");
  
  my $modifiedInitNames = "";
  my $modifiedInitValues = "";
  
  my $db_area = &getDBArea();
  
  #For now, if db_area starts with '+', the DB is an ASM DB
  my $startStr = substr($db_area, 0, 1);
  if($startStr ne '+')
  {
    my $largePoolSize = &getLargePoolSize();
    $largePoolSize = $largePoolSize + 1024000;
    $modifiedInitNames .= "LARGE_POOL_SIZE".${DELIMITER};
    $modifiedInitValues .= ${largePoolSize}.${DELIMITER};
  }
  
  EMD_PERL_DEBUG("convert.getLargePoolSizeParameter(): modifiedInitNames: $modifiedInitNames");
  EMD_PERL_DEBUG("convert.getLargePoolSizeParameter(): modifiedInitValues: $modifiedInitValues");

  EMD_PERL_DEBUG("convert.getLargePoolSizeParameter(): *** END ***");
  
  return ($modifiedInitNames, $modifiedInitValues);
}

# Retrun the large_pool_size (bytes).
# Call &set_env(oracleHome, oracleSid) before calling this method.
# getLargePoolSize()
sub getLargePoolSize
{
  EMD_PERL_DEBUG("convert.getLargePoolSize(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "variable pool_size number;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select value INTO :pool_size from v\$parameter where name = 'large_pool_size';\n";
  $sql_string .= "  IF NOT (:pool_size IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing large pool size value: ');\n";
  $sql_string .= "    dbms_output.put_line('poolsize# '||:pool_size);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $size = "";
  open (POOL_SIZE, "$filename") || die "Unable to open tempfile for POOL_SIZE\n";
  while (<POOL_SIZE>)
  {
    if ($_=~/\bpoolsize#/)
    {
      chomp($_); 
      $size = substr $_, 10; #poolsize name starts from position 10
    }
  }

  close POOL_SIZE;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.getLargePoolSize(): Large pool size: $size");
  EMD_PERL_DEBUG("convert.getLargePoolSize(): *** END ***");

  return $size;
}

# Retrun db_create_file_dest value.
# Call &set_env(oracleHome, oracleSid) before calling this method.
# getDBArea()
sub getDBArea
{
  EMD_PERL_DEBUG("convert.getDBArea(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "variable db_area varchar2(512);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select value INTO :db_area from v\$parameter where name = 'db_create_file_dest';\n";
  $sql_string .= "  IF NOT (:db_area IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing db area value: ');\n";
  $sql_string .= "    dbms_output.put_line('dbarea# '||:db_area);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $db_area = "";
  open (DB_AREA, "$filename") || die "Unable to open tempfile for DB_AREA\n";
  while (<DB_AREA>)
  {
    if ($_=~/\bdbarea#/)
    {
      chomp($_); 
      $db_area = substr $_, 8; #dbarea name starts from position 8
    }
  }

  close DB_AREA;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.getDBArea(): DB Area: $db_area");
  EMD_PERL_DEBUG("convert.getDBArea(): *** END ***");

  return $db_area;
}

# Append name=value to init parameter file
# appendInitFile(modifiedParamNames, modifiedParamValues, pfileFullName)
sub appendInitFile
{
  EMD_PERL_DEBUG("convert.appendInitFile(): *** START ***");
  
  my ($modifiedParamNames, $modifiedParamValues, $pfileFullName) = @_;

  if(($modifiedParamNames eq "") || ($modifiedParamNames eq "$DELIMITER"))
  {
    EMD_PERL_DEBUG("convert.appendInitFile(): NO PARAMETER TO MODIFY, returning");
    EMD_PERL_DEBUG("convert.appendInitFile(): *** END ***");
    return;
  }

  EMD_PERL_DEBUG("convert.appendInitFile(): modifiedParamNames: $modifiedParamNames");
  EMD_PERL_DEBUG("convert.appendInitFile(): modifiedParamValues: $modifiedParamValues");
  
  my @modifiedParamNames = split /$DELIMITER/, $modifiedParamNames;
  my @modifiedParamValues = split /$DELIMITER/, $modifiedParamValues;

  open(INIT_ORA, ">>$pfileFullName") || die "Cannot open $pfileFullName";

  #Add modified init parameters (name=value) in the materialized init.ora
  foreach (0 .. $#modifiedParamNames)
  {
    print INIT_ORA "$modifiedParamNames[$_]=$modifiedParamValues[$_]\n";
  }

  close INIT_ORA || die "Cannot close $pfileFullName";

  #For debug
  if($ENV{EMAGENT_PERL_TRACE_LEVEL} >= 0)
  {
    open (INIT_ORA_FILE, "$pfileFullName") || die "Unable to open tempfile for INIT_ORA_FILE\n";
    my @file_content = <INIT_ORA_FILE>;
    my $file_string = "@file_content";
    close INIT_ORA_FILE;
    EMD_PERL_DEBUG("convert.appendInitFile(): INIT_ORA_FILE:\n $file_string");
  }

  EMD_PERL_DEBUG("convert.appendInitFile(): *** END ***");
}

# Comment the control_files parameter in init parameter file
# commentCtlFileParamInitFile(pfileFullName)
sub commentCtlFileParamInitFile
{
  EMD_PERL_DEBUG("convert.commentCtlFileParamInitFile(): *** START ***");
  
  my ($pfileFullName) = @_;

  EMD_PERL_DEBUG("convert.commentCtlFileParamInitFile(): pfileFullName: $pfileFullName");
  
  open(ORIG_INIT_ORA, "$pfileFullName") || die "Cannot open $pfileFullName";
  my @output_content = <ORIG_INIT_ORA>;
  my $contentString = "@output_content";
  close ORIG_INIT_ORA;
  
  #comment name by prepending '#'
  my $name = "*.control_files";
  my $upperContentString = uc $contentString;
  my $upperName = uc $name;
  my $index = index($upperContentString, $upperName);
  if($index < 0)
  {
    $name = "control_files";
  }
  my $newName = "#"."$name";
  my $quoteName = quotemeta($name);
  $contentString =~ s/$quoteName/$newName/gi;
  
  (my $fh, my $filename) = &create_temp_file();
  open(INIT_ORA, ">$filename") || die "Cannot open $filename";
  print INIT_ORA $contentString;
  close INIT_ORA || die "Cannot close $filename";
  
  #overwrite the original file
  !copyFile($filename, $pfileFullName) || (EMD_PERL_DEBUG("convert.commentCtlFileParamInitFile(): Error copying $filename to $pfileFullName") && (die "convert.commentCtlFileParamInitFile(): Error copying $filename to $pfileFullName"));

  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.commentCtlFileParamInitFile(): *** END ***");
}

# Modify init parameter file
# If the name is found, comment it with '#', then append the new name=value
# at the end of the file, if not found, just append name=value at the end of the file.
# modifyInitFile(modifiedParamNames, modifiedParamValues, pfileFullName)
sub modifyInitFile
{
  EMD_PERL_DEBUG("convert.modifyInitFile(): *** START ***");
  
  my ($modifiedParamNames, $modifiedParamValues, $pfileFullName) = @_;

  if(($modifiedParamNames eq "") || ($modifiedParamNames eq "$DELIMITER"))
  {
    EMD_PERL_DEBUG("convert.modifyInitFile(): NO PARAMETER TO MODIFY, returning");
    EMD_PERL_DEBUG("convert.modifyInitFile(): *** END ***");
    return;
  }

  EMD_PERL_DEBUG("convert.modifyInitFile(): modifiedParamNames: $modifiedParamNames");
  EMD_PERL_DEBUG("convert.modifyInitFile(): modifiedParamValues: $modifiedParamValues");
  
  my @modifiedParamNames = split /$DELIMITER/, $modifiedParamNames;
  my @modifiedParamValues = split /$DELIMITER/, $modifiedParamValues;
  
  open(ORIG_INIT_ORA, "$pfileFullName") || die "Cannot open $pfileFullName";
  my @output_content = <ORIG_INIT_ORA>;
  my $contentString = "@output_content";
  close ORIG_INIT_ORA;
  
  #comment name by prepending '#'
  my $name = "";
  my $newName = "";
  my $index = -1;
  my $upperContentString = uc $contentString;
  my $upperName = "";
  foreach (0 .. $#modifiedParamNames)
  {
    $name = "*.".$modifiedParamNames[$_];
    $upperName = uc $name;
    $index = index($upperContentString, $upperName);
    if($index < 0)
    {
      $name = $modifiedParamNames[$_];
    }
    $newName = "#"."$name";
    my $quoteName = quotemeta($name);
    $contentString =~ s/$quoteName/$newName/gi;
  }
  
  (my $fh, my $filename) = &create_temp_file();
  open(INIT_ORA, ">>$filename") || die "Cannot open $filename";
  print INIT_ORA $contentString;
  
  #Append modified init parameters (name=value) in the materialized init.ora
  foreach (0 .. $#modifiedParamNames)
  {
    print INIT_ORA "$modifiedParamNames[$_]=$modifiedParamValues[$_]\n";
  }

  close INIT_ORA || die "Cannot close $filename";

  #For debug
  if($ENV{EMAGENT_PERL_TRACE_LEVEL} >= 0)
  {
    open (INIT_ORA_FILE, "$filename") || die "Unable to open tempfile for INIT_ORA_FILE\n";
    my @file_content = <INIT_ORA_FILE>;
    my $file_string = "@file_content";
    close INIT_ORA_FILE;
    EMD_PERL_DEBUG("convert.modifyInitFile(): INIT_ORA_FILE:\n $file_string");
  }
  
  #overwrite the original file
  !copyFile($filename, $pfileFullName) || (EMD_PERL_DEBUG("convert.modifyInitFile(): Error copying $filename to $pfileFullName") && (die "convert.modifyInitFile(): Error copying $filename to $pfileFullName"));

  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.modifyInitFile(): *** END ***");
}

# Modify spfile with given parameter names and values
# Define the third argument if want to reset control file parameters
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# modifySpfile(modifiedNames, modifiedValues, startNomount, resetCtl)
sub modifySpfile
{
  EMD_PERL_DEBUG("convert.modifySpfile(): *** START ***");
  
  my ($modifiedNames, $modifiedValues, $startNomount, $resetCtl) = @_;

  #Replace the "%%%" with "'" in $modifiedParamValues
  #This is for control file name delimiters
  #$modifiedValues =~ s/%%%/'/g;
  
  EMD_PERL_DEBUG("convert.modifySpfile(): parameter names: $modifiedNames");
  EMD_PERL_DEBUG("convert.modifySpfile(): parameter values: $modifiedValues");
  EMD_PERL_DEBUG("convert.modifySpfile(): startNomount: $startNomount");
  EMD_PERL_DEBUG("convert.modifySpfile(): resetCtl: $resetCtl");
  
  my @modifiedNames = split /$DELIMITER/, $modifiedNames;
  my @modifiedValues = split /$DELIMITER/, $modifiedValues;

  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  
  if($startNomount eq "Y")
  {
    $sql_string .= "startup force nomount;\n";
  }
  
  if($resetCtl eq "Y")
  {
    $sql_string .= "ALTER SYSTEM RESET control_files SCOPE=SPFILE sid='*'; \n";
  }
  
  foreach (0 .. $#modifiedNames)
  {
    $sql_string .= "ALTER SYSTEM SET $modifiedNames[$_]=$modifiedValues[$_] SCOPE=BOTH";
    if(((uc $modifiedNames[$_]) eq "DB_RECOVERY_FILE_DEST") ||
       ((uc $modifiedNames[$_]) eq "DB_RECOVERY_FILE_DEST_SIZE") ||
       (index((uc $modifiedNames[$_]), "DB_CREATE_ONLINE_LOG_DEST") >= 0))
    {
      $sql_string .= " sid='*'; \n";
    }
    else
    {
      $sql_string .= "; \n";
    }
  }
  
  $sql_string .= "EXIT;\n";

  my ($fh, $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.modifySpfile(): *** END ***");
}

# Modify dynamic parameters with given parameter names and values
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# modifyDynamicParameters(modifiedNames, modifiedValues)
sub modifyDynamicParameters
{
  EMD_PERL_DEBUG("convert.modifyDynamicParameters(): *** START ***");
  
  my ($modifiedNames, $modifiedValues) = @_;
  
  EMD_PERL_DEBUG("convert.modifyDynamicParameters(): parameter names: $modifiedNames");
  EMD_PERL_DEBUG("convert.modifyDynamicParameters(): parameter values: $modifiedValues");
  
  my @modifiedNames = split /$DELIMITER/, $modifiedNames;
  my @modifiedValues = split /$DELIMITER/, $modifiedValues;

  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  
  foreach (0 .. $#modifiedNames)
  {
    $sql_string .= "ALTER SYSTEM SET $modifiedNames[$_]=$modifiedValues[$_] ";
    if(((uc $modifiedNames[$_]) eq "DB_RECOVERY_FILE_DEST") ||
       ((uc $modifiedNames[$_]) eq "DB_RECOVERY_FILE_DEST_SIZE") ||
       (index((uc $modifiedNames[$_]), "DB_CREATE_ONLINE_LOG_DEST") >= 0))
    {
      $sql_string .= " sid='*'; \n";
    }
    else
    {
      $sql_string .= "; \n";
    }
  }
  
  $sql_string .= "EXIT;\n";

  my ($fh, $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.modifyDynamicParameters(): *** END ***");
}

# Restore one of the original control file to ASM.
# Return the restored control file names if pfile is used, otherwise, return empty.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# restoreControlFile(pfile, origControlFiles)
sub restoreControlFile
{
  EMD_PERL_DEBUG("convert.restoreControlFile(): *** START ***");
  
  my ($pfile, $origControlFiles) = @_;

  if($origControlFiles eq "")
  {
    EMD_PERL_ERROR("convert.restoreControlFile(): No original control file specified!");
    return;
  }
  
  EMD_PERL_DEBUG("convert.restoreControlFile(): pfile: $pfile");
  EMD_PERL_DEBUG("convert.restoreControlFile(): original control files: $origControlFiles");
  
  #workaround for 10.1.0.4 ASM db
  shutdownDB("abort");
  
  my @origControlFiles = split /$DELIMITER/, $origControlFiles;
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  if($pfile eq "")
  {
    $rman_string .= "startup force nomount;\n";
  }
  else
  {
    $rman_string .= "startup force nomount pfile='$pfile';\n";
  }
  $rman_string .= "restore controlfile from '$origControlFiles[0]'; \n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "alter database mount;\n";
  $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";
  $sql_string .= "EXIT;\n";

  ($fh, $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  my $newControlFiles = "";
  if($pfile ne "")
  {
    $newControlFiles = getControlFiles();
  }
  
  EMD_PERL_DEBUG("convert.restoreControlFile(): *** END ***");
  
  return $newControlFiles;
}

sub restoreControlFileDebug
{
  EMD_PERL_DEBUG("convert.restoreControlFileDebug(): *** START ***");
  
  my ($pfile, $origControlFiles) = @_;

  if($origControlFiles eq "")
  {
    EMD_PERL_ERROR("convert.restoreControlFileDebug(): No original control file specified!");
    return;
  }
  
  EMD_PERL_DEBUG("convert.restoreControlFileDebug(): pfile: $pfile");
  EMD_PERL_DEBUG("convert.restoreControlFileDebug(): original control files: $origControlFiles");
  
  my @origControlFiles = split /$DELIMITER/, $origControlFiles;
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  if($pfile eq "")
  {
    $rman_string .= "startup force nomount;\n";
  }
  else
  {
    $rman_string .= "startup force nomount pfile='$pfile';\n";
  }
  $rman_string .= "EXIT;\n";
  
  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  $rman_string .= "restore controlfile from '$origControlFiles[0]'; \n";
  $rman_string .= "EXIT;\n";
  ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "alter database mount;\n";
  $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";
  $sql_string .= "EXIT;\n";

  ($fh, $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  my $newControlFiles = "";
  if($pfile ne "")
  {
    $newControlFiles = getControlFiles();
  }
  
  EMD_PERL_DEBUG("convert.restoreControlFileDebug(): *** END ***");
  
  return $newControlFiles;
}

# Allocate 4 rman channels if flag is on, otherwise do nothing
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# allocateRMANChannels(allocateMultipleChannels)
sub allocateRMANChannels
{
  EMD_PERL_DEBUG("convert.allocateRMANChannels(): *** START ***");
  
  my ($allocateMultipleChannels) = @_;
  
  EMD_PERL_DEBUG("convert.allocateRMANChannels(): allocateMultipleChannels: $allocateMultipleChannels");
  
  my $rman_string = "";
  
  if($allocateMultipleChannels eq "Y")
  {
    $rman_string .= "allocate channel dev1 type disk;\n";
    $rman_string .= "allocate channel dev2 type disk;\n";
    $rman_string .= "allocate channel dev3 type disk;\n";
    $rman_string .= "allocate channel dev4 type disk;\n";
  }
  
  EMD_PERL_DEBUG("convert.allocateRMANChannels(): *** END ***");
  
  return $rman_string;
}

# Migrate all datafiles to ASM
# To migrate all database files, pass "" for datafileNums 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateDatafiles(datafileNums, diskGroups, dbFilesLoc, parallelizeCopying)
sub migrateDatafiles
{
  EMD_PERL_DEBUG("convert.migrateDatafiles(): *** START ***");
  
  my ($datafileNums, $diskGroups, $dbFilesLoc, $parallelizeCopying) = @_;
  
  EMD_PERL_DEBUG("convert.migrateDatafiles(): datafile numbers: $datafileNums");
  EMD_PERL_DEBUG("convert.migrateDatafiles(): disk groups: $diskGroups");
  EMD_PERL_DEBUG("convert.migrateDatafiles(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.migrateDatafiles(): parallelizeCopying: $parallelizeCopying");
  
  my @datafileNums = split /$DELIMITER/, $datafileNums;
  my @diskGroups = split /$DELIMITER/, $diskGroups;
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  $rman_string .= "run {\n";
  $rman_string .= &allocateRMANChannels($parallelizeCopying);
  if($#datafileNums == -1) #whole database migration
  {
    $rman_string .= "backup as copy database format '$dbFilesLoc'; \n";
  }
  else #file by file
  {
    $rman_string .= "backup as copy \n";
    #all datafiles except the last one
    foreach (0 .. $#datafileNums - 1)
    {
      $rman_string .= "  ($CUSTOMIZE_LEVEL '$datafileNums[$_]' format '$diskGroups[$_]')\n";
    }
    #the last datafile
    $rman_string .= "  ($CUSTOMIZE_LEVEL '$datafileNums[$#datafileNums]' format '$diskGroups[$#datafileNums]');\n";
  }
  $rman_string .= "} \n";
  
  $rman_string .= "switch database to copy;\n";
  $rman_string .= "change copy of database uncatalog; \n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateDatafiles(): *** END ***");
}

# Migrate all datafiles to ASM (hot level 0)
# To migrate all database files, pass "" for datafileNums 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateDatafilesLevelZero(datafileNums, diskGroups, dbFilesLoc, parallelizeCopying)
sub migrateDatafilesLevelZero
{
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelZero(): *** START ***");
  
  my ($datafileNums, $diskGroups, $dbFilesLoc, $parallelizeCopying) = @_;
  
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelZero(): datafile numbers: $datafileNums");
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelZero(): disk groups: $diskGroups");
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelZero(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelZero(): parallelizeCopying: $parallelizeCopying");
  
  my @datafileNums = split /$DELIMITER/, $datafileNums;
  my @diskGroups = split /$DELIMITER/, $diskGroups;
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  $rman_string .= "run {\n";
  $rman_string .= &allocateRMANChannels($parallelizeCopying);
  if($#datafileNums == -1) #whole database migration
  {
    $rman_string .= "backup incremental level 0 as copy tag 'ASM_Migration' database format '$dbFilesLoc'; \n";
  }
  else #file by file
  {
    $rman_string .= "backup incremental level 0 as copy tag 'ASM_Migration' \n";
    #all datafiles except the last one
    foreach (0 .. $#datafileNums - 1)
    {
      $rman_string .= "  ($CUSTOMIZE_LEVEL $datafileNums[$_] format '$diskGroups[$_]')\n";
    }
    #the last one
    $rman_string .= "  ($CUSTOMIZE_LEVEL $datafileNums[$#datafileNums] format '$diskGroups[$#datafileNums]');\n";
  }
  $rman_string .= "} \n";
  
  $rman_string .= "sql 'alter system archive log current';\n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelZero(): *** END ***");
}

# Migrate all datafiles to ASM (hot level 1)
# To migrate all database files, pass "" for datafileNums 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateDatafilesLevelOne(parallelizeCopying)
sub migrateDatafilesLevelOne
{
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelOne(): *** START ***");
  
  my ($parallelizeCopying) = @_;

  EMD_PERL_DEBUG("convert.migrateDatafilesLevelOne(): parallelizeCopying: $parallelizeCopying");
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  $rman_string .= "run { \n";
  $rman_string .= &allocateRMANChannels($parallelizeCopying);
  $rman_string .= "backup incremental level 1 for recover of copy with tag 'ASM_Migration' database; \n";
  $rman_string .= "recover copy of database with tag 'ASM_Migration'; \n";
  $rman_string .= "} \n";
  
  $rman_string .= "sql 'alter system archive log current';\n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateDatafilesLevelOne(): *** END ***");
}

# Migrate online logs to ASM 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateOnlineLogs()
sub migrateOnlineLogs
{
  EMD_PERL_DEBUG("convert.migrateOnlineLogs(): *** START ***");
  
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  
  $sql_string .= "declare\n";
  $sql_string .= "  cursor orlc is\n";
  $sql_string .= "    select distinct l.group#, l.thread#, l.bytes, lf.type\n";
  $sql_string .= "    from v\$log l, v\$logfile lf\n";
  $sql_string .= "    where l.group# = lf.group#\n";
  $sql_string .= "    order by l.thread#, l.group#;\n";
  $sql_string .= "  type numTab_t is table of number index by binary_integer;\n";
  $sql_string .= "  type charTab_t is table of varchar2(1024) index by binary_integer;\n";
  $sql_string .= "  grouplist numTab_t;\n";
  $sql_string .= "  threadlist numTab_t;\n";
  $sql_string .= "  byteslist numTab_t;\n";
  $sql_string .= "  typelist  charTab_t;\n";
  $sql_string .= "  procedure migrateorlfile(gnumber IN number, tnumber IN number, bytes IN number, type IN varchar2) is\n";
  $sql_string .= "    retry number;\n";
  $sql_string .= "    stmt varchar2(1024);\n";
  $sql_string .= "    als varchar2(1024) := 'alter system switch logfile';\n";
  $sql_string .= "    chk varchar2(1024) := 'alter system checkpoint global';\n";

  $sql_string .= "  begin\n";
  $sql_string .= "    dbms_output.enable(2000000);\n";
  $sql_string .= "    select count(*) into retry from v\$log;\n";
  $sql_string .= "    if (type = 'STANDBY') then\n";
  $sql_string .= "      stmt := 'alter database add standby logfile thread ' || tnumber || ' size ' || bytes;\n";
  $sql_string .= "    else\n";
  $sql_string .= "      stmt := 'alter database add logfile thread ' || tnumber || ' size ' || bytes;\n";
  $sql_string .= "    end if;\n";
  $sql_string .= "    dbms_output.put_line('Execute stmt: ' || stmt);\n";
  $sql_string .= "    execute immediate stmt;\n";
  $sql_string .= "    stmt := 'alter database drop logfile group ' || gnumber;\n";
  $sql_string .= "    for i in 1..retry+1 loop\n";
  $sql_string .= "      begin\n";
  $sql_string .= "        dbms_output.put_line('Execute stmt: ' || stmt);\n";
  $sql_string .= "        execute immediate stmt;\n";
  $sql_string .= "        exit;\n";
  $sql_string .= "      exception when others then\n";
  $sql_string .= "        if i > retry then\n";
  $sql_string .= "          raise;\n";
  $sql_string .= "        end if;\n";
  $sql_string .= "        dbms_output.put_line('Execute stmt: ' || als);\n";
  $sql_string .= "        execute immediate als;\n";
  $sql_string .= "        dbms_output.put_line('Execute stmt: ' || chk);\n";
  $sql_string .= "        execute immediate chk;\n";
  $sql_string .= "        dbms_backup_restore.sleep(30);\n";
  $sql_string .= "      end;\n";
  $sql_string .= "    end loop;\n";
  $sql_string .= "  end;\n";
  
  $sql_string .= "begin\n";
  $sql_string .= "  open orlc;\n";
  $sql_string .= "  fetch orlc bulk collect into grouplist, threadlist, byteslist, typelist;\n";
  $sql_string .= "  close orlc;\n";
  $sql_string .= "  for i in 1..grouplist.count loop\n";
  $sql_string .= "    migrateorlfile(grouplist(i), threadlist(i), byteslist(i), typelist(i));\n";
  $sql_string .= "  end loop;\n";
  $sql_string .= "  execute immediate 'alter system switch logfile';\n";
  $sql_string .= "end;\n";

  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n\n";
  
  (my $fh, my $filename) = &runSql($sql_string);
  
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateOnlineLogs(): *** END ***");
}

# Migrate online logs to ASM with hot migration approach
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateOnlineLogsHot()
sub migrateOnlineLogsHot
{
  EMD_PERL_DEBUG("convert.migrateOnlineLogsHot(): *** START ***");
  
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  
  $sql_string .= "declare\n";
  $sql_string .= "  cursor logfile_cur is\n";
  $sql_string .= "    select l.thread#, l.group#, l.bytes\n";
  $sql_string .= "    from v\$log l;\n";
  $sql_string .= "  type numTab_t is table of number index by binary_integer;\n";
  $sql_string .= "  grouplist numTab_t;\n";
  $sql_string .= "  threadlist numTab_t;\n";
  $sql_string .= "  byteslist numTab_t;\n";
  $sql_string .= "  procedure migrateorl ( thread# IN number, group# IN number, bytes IN number) is\n";
  $sql_string .= "    retry number := 5;\n";
  $sql_string .= "    stmt  varchar2(1024);\n";
  $sql_string .= "    als   varchar2(1024) := 'alter system archive log current';\n";
  $sql_string .= "    chk   varchar2(1024) := 'alter system checkpoint global';\n";

  $sql_string .= "  begin\n";
  $sql_string .= "    dbms_output.enable(2000000);\n";
  $sql_string .= "    stmt := 'alter database add logfile thread '||thread#||' size '||bytes;\n";
  $sql_string .= "    dbms_output.put_line('Execute stmt: ' || stmt);\n";
  $sql_string .= "    execute immediate stmt;\n";
  $sql_string .= "    stmt := 'alter database drop logfile group '||group#;\n";
  $sql_string .= "    for I in 1 .. retry loop\n";
  $sql_string .= "      begin\n";
  $sql_string .= "        dbms_output.put_line('Execute stmt: ' || stmt);\n";
  $sql_string .= "        execute immediate stmt;\n";
  $sql_string .= "        exit;\n";
  $sql_string .= "      exception\n";
  $sql_string .= "        when others then\n";
  $sql_string .= "          if I > retry then\n";
  $sql_string .= "            raise;\n";
  $sql_string .= "          end if;\n";
  $sql_string .= "          dbms_output.put_line('Execute stmt: ' || als);\n";
  $sql_string .= "          execute immediate als;\n";
  $sql_string .= "          dbms_output.put_line('Execute stmt: ' || chk);\n";
  $sql_string .= "          execute immediate chk;\n";
  $sql_string .= "      end;\n";
  $sql_string .= "    end loop;\n";
  $sql_string .= "  end;\n";
  
  $sql_string .= "begin\n";
  $sql_string .= "  open logfile_cur;\n";
  $sql_string .= "  fetch logfile_cur bulk collect into threadlist, grouplist, byteslist;\n";
  $sql_string .= "  close logfile_cur;\n";
  $sql_string .= "  for I in 1 .. threadlist.count loop\n";
  $sql_string .= "    migrateorl (threadlist(I), grouplist(I), byteslist(I) );\n";
  $sql_string .= "  end loop;\n";
  $sql_string .= "end;\n";

  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n\n";
  
  (my $fh, my $filename) = &runSql($sql_string);
  
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateOnlineLogsHot(): *** END ***");
}

# Migrate online logs to ASM for standby database with hot migration approach
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateOnlineLogsStandbyHot()
sub migrateOnlineLogsStandbyHot
{
  EMD_PERL_DEBUG("convert.migrateOnlineLogsStandbyHot(): *** START ***");
  
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  
  $sql_string .= "declare\n";
  $sql_string .= "  cursor logfile_cur is\n";
  $sql_string .= "    select l.thread#, l.group#, l.bytes\n";
  $sql_string .= "    from v\$standby_log l;\n";
  $sql_string .= "  type numTab_t is table of number index by binary_integer;\n";
  $sql_string .= "  grouplist numTab_t;\n";
  $sql_string .= "  threadlist numTab_t;\n";
  $sql_string .= "  byteslist numTab_t;\n";
  $sql_string .= "  procedure migratesrl ( thread# IN number, group# IN number, bytes IN number) is\n";
  $sql_string .= "    retry number := 5;\n";
  $sql_string .= "    stmt  varchar2(1024);\n";

  $sql_string .= "  begin\n";
  $sql_string .= "    dbms_output.enable(2000000);\n";
  $sql_string .= "    if thread# = 0 then\n";
  $sql_string .= "      stmt := 'alter database add standby logfile size '||bytes;\n";
  $sql_string .= "    else\n";
  $sql_string .= "      stmt := 'alter database add standby logfile thread '||thread#||' size '||bytes;\n";
  $sql_string .= "    end if;\n";
  $sql_string .= "    dbms_output.put_line('Execute stmt: ' || stmt);\n";
  $sql_string .= "    execute immediate stmt;\n";
  $sql_string .= "    stmt := 'alter database drop standby logfile group '||group#;\n";
  $sql_string .= "    dbms_output.put_line('Execute stmt: ' || stmt);\n";
  $sql_string .= "    execute immediate stmt;\n";
  $sql_string .= "    dbms_backup_restore.sleep(30);\n";
  $sql_string .= "  end;\n";
  
  $sql_string .= "begin\n";
  $sql_string .= "  open logfile_cur;\n";
  $sql_string .= "  fetch logfile_cur bulk collect into threadlist, grouplist, byteslist;\n";
  $sql_string .= "  close logfile_cur;\n";
  $sql_string .= "  for I in 1 .. threadlist.count loop\n";
  $sql_string .= "    migratesrl (threadlist(I), grouplist(I), byteslist(I) );\n";
  $sql_string .= "  end loop;\n";
  $sql_string .= "end;\n";

  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n\n";
  
  (my $fh, my $filename) = &runSql($sql_string);
  
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateOnlineLogsStandbyHot(): *** END ***");
}

# Retrun recovery file count.
# Call &set_env(oracleHome, oracleSid) before calling this method.
# getRecoveryFileCount()
sub getRecoveryFileCount
{
  EMD_PERL_DEBUG("convert.getRecoveryFileCount(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "variable df_cnt number;\n";
  $sql_string .= "variable cf_cnt number;\n";
  $sql_string .= "variable bs_cnt number;\n";
  $sql_string .= "variable al_cnt number;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";
  $sql_string .= "  select count(*) INTO :df_cnt from v\$datafile_copy where status = 'A' and file# != 0;\n";
  $sql_string .= "  IF NOT (:df_cnt IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing datafile copy count: ');\n";
  $sql_string .= "    dbms_output.put_line('df# '||:df_cnt);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "  select count(*) INTO :cf_cnt from v\$datafile_copy where status = 'A' and file# = 0;\n";
  $sql_string .= "  IF NOT (:cf_cnt IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing controlfile copy count: ');\n";
  $sql_string .= "    dbms_output.put_line('cf# '||:cf_cnt);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "  select count(*) INTO :bs_cnt from v\$backup_piece p, v\$backup_set s where p.set_stamp = s.set_stamp and p.set_count = s.set_count and status = 'A';\n";
  $sql_string .= "  IF NOT (:bs_cnt IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing backup set count: ');\n";
  $sql_string .= "    dbms_output.put_line('bs# '||:bs_cnt);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "  select count(*) INTO :al_cnt from v\$archived_log where status = 'A';\n";
  $sql_string .= "  IF NOT (:al_cnt IS NULL) then\n";
  $sql_string .= "    dbms_output.put_line('Start printing archived log count: ');\n";
  $sql_string .= "    dbms_output.put_line('al# '||:al_cnt);\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  my $df = -1;
  my $cf = -1;
  my $bs = -1;
  my $al = -1;
  open (FILE_COUNT, "$filename") || die "Unable to open tempfile for FILE_COUNT\n";
  while (<FILE_COUNT>)
  {
    if ($_=~/\bdf#/)
    {
      chomp($_); 
      $df = substr $_, 4; #df name starts from position 4
    }
    if ($_=~/\bcf#/)
    {
      chomp($_); 
      $cf = substr $_, 4; #cf name starts from position 4
    }
    if ($_=~/\bbs#/)
    {
      chomp($_); 
      $bs = substr $_, 4; #bs name starts from position 4
    }
    if ($_=~/\bal#/)
    {
      chomp($_); 
      $al = substr $_, 4; #al name starts from position 4
    }
  }

  close FILE_COUNT;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.getRecoveryFileCount(): Number of datafile copies: $df");
  EMD_PERL_DEBUG("convert.getRecoveryFileCount(): Number of controlfile copies: $cf");
  EMD_PERL_DEBUG("convert.getRecoveryFileCount(): Number of backup sets: $bs");
  EMD_PERL_DEBUG("convert.getRecoveryFileCount(): Number of archived logs: $al");
  EMD_PERL_DEBUG("convert.getRecoveryFileCount(): *** END ***");

  return ($df, $cf, $bs, $al);
}

# Migrate all recovery related files to ASM
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateRecoveryFiles(migrateArch, parallelizeCopying)
sub migrateRecoveryFiles
{
  EMD_PERL_DEBUG("convert.migrateRecoveryFiles(): *** START ***");
  
  my ($migrateArch, $parallelizeCopying) = @_;
  
  EMD_PERL_DEBUG("convert.migrateRecoveryFiles(): Migrate archived logs: $migrateArch");
  EMD_PERL_DEBUG("convert.migrateRecoveryFiles(): parallelizeCopying: $parallelizeCopying");
  
  crossCheckRecoveryFiles($migrateArch);
  
  my($df, $cf, $bs, $al) = getRecoveryFileCount();
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  $rman_string .= "run {\n";
  $rman_string .= &allocateRMANChannels($parallelizeCopying);
  if($df > 0)
  {
    $rman_string .= "backup as copy datafilecopy all delete input;\n";
  }
  
  if($cf > 0)
  {
    $rman_string .= "backup as copy controlfilecopy all delete input;\n";
  }
  
  if($bs > 0)
  {
    $rman_string .= "backup as backupset backupset all delete input;\n";
  }
  
  if(($migrateArch eq "Y") && ($al > 0))
  {
    $rman_string .= "backup as copy archivelog all delete input;\n";
  }
  $rman_string .= "} \n";
  
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.migrateRecoveryFiles(): *** END ***");
}

# Crosscheck recovery files before migration, otherwise we may encounter rman errors
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# crossCheckRecoveryFiles(migrateArch)
sub crossCheckRecoveryFiles
{
  EMD_PERL_DEBUG("convert.crossCheckRecoveryFiles(): *** START ***");
  
  my ($migrateArch) = @_;
  
  EMD_PERL_DEBUG("convert.crossCheckRecoveryFiles(): Migrate archived logs: $migrateArch");
  
  my $rman_string = "";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "crosscheck copy;\n";
  $rman_string .= "crosscheck backup;\n";
  $rman_string .= "crosscheck backupset;\n";
  
  if($migrateArch eq "Y")
  {
    $rman_string .= "crosscheck archivelog all;\n";
  }
  
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.crossCheckRecoveryFiles(): *** END ***");
}

# modify DB_RECOVERY_FILE_DEST_SIZE init param
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# modifyRecoveryDestSizeInitParam(pfile, size, startNomount)
sub modifyRecoveryDestSizeInitParam
{
  EMD_PERL_DEBUG("convert.modifyRecoveryDestSizeInitParam(): *** START ***");
  
  my ($pfile, $size, $startNomount) = @_;
  
  EMD_PERL_DEBUG("convert.modifyRecoveryDestSizeInitParam(): pfile: $pfile");
  EMD_PERL_DEBUG("convert.modifyRecoveryDestSizeInitParam(): DB_RECOVERY_FILE_DEST_SIZE: $size MB");
  EMD_PERL_DEBUG("convert.modifyRecoveryDestSizeInitParam(): startNomount: $startNomount");
  
  my $modifiedParamNames = "DB_RECOVERY_FILE_DEST_SIZE"."$DELIMITER";
  my $modifiedParamValues = "$size"."M"."$DELIMITER";
  if($pfile eq "")
  {
    modifySpfile($modifiedParamNames, $modifiedParamValues, $startNomount, "N");
  }
  else
  {
    modifyInitFile($modifiedParamNames, $modifiedParamValues, $pfile);
  }
  
  EMD_PERL_DEBUG("convert.modifyRecoveryDestSizeInitParam(): *** END ***");
}

# Shutdown and nomount DB for migration
# Call &set_env(oracleHome, oracleSid) before calling this method.
# closeDBForMigration(pfile)
sub closeDBForMigration
{
  EMD_PERL_DEBUG("convert.closeDBForMigration(): *** START ***");

  my ($pfile) = @_;
  
  #Check if the source DB is using spfile
  my $pfile_filename; #not defined
  my $spfile = &spfileUsed();
  if($spfile eq "") #not using spfile
  {
    $pfile_filename = $pfile;
    EMD_PERL_DEBUG("convert.closeDBForMigration(): pfile: $pfile_filename");
  }

  #shutdown the source DB
  &shutdownDB("immediate");

  #startup the source DB
  &startupDB("nomount", $pfile_filename);

  EMD_PERL_DEBUG("convert.closeDBForMigration(): *** END ***");
}

# Open the mounted source DB
# Call &set_env(oracleHome, oracleSid) before calling this method.
# alterDatabaseOpen()
sub alterDatabaseOpen
{
  EMD_PERL_DEBUG("convert.alterDatabaseOpen(): *** START ***");
  
  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "alter database open;\n";
  $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.alterDatabaseOpen(): *** END ***");
}

# Shutdown DB with specified option.
# Option: normal, immediate, transactional, abort. 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# shutdownDB(option)
sub shutdownDB
{
  EMD_PERL_DEBUG("convert.shutdownDB(): *** START ***");
  
  my ($option) = ($_[0]);

  EMD_PERL_DEBUG("convert.shutdownDB(): option: $option");
  
  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "shutdown $option\n";
  $sql_string .= "EXIT;\n";

  my ($fh, $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.shutdownDB(): *** END ***");
}

# Start DB to specified mode. 
# Mode: nomount, mount, open (""), restrict, force.
# Use the specified pfile if "pfileFullName" is defined.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# startupDB(mode, pfileFullName)
sub startupDB
{
  EMD_PERL_DEBUG("convert.startupDB(): *** START ***");
  
  my ($mode, $pfile) = @_;
 
  if($mode eq "")
  {
    $mode = "open";
  }

  EMD_PERL_DEBUG("convert.startupDB(): mode: $mode");

  if($pfile ne "")
  {
    $pfile = "pfile='$_[1]'";
    EMD_PERL_DEBUG("convert.startupDB(): pfile: $_[1]");
  }

  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "startup force $mode $pfile;\n";
  $sql_string .= "EXIT;\n";

  my ($fh, $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.startupDB(): *** END ***");
}

# Get DB version
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getDBVersion()
sub getDBVersion
{
  EMD_PERL_DEBUG("convert.getDBVersion(): *** START ***");

  my $db_version = "";
  
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n\n";
  $sql_string .= "variable db_version varchar2(20);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select version INTO :db_version from v\$instance;\n";
  $sql_string .= "  dbms_output.put_line('Get DB version');\n";
  $sql_string .= "  dbms_output.put_line('DBversion#: '||:db_version);\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);

  open (DB_VERSION, "$filename") || die "Unable to open tempfile for DB_VERSION\n";
  while (<DB_VERSION>)
  {
    if ($_=~/\bDBversion#/)
    {
      chomp($_); 
      $db_version = substr $_, 12;  #12 is the position that version starts
      EMD_PERL_DEBUG("convert.getDBVersion(): Database version: $db_version");
    }
  }
  close DB_VERSION;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.getDBVersion(): *** END ***");
  
  return $db_version;
}

# Cleanup the migrated database.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# cleanupDBConvert()
sub cleanupDBConvert
{
  EMD_PERL_DEBUG("convert.cleanupDBConvert(): *** START ***");

  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  $rman_string .= "delete copy of database; \n";
  $rman_string .= "YES\n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.cleanupDBConvert(): *** END ***");
}

# Get output from file
# getOutputFromFile(filename)
sub getOutputFromFile
{
  EMD_PERL_DEBUG("convert.getOutputFromFile(): *** START ***");

  my ($filename) = @_;
  
  #Open the file to get output
  open (OUT_PUT, "$filename") || die "Unable to open file $filename for OUT_PUT\n";
  my @output_content = <OUT_PUT>;
  my $mesg = "@output_content";
  close OUT_PUT;

  EMD_PERL_DEBUG("convert.getOutputFromFile(): *** END ***");
  
  return $mesg;
}

# This routine gets a unique dir name within a location based on given pattern.
# Return the found dir name.
# getUniqueDirName(dirPattern)
sub getUniqueDirName
{
  my ($dirPattern) = @_;
  EMD_PERL_DEBUG("convert.getUniqueDirName(): Get unique dir name based on $dirPattern");
  my $dirNotExist = &dirNotExists($dirPattern);
  if($dirNotExist eq "OK")
  {
    EMD_PERL_DEBUG("convert.getUniqueDirName(): Directory $dirPattern is already unique");
    return $dirPattern;
  }

  my $sibling = $dirPattern;
  
  while($dirNotExist eq "NOK")
  {
    EMD_PERL_DEBUG("convert.getUniqueDirName(): $sibling already exist");
    $sibling .= "_1";
    $dirNotExist = &dirNotExists($sibling);
  }

  return $sibling;
}

# Check if a specified directory NOT exists
# Return OK if the directory NOT exists, otherwise, return NOK.
# dirNotExists(dirName)
sub dirNotExists
{
  my ($dirName) = @_;
  if(! -e "$dirName")
  {
    EMD_PERL_DEBUG("convert.dirNotExists(): Directory $dirName does not exist");
    return "OK";
  }
  elsif(! -d "$dirName")
  {
    EMD_PERL_DEBUG("convert.dirNotExists(): $dirName is not a directory");
    return "NOK";
  }
  
  EMD_PERL_DEBUG("convert.dirNotExists(): Directory $dirName exists");
  
  return "NOK";
}

# Create temp location for recovery purpose
# createTempLocationForRecovery(location)
sub createTempLocationForRecovery
{
  my ($location) = @_;
  
  EMD_PERL_DEBUG("convert.createTempLocationForRecovery(): Location: $location");
  
  #No need since it is already unique when going through the wizard
  #$location = getUniqueDirName($location);
  #EMD_PERL_DEBUG("convert.createTempLocationForRecovery(): Unique Location: $location");
  
  my $ret = &mkDir($location);
  if($ret eq "NOK")
  {
    EMD_PERL_ERROR("convert.createTempLocationForRecovery(): Could not create location: $location");
    exit(1);
  }
}

# isAnyOnlinelogOnDiskgroup(logFiles)
sub isAnyOnlinelogOnDiskgroup
{
  my ($logFilesArray) = @_;
  
  EMD_PERL_DEBUG("convert.isAnyOnlinelogOnDiskgroup(): Log files: $logFilesArray");

  my @logFiles = split /$DELIMITER/, $logFilesArray;
  
  my $anyOnDG = "N";
  
  my $logFile = "";
  my $startStr = "";
  foreach $logFile (@logFiles)
  {
    $startStr = substr($logFile, 0, 1);
    if($startStr eq "+") 
    {
      EMD_PERL_DEBUG("convert.isAnyOnlinelogOnDiskgroup(): $logFile starts with: $startStr");
      $anyOnDG = "Y";
      last;
    }
  }
  
  EMD_PERL_DEBUG("convert.isAnyOnlinelogOnDiskgroup(): Any logfile on disk group: $anyOnDG");
  
  return $anyOnDG;
}

# Backup online logs
# Return backup log file names
# backupOnlineLogs(location, logFiles)
sub backupOnlineLogs
{
  my ($location, $logFilesArray) = @_;
  
  EMD_PERL_DEBUG("convert.backupOnlineLogs(): Location: $location");
  EMD_PERL_DEBUG("convert.backupOnlineLogs(): Log files: $logFilesArray");

  my @logFiles = split /$DELIMITER/, $logFilesArray;
  my $slash = "/";
  if($NT)
  {
    $slash = "\\";
  }
  
  my $index = 1;
  my $filename = "";
  my $newName = "";
  my $newNames = "";
  my $logFile = "";
  foreach $logFile (@logFiles)
  {
    $filename = &getBasename($logFile);
    $newName =  $location.$slash.$filename.$index;
    !copyFile($logFile, $newName) || (EMD_PERL_DEBUG("Error copying $logFile to $location") && (die "Error copying $logFile to $location"));
    $index ++;
    $newNames .= $newName.$DELIMITER;
  }
  
  EMD_PERL_DEBUG("convert.backupOnlineLogs(): New Names: $newNames");
  
  return $newNames;
}

# Backup original control files
# Return backup control file names
# backupOrigControlFiles(location, controlFiles)
sub backupOrigControlFiles
{
  my ($location, $controlFilesArray) = @_;
  
  EMD_PERL_DEBUG("convert.backupOrigControlFiles(): Location: $location");
  EMD_PERL_DEBUG("convert.backupOrigControlFiles(): Control files: $controlFilesArray");

  my @controlFiles = split /$DELIMITER/, $controlFilesArray;
  my $slash = "/";
  if($NT)
  {
    $slash = "\\";
  }
  
  my $index = 1;
  my $filename = "";
  my $newName = "";
  my $newNames = "";
  my $controlFile = "";
  foreach $controlFile (@controlFiles)
  {
    $filename = &getBasename($controlFile);
    $newName =  $location.$slash.$filename.$index;
    !copyFile($controlFile, $newName) || (EMD_PERL_DEBUG("Error copying $controlFile to $location") && (die "Error copying $controlFile to $location"));
    $index ++;
    $newNames .= $newName.$DELIMITER;
  }
  
  EMD_PERL_DEBUG("convert.backupOrigControlFiles(): New Names: $newNames");
  
  return $newNames;
}

# Restore online logs
# restoreOnlineLogs(backupLogFiles, logFiles)
sub restoreOnlineLogs
{
  EMD_PERL_DEBUG("convert.restoreOnlineLogs(): *** START ***");
  
  my ($backupLogFilesArray, $logFilesArray) = @_;
  
  EMD_PERL_DEBUG("convert.restoreOnlineLogs(): Backup log files: $backupLogFilesArray");
  EMD_PERL_DEBUG("convert.restoreOnlineLogs(): Log files: $logFilesArray");

  my @backupLogFiles = split /$DELIMITER/, $backupLogFilesArray;
  my @logFiles = split /$DELIMITER/, $logFilesArray;
  
  my $backupLogFile = "";
  my $index = 0;
  foreach $backupLogFile (@backupLogFiles)
  {
    #&removeFile($logFiles[$index]);
    !copyFile($backupLogFile, $logFiles[$index]) || (EMD_PERL_DEBUG("Error copying $backupLogFile to $logFiles[$index]") && (die "Error copying $backupLogFile to $logFiles[$index]"));
    $index = $index + 1;
  }
  
  EMD_PERL_DEBUG("convert.restoreOnlineLogs(): *** END ***");
}

# Restore control files
# restoreOrigControlFiles(backupControlFiles, controlFiles)
sub restoreOrigControlFiles
{
  EMD_PERL_DEBUG("convert.restoreOrigControlFiles(): *** START ***");
  
  my ($backupControlFilesArray, $controlFilesArray) = @_;
  
  EMD_PERL_DEBUG("convert.restoreOrigControlFiles(): Backup control files: $backupControlFilesArray");
  EMD_PERL_DEBUG("convert.restoreOrigControlFiles(): Control files: $controlFilesArray");

  my @backupControlFiles = split /$DELIMITER/, $backupControlFilesArray;
  my @controlFiles = split /$DELIMITER/, $controlFilesArray;
  
  my $backupControlFile = "";
  my $index = 0;
  foreach $backupControlFile (@backupControlFiles)
  {
    &removeFile($controlFiles[$index]);
    !copyFile($backupControlFile, $controlFiles[$index]) || (EMD_PERL_DEBUG("Error copying $backupControlFile to $controlFiles[$index]") && (die "Error copying $backupControlFile to $controlFiles[$index]"));
    $index = $index + 1;
  }
  
  EMD_PERL_DEBUG("convert.restoreOrigControlFiles(): *** END ***");
}

# Create or migrate spfile to ASM.
# If pfile is used, create spfile from it to ASM; if spfile is used, create
# a pfile from it on file system first, then create spfile from the pfile to ASM.
# Create a pfile pointing to the migrated spfile under the same location as original
# pfile or spfile (save the original pfile if there is any at that location).
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# migrateSPFile(pfile, spfile, migratedSpfile, tempLoc)
sub migrateSPFile
{
  EMD_PERL_DEBUG("convert.migrateSPFile(): *** START ***");
  
  #my ($pfile, $spfile, $migratedSpfile, $tempLoc) = @_;
  my ($pfile, $spfile, $migratedSpfile) = @_;
  (my $tempfh, my $tempFileName) = &create_temp_file();
  close $tempfh;
  EMD_PERL_DEBUG("convert.migrateSPFile(): pfile: $pfile");
  EMD_PERL_DEBUG("convert.migrateSPFile(): spfile: $spfile");
  EMD_PERL_DEBUG("convert.migrateSPFile(): migratedSpfile: $migratedSpfile");
  #EMD_PERL_DEBUG("convert.migrateSPFile(): tempLoc: $tempLoc");
  
  my $slash = "/";
  if($NT)
  {
    $slash = "\\";
  }
  
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";

  if($pfile ne "")
  {
    $sql_string .= "create spfile='$migratedSpfile' from pfile='$pfile';\n";
  }
  else
  {
    #my $temppfile = ${tempLoc}.${slash}."init.ora";
    $sql_string .= "create pfile='$tempFileName' from spfile='$spfile';\n";
    $sql_string .= "create spfile='$migratedSpfile' from pfile='$tempFileName';\n";
  }
  
  $sql_string .= "exit;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  my $initFile = "";
  if($pfile ne "")
  {
    $initFile = $pfile;
  }
  else
  {
    #my $initDir = &getDirname($spfile);
    my $initDir = &getDefaultDBLocation();
    my $startStr = substr($initDir, 0, 1);
    if($startStr eq "+")
    {
      EMD_PERL_DEBUG("convert.migrateSPFile(): $initDir starts with: $startStr");
      $initDir = &getDefaultDBLocation();
    }
    
    $initFile = ${initDir}.${slash}."init".$ENV{ORACLE_SID}.".ora";
  }
  
  backupFile($initFile);
  
  open(INIT_ORA, ">$initFile") || die "Cannot open $initFile";
  print INIT_ORA "spfile='$migratedSpfile'";
  close INIT_ORA || die "Cannot close $initFile";
 
  # If original spfile is the default then rename it otherwise db will pick it up after a restart
  if($spfile ne "")
  {
    if(spfileAtDefaultLoc($spfile) eq "Y")
    {
      &backupFile($spfile); 
      &removeFile($spfile);
    }
  }    	 
   
  
  EMD_PERL_DEBUG("convert.migrateSPFile(): *** END ***");
  
  return $initFile;
}

# Check if only setup recovery area without migrating database files
# isOnlySetupRecoveryArea(isMigrateDBFiles, isMigrateRecoveryFiles,
#                         isSetupRecoveryAreaOnly)
sub isOnlySetupRecoveryArea
{
  my ($isMigrateDBFiles, $isMigrateRecoveryFiles, $isSetupRecoveryAreaOnly) = @_;
  
  my $setupRecoveryAreaOnly = "FALSE";
  
  if(($isMigrateDBFiles ne "Y") && ($isMigrateRecoveryFiles eq "Y") && 
     ($isSetupRecoveryAreaOnly eq "Y"))
  {
    $setupRecoveryAreaOnly = "TRUE";
  }
  
  return $setupRecoveryAreaOnly;
}

# Check if pfile exists if it is used
# Return (spfileName, pfileFullName)
# Non empty value means it is being used
# checkPfile(pfileFullName)
sub checkPfile
{
  my ($pfileFullName) = @_;
  
  #Get spfile usage
  my $spfileName = spfileUsed();
  
  if($spfileName eq "")
  {
    EMD_PERL_DEBUG("convert.checkPfile(): Using pfile: $pfileFullName");
    if(! -e "$pfileFullName")
    {
      EMD_PERL_ERROR("convert.checkPfile(): File $pfileFullName does not exist");
      exit(1);
    }
  }
  else
  {
    $pfileFullName = "";
    EMD_PERL_DEBUG("convert.checkPfile(): Using spfile: $spfileName");
  }
  
  return ($spfileName, $pfileFullName);
}

# Check if spfile is at default location ($OH/dbs)
# Return Y/N
# spfileAtDefaultLoc(spfile)
sub spfileAtDefaultLoc
{
  my ($spfile) = @_;
  
  my $atDefaultLoc = "Y";
  
  my $OH = $ENV{ORACLE_HOME};
  my $DBS = "dbs";
  if($NT)
  {
    $DBS = "database";
  }
  
  my $loc = &getDirname($spfile);
  my $spfile_OH = &getDirname($loc);
  my $dbs = &getBasename($loc);
  EMD_PERL_DEBUG("convert.spfileAtDefaultLoc(): spfile_OH: $spfile_OH");
  EMD_PERL_DEBUG("convert.spfileAtDefaultLoc(): dbs: $dbs");
  
  if($NT)
  {
    $spfile_OH = uc $spfile_OH;
    $OH = uc $OH;
    $dbs = uc $dbs;
    $DBS = uc $DBS;
  }
  
  if($spfile_OH ne $OH)
  {
    $atDefaultLoc = "N";
    EMD_PERL_DEBUG("convert.spfileAtDefaultLoc(): $spfile is not under $OH");
  }
  else
  {
    if($dbs ne $DBS)
    {
      $atDefaultLoc = "N";
      EMD_PERL_DEBUG("convert.spfileAtDefaultLoc(): $spfile is not under $DBS");
    }
  }
  
  return $atDefaultLoc;
}

# Get default database location ($OH/dbs)
# Return location
# getDefaultDBLocation()
sub getDefaultDBLocation
{
  my $OH = $ENV{ORACLE_HOME};
  my $DBS = "dbs";
  if($NT)
  {
    $DBS = "database";
  }
  my $defaultLoc = File::Spec->catfile($OH, $DBS);
  EMD_PERL_DEBUG("convert.getDefaultDBLocation(): Default database location is $defaultLoc");
  
  return $defaultLoc;
}

# Switch database to datafile copies at ASM 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# switchDatafileCopies()
sub switchDatafileCopies
{
  EMD_PERL_DEBUG("convert.switchDatafileCopies(): *** START ***");
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  $rman_string .= "switch database to copy; \n";
  $rman_string .= "change copy of database uncatalog; \n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.switchDatafileCopies(): *** END ***");
}

# Recover database 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# recoverDatabase()
sub recoverDatabase
{
  EMD_PERL_DEBUG("convert.recoverDatabase(): *** START ***");
  
  my $rman_string = "";
  $rman_string .= "set echo off\n";
  $rman_string .= "CONNECT TARGET $userID;\n";
  $rman_string .= "set echo on\n";
  
  $rman_string .= "recover database; \n";
  $rman_string .= "EXIT;\n";

  my ($fh, $filename) = &runRman($rman_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.recoverDatabase(): *** END ***");
}

# Shutdown all db instances
# Call &set_env(oracleHome, oracleSid) before calling this method (only OH needs to be set).
# shutdownAllInstances(isRac, dbName)
sub shutdownAllInstances
{
  EMD_PERL_DEBUG("convert.shutdownAllInstances(): *** START ***");
  
  my ($isRac, $dbName) = @_;
  EMD_PERL_DEBUG("convert.shutdownAllInstances(): isRac: $isRac");
  EMD_PERL_DEBUG("convert.shutdownAllInstances(): dbName: $dbName");
  
  if($isRac eq "Y")
  {
    my $cmd = "stop database -d $dbName";
    my $statusCmd = "status database -d $dbName";
    runSrvctl($cmd);
    runSrvctl($statusCmd);
  }
  else
  {
    EMD_PERL_DEBUG("convert.shutdownAllInstances(): $dbName is not a cluster database");
  }
  
  EMD_PERL_DEBUG("convert.shutdownAllInstances(): *** END ***");
}

# Startup all db instances
# Call &set_env(oracleHome, oracleSid) before calling this method (only OH needs to be set).
# startupAllInstances(isRac, dbName)
sub startupAllInstances
{
  EMD_PERL_DEBUG("convert.startupAllInstances(): *** START ***");
  
  my ($isRac, $dbName) = @_;
  EMD_PERL_DEBUG("convert.startupAllInstances(): isRac: $isRac");
  EMD_PERL_DEBUG("convert.startupAllInstances(): dbName: $dbName");
  
  if($isRac eq "Y")
  {
    my $cmd = "start database -d $dbName";
    my $statusCmd = "status database -d $dbName";
    runSrvctl($cmd);
    runSrvctl($statusCmd);
  }
  else
  {
    EMD_PERL_DEBUG("convert.startupAllInstances(): $dbName is not a cluster database");
  }
  
  EMD_PERL_DEBUG("convert.startupAllInstances(): *** END ***");
}

# Associate all db instances with corresponding asm instances for RAC case
# Call &set_env(oracleHome, oracleSid) before calling this method (only OH needs to be set).
# associateDbAsmInstances(isRac, dbName, dbInstancesArray, asmInstancesArray)
sub associateDbAsmInstances
{
  EMD_PERL_DEBUG("convert.associateDbAsmInstances(): *** START ***");
  
  my ($isRac, $dbName, $dbInstancesArray, $asmInstancesArray) = @_;
  
  my @dbInstances = split /$DELIMITER/, $dbInstancesArray;
  my @asmInstances = split /$DELIMITER/, $asmInstancesArray;
  
  EMD_PERL_DEBUG("convert.associateDbAsmInstances(): isRac: $isRac");
  EMD_PERL_DEBUG("convert.associateDbAsmInstances(): dbName: $dbName");
  EMD_PERL_DEBUG("convert.associateDbAsmInstances(): dbInstances: @dbInstances");
  EMD_PERL_DEBUG("convert.associateDbAsmInstances(): asmInstances: @asmInstances");
  
  if($isRac eq "Y")
  {
    my $cmd;
    my $dbInstance;
    my $index = 0;
    foreach $dbInstance (@dbInstances)
    {
      $cmd = "modify instance -d $dbName -i $dbInstance -s $asmInstances[$index]";
      runSrvctl($cmd);
      $index = $index + 1;
    }
  }
  else
  {
    EMD_PERL_DEBUG("convert.associateDbAsmInstances(): $dbName is not a cluster database");
  }
  
  EMD_PERL_DEBUG("convert.associateDbAsmInstances(): *** END ***");
}

# Migrate the flashback files
# Call &set_env(oracleHome, oracleSid) before calling this method.
# migrateFlashbackFiles(pfileFullName, isRac, dbName)
sub migrateFlashbackFiles
{
  EMD_PERL_DEBUG("convert.migrateFlashbackFiles(): *** START ***");
  
  my ($pfileFullName, $isRac, $dbName) = @_;
  EMD_PERL_DEBUG("convert.migrateFlashbackFiles(): pfileFullName: $pfileFullName");
  
  shutdownDB("immediate");
  shutdownAllInstances($isRac, $dbName);
  startupDB("mount", $pfileFullName);
  
  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "alter database flashback off;\n";
  $sql_string .= "alter database flashback on;\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  alterDatabaseOpen();
  startupAllInstances($isRac, $dbName);
  
  EMD_PERL_DEBUG("convert.migrateFlashbackFiles(): *** END ***");
}

# Query the names of all database files
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# checkDatabaseFiles()
sub checkDatabaseFiles
{
  EMD_PERL_DEBUG("convert.checkDatabaseFiles(): *** START ***");

  my $sql_string = "";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";

  $sql_string .= "select name \"datafile\" from v\$datafile;\n";
  $sql_string .= "select name \"tempfile\" from v\$tempfile;\n";
  $sql_string .= "select member \"logfile\" from v\$logfile;\n";
  $sql_string .= "select name \"controlfile\" from v\$controlfile;\n";
  $sql_string .= "select filename \"block_change_tracking\" from v\$block_change_tracking;\n";
  $sql_string .= "select name \"flashback_database_logfile\" from v\$flashback_database_logfile;\n";
  $sql_string .= "select value \"spfile\" from v\$parameter where name='spfile';\n";
  
  $sql_string .= "exit;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("convert.checkDatabaseFiles(): *** END ***");
}

# Insert a script to an existing file
# insertScriptToFile(directory, filename, script, insertFlag)
sub insertScriptToFile
{
  EMD_PERL_DEBUG("convert.insertScriptToFile(): *** START ***");
  
  my ($directory, $filename, $script, $insertFlag) = @_;
  
  EMD_PERL_DEBUG("convert.insertScriptToFile(): directory: $directory");
  EMD_PERL_DEBUG("convert.insertScriptToFile(): filename: $filename");
  EMD_PERL_DEBUG("convert.insertScriptToFile(): script: $script");
  EMD_PERL_DEBUG("convert.insertScriptToFile(): insertFlag: $insertFlag");
  
  my $recoveryScript = File::Spec->catfile($directory, $filename);
  my $tempScript = File::Spec->catfile($directory, "temp.pl");
  open(TEMP_SCRIPT, ">$tempScript") || die "Cannot open $tempScript";
  
  my $oneLine = "";
  open (RECOVERY_SCRIPT, "$recoveryScript") || die "Unable to open $recoveryScript\n";
  while ($oneLine = <RECOVERY_SCRIPT>)
  {      
    if($oneLine=~/$insertFlag/)
    {
      print TEMP_SCRIPT "$oneLine";
      print TEMP_SCRIPT "$script";
    }
    print TEMP_SCRIPT "$oneLine";
  }
  close RECOVERY_SCRIPT;
  close TEMP_SCRIPT;
  
  !copyFile($tempScript, $recoveryScript) || (EMD_PERL_DEBUG("convert.insertScriptToFile(): Error copying $tempScript to $recoveryScript") && (die "convert.insertScriptToFile(): Error copying $tempScript to $recoveryScript"));  
  &removeFile($tempScript);
  
  EMD_PERL_DEBUG("convert.insertScriptToFile(): *** END ***");
}

# Generate script to restore online logs for the source database in case of failure
# generateRestoreLogsScript(logBackupLoc, backupLogFiles, logFiles)
sub generateRestoreLogsScript
{
  EMD_PERL_DEBUG("convert.generateRestoreLogsScript(): *** START ***");
  
  my ($logBackupLoc, $backupLogFilesArrayArg, $logFilesArrayArg) = @_;
  EMD_PERL_DEBUG("convert.generateRestoreLogsScript(): logBackupLoc: $logBackupLoc");
  EMD_PERL_DEBUG("convert.generateRestoreLogsScript(): Backup log files: $backupLogFilesArrayArg");
  EMD_PERL_DEBUG("convert.generateRestoreLogsScript(): Log files: $logFilesArrayArg");
  
  if($NT)
  {
    $backupLogFilesArrayArg = &doubleBackSlashes($backupLogFilesArrayArg);
    $logFilesArrayArg = &doubleBackSlashes($logFilesArrayArg);
  }

  my $perlScript = "";
  $perlScript .= "my \$backupLogFilesArray = \"$backupLogFilesArrayArg\";\n";
  $perlScript .= "my \$logFilesArray = \"$logFilesArrayArg\";\n";
  $perlScript .= "my \$delimiter = \":::\";\n";
  $perlScript .= "my \@backupLogFiles = split /\$delimiter/, \$backupLogFilesArray;\n";
  $perlScript .= "my \@logFiles = split /\$delimiter/, \$logFilesArray;\n";
  
  $perlScript .= "my \$backupLogFile = \"\";\n";
  $perlScript .= "my \$index = 0;\n";
  $perlScript .= "foreach \$backupLogFile (\@backupLogFiles)\n";
  $perlScript .= "{\n";
  $perlScript .= "  copy(\$backupLogFile, \$logFiles[\$index]) || (die \"Error copying \$backupLogFile to \$logFiles[\$index]\");\n";
  $perlScript .= "  \$index = \$index + 1;\n";
  $perlScript .= "}\n";
  $perlScript .= "\n";
  
  EMD_PERL_DEBUG("convert.generateRestoreLogsScript(): restore logs script: $perlScript");
  
  insertScriptToFile($logBackupLoc, "revert.pl", $perlScript, "# Restore the original online logs");
  
  EMD_PERL_DEBUG("convert.generateRestoreLogsScript(): *** END ***");
}

# Generate recovery script to recover the source database in case of failure
# Call &set_env(oracleHome, oracleSid) before calling this method.
# generateRecoveryScript(logBackupLoc, spfileName, pfileFullName, 
#                        backupInitOrSPFileName, isRac, dbName)
sub generateRecoveryScript
{
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): *** START ***");
  
  my ($logBackupLoc, $spfileName, $pfileFullName, $backupInitOrSPFileName,
      $isRac, $dbName) = @_;
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): logBackupLoc: $logBackupLoc");
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): spfileName: $spfileName");
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): pfileFullName: $pfileFullName");
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): backupInitOrSPFileName: $backupInitOrSPFileName");
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): isRac: $isRac");
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): dbName: $dbName");
  
  my $origInitFile = $spfileName;
  if ($spfileName eq "")
  {
    $origInitFile = $pfileFullName;
  }
  
  my $PATH_SP = ":";
  my $SLASH = "/";
  if($NT)
  {
    $PATH_SP =";";
    $SLASH = "\\";
  }
  
  my $ORACLE_HOME = "";
  my $ORACLE_SID = "";
  my $LD_LIBRARY_PATH = "";
  my $SHLIB_PATH = "";
  my $LIBPATH = "";
  my $PATH = "";
  my $sqlplus = "";
  
  $ORACLE_HOME = $ENV{ORACLE_HOME};
  $ORACLE_SID = $ENV{ORACLE_SID};
  
  
	if(defined($ENV{LD_LIBRARY_PATH})){
    $LD_LIBRARY_PATH = "$ENV{ORACLE_HOME}${SLASH}lib${PATH_SP}$ENV{LD_LIBRARY_PATH}";
	}
	else{
    $LD_LIBRARY_PATH = "$ENV{ORACLE_HOME}${SLASH}lib";
	}

	if(defined($ENV{SHLIB_PATH})){
    $SHLIB_PATH = "$ENV{ORACLE_HOME}${SLASH}lib${PATH_SP}$ENV{SHLIB_PATH}";
	}
	else{
    $SHLIB_PATH = "$ENV{ORACLE_HOME}${SLASH}lib";
	}

	if(defined($ENV{LIBPATH})){
    $LIBPATH = "$ENV{ORACLE_HOME}${SLASH}lib${PATH_SP}$ENV{LIBPATH}";
	}
	else{
    $LIBPATH = "$ENV{ORACLE_HOME}${SLASH}lib";
	}

	if(defined($ENV{PATH})){
    $PATH = "$ENV{ORACLE_HOME}${SLASH}bin${PATH_SP}$ENV{PATH}";
	}
	else{
    $PATH = "$ENV{ORACLE_HOME}${SLASH}bin";
	}
  
  $sqlplus = "$ENV{ORACLE_HOME}${SLASH}bin${SLASH}sqlplus";
  
  if($NT)
  {
    $sqlplus = &doubleBackSlashes($sqlplus);
    $backupInitOrSPFileName = &doubleBackSlashes($backupInitOrSPFileName);
    $origInitFile = &doubleBackSlashes($origInitFile);
    $LD_LIBRARY_PATH = &doubleBackSlashes($LD_LIBRARY_PATH);
    $SHLIB_PATH = &doubleBackSlashes($SHLIB_PATH);
    $LIBPATH = &doubleBackSlashes($LIBPATH);
    $PATH = &doubleBackSlashes($PATH);
    $ORACLE_HOME = &doubleBackSlashes($ORACLE_HOME);
  }
  
  my $sqlScript = "";
  if($isRac ne "Y")
  {
    $sqlScript .= "open(SQL_SCRIPT, \"|$sqlplus /nolog\")\n";
    $sqlScript .= "  || die \"Cannot open pipe for SQL_SCRIPT\";\n";
    $sqlScript .= "print SQL_SCRIPT \"connect / as sysdba\\n\";\n";
    $sqlScript .= "print SQL_SCRIPT \"shutdown abort\\n\";\n";
    if ($spfileName eq "")
    {
      $sqlScript .= "print SQL_SCRIPT \"startup pfile='$origInitFile'\\n\";\n";
    }
    else
    {
      $sqlScript .= "print SQL_SCRIPT \"startup\\n\";\n";
    }
    $sqlScript .= "close SQL_SCRIPT || die \"Bad SQL_SCRIPT\";\n";
  }
  else
  {
    $sqlScript .= "print \"srvctl stop database -d $dbName ... \\n\";\n";
    $sqlScript .= "my \@ret = `srvctl stop database -d $dbName`;\n";
    $sqlScript .= "print \"\@ret\\n\";\n";
    $sqlScript .= "print \"srvctl start database -d $dbName ... \\n\";\n";
    $sqlScript .= "\@ret = `srvctl start database -d $dbName`;\n";
    $sqlScript .= "print \"\@ret\\n\";\n";
    $sqlScript .= "print \"srvctl status database -d $dbName ... \\n\";\n";
    $sqlScript .= "\@ret = `srvctl status database -d $dbName`;\n";
    $sqlScript .= "print \"\@ret\\n\";\n";
  }
  
  my $restoreLogScript = "";
  $restoreLogScript .= "# Restore the original online logs \n";

  my $perlScript = "";
  $perlScript .= "# Run this script to recover the original database.  \n";
  $perlScript .= "# It is assumed that the user running this script is a dba member.  \n";
  $perlScript .= "# If you could not connect the database with OS authentication, \n";
  $perlScript .= "# please connect it as sys with sysdba role (by providing sys password), \n";
  $perlScript .= "# then execute the following sql commands:  \n";
  $perlScript .= "#   shutdown abort; startup \n";
  $perlScript .= "\n";
  $perlScript .= "use strict;\n";
  $perlScript .= "use File::Copy;\n";
  $perlScript .= "\n";
  $perlScript .= "# Restore the original init.ora \n";
  $perlScript .= "copy(\"$backupInitOrSPFileName\", \"$origInitFile\")\n";
  $perlScript .= "  or (die \"Can't copy '$backupInitOrSPFileName' to '$origInitFile': \$!\");\n";
  $perlScript .= "\n";
  $perlScript .= "$restoreLogScript";
  $perlScript .= "# Set necessary environmental variables \n";
  $perlScript .= "\$ENV{LD_LIBRARY_PATH} = \"$LD_LIBRARY_PATH\";\n";
  $perlScript .= "\$ENV{SHLIB_PATH} = \"$SHLIB_PATH\";\n";
  $perlScript .= "\$ENV{LIBPATH} = \"$LIBPATH\";\n";
  $perlScript .= "\$ENV{PATH} = \"$PATH\";\n";
  $perlScript .= "\$ENV{ORACLE_HOME} = \"$ORACLE_HOME\";\n";
  $perlScript .= "\$ENV{ORACLE_SID} = \"$ORACLE_SID\";\n";
  $perlScript .= "\n";
  $perlScript .= "# Run sql script to start the original database \n";
  $perlScript .= "$sqlScript\n";
  $perlScript .= "\n";
  
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): recovery script: \n\n$perlScript");
  
  my $recoveryScript = File::Spec->catfile($logBackupLoc, "revert.pl");
  open(RECOVERY_SCRIPT, ">$recoveryScript") || die "Cannot open $recoveryScript";
  print RECOVERY_SCRIPT "$perlScript";
  close RECOVERY_SCRIPT || die "Cannot close $recoveryScript";
  
  EMD_PERL_DEBUG("convert.generateRecoveryScript(): *** END ***");
}

# Start deferring the standard output  
# set global variables: DEFER_OUTPUT, OUTPUT_LOC, INDEX
# startDeferOutput(logBackupLoc)
sub startDeferOutput
{
  EMD_PERL_DEBUG("convert.startDeferOutput(): *** START ***");
  
  my ($logBackupLoc) = @_;
  
  $DEFER_OUTPUT = 'Y';
  $OUTPUT_LOC = File::Spec->catfile($logBackupLoc, "downtime_output");
  $INDEX = 1;
  
  my $ret = &mkDir($OUTPUT_LOC);
  if($ret eq "NOK")
  {
    EMD_PERL_ERROR("convert.startDeferOutput(): Could not create location: $OUTPUT_LOC");
    exit(1);
  }
  
  EMD_PERL_DEBUG("convert.startDeferOutput(): *** END ***");
}

# End deferring the standard output and print output file contents to STDOUT
# reset global variables: DEFER_OUTPUT, OUTPUT_LOC, INDEX
# endDeferOutput()
sub endDeferOutput
{
  EMD_PERL_DEBUG("convert.endDeferOutput(): *** START ***");
  
  my $index = 1;
  my $outputFile;
  foreach (1 .. ($INDEX - 1))
  {
    $outputFile = File::Spec->catfile($OUTPUT_LOC, "output_file_".$index);
    
    #Open the file to get output
    open (OUT_PUT, "$outputFile") || die "Unable to open file $outputFile for OUT_PUT\n";
    my @output_content = <OUT_PUT>;
    my $mesg = "@output_content";
    close OUT_PUT;
    
    print STDOUT $mesg;
  
    $index ++;
  }
  
  #Remove the output location
  &removeDir($OUTPUT_LOC);
      
  $DEFER_OUTPUT = 'N';
  $OUTPUT_LOC = "";
  $INDEX = 1;
  
  EMD_PERL_DEBUG("convert.endDeferOutput(): *** END ***");
}

# Enable/disable threads for other rac instances
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# handleThreadsForOtherRacInstances(instance, action)
sub handleThreadsForOtherRacInstances
{
  EMD_PERL_DEBUG("convert.handleThreadsForOtherRacInstances(): *** START ***");
  
  my ($instance, $action) = @_;

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set echo on\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  FOR tdrec IN (SELECT thread# FROM v\$thread WHERE instance <> '$instance')\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('thread# ' || tdrec.thread#);\n";
  $sql_string .= "    execute immediate 'alter database $action thread ' || tdrec.thread#;\n";
  $sql_string .= "  END LOOP;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  (my $fh, my $filename) = &runSql($sql_string);
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  
  EMD_PERL_DEBUG("convert.handleThreadsForOtherRacInstances(): *** END ***");
}

# Migrate all recovery related files and backup datafiles as copies to ASM (hot)
#
# Modify init parameters
# Migrate recovery related files
# Bounce or enable block change tracking
# Backup datafile as copies to ASM
#
# To migrate the whole database, pass "" for datafileNums 
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# preMigration(isMigrateDBFiles, isMigrateRecoveryFiles, isSetupRecoveryAreaOnly,
#              dbFilesLoc, recoveryFilesSize, recoveryFilesLoc, archLogLocation,
#              dbFileIDsArray, dbFileLocsArray, pfileFullName, multiplexLocsArray,
#              hotMigrationFlag, logBackupLoc, parallelizeCopying)
sub preMigration
{
  EMD_PERL_DEBUG("convert.preMigration(): *** START ***");
  
  my ($isMigrateDBFiles, $isMigrateRecoveryFiles, $isSetupRecoveryAreaOnly,
      $dbFilesLoc, $recoveryFilesSize, $recoveryFilesLoc, $archLogLocation,
      $dbFileIDsArray, $dbFileLocsArray, $pfileFullName, $multiplexLocsArray,
      $hotMigrationFlag, $logBackupLoc, $parallelizeCopying) = @_;
  
  EMD_PERL_DEBUG("convert.preMigration(): isMigrateDBFiles: $isMigrateDBFiles");
  EMD_PERL_DEBUG("convert.preMigration(): isMigrateRecoveryFiles: $isMigrateRecoveryFiles");
  EMD_PERL_DEBUG("convert.preMigration(): isSetupRecoveryAreaOnly: $isSetupRecoveryAreaOnly");
  EMD_PERL_DEBUG("convert.preMigration(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.preMigration(): recoveryFilesSize: $recoveryFilesSize");
  EMD_PERL_DEBUG("convert.preMigration(): recoveryFilesLoc: $recoveryFilesLoc");
  EMD_PERL_DEBUG("convert.preMigration(): archLogLocation: $archLogLocation");
  EMD_PERL_DEBUG("convert.preMigration(): dbFileIDsArray: $dbFileIDsArray");
  EMD_PERL_DEBUG("convert.preMigration(): dbFileLocsArray: $dbFileLocsArray");
  EMD_PERL_DEBUG("convert.preMigration(): pfileFullName: $pfileFullName");
  EMD_PERL_DEBUG("convert.preMigration(): multiplexLocsArray: $multiplexLocsArray");
  EMD_PERL_DEBUG("convert.preMigration(): hotMigrationFlag: $hotMigrationFlag");
  #EMD_PERL_DEBUG("convert.preMigration(): logBackupLoc: $logBackupLoc");
  EMD_PERL_DEBUG("convert.preMigration(): parallelizeCopying: $parallelizeCopying");
  
  ###Define variables used in this sub
  
  #for customizing datafile locations
  my @datafileNums = split /$DELIMITER/, $dbFileIDsArray;
  my @diskGroups = split /$DELIMITER/, $dbFileLocsArray;

  my $setupRecoveryAreaOnly = "FALSE";
  my $spfileName;
  my $space = 0;
  my $modifiedInitNames;
  my $modifiedInitValues;
  my $backupInitOrSPFileName = "";
  my $isRac;
  my $dbName;
  
  ###Get necessary info
  
  #check if setupRecoveryAreaOnly
  $setupRecoveryAreaOnly = isOnlySetupRecoveryArea($isMigrateDBFiles, 
                                $isMigrateRecoveryFiles, $isSetupRecoveryAreaOnly);
  
  #Get init file name, non empty value means it is being used
  ($spfileName, $pfileFullName) = checkPfile($pfileFullName);
  
  #Get space used in recovery area
  $space = getSpaceUsedInRecoveryArea();

  ###Modify init parameters
  
  #Save the original init file or spfile
  #if($spfileName eq "")
  #{
   # $backupInitOrSPFileName = backupFile($pfileFullName);
  #}
  #else
  #{
   # $backupInitOrSPFileName = backupFile($spfileName);
  #}
  
  #Get isRac and dbName
  ($isRac, $dbName) = getIsRacDbName();
  
  #Create temp location for recovery
  #This should be done after saving the original init file
  #so the generated recovery script contains the original init file location info.
  #The generated script should be saved in this location.
  #if($isMigrateDBFiles eq "Y")
  #{
   # createTempLocationForRecovery($logBackupLoc);
   # generateRecoveryScript($logBackupLoc, $spfileName, $pfileFullName, 
   #                        $backupInitOrSPFileName, $isRac, $dbName);
  #}
  
  #construct init parameters based on user selections
  ($modifiedInitNames, $modifiedInitValues) = constructInitParameters(
      $isMigrateDBFiles, $isMigrateRecoveryFiles, $isSetupRecoveryAreaOnly,
      $dbFilesLoc, $recoveryFilesLoc, $recoveryFilesSize, $multiplexLocsArray, $space);
  
  #Add or modify parameters in init file
  
  if($spfileName eq "")
  {
    modifyInitFile($modifiedInitNames, $modifiedInitValues, $pfileFullName);
    modifyDynamicParameters($modifiedInitNames, $modifiedInitValues);
  }
  else
  {
    modifySpfile($modifiedInitNames, $modifiedInitValues, "N", "N");
  }
  
  if($setupRecoveryAreaOnly eq "TRUE")
  {
    return;
  }
  
  ###Migrate recovery related files
  
  if(($isMigrateRecoveryFiles eq "Y") && ($isSetupRecoveryAreaOnly ne "Y"))
  {
    migrateRecoveryFiles($archLogLocation, $parallelizeCopying);
    #Modify DB_RECOVERY_FILE_DEST_SIZE to reduce the used space by recovery files
    modifyRecoveryDestSizeInitParam($pfileFullName, $recoveryFilesSize, "N");
  }

  ###Bounce or enable block change tracking
  
  if($isMigrateDBFiles eq "Y")
  {
    checkAndDisableChangeTracking();
    if($hotMigrationFlag eq "Y")
    {
      enableChangeTracking();
    }
  }
  
  ###Backup datafile as copies to ASM
  
  if(($hotMigrationFlag eq "Y") && ($isMigrateDBFiles eq "Y"))
  {
    migrateDatafilesLevelZero($dbFileIDsArray, $dbFileLocsArray, $dbFilesLoc, $parallelizeCopying);
  }
  
  EMD_PERL_DEBUG("convert.preMigration(): *** END ***");
}

# Switch the database to use the datafile copies at ASM (cold)
#
# Backup database at level 1 (increamental)
# Shutdown database
# Restore control file
# Switch database to copies at ASM
# Recover database
# Migrate spfile
# Open database
# Migrate temp files
# Migrate online logs
# Migrate flashback files (need to restart database)
# Cleanup files on file system
#
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# switchDatabase(pfileFullName, dbFilesLoc, dbFileIDsArray, dbFileLocsArray,
#                isMigrateSPFile, migratedSpfile, isDeleteSourceDB, 
#                logBackupLoc, flashbackFlag, hotMigrationFlag,
#                dbInstancesArray, asmInstancesArray, targetDBReposDB, 
#                parallelizeCopying, tempIDs, tempDGs, asmTest)
sub switchDatabase
{
  EMD_PERL_DEBUG("convert.switchDatabase(): *** START ***");
  
  my ($pfileFullName, $dbFilesLoc, $dbFileIDsArray, $dbFileLocsArray, 
      $isMigrateSPFile, $migratedSpfile, $isDeleteSourceDB, $logBackupLoc, 
      $flashbackFlag, $hotMigrationFlag, $dbInstancesArray, $asmInstancesArray,
      $targetDBReposDB, $parallelizeCopying, $tempIDs, $tempDGs, $asmTest) = @_;
  
  EMD_PERL_DEBUG("convert.switchDatabase(): pfileFullName: $pfileFullName");
  EMD_PERL_DEBUG("convert.switchDatabase(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.switchDatabase(): dbFileIDsArray: $dbFileIDsArray");
  EMD_PERL_DEBUG("convert.switchDatabase(): dbFileLocsArray: $dbFileLocsArray");
  EMD_PERL_DEBUG("convert.switchDatabase(): isMigrateSPFile: $isMigrateSPFile");
  EMD_PERL_DEBUG("convert.switchDatabase(): migratedSpfile: $migratedSpfile");
  EMD_PERL_DEBUG("convert.switchDatabase(): isDeleteSourceDB: $isDeleteSourceDB");
  #EMD_PERL_DEBUG("convert.switchDatabase(): logBackupLoc: $logBackupLoc");
  EMD_PERL_DEBUG("convert.switchDatabase(): flashbackFlag: $flashbackFlag");
  EMD_PERL_DEBUG("convert.switchDatabase(): hotMigrationFlag: $hotMigrationFlag");
  EMD_PERL_DEBUG("convert.switchDatabase(): dbInstancesArray: $dbInstancesArray");
  EMD_PERL_DEBUG("convert.switchDatabase(): asmInstancesArray: $asmInstancesArray");
  EMD_PERL_DEBUG("convert.switchDatabase(): targetDBReposDB: $targetDBReposDB");
  EMD_PERL_DEBUG("convert.switchDatabase(): parallelizeCopying: $parallelizeCopying");
  EMD_PERL_DEBUG("convert.switchDatabase(): tempIDs: $tempIDs");
  EMD_PERL_DEBUG("convert.switchDatabase(): tempDGs: $tempDGs");
  EMD_PERL_DEBUG("convert.switchDatabase(): asmTest: $asmTest");
  
  ###Define variables used in this sub
  
  my $spfileName;
  my $controlFileNamesArray;
  my $logFilesNamesArray;
  my $tempFiles;
  my $fileIds;
  my $sizes;
  my $tablespaces;
  my $autoextendClauses;
  my $backupLogs;
  my $isRac;
  my $dbName;
  my $anyOnlinelogOnDG;
  my $toLocationsForTempfiles;
  
  ###Get necessary info
  
  #Get init file name, non empty value means it is being used
  ($spfileName, $pfileFullName) = checkPfile($pfileFullName);
  
  #Get control file info
  $controlFileNamesArray = getControlFiles();
  
  #Get the fullnames of valid log files
  $logFilesNamesArray = getLogFiles();
  
  #Get tempfile names and attributes
  ($tempFiles, $fileIds, $sizes, $tablespaces, $autoextendClauses) = getTempFiles();
  
  #Get isRac and dbName
  ($isRac, $dbName) = getIsRacDbName();
  
  #check if any onlinelog resides on diskgroup
  $anyOnlinelogOnDG = isAnyOnlinelogOnDiskgroup($logFilesNamesArray);

  ###Backup database at level 1
  if($hotMigrationFlag eq "Y")
  {
    migrateDatafilesLevelOne($parallelizeCopying);
  }
  
  if($targetDBReposDB eq 'Y')
  {
    #startDeferOutput($logBackupLoc);
    startDeferOutput(&getDefaultDBLocation);
  }
  
  ###Shutdown database
  shutdownDB("immediate");
  
  #if rac, shutdown all instances
  shutdownAllInstances($isRac, $dbName);
  
  #if rac, disable crs service for the connected db instance
  if($isRac eq "Y")
  {
    runSrvctl("disable database -d $dbName");
  }
  
  ###Backup online logs
  #if($anyOnlinelogOnDG eq "N")
  #{
  #  $backupLogs = backupOnlineLogs($logBackupLoc, $logFilesNamesArray);
  #}
  
  ###Restore control file
  
  #reset control file parameters
  if($spfileName eq "")
  {
    commentCtlFileParamInitFile($pfileFullName);
  }
  else
  {
    modifySpfile($DELIMITER, $DELIMITER, "Y", "Y");
  }
  
  #Restore the control files to ASM and mount the instance
  my $restoredControlFiles = restoreControlFile($pfileFullName, $controlFileNamesArray);
  
  #if using pfile, add restored control files to init file and restart instance
  if($restoredControlFiles ne "")
  {
    addControlFileToInitFile($restoredControlFiles, $pfileFullName);
    shutdownDB("abort");
    startupDB("mount", $pfileFullName);
  }
  
  ###Migrate spfile
  
  if($isMigrateSPFile eq "Y")
  {
    my $initFile = migrateSPFile($pfileFullName, $spfileName, $migratedSpfile);
    shutdownDB("abort");
    startupDB("mount", $initFile);
  }
  
  ###Migrate datafiles
  if($hotMigrationFlag eq "Y")
  {
    ###Switch database to copies at ASM
    switchDatafileCopies();
    ###Recover database
    recoverDatabase();
  }
  else
  {
    migrateDatafiles($dbFileIDsArray, $dbFileLocsArray, $dbFilesLoc, $parallelizeCopying);
  }
    
  ###Drop temp files residing on file system
  dropTempfiles($tempFiles);
  
  #Generate restore log script before openning database
  #generateRestoreLogsScript($logBackupLoc, $backupLogs, $logFilesNamesArray);
  
  ###Open database
  alterDatabaseOpen();
  
  if($targetDBReposDB eq 'Y')
  {
    endDeferOutput();
  }
  
  ###Add temp files to ASM
  $toLocationsForTempfiles = getToLocationsForTempfiles($fileIds, $tempIDs, $tempDGs, $dbFilesLoc);
  addTempfilesConvert($toLocationsForTempfiles, $sizes, $tablespaces, $autoextendClauses);
  
  if($isRac eq "Y")
  {
    handleThreadsForOtherRacInstances($ENV{ORACLE_SID}, "disable");
  }
  
  ###Migrate online log files
  if($hotMigrationFlag eq "Y")
  {
    migrateOnlineLogsHot();
    migrateOnlineLogsStandbyHot();
  }
  else
  {
    migrateOnlineLogs();
  }
  
  if($isRac eq "Y")
  {
    handleThreadsForOtherRacInstances($ENV{ORACLE_SID}, "enable public");
  }
  
  #if rac, enable crs service for the connected db instance
  if($isRac eq "Y")
  {
    runSrvctl("enable database -d $dbName");
  }
  
  #if rac, startup all instances
  startupAllInstances($isRac, $dbName);
    
  if($isDeleteSourceDB ne "Y")
  {
    #Overwrite original online logs with the backup online logs
    if($anyOnlinelogOnDG eq "N")
    {
      #restoreOnlineLogs($backupLogs, $logFilesNamesArray);
    }
  }
  
  ###Migrate flashback files
  if($flashbackFlag eq "Y")
  {
    migrateFlashbackFiles($pfileFullName, $isRac, $dbName);
  }
  
  ###RAC: Associate database instances with asm instances
  associateDbAsmInstances($isRac, $dbName, $dbInstancesArray, $asmInstancesArray);
  
  ###Cleanup files on file system
  if($isDeleteSourceDB eq "Y")
  {
    #Cleanup database copy
    cleanupDBConvert();
    #delete other database files on file system
    &removeFiles($controlFileNamesArray);
    &removeFiles($logFilesNamesArray);
    &removeFiles($tempFiles);
  }
  
  #Remove the temp backup location
  if($asmTest ne "Y")
  {
    &removeDir($logBackupLoc);
  }
  
  EMD_PERL_DEBUG("convert.switchDatabase(): *** END ***");
}

# Verify the database has been moved to ASM (hot)
#
# Disable the block change tracking if it was off before the migration
# Verify all files are residing on ASM
#
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# postMigration(changeTrackingFlag, hotMigrationFlag)
sub postMigration
{
  EMD_PERL_DEBUG("convert.postMigration(): *** START ***");
  
  my ($changeTrackingFlag, $hotMigrationFlag) = @_;

  EMD_PERL_DEBUG("convert.postMigration(): changeTrackingFlag: $changeTrackingFlag");
  EMD_PERL_DEBUG("convert.postMigration(): hotMigrationFlag: $hotMigrationFlag");
  
  ###Disable/enable block change tracking 
  # Hot: if it was disabled before the migration, then disable it here
  # Cold: if it was enabled before the migration, then enable it here
  if($hotMigrationFlag eq "Y")
  {
    if($changeTrackingFlag eq "N")
    {
      #For now, do not disable the change tracking since it will delete the tracking
      #file and the original database has migrated its tracking file to ASM.
      #If disable, the original database is not openable.
      #checkAndDisableChangeTracking();
    }
  }
  else
  {
    if($changeTrackingFlag eq "Y")
    {
      enableChangeTracking();
    }
  }
  
  ###Verify all files are residing on ASM
  checkDatabaseFiles();

  EMD_PERL_DEBUG("convert.postMigration(): *** END ***");
}

# Migrate the target DB to ASM
# if hotMigrationFlag is set to "Y", do a hot migration, otherwise, do a cold migration
#
# HOT migration:
# Migrate the target DB to ASM with short outage
# Require the database be in ARCHIVELOG mode
#
# preMigration: migrate recovery files and backup the database as copies to ASM (hot)
# switchDatabase: switch database to ASM copies (cold)
# postMigration: disable or enable block change tracking files (hot)
#
# COLD migration:
# Migrate the target DB to ASM with long outage
# Do NOT require the target DB be in ARCHIVELOG mode
#
# preMigration: migrate recovery related files (hot)
# switchDatabase: backup datafiles as ASM copies and switch database to copies (cold)
# postMigration: disable or enable block change tracking files (hot)
#
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# Arguments values:
#   isMigrateDBFiles: Y/N, isMigrateRecoveryFiles: Y/N, archLogLocation: Y/N (migrate arch or not)
#   pfileFullName: a file full name/N, dbFilesLoc: one disk group, 
#   dbFileIDsArray: file ID's separated by delimiters,
#   dbFileLocsArray: disk groups separated by delimiters, 
#   isMigrateSPFile: Y/N, migratedSpfile: a unique file full name,
#   isDeleteSourceDB: Y/N, multiplexLocsArray: disk groups separated by delimiters,
#   recoveryFilesLoc: one disk group, recoveryFilesSize: size in MB, 
#   isSetupRecoveryAreaOnly: Y/N, logBackupLoc: location to backup logs
#   flashbackFlag: Y/N, changeTrackingFlag: Y/N, hotMigrationFlag: Y/N
#   dbInstancesArray: db instance names for RAC, 
#   asmInstancesArray: asm instance names for RAC, targetDBReposDB: Y/N 
#   parallelizeCopying: allocate multiple rman channels: Y/N
#   tempIDs, tempDGs: the id's and disk groups for temp files
#   asmTest: a flag for regression: Y/N
# migrateToASM(isMigrateDBFiles, isMigrateRecoveryFiles, archLogLocation, pfileFullName, 
# dbFilesLoc, dbFileIDsArray, dbFileLocsArray, isMigrateSPFile, migratedSpfile, 
# isDeleteSourceDB, multiplexLocsArray, recoveryFilesLoc, recoveryFilesSize, 
# isSetupRecoveryAreaOnly, logBackupLoc, flashbackFlag, changeTrackingFlag,hotMigrationFlag,
# dbInstancesArray, asmInstancesArray, targetDBReposDB, parallelizeCopying, tempIDs, tempDGs, 
# asmTest)
sub migrateToASM
{
  EMD_PERL_DEBUG("convert.migrateToASM(): *** START ***");
  
  my ($isMigrateDBFiles, $isMigrateRecoveryFiles, $archLogLocation, $pfileFullName, $dbFilesLoc,
      $dbFileIDsArray, $dbFileLocsArray, $isMigrateSPFile, $migratedSpfile, $isDeleteSourceDB, 
      $multiplexLocsArray, $recoveryFilesLoc, $recoveryFilesSize, $isSetupRecoveryAreaOnly, 
      $logBackupLoc, $flashbackFlag, $changeTrackingFlag, $hotMigrationFlag,
      $dbInstancesArray, $asmInstancesArray, $targetDBReposDB, $parallelizeCopying,
      $tempIDs, $tempDGs, $asmTest) = @_;
      
  EMD_PERL_DEBUG("convert.migrateToASM(): isMigrateDBFiles: $isMigrateDBFiles");
  EMD_PERL_DEBUG("convert.migrateToASM(): isMigrateRecoveryFiles: $isMigrateRecoveryFiles");
  EMD_PERL_DEBUG("convert.migrateToASM(): archLogLocation: $archLogLocation");
  EMD_PERL_DEBUG("convert.migrateToASM(): pfileFullName: $pfileFullName");
  EMD_PERL_DEBUG("convert.migrateToASM(): dbFilesLoc: $dbFilesLoc");
  EMD_PERL_DEBUG("convert.migrateToASM(): dbFileIDsArray: $dbFileIDsArray");
  EMD_PERL_DEBUG("convert.migrateToASM(): dbFileLocsArray: $dbFileLocsArray");
  EMD_PERL_DEBUG("convert.migrateToASM(): isMigrateSPFile: $isMigrateSPFile");
  EMD_PERL_DEBUG("convert.migrateToASM(): migratedSpfile: $migratedSpfile");
  EMD_PERL_DEBUG("convert.migrateToASM(): isDeleteSourceDB: $isDeleteSourceDB");
  EMD_PERL_DEBUG("convert.migrateToASM(): multiplexLocsArray: $multiplexLocsArray");
  EMD_PERL_DEBUG("convert.migrateToASM(): recoveryFilesLoc: $recoveryFilesLoc");
  EMD_PERL_DEBUG("convert.migrateToASM(): recoveryFilesSize: $recoveryFilesSize");
  EMD_PERL_DEBUG("convert.migrateToASM(): isSetupRecoveryAreaOnly: $isSetupRecoveryAreaOnly");
  #EMD_PERL_DEBUG("convert.migrateToASM(): logBackupLoc: $logBackupLoc");
  EMD_PERL_DEBUG("convert.migrateToASM(): flashbackFlag: $flashbackFlag");
  EMD_PERL_DEBUG("convert.migrateToASM(): changeTrackingFlag: $changeTrackingFlag");
  EMD_PERL_DEBUG("convert.migrateToASM(): hotMigrationFlag: $hotMigrationFlag");
  EMD_PERL_DEBUG("convert.migrateToASM(): dbInstancesArray: $dbInstancesArray");
  EMD_PERL_DEBUG("convert.migrateToASM(): asmInstancesArray: $asmInstancesArray");
  EMD_PERL_DEBUG("convert.migrateToASM(): targetDBReposDB: $targetDBReposDB");
  EMD_PERL_DEBUG("convert.migrateToASM(): parallelizeCopying: $parallelizeCopying");
  EMD_PERL_DEBUG("convert.migrateToASM(): tempIDs: $tempIDs");
  EMD_PERL_DEBUG("convert.migrateToASM(): tempDGs: $tempDGs");
  EMD_PERL_DEBUG("convert.migrateToASM(): asmTest: $asmTest");
  
  preMigration($isMigrateDBFiles, $isMigrateRecoveryFiles, $isSetupRecoveryAreaOnly,
               $dbFilesLoc, $recoveryFilesSize, $recoveryFilesLoc, $archLogLocation,
               $dbFileIDsArray, $dbFileLocsArray, $pfileFullName, $multiplexLocsArray,
               $hotMigrationFlag, $logBackupLoc, $parallelizeCopying);
               
  if($isMigrateDBFiles eq "Y") 
  {
    switchDatabase($pfileFullName, $dbFilesLoc, $dbFileIDsArray, $dbFileLocsArray,
                   $isMigrateSPFile, $migratedSpfile, $isDeleteSourceDB, $logBackupLoc, 
                   $flashbackFlag, $hotMigrationFlag, $dbInstancesArray, 
                   $asmInstancesArray, $targetDBReposDB, $parallelizeCopying, 
                   $tempIDs, $tempDGs, $asmTest);
  }
  
  if($isMigrateDBFiles eq "Y") 
  {
    postMigration($changeTrackingFlag, $hotMigrationFlag);
  }

  EMD_PERL_DEBUG("convert.migrateToASM(): *** END ***");
}
1;

#Tests
sub main_convert
{
  #General tests

  $ENV{EMAGENT_PERL_TRACE_LEVEL} = 0;

  set_env("/private2/oracle/10.1.0.2", "v10102");
  #set_env("/private2/oracle/10.1.0.2", "v10102", "/private2/oracle/10.1.0.2/network/admin/listener.ora");

  #NT
  #set_env("C:/ade/szhu_sa0804/oracle", "ssa0804");

  setSrcDBCredential("sys", "oracle");
  
  #define variables for testing

  #Hot migration requires the DB ruuning in ARCHIVELOG mode
  my $hotMigrationFlag = "Y";
  
  my $isMigrateDBFiles = "Y";
  my $isMigrateRecoveryFiles = "Y";
  my $archLogLocation = "N";
  my $pfileFullName = "/private2/oracle/10.1.0.2/dbs/initv10102.ora";
  my $dbFilesLoc = "+DATA1";
  my $dbFileIDsArray = "1:::2:::3:::4:::";
  my $dbFileLocsArray = "+DATA1:::+DATA2:::+DATA3:::+DATA3:::";
  my $isMigrateSPFile = "N";
  my $migratedSpfile = "+DATA1/v10102/spfilev10102.ora_121";
  my $isDeleteSourceDB = "N";
  my $multiplexLocsArray = ":::";
  my $recoveryFilesLoc = "+DATA2";
  my $recoveryFilesSize = "2048M";
  my $isSetupRecoveryAreaOnly = "Y";
  my $logBackupLoc = "/private2/oracle/10.1.0.2/dbs/v10102_121";
  my $flashbackFlag = "N";
  my $changeTrackingFlag = "N"; 
  my $dbInstancesArray = ":::";
  my $asmInstancesArray = ":::";
  my $targetDBReposDB = ":::";
  my $parallelizeCopying = "N";
  my $tempIDs = ":::";
  my $tempDGs = ":::";
  my $asmTest = "N";
  
  #test view db
  $hotMigrationFlag = "Y";
  $isSetupRecoveryAreaOnly = "Y";
  #set_env("/ade/szhu_sa0506/oracle", "ssa0506");
  #setSrcDBCredential("sysman", "sysman");
  #$pfileFullName = "/ade/szhu_sa0506/oracle/dbs/initssa0506.ora";
  #$migratedSpfile = "+DATA1/ssa0506/spfilessa0506.ora_121";
  #$logBackupLoc = "/ade/szhu_sa0506/oracle/dbs/ssa0506_121";
  
  migrateToASM($isMigrateDBFiles, $isMigrateRecoveryFiles, $archLogLocation, $pfileFullName, $dbFilesLoc,
  $dbFileIDsArray, $dbFileLocsArray, $isMigrateSPFile, $migratedSpfile, $isDeleteSourceDB, 
  $multiplexLocsArray, $recoveryFilesLoc, $recoveryFilesSize, $isSetupRecoveryAreaOnly, 
  $logBackupLoc, $flashbackFlag, $changeTrackingFlag, $hotMigrationFlag, $dbInstancesArray, 
  $asmInstancesArray, $targetDBReposDB, $parallelizeCopying, $tempIDs, $tempDGs, $asmTest);
}

#main_convert();
