# $Header: emdb/sysman/webapps/em/WEB-INF/perl/db_clone_10_2.pl /st_emdbsa_11.2/4 2010/10/07 10:35:51 sjconnol Exp $
#
# db_clone_10_2.pl
# 
# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 
#
# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      db_clone_10_2.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      This script extends sysman/admin/scripts/db/dbclone/db_clone.pl
#      to hold new and modified scripts for 10gR2 release.
#      All script for 10gR2 should be added in this file.
#      10gR2 OMS uses the original db_clone.pl and db_clone_10_2.pl.
#      10gR1 OMS only uses the original db_clone.pl.
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    sjconnol    10/04/10 - Bug 10162200
#    rimmidi     03/13/09 - Bug fix 8323159
#    mmootha     09/22/08 - 
#    rimmidi     09/04/08 - Backport rimmidi_bug-6139170 from main
#    sxzhu       03/26/07 - Use ComSpec for sc
#    sxzhu       01/05/07 - Support customer script
#    sxzhu       12/10/06 - Workaround emctl start dbconsole in view
#    sxzhu       10/25/06 - Workaround EMCA in views on Windows 
#    sxzhu       08/30/06 - Set linesize
#    sxzhu       08/21/06 - Workaround bug 5443957
#    sxzhu       06/29/06 - Use RMAN duplicate
#    sxzhu       06/28/06 - User RMAN backup
#    sxzhu       06/28/06 - Fix oracle_version to get OMF name
#    sxzhu       08/27/05 - Add createSpfile on ASM
#    rimmidi     08/28/08 - Backport rimmidi_bug-6139170 from main
#    rimmidi     05/05/08 - Code slap from 11GC to 10.2.0.5
#    rpattabh    04/16/08 - Project 25671: Clone Mask Integration
#    sxzhu       08/14/06 - Backport fix for bug 5352507
#    sxzhu       08/27/05 - Add createSpfile on ASM
#    sxzhu       08/14/05 - Handle no ORDSYS
#    sxzhu       07/29/05 - Use dyanmic sql to get db version
#    sxzhu       07/21/05 - Add reWriteNetConfigFiles()
#    sxzhu       06/07/05 - Remove version check
#    sxzhu       05/16/05 - Handle open resetlogs with RAC
#    sxzhu       04/20/05 - Handle cold clone for switchDatafileCopy
#    sxzhu       04/07/05 - Handle large plsql output
#    sxzhu       03/22/05 - Config dbconsole for ASM database
#    sxzhu       02/14/05 - Set dbsnmp passwd during configuring db ctl
#    sxzhu       01/31/05 - Add getDirsFromFiles
#    sxzhu       11/11/04 - Configure dbconsole after cloning db
#    sxzhu       10/27/04 - Specify disk group locations when adding tempfile
#    sjconnol    09/08/04 - Change mount cmd for pre-10g standbys
#    sjconnol    08/10/04 - Add addLogfiles_10_2
#    sxzhu       08/06/04 - Use automatic recovery to handle rac db
#    sxzhu       08/05/04 - Handle 817 DB
#    sxzhu       08/02/04 - Pass in datafile names for non-OMF db
#    sxzhu       07/30/04 - sxzhu_clone_0721
#    sxzhu       07/09/04 - Creation
#

require "$ENV{EMDROOT}/sysman/admin/scripts/db/dbclone/db_clone.pl";

use strict;
use warnings;
use DBI;

use vars qw/ $userID $clonePurpose $clodClone $OS $NT $S $TEMP $CP $MV $PS $DF $DELIMITER
             $AGENT_ORACLE_HOME $AGENT_LD_LIBRARY_PATH $AGENT_SHLIB_PATH $AGENT_LIBPATH
             $AGENT_PATH $AGENT_JAVA_HOME $AGENT_ORA_NLS $AGENT_ORA_NLS32 $AGENT_ORA_NLS33
             $TARGET_ORACLE_HOME $TARGET_ORACLE_SID
             $TNS_CONNECTION_STRING
           /;

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

# Restore backup control file to destination database and mount the database
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# restoreBackupControlFile(backupCtlFileName, useRMANBackup)
sub restoreBackupControlFile
{
  EMD_PERL_DEBUG("db_clone_10_2.restoreBackupControlFile(): *** START ***");

  my ($backupCtlFileName, $useRMANBackup) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.restoreBackupControlFile(): backupCtlFileName: $backupCtlFileName");
  if(defined($useRMANBackup)) {
    EMD_PERL_DEBUG("db_clone_10_2.restoreBackupControlFile(): useRMANBackup: $useRMANBackup");
  }

  #restore backup control file
  my $sql_string = "";

  if(defined($useRMANBackup) && $useRMANBackup eq 'Y')
  {
    my $restored_controlfile = ${backupCtlFileName}.'_temp';
    $sql_string .= "set echo off\n";

    $sql_string .= "variable devicename varchar2(255);\n";

    $sql_string .= "declare\n";
    $sql_string .= "  done boolean;\n";

    $sql_string .= "BEGIN\n";
    $sql_string .= "  :devicename := dbms_backup_restore.deviceAllocate;\n";
    $sql_string .= "  dbms_backup_restore.restoreSetDataFile;\n";
    $sql_string .= "  dbms_backup_restore.restoreControlfileTo('$restored_controlfile');\n";
    $sql_string .= "  dbms_backup_restore.restoreBackupPiece('$backupCtlFileName', done);\n\n";
    $sql_string .= "END;\n";
    $sql_string .= "/\n";
    $sql_string .= "EXIT;\n\n";

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

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

    #swap the backup and restored control file
    &removeFile($backupCtlFileName);
    &copyFile($restored_controlfile, $backupCtlFileName);
    &removeFile($restored_controlfile);
  }

  $sql_string = "";
  $sql_string .= "set echo off\n";

  $sql_string .= "declare\n";
  $sql_string .= "  src_name  varchar2(512);\n";
  $sql_string .= "  dest_name varchar2(512);\n";
  $sql_string .= "  full_name varchar2(512);\n";
  $sql_string .= "  recid     number;\n";
  $sql_string .= "  stamp     number;\n";

  $sql_string .= "BEGIN\n";
  $sql_string .= "  src_name := sys.dbms_backup_restore.normalizefilename('$backupCtlFileName');\n";
  $sql_string .= "  for i in 1..999 loop\n";
  $sql_string .= "    dest_name := sys.dbms_backup_restore.getparm(\n";
  $sql_string .= "                   sys.dbms_backup_restore.control_file, i);\n";
  $sql_string .= "    if dest_name is null then exit; end if;\n";
  $sql_string .= "    if src_name <> dest_name then\n";
  $sql_string .= "      sys.dbms_backup_restore.copyControlFile(src_name  => src_name,\n";
  $sql_string .= "                                              dest_name => dest_name,\n";
  $sql_string .= "                                              recid     => recid,\n";
  $sql_string .= "                                              stamp     => stamp,\n";
  $sql_string .= "                                              full_name => full_name);\n";
  $sql_string .= "    end if;\n";
  $sql_string .= "  end loop;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "\n";
  $sql_string .= "EXIT;\n\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.restoreBackupControlFile(): *** END ***");
}

# Mount the newly created DB instance and leanup datafile copy records
# from the backup control file's v$datafile_copy.
# NOTE: this is for 10g and later db only.
# The database instance should be mounted.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# mountInstanceCleanupControlFileDatafileCopy(v9i, v10g)
sub mountInstanceCleanupControlFileDatafileCopy
{
  EMD_PERL_DEBUG("db_clone_10_2.mountInstanceCleanupControlFileDatafileCopy(): *** START ***");

  my ($v9i, $v10g) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.mountInstanceCleanupControlFileDatafileCopy(): v9i: $v9i");
  EMD_PERL_DEBUG("db_clone_10_2.mountInstanceCleanupControlFileDatafileCopy(): v10g: $v10g");

  if($v9i ne 'Y')
  {
    EMD_PERL_DEBUG("db_clone_10_2.mountInstanceCleanupControlFileDatafileCopy(): Do not mount the instance, returning");
    EMD_PERL_DEBUG("db_clone_10_2.mountInstanceCleanupControlFileDatafileCopy(): *** END ***");
    return;
  }

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n\n";

  # Different mount cmd for 9.2 phys standby
  if(($clonePurpose eq "STANDBY_NO_RECOVERY") && ($v10g ne 'Y')){
    $sql_string .= "alter database mount standby database;\n";
  }
  else{
    $sql_string .= "alter database mount;\n";
  }

  if($v10g eq 'Y')
  {
    $sql_string .= "execute sys.dbms_backup_restore.resetCfileSection(dbms_backup_restore.RTYP_DFILE_COPY);\n";
  }

  $sql_string .= "EXIT;\n";

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

  EMD_PERL_DEBUG("db_clone_10_2.mountInstanceCleanupControlFileDatafileCopy(): *** END ***");
}

# Backup one datafile and store it as given backupPieceName
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# backupOneDatafileWithCompressOpt(backupPieceName, fileNum, compressBackupFiles)
sub backupOneDatafileWithCompressOpt
{
  EMD_PERL_DEBUG("db_clone_10_2.backupOneDatafileWithCompressOpt(): *** START ***");

  my ($backupPieceName, $fileNum, $compressBackupFiles) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.backupOneDatafileWithCompressOpt(): fileNum to be backed up: $fileNum");
  EMD_PERL_DEBUG("db_clone_10_2.backupOneDatafileWithCompressOpt(): fileName to store backup piece: $backupPieceName");
  EMD_PERL_DEBUG("db_clone_10_2.backupOneDatafileWithCompressOpt(): Compress backup files flag: $compressBackupFiles");

  #backup one datafile
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";

  $sql_string .= "variable devicename varchar2(255);\n";
  $sql_string .= "variable set_stamp  number;\n";
  $sql_string .= "variable set_count  number;\n\n";

  $sql_string .= "declare\n";
  $sql_string .= "  pieceno binary_integer;\n";
  $sql_string .= "  done    boolean;\n";
  $sql_string .= "  handle  varchar2(256);\n";
  $sql_string .= "  comment varchar2(256);\n";
  $sql_string .= "  media   varchar2(256);\n";
  $sql_string .= "  concur  boolean;\n";
  $sql_string .= "  params  varchar2(256);\n";
  $sql_string .= "  archlog_failover boolean;\n";
  $sql_string .= "  recid number;\n";
  $sql_string .= "  stamp number;\n";
  $sql_string .= "  tag varchar2(32);\n\n";

  $sql_string .= "BEGIN\n";
  $sql_string .= "  :devicename := dbms_backup_restore.deviceAllocate;\n";
  $sql_string .= "  dbms_backup_restore.backupSetDataFile(:set_stamp, :set_count);\n";
  $sql_string .= "  dbms_backup_restore.backupDataFile($fileNum);\n";
  $sql_string .= "  dbms_backup_restore.backupPieceCreate('$backupPieceName',\n";
  $sql_string .= "                                        pieceno, done,\n";
  $sql_string .= "                                        handle, comment,\n";
  $sql_string .= "                                        media, concur,\n";

  if($compressBackupFiles eq 'Y')
  {
    $sql_string .= "                                        params, reuse=>true,\n";
    $sql_string .= "                                        archlog_failover=>archlog_failover, deffmt=>0,\n";
    $sql_string .= "                                        recid=>recid, stamp=>stamp,\n";
    $sql_string .= "                                        tag=>tag, docompress=>true);\n";
  }
  else
  {
    $sql_string .= "                                        params, reuse=>true);\n";
  }

  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n\n";

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

  EMD_PERL_DEBUG("db_clone_10_2.backupOneDatafileWithCompressOpt(): *** END ***");
}

# getRestoreOneDatafileSqlSrcipt(backupPieceName, fileNum, fileName, deletePiece,
#                                omfFlag, asmFlag)
sub getRestoreOneDatafileSqlSrcipt
{
  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): *** START ***");

  my ($backupPieceName, $fileNum, $fileName, $deletePiece, $omfFlag, $asmFlag) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): Backup piece name: $backupPieceName");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): File number to be restored: $fileNum");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): The given file name: $fileName");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): Delete backup piece: $deletePiece");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): omfFlag: $omfFlag");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): asmFlag: $asmFlag");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "variable devicename varchar2(255);\n";

  $sql_string .= "declare\n";
  $sql_string .= "  done boolean;\n";
  $sql_string .= "  oracle_version number;\n";
  $sql_string .= "  tbsName varchar2(30);\n";
  $sql_string .= "  omfname varchar2(512) := NULL;\n";

  $sql_string .= "BEGIN\n";
  $sql_string .= "  :devicename := dbms_backup_restore.deviceAllocate;\n";
  $sql_string .= "  dbms_backup_restore.restoreSetDataFile;\n";

  if($omfFlag eq "Y")
  {
    $sql_string .= "  oracle_version := sys.dbms_backup_restore.protocol_version_number_max;\n";
    $sql_string .= "  IF (oracle_version >= 9)\n";
    $sql_string .= "  THEN\n";
    $sql_string .= "    SELECT ts.name INTO tbsName FROM V\$DATAFILE df, V\$TABLESPACE ts WHERE df.file# = $fileNum and df.ts# = ts.ts#;\n";
    $sql_string .= "    dbms_backup_restore.getOMFFileName(tbsName, omfname);\n";
    $sql_string .= "    IF (omfname is NOT NULL)\n";
    $sql_string .= "    THEN\n";
    $sql_string .= "      IF (oracle_version >= 10)\n";
    $sql_string .= "      THEN\n";
    $sql_string .= "        dbms_backup_restore.restoreDataFileTo($fileNum, omfname, 0, tbsName);\n";
    $sql_string .= "      ELSE\n";
    $sql_string .= "        dbms_backup_restore.restoreDataFileTo($fileNum, omfname);\n";
    $sql_string .= "      END IF;\n";
    $sql_string .= "    END IF;\n";
    $sql_string .= "  END IF;\n";
  }
  elsif($asmFlag eq "Y")
  {
    $sql_string .= "  SELECT ts.name INTO tbsName FROM V\$DATAFILE df, V\$TABLESPACE ts WHERE df.file# = $fileNum and df.ts# = ts.ts#;\n";
    $sql_string .= "  dbms_backup_restore.restoreDataFileTo($fileNum, '$fileName', 0, tbsName);\n";
  }
  else
  {
    $sql_string .= "  dbms_backup_restore.restoreDataFileTo($fileNum, '$fileName');\n";
  }

  $sql_string .= "  dbms_backup_restore.restoreBackupPiece('$backupPieceName', done);\n\n";

  if($deletePiece eq 'Y')
  {
    $sql_string .= "  IF done then\n";
    $sql_string .= "    dbms_backup_restore.deletefile('$backupPieceName');\n";
    $sql_string .= "  end if;\n";
  }

  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n\n";

  EMD_PERL_DEBUG("db_clone_10_2.getRestoreOneDatafileSqlSrcipt(): *** END ***");

  return $sql_string;
}

# Restore one datafile as given name or OMF name
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# restoreOneDatafileOmf(backupPieceName, fileNum, fileName, omfFlag, asmFlag, keepPieceFlag)
sub restoreOneDatafileOmf
{
  EMD_PERL_DEBUG("db_clone_10_2.restoreOneDatafileOmf(): *** START ***");

  my ($backupPieceName, $fileNum, $fileName, $omfFlag, $asmFlag, $keepPieceFlag) = @_;

  my $deletePieceFlag = 'Y';

  if(defined($keepPieceFlag))
  {
    $deletePieceFlag = 'N';
  }

  my $sql_string = getRestoreOneDatafileSqlSrcipt($backupPieceName, $fileNum, $fileName, $deletePieceFlag, $omfFlag, $asmFlag);

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

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

  EMD_PERL_DEBUG("db_clone_10_2.restoreOneDatafileOmf(): *** END ***");
}

# Restore one datafile as the given fileName or OMF name on same host
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# restoreOneDatafileOmfSameHost(backupPieceName, fileNum, fileName, omfFlag, asmFlag)
sub restoreOneDatafileOmfSameHost
{
  EMD_PERL_DEBUG("db_clone_10_2.restoreOneDatafileOmfSameHost(): *** START ***");

  my ($backupPieceName, $fileNum, $fileName, $omfFlag, $asmFlag) = @_;

  my $sql_string = getRestoreOneDatafileSqlSrcipt($backupPieceName, $fileNum, $fileName, 'N', $omfFlag, $asmFlag);

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

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

  EMD_PERL_DEBUG("db_clone_10_2.restoreOneDatafileOmfSameHost(): *** END ***");
}

# Get datafile copy list attributes (separated by delimiters)
# Return recids and stamps
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getDatafileCopyListBack(maxStamp)
sub getDatafileCopyListBack
{
  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): *** START ***");

  my ($maxStamp) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): maxStamp: $maxStamp");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\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 recid, stamp \n";
  $sql_string .= "                FROM v\$datafile_copy \n";
  $sql_string .= "                WHERE status = 'A' and checkpoint_change# > $maxStamp )\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('recid# '||tfrec.recid);\n";
  $sql_string .= "    dbms_output.put_line('stamp# '||tfrec.stamp);\n";
  $sql_string .= "    i := i + 1;\n";
  $sql_string .= "  END LOOP;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  my $hideOutput = "";
  (my $fh, my $filename) = &runSqlOnDestination($sql_string, $hideOutput);

  my $recid = "";
  my $recids = "";
  my $stamp = "";
  my $stamps = "";

  open (DATAFILE_COPY, "$filename") || die "Unable to open tempfile for DATAFILE_COPY\n";
  while (<DATAFILE_COPY>)
  {
    if ($_=~/\brecid#/)
    {
      chomp($_);
      $recid = substr $_, 7; #recid starts from position 7
      $recids .= ${recid}.${DELIMITER};
    }
    if ($_=~/\bstamp#/)
    {
      chomp($_);
      $stamp = substr $_, 7; #stamp starts from position 7
      $stamps .= ${stamp}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): datafile copy recids: $recids");
  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): datafile copy stamps: $stamps");

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): *** END ***");

  return ($recids, $stamps);
}

# Get datafile copy list attributes (separated by delimiters)
# Return recids and stamps
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getDatafileCopyList(maxStamp)
sub getDatafileCopyList
{
  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): *** START ***");

  my ($maxStamp) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): maxStamp: $maxStamp");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 512;\n";

  $sql_string .= "SELECT 'recid# ' as \"R_FLAG\", recid, 'stamp# ' as \"S_FLAG\", stamp \n";
  $sql_string .= "FROM v\$datafile_copy \n";
  $sql_string .= "WHERE status = 'A' and checkpoint_change# > $maxStamp; \n";

  $sql_string .= "EXIT;\n";

  my $hideOutput = "";
  (my $fh, my $filename) = &runSqlOnDestination($sql_string, $hideOutput);

  my $recid = "";
  my $recids = "";
  my $stamp = "";
  my $stamps = "";
  my @tokens;

  open (DATAFILE_COPY, "$filename") || die "Unable to open tempfile for DATAFILE_COPY\n";
  while (<DATAFILE_COPY>)
  {
    if (($_=~/\brecid#/) && ($_=~/stamp#/))
    {
      chomp($_);
      @tokens = split;
      $recid = trim($tokens[1]);
      $recids .= ${recid}.${DELIMITER};
      $stamp = trim($tokens[3]);
      $stamps .= ${stamp}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): datafile copy recids: $recids");
  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): datafile copy stamps: $stamps");

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileCopyList(): *** END ***");

  return ($recids, $stamps);
}

# Switch datafile copies
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# switchDatafileCopy(maxStamp)
sub switchDatafileCopy
{
  EMD_PERL_DEBUG("db_clone_10_2.switchDatafileCopy(): *** START ***");

  my ($maxStamp) = @_;

  (my $recids, my $stamps) = getDatafileCopyList($maxStamp);

  my @dfRecids = split /$DELIMITER/, $recids;
  my @dfStamps = split /$DELIMITER/, $stamps;

  EMD_PERL_DEBUG("db_clone_10_2.switchDatafileCopy(): recids: @dfRecids");
  EMD_PERL_DEBUG("db_clone_10_2.switchDatafileCopy(): stamps: @dfStamps");

  my $sql_string = "";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";

  my $recid;
  my $index = 0;
  foreach $recid (@dfRecids)
  {
    $sql_string .= "  dbms_backup_restore.switchToCopy($recid, $dfStamps[$index]);\n";
    $index ++;
  }

  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.switchDatafileCopy(): *** END ***");
}

# Get restored datafile ids and names
# The datafile names will be used to create new control file
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getRestoredDatafilesAfterSwitchingCopy()
sub getRestoredDatafilesAfterSwitchingCopy
{
  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\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 dfrec IN (SELECT file#, name FROM V\$DATAFILE WHERE status = 'ONLINE' OR status = 'SYSTEM')\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('file# '||dfrec.file#);\n";
  $sql_string .= "    dbms_output.put_line('name# '||dfrec.name);\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) = &runSqlOnDestination($sql_string);

  my $fileid = "";
  my $fileids = "";
  my $dfname = "";
  my $dfnames = "";

  open (DATAFILE_NUM_NAME, "$filename") || die "Unable to open tempfile for DATAFILE_NUM_NAME\n";
  while (<DATAFILE_NUM_NAME>)
  {
    if (($_=~/\d/) && ($_=~/\bfile#/))
    {
      chomp($_);
      $fileid = substr $_, 6; #fileid starts from position 6
      $fileids .= ${fileid}.${DELIMITER};
    }
    if ($_=~/\bname#/)
    {
      chomp($_);
      $dfname = substr $_, 6; #dfname starts from position 6
      $dfnames .= ${dfname}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): datafile ids: $fileids");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): datafile names: $dfnames");

  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): *** END ***");

  return ($fileids, $dfnames);
}

# Get offline datafile ids and names
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getOfflineDatafiles()
sub getOfflineDatafiles
{
  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafiles(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\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 dfrec IN (SELECT file#, name FROM V\$DATAFILE WHERE status = 'OFFLINE' order by file#)\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('file# '||dfrec.file#);\n";
  $sql_string .= "    dbms_output.put_line('name# '||dfrec.name);\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) = &runSqlOnDestination($sql_string);

  my $fileid = "";
  my $fileids = "";
  my $dfname = "";
  my $dfnames = "";

  open (DATAFILE_NUM_NAME, "$filename") || die "Unable to open tempfile for DATAFILE_NUM_NAME\n";
  while (<DATAFILE_NUM_NAME>)
  {
    if (($_=~/\d/) && ($_=~/\bfile#/))
    {
      chomp($_);
      $fileid = substr $_, 6; #fileid starts from position 6
      $fileids .= ${fileid}.${DELIMITER};
    }
    if ($_=~/\bname#/)
    {
      chomp($_);
      $dfname = substr $_, 6; #dfname starts from position 6
      $dfnames .= ${dfname}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafiles(): datafile ids: $fileids");
  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafiles(): datafile names: $dfnames");

  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafiles(): *** END ***");

  return ($fileids, $dfnames);
}

# Get offline datafile ids and names
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getOfflineDatafilesFromDatafileCopy(fileIds)
sub getOfflineDatafilesFromDatafileCopy
{
  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): *** START ***");

  my ($offlineFileIds) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): offline datafile ids: $offlineFileIds");

  my $fileNumbers = "";

  my @fileNumberArray = split /$DELIMITER/, $offlineFileIds;

  if($#fileNumberArray < 1)
  {
    EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): No offline datafiles");
    EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): *** END ***");
    return ("", "");
  }

  foreach (0 .. $#fileNumberArray - 1)
  {
    $fileNumbers .= $fileNumberArray[$_];
    $fileNumbers .= ",";
  }
  $fileNumbers .= $fileNumberArray[$#fileNumberArray];

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\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 dfrec IN (SELECT file#, name FROM V\$DATAFILE_COPY WHERE file# in ( $fileNumbers ) order by file#)\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('file# '||dfrec.file#);\n";
  $sql_string .= "    dbms_output.put_line('name# '||dfrec.name);\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) = &runSqlOnDestination($sql_string);

  my $fileid = "";
  my $fileids = "";
  my $dfname = "";
  my $dfnames = "";

  open (DATAFILE_NUM_NAME, "$filename") || die "Unable to open tempfile for DATAFILE_NUM_NAME\n";
  while (<DATAFILE_NUM_NAME>)
  {
    if (($_=~/\d/) && ($_=~/\bfile#/))
    {
      chomp($_);
      $fileid = substr $_, 6; #fileid starts from position 6
      $fileids .= ${fileid}.${DELIMITER};
    }
    if ($_=~/\bname#/)
    {
      chomp($_);
      $dfname = substr $_, 6; #dfname starts from position 6
      $dfnames .= ${dfname}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): datafile ids: $fileids");
  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): datafile names: $dfnames");

  EMD_PERL_DEBUG("db_clone_10_2.getOfflineDatafilesFromDatafileCopy(): *** END ***");

  return ($fileids, $dfnames);
}

# This version does not require switching the datafile copies.
# It gets datafile names from v$datafile_copy and need to clean up the
# temp control file before restoring datafiles.
# It may be useful if we do not want to use the temp control file to recover
# the database.  In this case, we either create a new control file, or
# use the backup control file from source database (and rename datafiles) to
# do the recovery.
# Get restored datafile ids and names
# The datafile names will be used to create new control file
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getRestoredDatafiles()
sub getRestoredDatafiles
{
  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 513;\n";
  $sql_string .= "declare\n";
  $sql_string .= "  i    binary_integer := 1;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";
  ## Get all datafile names for DG
  if($clonePurpose eq "STANDBY_NO_RECOVERY" || $clonePurpose =~ /LOGICAL_STANDBY/){
    $sql_string .= "  FOR dfrec IN (SELECT c.file#, c.name FROM V\$DATAFILE_COPY c, V\$DATAFILE d WHERE c.file# <> 0 AND c.file# = d.file#)\n";
  }
  else{
    $sql_string .= "  FOR dfrec IN (SELECT c.file#, c.name FROM V\$DATAFILE_COPY c, V\$DATAFILE d WHERE c.file# <> 0 AND c.file# = d.file# AND (d.status = 'ONLINE' OR d.status = 'SYSTEM'))\n";
  }

  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('file# '||dfrec.file#);\n";
  $sql_string .= "    dbms_output.put_line('name# '||dfrec.name);\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) = &runSqlOnDestination($sql_string);

  my $fileid = "";
  my $fileids = "";
  my $dfname = "";
  my $dfnames = "";

  open (DATAFILE_NUM_NAME, "$filename") || die "Unable to open tempfile for DATAFILE_NUM_NAME\n";
  while (<DATAFILE_NUM_NAME>)
  {
    if (($_=~/\d/) && ($_=~/\bfile#/))
    {
      chomp($_);
      $fileid = substr $_, 6; #fileid starts from position 6
      $fileids .= ${fileid}.${DELIMITER};
    }
    if ($_=~/\bname#/)
    {
      chomp($_);
      $dfname = substr $_, 6; #dfname starts from position 6
      $dfnames .= ${dfname}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): datafile ids: $fileids");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): datafile names: $dfnames");

  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): *** END ***");

  return ($fileids, $dfnames);
}

# Modify init parameter file
# If the name is found, comment it with '#'
# commentInitFileEntry(modifiedParamNames, pfileFullName)
sub commentInitFileEntry
{
  EMD_PERL_DEBUG("db_clone_10_2.commentInitFileEntry(): *** START ***");

  my ($modifiedParamNames, $pfileFullName) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.commentInitFileEntry(): modifiedParamNames: $modifiedParamNames");

  my @modifiedParamNames = split /$DELIMITER/, $modifiedParamNames;

  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();
  if($NT)
  {
    $filename = "$TEMP\\"."dbclone.$$";
  }
  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("db_clone_10_2.modifyInitFileContent(): Error copying $filename to $pfileFullName") && (die "db_clone_10_2.modifyInitFileContent(): Error copying $filename to $pfileFullName"));

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

  EMD_PERL_DEBUG("db_clone_10_2.commentInitFileEntry(): *** END ***");
}

# Create new init parameter file to have new (target) database name
# Also comment control_files and db_unique_name entries
# startup db in nomount state (create spfile if necessary)
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# modifyInitFileWithTargetDBName(pfileFullName, spfile, targetDB)
sub modifyInitFileWithTargetDBName
{
  EMD_PERL_DEBUG("db_clone_10_2.modifyInitFileWithTargetDBName(): *** START ***");

  my ($pfileFullName, $spfile, $targetDB) = @_;

  &commentInitFileEntry("control_files".${DELIMITER}."db_name".${DELIMITER}."db_unique_name".${DELIMITER}."lock_name_space", $pfileFullName);
  &modifyInitFile("db_name", $targetDB, $pfileFullName);

  &clonePrepare($pfileFullName, $spfile);

  EMD_PERL_DEBUG("db_clone_10_2.modifyInitFileWithTargetDBName(): *** END ***");
}

# Modify init parameter file based on destination host properties
# modifyInitFile(modifiedParamNames, modifiedParamValues, pfileFullName)
# (This is copied from db_clone.pl modifyInitFile; need to move it to OMS side.)
sub modifyInitFile_102
{
  EMD_PERL_DEBUG("db_clone.modifyInitFile(): *** START ***");

  my ($modifiedParamNames, $modifiedParamValues, $pfileFullName) = @_;

  ## For Data Guard; *_file_name_convert params are comma-separated
  ##  lists; the commas will mess-up the array parsing above, so
  ##  they come in from the java as # instead of commans. Need
  ##  to put them back to commas here
  $modifiedParamValues =~ s/%%%/'/g;
  $modifiedParamValues =~ s/\'#\'/\',\'/g;
  $modifiedParamValues =~ s/ROLES#ONLINE/ROLES,ONLINE/g;
  $modifiedParamValues =~ s/ROLE#STANDBY/ROLE,STANDBY/g;
  $modifiedParamValues =~ s/ALL_ROLES#ALL_LOGFILES/ALL_ROLES,ALL_LOGFILES/g;
  $modifiedParamValues =~ s/ALL_LOGFILES#ALL_ROLES/ALL_LOGFILES,ALL_ROLES/g;
  $modifiedParamValues =~ s/ALL_ROLES#ONLINE_LOGFILE/ALL_ROLES,ONLINE_LOGFILE/g;
  $modifiedParamValues =~ s/ONLINE_LOGFILE#ALL_ROLES/ONLINE_LOGFILE,ALL_ROLES/g;
  $modifiedParamValues =~ s/STANDBY_ROLE#STANDBY_LOGFILE/STANDBY_ROLE,STANDBY_LOGFILE/g;
  $modifiedParamValues =~ s/STANDBY_LOGFILE#STANDBY_ROLE/STANDBY_LOGFILE,STANDBY_ROLE/g;

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

  #Replace the "###" with "'" in $modifiedParamValues since job system reserves ","
  #This is for control file name delimiters
  #$modifiedParamValues =~ s/###/'/g;

  EMD_PERL_DEBUG("db_clone.modifyInitFile(): modifiedParamNames: $modifiedParamNames");
  EMD_PERL_DEBUG("db_clone.modifyInitFile(): 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("db_clone.modifyInitFile(): INIT_ORA_FILE:\n $file_string");
  }

  EMD_PERL_DEBUG("db_clone.modifyInitFile(): *** END ***");
}

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

  my $sql_string = "";
  $sql_string .= "set echo off\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, name FROM v\$controlfile WHERE status is NULL)\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('filename# '||cfrec.name);\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) = &runSqlOnDestination($sql_string);
  my $controlFile = "";
  my $controlFiles = "";
  open (CONTROL_FILE, "$filename") || die "Unable to open tempfile for CONTROL_FILE\n";
  while (<CONTROL_FILE>)
  {
    if ($_=~/\bfilename#/)
    {
      chomp($_);
      $controlFile = substr $_, 10; #controlFile name starts from position 10
      $controlFiles .= ${controlFile}.${DELIMITER};
      EMD_PERL_DEBUG("db_clone_10_2.getControlFiles(): Filename: $controlFile");
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getControlFiles(): *** END ***");

  return $controlFiles;
}

# Add control files to init parameter file
# addControlFileToInitFile(controlFileNames, pfileFullName)
sub addControlFileToInitFile
{
  EMD_PERL_DEBUG("db_clone_10_2.addControlFileToInitFile(): *** START ***");

  my ($controlFileNames, $pfileFullName) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.addControlFileToInitFile(): control file names: $controlFileNames");
  EMD_PERL_DEBUG("db_clone_10_2.addControlFileToInitFile(): pfile name: $pfileFullName");

  my @controlFileNames = split /$DELIMITER/, $controlFileNames;

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

  if($#controlFileNames == 0)
  {
    print INIT_ORA "control_files='$controlFileNames[0]'\n";
  }
  elsif($#controlFileNames == 1)
  {
    print INIT_ORA "control_files='$controlFileNames[0]',";
    print INIT_ORA "'$controlFileNames[1]'\n";
  }
  else
  {
    print INIT_ORA "control_files='$controlFileNames[0]',";
    foreach (1 .. ($#controlFileNames - 1))
    {
      print INIT_ORA "'$controlFileNames[$_]',";
    }
    print INIT_ORA "'$controlFileNames[$#controlFileNames]'\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("db_clone_10_2.addControlFileToInitFile(): INIT_ORA_FILE:\n $file_string");
  }

  EMD_PERL_DEBUG("db_clone_10_2.addControlFileToInitFile(): *** END ***");
}

# Add control file names
# startup db in nomount state (create spfile if necessary)
# addControlFileNamesInInitFile(pfileFullName, spfile, controlFiles)
sub addControlFileNamesInInitFile
{
  EMD_PERL_DEBUG("db_clone_10_2.addControlFileNamesInInitFile(): *** START ***");

  my ($pfileFullName, $spfile, $controlFiles) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.addControlFileNamesInInitFile(): pfileFullName: $pfileFullName");
  EMD_PERL_DEBUG("db_clone_10_2.addControlFileNamesInInitFile(): spfile: $spfile");

  my $restoredControlFiles = $controlFiles;

  if(!defined($restoredControlFiles))
  {
    $restoredControlFiles = &getControlFiles();
  }

  &addControlFileToInitFile($restoredControlFiles, $pfileFullName);

  if($clonePurpose ne "STANDBY_NO_RECOVERY" && $clonePurpose !~ /LOGICAL_STANDBY/){
    &clonePrepare($pfileFullName, $spfile);
  }

  EMD_PERL_DEBUG("db_clone_10_2.addControlFileNamesInInitFile(): *** END ***");
}

# Create a new control file
# One file name in logfileArray represents one GROUP of log file, this will be
# changed later.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# createControlFile_10_2(dbName, datafileArray, loggroupArray, logfileArray, logfileSizeArray,
#                        maxInfoArray, pfileFullName, spfile, omfFlag, asmFlag)
sub createControlFile_10_2
{
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): *** START ***");

  my ($dbName, $datafileArray, $loggroupArray, $logfileArray, $logfileSizeArray,
      $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag) = @_;

  my @datafileNames = split /$DELIMITER/, $datafileArray;
  my @loggroupNames = split /$DELIMITER/, $loggroupArray;
  my @logfileNames = split /$DELIMITER/, $logfileArray;
  my @logfileSizes = split /$DELIMITER/, $logfileSizeArray;
  my @maxInfo = split /$DELIMITER/, $maxInfoArray;

  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): Database Name: $dbName");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): Datafile names: @datafileNames");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): Created online redo log groups: @loggroupNames");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): Created online redo log files: @logfileNames");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): Created online redo log sizes: @logfileSizes");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): Control file max info: @maxInfo");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): omf flag: $omfFlag");
  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): asm flag: $asmFlag");

  my $sql_string = "";

  if($spfile eq "Y")
  {
    $sql_string .= "startup force nomount;\n";
  }
  else
  {
    $sql_string .= "startup force nomount pfile='$pfileFullName';\n";
  }

  $sql_string .= "create controlfile reuse set database $dbName resetlogs archivelog\n";
  $sql_string .= "datafile\n";
  foreach (0 .. $#datafileNames - 1)
  {
    $sql_string .= "    '$datafileNames[$_]'  reuse,\n";
  }
  $sql_string .= "    '$datafileNames[$#datafileNames]'  reuse\n";

  if(($omfFlag ne "Y") && ($asmFlag ne "Y"))
  {
    my $prev_group = "";
    my $curr_group = "";
    my $next_group = "";
    $sql_string .= "logfile\n";
    foreach (0 .. $#loggroupNames - 1)
    {
      $curr_group = $loggroupNames[$_];
      $next_group = $loggroupNames[$_ + 1];
      if(($curr_group ne $prev_group) && ($curr_group ne $next_group))
      {
        $sql_string .= "  group $loggroupNames[$_] '$logfileNames[$_]' size $logfileSizes[$_] reuse,\n";
      }
      elsif(($curr_group ne $prev_group) && ($curr_group eq $next_group))
      {
        $sql_string .= "  group $loggroupNames[$_] ('$logfileNames[$_]',\n";
      }
      elsif(($curr_group eq $prev_group) && ($curr_group ne $next_group))
      {
        $sql_string .= "  '$logfileNames[$_]') size $logfileSizes[$_] reuse,\n";
      }
      elsif(($curr_group eq $prev_group) && ($curr_group eq $next_group))
      {
        $sql_string .= "  '$logfileNames[$_]',\n";
      }

      $prev_group = $curr_group;
    }
    $curr_group = $loggroupNames[$#loggroupNames];
    if($curr_group ne $prev_group)
    {
      $sql_string .= "  group $loggroupNames[$#loggroupNames] '$logfileNames[$#logfileNames]' size $logfileSizes[$_] reuse\n";
    }
    else
    {
      $sql_string .= "  '$logfileNames[$#logfileNames]') size $logfileSizes[$_] reuse\n";
    }
  }
  else
  {
    my $prev_group = "";
    my $curr_group = "";
    my $next_group = "";
    $sql_string .= "logfile\n";
    foreach (0 .. $#loggroupNames - 1)
    {
      $curr_group = $loggroupNames[$_];
      $next_group = $loggroupNames[$_ + 1];
      if(($curr_group ne $prev_group) && ($curr_group ne $next_group))
      {
        $sql_string .= "  group $loggroupNames[$_] size $logfileSizes[$_],\n";
      }
      elsif(($curr_group ne $prev_group) && ($curr_group eq $next_group))
      {
        $sql_string .= "  group $loggroupNames[$_] ";
      }
      elsif(($curr_group eq $prev_group) && ($curr_group ne $next_group))
      {
        $sql_string .= "size $logfileSizes[$_],\n";
      }
      $prev_group = $curr_group;
    }
    $curr_group = $loggroupNames[$#loggroupNames];
    if($curr_group ne $prev_group)
    {
      $sql_string .= "  group $loggroupNames[$#loggroupNames] size $logfileSizes[$_]\n";
    }
    else
    {
      $sql_string .= "  size $logfileSizes[$_]\n";
    }
  }

  ## If this is existing backup, maxlogfiles may have been increased since backup was taken.
  ## Increase if there are more logfiles.
  my $maxlogs = $maxInfo[0];
  if($maxlogs < @logfileNames){
    $maxlogs = $#logfileNames + 1;
    EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): increasing MAXLOGFILES to $maxlogs");
  }
  $sql_string .= "maxlogfiles $maxlogs\n";
  $sql_string .= "maxlogmembers $maxInfo[1]\n";
  $sql_string .= "maxdatafiles $maxInfo[2]\n";
  $sql_string .= "maxinstances $maxInfo[3]\n";
  $sql_string .= "maxarchlogs $maxInfo[4]\n";
  $sql_string .= "character set $maxInfo[5];\n";
  $sql_string .= "EXIT;\n\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.createControlFile_10_2(): *** END ***");
}

# runSqlWithDBI(sql, username, password, tns)
sub runSqlWithDBI
{
  EMD_PERL_DEBUG("db_clone_10_2.runSqlWithDBI(): *** START ***");

  my ($sql) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.runSqlWithDBI(): SQL script: $sql");

  #get user name and password
  my $slash = index($userID, '/');
  my $username = substr($userID, 0, $slash);
  my $password = substr($userID, $slash + 1);
  my $tns = $TNS_CONNECTION_STRING;

  EMD_PERL_DEBUG("db_clone_10_2.runSqlWithDBI(): username: $username");
  EMD_PERL_DEBUG("db_clone_10_2.runSqlWithDBI(): tns: $tns");

  my $mode = 2; # SYSDBA

  my $lda;

  if(!$tns)
  {
    $lda = DBI->connect('dbi:Oracle:', "$username", "$password",
                        {ora_session_mode => $mode, PrintError => 0,
                         RaiseError => 1, AutoCommit => 0})
                       or die "Could not connect to DB instance: $DBI::errstr\n";
  }
  else
  {
    $lda = DBI->connect('dbi:Oracle:', "$username@".$tns, "$password",
                        {ora_session_mode => $mode, PrintError => 0,
                         RaiseError => 1, AutoCommit => 0})
                       or die "Could not connect to DB instance: $DBI::errstr\n";
  }

  my $cur = $lda->prepare($sql)
    or warn "prepare($sql): $DBI::errstr\n";
  $cur->execute()
    or warn "cur->execute(): $DBI::errstr\n";

  my @fetch_row;
  my @rows;
  my $i = 0;
  while ( @fetch_row = $cur->fetchrow_array() )
  {
    $rows[$i] = [@fetch_row];
    $i++;
    EMD_PERL_DEBUG("db_clone_10_2.runSqlWithDBI(): fetchrow_array: @fetch_row");
  }

  $lda->disconnect
    or warn "disconnect $DBI::errstr\n";

  EMD_PERL_DEBUG("db_clone_10_2.runSqlWithDBI(): *** END ***");

  return @rows;
}

# Get restored datafile ids and names
# The datafile names will be used to create new control file
# Set TNS_CONNECTION_STRING before calling this method
# getRestoredDatafilesWithDBI()
sub getRestoredDatafilesWithDBI
{
  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): *** START ***");

  my $sql = "SELECT file#, name FROM V\$DATAFILE WHERE status = 'ONLINE' OR status = 'SYSTEM'";

  my @results = runSqlWithDBI($sql);

  my ($fileids, $dfnames);
  my $i = 0;
  for $i (0 .. $#results)
  {
    $fileids .= $results[$i][0].${DELIMITER};
    $dfnames .= $results[$i][1].${DELIMITER};
  }

  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): datafile ids: $fileids");
  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): datafile names: $dfnames");

  EMD_PERL_DEBUG("db_clone_10_2.getRestoredDatafiles(): *** END ***");

  return ($fileids, $dfnames);
}

# setTNS(host, port, sid)
sub setTNS
{
  EMD_PERL_DEBUG("db_clone_10_2.setTNS(): *** START ***");

  my ($host, $port, $sid) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.setTNS(): host: $host");
  EMD_PERL_DEBUG("db_clone_10_2.setTNS(): port: $port");
  EMD_PERL_DEBUG("db_clone_10_2.setTNS(): sid: $sid");

  $TNS_CONNECTION_STRING = "(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=${host})(PORT=${port})))(CONNECT_DATA=(SID=${sid})(SERVER=DEDICATED)))";

  EMD_PERL_DEBUG("db_clone_10_2.setTNS(): TNS_CONNECTION_STRING: $TNS_CONNECTION_STRING");

  EMD_PERL_DEBUG("db_clone_10_2.setTNS(): *** END ***");
}

# Recover datafiles automatically from log files generated during cloning process
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# recoverDatafileAutomatic(backupArchName, pfileFullName, spfile)
sub recoverDatafileAutomatic
{
  EMD_PERL_DEBUG("db_clone.recoverDatafileAutomatic(): *** START ***");

  if($clodClone eq "Y")
  {
    EMD_PERL_DEBUG("db_clone.recoverDatafileAutomatic(): No recovery has been done since cold clone flag is: $clodClone");
    EMD_PERL_DEBUG("db_clone.recoverDatafileAutomatic(): *** END ***");
    return;
  }

  my ($backupArchName, $pfileFullName, $spfile) = @_;

  EMD_PERL_DEBUG("db_clone.recoverDatafileAutomatic(): Location of transferred archived log files: $backupArchName");

  my $sql_string = "";

  if($spfile eq "Y")
  {
    $sql_string .= "startup force mount;\n";
  }
  else
  {
    $sql_string .= "startup force mount pfile='$pfileFullName';\n";
  }

  my $archDest = $backupArchName;
  $sql_string .= "ALTER DATABASE RECOVER AUTOMATIC FROM '$archDest' DATABASE UNTIL CANCEL USING BACKUP CONTROLFILE;\n";

  $sql_string .= "alter database recover cancel;\n";
  $sql_string .= "EXIT;\n\n";

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

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

  EMD_PERL_DEBUG("db_clone.recoverDatafileAutomatic(): Ignore errors ORA-00278, ORA-00279, ORA-00280, and ORA-00289.  These are normal messages.");

  EMD_PERL_DEBUG("db_clone.recoverDatafileAutomatic(): *** END ***");
}

# Rename datafiles
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# renameDatafiles(oldIdsArray, oldDatafilesArrsy, newIdsArray, newDatafilesArry)
sub renameDatafiles
{
  EMD_PERL_DEBUG("db_clone_10_2.renameDatafiles(): *** START ***");

  my ($oldIdsArray, $oldDatafilesArrsy, $newIdsArray, $newDatafilesArry) = @_;

  my @oldIds = split /$DELIMITER/, $oldIdsArray;
  my @oldDatafiles = split /$DELIMITER/, $oldDatafilesArrsy;
  my @newIds = split /$DELIMITER/, $newIdsArray;
  my @newDatafiles = split /$DELIMITER/, $newDatafilesArry;

  EMD_PERL_DEBUG("db_clone_10_2.renameDatafiles(): oldIds: @oldIds");
  EMD_PERL_DEBUG("db_clone_10_2.renameDatafiles(): oldDatafiles: @oldDatafiles");
  EMD_PERL_DEBUG("db_clone_10_2.renameDatafiles(): newIds: @newIds");
  EMD_PERL_DEBUG("db_clone_10_2.renameDatafiles(): newDatafiles: @newDatafiles");

  my $sql_string = "";

  my $oldDatafile;
  my $index = 0;
  foreach $oldDatafile (@oldDatafiles)
  {
    if($oldIds[$index] eq $newIds[$index])
    {
      $sql_string .= "alter database rename file '$oldDatafile' to '$newDatafiles[$index]';\n";
      $index ++;
    }
  }

  $sql_string .= "EXIT;\n\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.renameDatafiles(): *** END ***");
}

# Rename offline datafiles
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# renameOfflineDatafiles(newIdsArray, newDatafilesArray)
sub renameOfflineDatafiles
{
  EMD_PERL_DEBUG("db_clone_10_2.renameOfflineDatafiles(): *** START ***");

  my ($newIdsArray, $newDatafilesArray) = @_;

  my ($oldIdsArray, $oldDatafilesArrsy) = &getOfflineDatafiles();

  if(($newIdsArray eq "") || ($oldIdsArray eq ""))
  {
    EMD_PERL_DEBUG("db_clone_10_2.renameOfflineDatafiles(): No offline datafile to be renamed");
    EMD_PERL_DEBUG("db_clone_10_2.renameOfflineDatafiles(): *** END ***");
    return;
  }

  &renameDatafiles($oldIdsArray, $oldDatafilesArrsy, $newIdsArray, $newDatafilesArray);

  EMD_PERL_DEBUG("db_clone_10_2.renameOfflineDatafiles(): *** END ***");
}

# Recover the database
# 9i and above db's: use backup control file to do recovery
#     the cloned instance has been mounted during the backup/restore process
#     switch the datafile copies from v$datafile_copy to v$datafile before recovery
#     get datafile names from v$datafile for OMF or ASM db's
#     pass in datafle names obtained from UI for non-OMF and non-ASM db's
# 817 db's: create new control file to do recovery
#     the cloned instance has been in nomount state during back/restore process
#     pass in datafile names obtained from UI
# recoverDatabaseOmf(dbName, onlineDatafileArry, offlineDatafileArry,
#                    offlineDatafileIdArry, loggroupArray, logfileArray,
#                    logfileSizeArray,maxInfoArray,
#                    backupArchName, pfileFullName, spfile, maxStamp,
#                    omfFlag, asmFlag, controlFiles, adminInitFile, v9i,
#                    spfileFullName, skipSwitchRecover)
sub recoverDatabaseOmf
{
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): *** START ***");

  if($clonePurpose eq "STANDBY_NO_RECOVERY" || $clonePurpose =~ /LOGICAL_STANDBY/)
  {
    EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): No recovery has been done since clone purpose is: $clonePurpose");
    EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): *** END ***");
    return;
  }

  my ($dbName, $onlineDatafileArry, $offlineDatafileArry, $offlineDatafileIdArry,
      $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray,
      $backupArchName, $pfileFullName, $spfile, $maxStamp, $omfFlag, $asmFlag,
      $controlFiles, $adminInitFile, $v9i, $spfileFullName, $skipSwitchRecover) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): dbName: $dbName");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): onlineDatafileArry: $onlineDatafileArry");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): offlineDatafileArry: $offlineDatafileArry");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): offlineDatafileIdArry: $offlineDatafileIdArry");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): loggroupArray: $loggroupArray");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): logfileArray: $logfileArray");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): logfileSizeArray: $logfileSizeArray");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): maxInfoArray: $maxInfoArray");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): backupArchName: $backupArchName");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): pfileFullName: $pfileFullName");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): spfile: $spfile");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): maxStamp: $maxStamp");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): omfFlag: $omfFlag");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): asmFlag: $asmFlag");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): controlFiles: $controlFiles");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): adminInitFile: $adminInitFile");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): v9i: $v9i");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): spfileFullName: $spfileFullName");
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): skipSwitchRecover: $skipSwitchRecover");

  if($v9i eq 'Y')
  {
    recoverDatabaseUsingBackupControlFile($dbName, $onlineDatafileArry, $offlineDatafileArry,
      $offlineDatafileIdArry, $loggroupArray, $logfileArray, $logfileSizeArray,
      $maxInfoArray, $backupArchName, $pfileFullName, $spfile, $maxStamp, $omfFlag,
      $asmFlag, $controlFiles, $adminInitFile, $spfileFullName, $skipSwitchRecover);
  }
  else
  {
    recoverDatabaseUsingNewControlFile($dbName, $onlineDatafileArry,
      $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray,
      $backupArchName, $pfileFullName, $spfile, $maxStamp, $omfFlag, $asmFlag,
      $controlFiles, $adminInitFile, $skipSwitchRecover);
  }

  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseOmf(): *** END ***");
}

# Recover the database using backup control file (also handle RAC case)
# Include:
#   switchDatafileCopy
#   getRestoredDatafiles
#   recoverDatafileAutomatic
#   nullifyDBid
#   modifyInitFileWithTargetDBName
#   createControlFile
#   addControlFileNamesInInitFile
#   openDBwithResetLog_10_2
# recoverDatabaseUsingBackupControlFile(dbName, onlineDatafileArry, offlineDatafileArry,
#                    offlineDatafileIdArry, loggroupArray, logfileArray, logfileSizeArray,
#                    maxInfoArray, backupArchName, pfileFullName, spfile, maxStamp,
#                    omfFlag, asmFlag, controlFiles, adminInitFile, spfileFullName, skipSwitchRecover)
sub recoverDatabaseUsingBackupControlFile
{
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseUsingBackupControlFile(): *** START ***");

  my ($dbName, $onlineDatafileArry, $offlineDatafileArry, $offlineDatafileIdArry,
      $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray,
      $backupArchName, $pfileFullName, $spfile, $maxStamp, $omfFlag, $asmFlag,
      $controlFiles, $adminInitFile, $spfileFullName, $skipSwitchRecover) = @_;

  if(!defined($skipSwitchRecover))
  {
    &switchDatafileCopy($maxStamp);
  }

  my $restoredControlFiles; #not defined
  if(($omfFlag eq "Y") || ($asmFlag eq "Y"))
  {
    (my $onlineIdArray, $onlineDatafileArry) = &getRestoredDatafilesAfterSwitchingCopy();
    ($offlineDatafileIdArry, $offlineDatafileArry) = &getOfflineDatafiles();
    ($offlineDatafileIdArry, $offlineDatafileArry) = &getOfflineDatafilesFromDatafileCopy($offlineDatafileIdArry);
  }
  else
  {
    $restoredControlFiles = $controlFiles;
  }

  if(!defined($skipSwitchRecover))
  {
    &recoverDatafileAutomatic($backupArchName, $pfileFullName, $spfile);
  }

  &nullifyDBid();

  if(($omfFlag eq "Y") || ($asmFlag eq "Y"))
  {
    &modifyInitFileWithTargetDBName($pfileFullName, $spfile, $dbName);
    &createControlFile_10_2($dbName, $onlineDatafileArry, $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag);
    &addControlFileNamesInInitFile($pfileFullName, $spfile, $restoredControlFiles);
  }
  else
  {
    &modifyInitFileWithTargetDBName($pfileFullName, $spfile, $dbName);
    &addControlFileNamesInInitFile($pfileFullName, $spfile, $restoredControlFiles);
    &createControlFile_10_2($dbName, $onlineDatafileArry, $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag);
  }

  &copyInitFile($pfileFullName, $adminInitFile, $spfile);

  if(($spfile eq "Y") && ($asmFlag eq "Y"))
  {
    &createSpfile($pfileFullName, $spfileFullName);
  }

  &openDBwithResetLog_10_2($pfileFullName, $spfile);

  &renameOfflineDatafiles($offlineDatafileIdArry, $offlineDatafileArry);

  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseUsingBackupControlFile(): *** END ***");
}

# Recover the database using new control file (could not handle RAC case)
# This version mainly deals with 817 db's although it works with all non-RAC db's.
# Include:
#   getRestoredDatafiles (from datafile_copy)
#   modifyInitFileWithTargetDBName
#   createControlFile
#   addControlFileNamesInInitFile
#   recoverDatafileAutomatic
#   nullifyDBid
#   commentInitFileEntry
#   createControlFile
#   addControlFileNamesInInitFile
#   openDBwithResetLog
# recoverDatabaseUsingNewControlFile(dbName, datafileArray,
#                    loggroupArray, logfileArray, logfileSizeArray, maxInfoArray,
#                    backupArchName, pfileFullName, spfile, maxStamp,
#                    omfFlag, asmFlag, controlFiles, adminInitFile, skipSwitchRecover)
sub recoverDatabaseUsingNewControlFile
{
  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseUsingNewControlFile(): *** START ***");

  my ($dbName, $datafileArray, $loggroupArray, $logfileArray, $logfileSizeArray,
      $maxInfoArray, $backupArchName, $pfileFullName, $spfile, $maxStamp, $omfFlag,
      $asmFlag, $controlFiles, $adminInitFile, $skipSwitchRecover) = @_;

  my $restoredControlFiles; #not defined
  if(($omfFlag eq "Y") || ($asmFlag eq "Y"))
  {
    (my $idArray, $datafileArray) = &getRestoredDatafiles();
    &modifyInitFileWithTargetDBName($pfileFullName, $spfile, $dbName);
    &createControlFile_10_2($dbName, $datafileArray, $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag);
    &addControlFileNamesInInitFile($pfileFullName, $spfile, $restoredControlFiles);
  }
  else
  {
    $restoredControlFiles = $controlFiles;
    &modifyInitFileWithTargetDBName($pfileFullName, $spfile, $dbName);
    &addControlFileNamesInInitFile($pfileFullName, $spfile, $restoredControlFiles);
    &createControlFile_10_2($dbName, $datafileArray, $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag);
  }

  if(!defined($skipSwitchRecover))
  {
    &recoverDatafileAutomatic($backupArchName, $pfileFullName, $spfile);
  }

  &nullifyDBid();

  if(($omfFlag eq "Y") || ($asmFlag eq "Y"))
  {
    &commentInitFileEntry("control_files", $pfileFullName);
    &clonePrepare($pfileFullName, $spfile);
    &createControlFile_10_2($dbName, $datafileArray, $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag);
    &addControlFileNamesInInitFile($pfileFullName, $spfile, $restoredControlFiles);
  }
  else
  {
    &createControlFile_10_2($dbName, $datafileArray, $loggroupArray, $logfileArray, $logfileSizeArray, $maxInfoArray, $pfileFullName, $spfile, $omfFlag, $asmFlag);
  }

  &copyInitFile($pfileFullName, $adminInitFile, $spfile);

  &openDBwithResetLog($pfileFullName, $spfile);

  EMD_PERL_DEBUG("db_clone_10_2.recoverDatabaseUsingNewControlFile(): *** END ***");
}

# Add tempfiles after the database is opened.
# The temp files are sorted by file IDs before being passed in.
# addTempFilesToDBOmf(fileNames, tablespaces, sizes, autoextends, omfFlag, asmFlag)
sub addTempFilesToDBOmf
{
  EMD_PERL_DEBUG("db_clone_10_2.addTempFilesToDBOmf(): *** START ***");

  if($clonePurpose eq "STANDBY_NO_RECOVERY" || $clonePurpose =~ /LOGICAL_STANDBY/)
  {
    EMD_PERL_DEBUG("db_clone_10_2.addTempFilesToDBOmf(): No temp files will be added since clone purpose is: $clonePurpose");
    EMD_PERL_DEBUG("db_clone_10_2.addTempFilesToDBOmf(): *** END ***");
    return;
  }

  my ($fileNames, $tablespaces, $sizes, $autoextends, $omfFlag, $asmFlag) = @_;

  if(($omfFlag eq "Y") && ($asmFlag ne "Y"))
  {
    addTempfilesOmf("", $tablespaces, $sizes, $autoextends);
  }
  elsif($asmFlag eq "Y")
  {
    addTempfilesOmf($fileNames, $tablespaces, $sizes, $autoextends);
  }
  else
  {
    &addTempFilesToDB($fileNames, $tablespaces, $sizes, $autoextends);
    &moreCleanupDB(&getDBVersion());
  }

  EMD_PERL_DEBUG("db_clone_10_2.addTempFilesToDBOmf(): *** END ***");
}

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

  my $db_version = "";

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n\n";
  $sql_string .= "set linesize 512;\n";
  $sql_string .= "declare\n";
  $sql_string .= "  sql_stmt   varchar2(200);\n";
  $sql_string .= "  db_version varchar2(20);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  sql_stmt := 'SELECT version FROM v\$instance';\n";
  $sql_string .= "  EXECUTE IMMEDIATE sql_stmt INTO db_version;\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) = &runSqlOnDestination($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("db_clone_10_2.getDBVersion(): Database version: $db_version");
    }
  }
  close DB_VERSION;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("db_clone_10_2.getDBVersion(): *** END ***");

  return $db_version;
}

# Check whether ORDSYS user exists in cloned database
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# isORDSYSExist()
sub isORDSYSExist
{
  EMD_PERL_DEBUG("db_clone_10_2.isORDSYSExist(): *** START ***");

  my $ordsys = "";

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n\n";
  $sql_string .= "set linesize 512;\n";
  $sql_string .= "variable rowcount number;\n";
  $sql_string .= "variable user_name varchar2(30);\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select count(*) INTO :rowcount from dba_users where username = 'ORDSYS';\n";
  $sql_string .= "  dbms_output.put_line('Row count: '||:rowcount);\n";
  $sql_string .= "  IF (:rowcount > 0) then\n";
  $sql_string .= "    select username INTO :user_name from dba_users where username = 'ORDSYS';\n";
  $sql_string .= "    IF NOT (:user_name IS NULL) then\n";
  $sql_string .= "      dbms_output.put_line('Check ORDSYS user');\n";
  $sql_string .= "      dbms_output.put_line('ordsysuser#: '||:user_name);\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) = &runSqlOnDestination($sql_string);

  open (ORDSYS_USER, "$filename") || die "Unable to open tempfile for ORDSYS_USER\n";
  while (<ORDSYS_USER>)
  {
    if ($_=~/\bordsysuser#/)
    {
      chomp($_);
      $ordsys = substr $_, 13;  #13 is the position that username starts
      EMD_PERL_DEBUG("db_clone_10_2.isORDSYSExist(): ORDSYS username: $ordsys");
    }
  }
  close ORDSYS_USER;
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }

  if($ordsys eq 'ORDSYS')
  {
    $ordsys = 'Y';
  }
  else
  {
    $ordsys = 'N';
  }

  EMD_PERL_DEBUG("db_clone_10_2.isORDSYSExist(): ORDSYS existence: $ordsys");

  EMD_PERL_DEBUG("db_clone_10_2.isORDSYSExist(): *** END ***");

  return $ordsys;
}

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

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

  my $db_version = &getDBVersion();

  if(($tablespaces eq "$DELIMITER") && ($clonePurpose ne "STANDBY_NO_RECOVERY") && ($clonePurpose !~ /LOGICAL_STANDBY/)){
    &cleanupDB($db_version);
    &moreCleanupDB($db_version);
    EMD_PERL_DEBUG("db_clone_10_2.addTempfilesOmf(): NO TEMPFILES TO ADD, returning");
    EMD_PERL_DEBUG("db_clone_10_2.addTempfilesOmf(): *** END ***");
    return;
  }

  my @tempFileNames = split /$DELIMITER/, $fileNames;
  my @tempTablespaces = split /$DELIMITER/, $tablespaces;
  my @tempSizes = split /$DELIMITER/, $sizes;
  my @tempAutoextends = split /$DELIMITER/, $autoextends;

  #add multiple tempfiles
  my $sql_string = "";

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

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

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

  ## These don't work for non-open database
  if(($clonePurpose ne "STANDBY_NO_RECOVERY") && ($clonePurpose !~ /LOGICAL_STANDBY/)){
    &cleanupDB($db_version);
    &moreCleanupDB($db_version);
  }

  EMD_PERL_DEBUG("db_clone_10_2.addTempfilesOmf(): *** END ***");
}

# Cleanup the cloned database.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# moreCleanupDB(version)
sub moreCleanupDB
{
  EMD_PERL_DEBUG("db_clone_10_2.moreCleanupDB(): *** START ***");

  my ($db_version) = @_;

  #Cleanup is only supported in DB above 10.1.0.2 version
  if(&compareVersion($db_version, "10.1.0.2") < 0)
  {
    EMD_PERL_DEBUG("db_clone_10_2.moreCleanupDB(): DB version less than 10.1.0.2.  No cleanup is done.");
    return;
  }

  EMD_PERL_DEBUG("db_clone_10_2.moreCleanupDB(): DB version is or above 10.1.0.2.  Cleanup will be performed.");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n\n";

  $sql_string .= "\@$ENV{ORACLE_HOME}${S}rdbms${S}admin${S}dbmssml.sql;\n";

  if(&isORDSYSExist() eq 'Y')
  {
    $sql_string .= "alter session set current_schema=ORDSYS;\n";
    $sql_string .= "\@$ENV{ORACLE_HOME}${S}ord${S}im${S}admin${S}ordlib.sql;\n";
    $sql_string .= "alter session set current_schema=SYS;\n";
  }

  $sql_string .= "EXIT;\n";

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

  EMD_PERL_DEBUG("db_clone_10_2.moreCleanupDB(): *** END ***");
}

# Re-create directory objects after opening the cloned database
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# createDirectoryObj(dirObjNames, dirObjPaths)
sub createDirectoryObj
{
  EMD_PERL_DEBUG("db_clone_10_2.createDirectoryObj(): *** START ***");

  my ($dirObjNames, $dirObjPaths) = @_;

  if($dirObjNames eq "$DELIMITER"){
    EMD_PERL_DEBUG("db_clone_10_2.createDirectoryObj(): No directory objects need to be created, returning");
    EMD_PERL_DEBUG("db_clone_10_2.createDirectoryObj(): *** END ***");
    return;
  }

  my @tempDirObjNames = split /$DELIMITER/, $dirObjNames;
  my @tempDirObjPaths = split /$DELIMITER/, $dirObjPaths;

  my $sql_string = "";

  my $tempDirNames;
  my $index = 0;
  foreach $tempDirNames (@tempDirObjNames)
  {
    $sql_string .= "CREATE OR REPLACE DIRECTORY \"$tempDirNames\" AS '$tempDirObjPaths[$index]';\n";
    $index ++;
  }
  $sql_string .= "EXIT;\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.createDirectoryObj(): *** END ***");
}

# Copy multiple files to one dir
# copyFilesToOneDir(externalFilesArray, sourceBSLoc, pattern, externalIDsArray)
sub copyFilesToOneDir
{
  my ($externalFilesArray, $sourceBSLoc, $pattern, $externalIDsArray) = @_;

  my $dirExist = &dirExists($sourceBSLoc);
  if($dirExist ne "OK")
  {
    return;
  }

  my @externalFiles = split /$DELIMITER/, $externalFilesArray;
  my @externalIDs = split /$DELIMITER/, $externalIDsArray;
  my $externalFiles;
  my $slash = "/";

  if($NT)
  {
    $slash = "\\";
  }

  my $prefix = $pattern."_";

  my $index = 0;
  foreach $externalFiles (@externalFiles)
  {
    !copyFile2($externalFiles, $sourceBSLoc.$slash.$prefix.$externalIDs[$index]) || (EMD_PERL_DEBUG("Error copying $externalFiles to $sourceBSLoc") && (die "Error copying $externalFiles to $sourceBSLoc"));
    $index ++;
  }
}

# Copy multiple files to one dir
# copyFilesFromOneDir(sourceBSLoc, externalFilesArray, pattern, externalIDsArray)
sub copyFilesFromOneDir
{
  my ($sourceBSLoc, $externalFilesArray, $pattern, $externalIDsArray) = @_;

  my $dirExist = &dirExists($sourceBSLoc);
  if($dirExist ne "OK")
  {
    return;
  }

  my @externalFiles = split /$DELIMITER/, $externalFilesArray;
  my @externalIDs = split /$DELIMITER/, $externalIDsArray;
  my $externalFiles;
  my $sourceFileNames;
  my $srcBasename = "";
  my $destBasename = "";
  my $slash = "/";

  if($NT)
  {
    $slash = "\\";
  }

  my @sourceFileNames = glob $sourceBSLoc.$slash.$pattern."_*";
  my $index = 0;

  foreach $sourceFileNames (@sourceFileNames)
  {
    $index = 0;
    foreach $externalFiles (@externalFiles)
    {
      $srcBasename = &getBasename($sourceFileNames);
      $destBasename = $pattern."_".$externalIDs[$index];
      if($srcBasename eq $destBasename)
      {
        !copyFile2($sourceFileNames, $externalFiles) || (EMD_PERL_DEBUG("Error copying $externalFiles to $sourceBSLoc") && (die "Error copying $externalFiles to $sourceBSLoc"));
      }
      $index ++;
    }
  }
}

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

  my ($v9i) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.checkDatabaseFiles(): v9i: $v9i");

  my $sql_string = "";

  $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 directory_name \"directory name\", directory_path \"directory path\" from dba_directories;\n";

  if($v9i eq 'Y')
  {
    $sql_string .= "select unique location \"external file\", directory_name \"directory name\" from dba_external_locations;\n";
  }

  $sql_string .= "select value \"spfile\" from v\$parameter where name='spfile';\n";

  $sql_string .= "exit;\n";

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

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

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

# Run given emca command on a local machine
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# The caller is responsible to close the returned fileHandle
# runEMCA(lsnrPort, httpPort, emcaScript, asmArgs, hideOutput) hides STD output
# if "hideOutput" defined
# runEMCA(lsnrPort, httpPort, emcaScript, asmArgs) will print standard output
sub runEMCA
{
  EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): *** START ***");

  my ($lsnrPort, $httpPort, $emca_string, $asmArgs) = @_;
  my $emca_string_debug = $emca_string;
  #Do not enable this since it contains passwords
  #EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): EMCA input:\n$emca_string_debug");

  (my $fh, my $filename) = &create_temp_file();
  if($NT)
  {
    $filename = "$TEMP\\"."dbclone.$$";
  }

  my $sid = $ENV{ORACLE_SID};
  my $oracleHome = $ENV{ORACLE_HOME};
  my $listenerOracleHome = $ENV{LISTENER_OH};
  my $args = "";
  $args .= "-config dbcontrol db -repos recreate ";
  $args .= "-SID $sid -PORT $lsnrPort -ORACLE_HOME $oracleHome -DBCONTROL_HTTP_PORT $httpPort ";
  $args .= "-LISTENER_OH $listenerOracleHome";
  $args .= "$asmArgs";

  EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): EMCA args: $args");

  #workaround bug 5443957 by unsetting some env variables
  #EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): EMSTATE before deleting: $ENV{EMSTATE}");
  delete $ENV{EMSTATE};
  delete $ENV{EMHOME};
  delete $ENV{CONSOLE_CFG};
  #EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): EMSTATE after deleting: $ENV{EMSTATE}");

  open(EMCA_SCRIPT, "|$ENV{ORACLE_HOME}/bin/emca $args >$filename")
    || die "Cannot open pipe for EMCA_SCRIPT";
  print EMCA_SCRIPT $emca_string;
  close EMCA_SCRIPT || print "Could not close pipe for EMCA_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;

  EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): OUT_PUT:\n$output_string");

  if(!defined($_[4]))
  {
    print STDOUT $output_string;
  }

  EMD_PERL_DEBUG("db_clone_10_2.runEMCA(): *** END ***");

  return ($fh, $filename);
}

# Deconfigure the DB Console by running EMCA command.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# deconfigDBConsole(hideOutput) will hide standard output if "hideOutput" defined
# deconfigDBConsole()
sub deconfigDBConsole
{
  EMD_PERL_DEBUG("db_clone_10_2.deconfigDBConsole(): *** START ***");

  # Do NOT check the return value of this command
  my $cleanArgs =  "-deconfig dbcontrol db -silent -SID $ENV{ORACLE_SID}";
  my $command = "$ENV{ORACLE_HOME}${S}bin${S}emca ".${cleanArgs};

  EMD_PERL_DEBUG("db_clone_10_2.deconfigDBConsole(): EMCA command:\n$command");

  #workaround bug 5443957 by unsetting some env variables
  EMD_PERL_DEBUG("db_clone_10_2.deconfigDBConsole(): EMSTATE before deleting: $ENV{EMSTATE}");
  delete $ENV{EMSTATE};
  delete $ENV{EMHOME};
  delete $ENV{CONSOLE_CFG};
  EMD_PERL_DEBUG("db_clone_10_2.deconfigDBConsole(): EMSTATE after deleting: $ENV{EMSTATE}");

  (my $fh, my $filename) = &create_temp_file();
  if($NT)
  {
    $filename = "$TEMP\\"."dbclone.$$";
  }
  my(@res) = `$command >$filename 2>&1`;

  my $mesg = getOutputFromFile($filename);

  EMD_PERL_DEBUG("db_clone_10_2.deconfigDBConsole(): EMCA output:\n$mesg");

  if(!defined($_[0]))
  {
    print STDOUT $mesg;
  }

  if($?)
  {
    my($err) = "@res";
    EMD_PERL_ERROR("db_clone_10_2.deconfigDBConsole(): $command: $err");
    exit(1);
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.deconfigDBConsole(): *** END ***");
}

# Configure the DB Console by running EMCA command.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# configDBConsole(lsnrPort, httpPort, syspwd, dbsnmppwd, sysmanpwd,
#                 asmOracleHome, asmSID, asmPort, asmRole, asmUsername,
#                 sysPassword, asmFlag, hostUsername, hostPassword)
sub configDBConsole
{
  EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): *** START ***");

  #deconfig first to avoid unexpected EMCA prompt
  #&deconfigDBConsole();

  my ($listenerOracleHome, $lsnrPort, $httpPort, $syspwd, $dbsnmppwd, $sysmanpwd,
      $asmOracleHome, $asmSID, $asmPort, $asmRole, $asmUsername, $sysPassword, $asmFlag, $hostUsername, $hostPassword) = @_;

  my $asmArgs = "";
  if($asmFlag eq "Y")
  {
    $asmArgs .= " -ASM_OH $asmOracleHome";
    $asmArgs .= " -ASM_SID $asmSID";
    $asmArgs .= " -ASM_PORT $asmPort";
    $asmArgs .= " -ASM_USER_ROLE $asmRole";
    $asmArgs .= " -ASM_USER_NAME $asmUsername";
  }

  #set password for dbsnmp user since it might be reset by users
  &setDBSNMPpassword($dbsnmppwd);

  #set password for sysman user
  &setDBPassword('SYSMAN', $sysmanpwd);

  #set the listener_oh for emca
  if($listenerOracleHome ne '')
  {
    $ENV{LISTENER_OH} = $listenerOracleHome;
  }
  EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): listenerOracleHome: $listenerOracleHome");

  my $sid = $ENV{ORACLE_SID};
  my $oracleHome = $ENV{ORACLE_HOME};

  my $emca_string = "";
  $emca_string .= "$syspwd\n";
  $emca_string .= "$dbsnmppwd\n";
  $emca_string .= "$sysmanpwd\n";
  $emca_string .= "\n";
  $emca_string .= "\n";

  if($asmFlag eq "Y")
  {
    $emca_string .= "$sysPassword\n";
  }

  $emca_string .= "Y\n";

  (my $fh, my $filename) = &runEMCA($lsnrPort, $httpPort, $emca_string, $asmArgs, $_[12]);
  close $fh;
  if($NT)
  {
    #view workaroud for EMCA
    my $domain = "";
    my $in_vob_flag = $ENV{IN_VOB_FLAG};
    my $ade_in_oracleHome = ($ENV{ORACLE_HOME} =~/:\\ade\\/i);
    #EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): IN_VOB_FLAG: $in_vob_flag");
    EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): ade_in_oracleHome: $ade_in_oracleHome");
    if($in_vob_flag && ($in_vob_flag eq 'TRUE') && ($ade_in_oracleHome))
    {
      EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): In vob and ORACLE_HOME contains ':\\ade\\'");
      $domain =  $ENV{USERDOMAIN};
    }
    if ($domain ne "")
    {
  EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): USERDOMAIN: $domain");
  my $comSpec = $ENV{ComSpec}." /c";
  my $cmdNoPasswd = "$comSpec sc config OracleDBConsole".$ENV{ORACLE_SID}." obj= ".${hostUsername}." password= ";
  my $cmd = ${cmdNoPasswd}.${hostPassword};
        EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): config service in view only: $cmdNoPasswd");
        my @res = `$cmd >$filename 2>&1`;
  EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): config service output: @res");

  $cmd =  $ENV{ORACLE_HOME}."${S}bin${S}emctl start dbconsole >>$filename 2>&1";

  EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): start dbconsole: $cmd");

  #this does not work, have to use system()
        #@res = `$cmd >$filename 2>&1`;
  delete $ENV{DBCONSOLE_SERVICE_NAME};
  system($cmd);

        EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): start dbconsole output is in temp file: $filename");
    }
    &removeFile($filename);
  }

  EMD_PERL_DEBUG("db_clone_10_2.configDBConsole(): *** END ***");
}

# Set the password for a database user.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# setDBPassword(user, password)
sub setDBPassword
{
  EMD_PERL_DEBUG("db_clone_10_2.setDBPassword(): *** START ***");

  my ($user, $password) = @_;

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "ALTER USER $user IDENTIFIED BY \"${password}\";\n";
  $sql_string .= "EXIT;\n";

  my $notHideOutput;
  (my $fh, my $filename) = &runSqlOnDestination($sql_string, $notHideOutput, "hideSQL");
  close $fh;
  if($NT)
  {
    &removeFile($filename);
  }
  EMD_PERL_DEBUG("db_clone_10_2.setDBPassword(): *** END ***");
}

# Return dirs for given filenames
# getDirsFromFiles(filenamesArray)
sub getDirsFromFiles
{
  EMD_PERL_DEBUG("db_clone_10_2.getDirsFromFiles(): *** START ***");
  my ($filenamesArray) = @_;
  my @filenames = split /$DELIMITER/, $filenamesArray;
  my $filename;
  my $dirs = "";
  foreach $filename (@filenames)
  {
    $dirs .= &getDirname($filename);
    $dirs .= $DELIMITER;
  }

  EMD_PERL_DEBUG("db_clone_10_2.getDirsFromFiles(): Dirs: $dirs");
  EMD_PERL_DEBUG("db_clone_10_2.getDirsFromFiles(): *** END ***");
  return $dirs;
}

# Set dynamic parameter for a given db instance.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# setDynamicParameter(parameter)
sub setDynamicParameter
{
  EMD_PERL_DEBUG("db_clone_10_2.setDynamicParameter(): *** START ***");

  my ($parameter) = @_;
  EMD_PERL_DEBUG("db_clone_10_2.setDynamicParameter(): Parameter: $parameter.");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n\n";
  $sql_string .= "alter system set $parameter;\n";
  $sql_string .= "EXIT;\n";

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

  EMD_PERL_DEBUG("db_clone_10_2.setDynamicParameter(): *** END ***");
}

# Open the cloned database with resetlogs
# Set an underscore parameter dynamically before openning DB resetulogs
# to handle cloning from RAC case.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# openDBwithResetLog_10_2(pfileFullName, spfile)
sub openDBwithResetLog_10_2
{
  EMD_PERL_DEBUG("db_clone.openDBwithResetLog_10_2(): *** START ***");

  my ($pfileFullName, $spfile) = @_;

  my $db_version = &getDBVersion();

  #open the database with resetlogs
  my $sql_string = "";
  $sql_string .= "set echo off\n";

  if($spfile eq "Y")
  {
    $sql_string .= "startup force mount;\n";
  }
  else
  {
    $sql_string .= "startup force mount pfile='$pfileFullName';\n";
  }

  if(&compareVersion($db_version, "10.2.0.1") >= 0)
  {
    $sql_string .= "alter system set \"_no_recovery_through_resetlogs\"=true scope=memory;\n";
  }

  $sql_string .= "alter database open resetlogs;\n";
  $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";

  if($clodClone eq "Y")
  {
    $sql_string .= "shutdown immediate;\n";
    if($spfile eq "Y")
    {
      $sql_string .= "startup mount;\n";
    }
    else
    {
      $sql_string .= "startup mount pfile='$pfileFullName';\n";
    }
    $sql_string .= "alter database NOARCHIVELOG;\n";
    $sql_string .= "alter database open;\n";
    $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";
  }

  $sql_string .= "exit;\n";

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

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

  EMD_PERL_DEBUG("db_clone.openDBwithResetLog_10_2(): *** END ***");
}

# compareVersion compares 2 version numbers (v1 and v2)
# The match compares v1 to the number of significant
# digits in v2; for example, assume the v1 is 8.0.2.0.1:
#      if v2 = 8.0     returns 0
#      if v2 = 8.0.2   returns 0
#      if v2 = 8.0.1   returns 1
#      if v2 = 8.0.2.1 returns -1
# compareVersion(version1, version2)
sub compareVersion
{
  EMD_PERL_DEBUG("db_clone_10_2.compareVersion(): *** START ***");
  my ($version1, $version2) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.compareVersion(): version1: $version1");
  EMD_PERL_DEBUG("db_clone_10_2.compareVersion(): version2: $version2");

  my $compareValue = 0;
  my $separator = '\.';
  my @version1s = split /$separator/, $version1;
  my @version2s = split /$separator/, $version2;
  my ($v1, $v2);
  my $index = 0;

  while(($#version1s >= $index) && ($#version2s >= $index))
  {
    $v1 = $version1s[$index];
    $v2 = $version2s[$index];

    if($v1 < $v2)
    {
      $compareValue = -1;
      last;
    }
    elsif ($v1 > $v2)
    {
      $compareValue = 1;
      last;
    }

    $index ++;
  }

  EMD_PERL_DEBUG("db_clone_10_2.compareVersion(): compareValue: $compareValue");
  EMD_PERL_DEBUG("db_clone_10_2.compareVersion(): *** END ***");
  return $compareValue;
}

# Re-write the listener.ora and tnsnames.ora files to avoid platform dependent format
# since these two files are sent over from OMS.
# reWriteNetConfigFiles(location)
sub reWriteNetConfigFiles
{
  EMD_PERL_DEBUG("db_clone_10_2.reWriteNetConfigFiles(): *** START ***");

  if(!$NT)
  {
    EMD_PERL_DEBUG("db_clone_10_2.reWriteNetConfigFiles(): Not Windows platform, return ...");
    return;
  }

  my ($location) = @_;
  my $listenerFile = "${location}listener.ora";
  my $tnsnamesFile = "${location}tnsnames.ora";

  &reWriteFile($listenerFile);
  &reWriteFile($tnsnamesFile);

  EMD_PERL_DEBUG("db_clone_10_2.reWriteNetConfigFiles(): *** END ***");
}

# Re-write a file
# reWriteFile(file)
sub reWriteFile
{
  EMD_PERL_DEBUG("db_clone_10_2.reWriteFile(): *** START ***");

  my ($file) = @_;
  EMD_PERL_DEBUG("db_clone_10_2.reWriteFile: To rewrite $file");

  (my $fh, my $fileName) = &create_temp_file();
  if($NT)
  {
    $fileName = "$TEMP\\"."dbclone.$$";
  }

  EMD_PERL_DEBUG("db_clone_10_2.reWriteFile: Write content of $file to $fileName");

  #Open the original file to get output and the temp file to write content
  open (FILE_OUT, "$file") || die "Unable to open $file for FILE_OUT\n";
  open (FILE_IN, ">$fileName") || die "Unable to open a file for FILE_IN\n";

  while (<FILE_OUT>)
  {
    chomp($_);
    print FILE_IN "$_\n";
  }

  close FILE_OUT;
  close FILE_IN || die "Unable to close FILE_IN";

  EMD_PERL_DEBUG("db_clone_10_2.reWriteFile: Overwrite $file with $fileName");
  &copyFile($fileName, $file);

  EMD_PERL_DEBUG("clone_util.reWriteFile: Finished rewriting $file");

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

  EMD_PERL_DEBUG("db_clone_10_2.reWriteFile(): *** END ***");
}

# Create spfile to ASM and save file system spfile if any.
# Assume pfile is available (named with *.saved), create spfile from it to ASM.
# Create a pfile pointing to the created spfile under the same location as original
# pfile.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# createSpfile(pfile, createdSpfile)
sub createSpfile
{
  EMD_PERL_DEBUG("db_clone_10_2.createSpfile(): *** START ***");

  my ($pfile, $createdSpfile) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.createSpfile(): pfile: $pfile");
  EMD_PERL_DEBUG("db_clone_10_2.createSpfile(): createdSpfile: $createdSpfile");

  #save spfile on file system
  my $tempSpfile = &getDestSpfile();
  #If spfile name starts with '+', it is on ASM, do not try to save it
  if($tempSpfile ne "")
  {
      my $startStr = substr($tempSpfile, 0, 1);
      if($startStr ne '+')
      {
    my $saved_spfile = ${tempSpfile}.".saved";
    !copyFile($tempSpfile, $saved_spfile) || (EMD_PERL_DEBUG("db_clone_10_2.createSpfile(): Error copying $tempSpfile to $saved_spfile") && (die "db_clone_10_2.createSpfile(): Error copying $tempSpfile to $saved_spfile"));
    removeFile($tempSpfile);
      }
  }
  my $src_pfile = ${pfile}.".saved";

  my $sql_string = "";
  $sql_string .= "set echo on\n";
  $sql_string .= "create spfile='$createdSpfile' from pfile='$src_pfile';\n";
  $sql_string .= "exit;\n";

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

  my $initFile = $pfile;
  open(INIT_ORA, ">$initFile") || die "Cannot open $initFile";
  print INIT_ORA "spfile='$createdSpfile'";
  close INIT_ORA || die "Cannot close $initFile";

  #initFile is at the default location $OH/dbs or database (on NT)
  #Since the original spfile has been moved, the default pfile (initFile) is used.
  $sql_string = "";
  $sql_string .= "shutdown abort\n";
  $sql_string .= "startup force nomount;\n";
  $sql_string .= "exit;\n";

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

  EMD_PERL_DEBUG("db_clone_10_2.createSpfile(): *** END ***");
}

# Return spfile name on destination instance: if empty, no spfile is being used.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getDestSpfile()
sub getDestSpfile
{
  EMD_PERL_DEBUG("db_clone_10_2.getDestSpfile(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\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 .= "  dbms_output.enable(2000000);\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) = &runSqlOnDestination($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("db_clone_10_2.getDestSpfile(): spfile name: $spfileName");
  EMD_PERL_DEBUG("db_clone_10_2.getDestSpfile(): *** END ***");

  return $spfileName;
}

############# helper methods for testing purpose ########

#To use DBI, have to save and set agent env
sub save_agent_env()
{
  EMD_PERL_DEBUG("db_clone_10_2.save_agent_env(): *** START ***");
  $AGENT_ORACLE_HOME = $ENV{ORACLE_HOME};
  $AGENT_LD_LIBRARY_PATH = $ENV{LD_LIBRARY_PATH};
  $AGENT_SHLIB_PATH = $ENV{SHLIB_PATH};
  $AGENT_LIBPATH = $ENV{LIBPATH};
  $AGENT_PATH = $ENV{PATH};
  $AGENT_JAVA_HOME = $ENV{JAVA_HOME};
  $AGENT_ORA_NLS = $ENV{ORA_NLS};
  $AGENT_ORA_NLS32 = $ENV{ORA_NLS32};
  $AGENT_ORA_NLS33 = $ENV{ORA_NLS33};
  EMD_PERL_DEBUG("db_clone_10_2.save_agent_env(): *** END ***");
}

sub set_agent_env()
{
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): *** START ***");
  $ENV{ORACLE_HOME} = $AGENT_ORACLE_HOME;
  $ENV{LD_LIBRARY_PATH} = $AGENT_LD_LIBRARY_PATH;
  $ENV{SHLIB_PATH} = $AGENT_SHLIB_PATH;
  $ENV{LIBPATH} = $AGENT_LIBPATH;
  $ENV{PATH} = $AGENT_PATH;
  $ENV{JAVA_HOME} = $AGENT_JAVA_HOME;
  $ENV{ORA_NLS} = $AGENT_ORA_NLS;
  $ENV{ORA_NLS32} = $AGENT_ORA_NLS32;
  $ENV{ORA_NLS33} = $AGENT_ORA_NLS33;

  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): ORACLE_HOME = $ENV{ORACLE_HOME}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): LD_LIBRARY_PATH = $ENV{LD_LIBRARY_PATH}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): SHLIB_PATH = $ENV{SHLIB_PATH}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): LIBPATH = $ENV{LIBPATH}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): PATH = $ENV{PATH}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): JAVA_HOME = $ENV{JAVA_HOME}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): ORA_NLS = $ENV{ORA_NLS}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): ORA_NLS32 = $ENV{ORA_NLS32}");
  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): ORA_NLS33 = $ENV{ORA_NLS33}");

  EMD_PERL_DEBUG("db_clone_10_2.set_agent_env(): *** END ***");
}

sub save_target_env()
{
  EMD_PERL_DEBUG("db_clone_10_2.save_target_env(): *** START ***");
  $TARGET_ORACLE_HOME = $ENV{ORACLE_HOME};
  $TARGET_ORACLE_SID = $ENV{ORACLE_SID};
  EMD_PERL_DEBUG("db_clone_10_2.save_target_env(): *** END ***");
}

# set_target_env(destListenerFile)
sub set_target_env()
{
  EMD_PERL_DEBUG("db_clone_10_2.set_target_env(): *** START ***");
  my ($destListenerFile) = @_;
  set_env($TARGET_ORACLE_HOME, $TARGET_ORACLE_SID, $destListenerFile);
  EMD_PERL_DEBUG("db_clone_10_2.set_target_env(): *** END ***");
}

# Get datafile numbers and tablespace names
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getDatafileNumTbsName()
sub getDatafileNumTbsName
{
  EMD_PERL_DEBUG("db_clone_10_2.getDatafileNumTbsName(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 512;\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 dfrec IN (SELECT file#, ts.name tsName FROM V\$DATAFILE df, V\$TABLESPACE ts WHERE df.status <> 'OFFLINE' and df.ts# = ts.ts#\n";
  $sql_string .= "                union \n";
  $sql_string .= "                SELECT file#, ts.name tsName FROM V\$DATAFILE df, V\$TABLESPACE ts WHERE df.status = 'OFFLINE' and file# in (SELECT file# FROM v\$datafile_header) and df.ts# = ts.ts#)\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    dbms_output.put_line('Checked file ' || i || ':');\n";
  $sql_string .= "    dbms_output.put_line('file# '||dfrec.file#);\n";
  $sql_string .= "    dbms_output.put_line('tsname# '||dfrec.tsName);\n";
  $sql_string .= "    i := i + 1;\n";
  $sql_string .= "  END LOOP;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  my $hideOutput = "";
  (my $fh, my $filename) = &runSqlOnSource($sql_string, $hideOutput);

  my $fileid;
  my $fileids;
  my $tbsname;
  my $tbsnames;

  open (DATAFILE_NUM, "$filename") || die "Unable to open tempfile for DATAFILE_NUM\n";
  while (<DATAFILE_NUM>)
  {
    if (($_=~/\d/) && ($_=~/\bfile#/))
    {
      chomp($_);
      $fileid = substr $_, 6; #fileid starts from position 6
      $fileids .= ${fileid}.${DELIMITER};
    }
    if ($_=~/\btsname#/)
    {
      chomp($_);
      $tbsname = substr $_, 8; #tbsname starts from position 8
      $tbsnames .= ${tbsname}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileNumTbsName(): datafile ids: $fileids");
  EMD_PERL_DEBUG("db_clone_10_2.getDatafileNumTbsName(): tablespace names: $tbsnames");

  EMD_PERL_DEBUG("db_clone_10_2.getDatafileNumTbsName(): *** END ***");

  return ($fileids, $tbsnames);
}

# Get max sequence, stamp, and maxinfo
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# getMaxs()
sub getMaxs
{
  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "CONNECT $userID AS SYSDBA;\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "set linesize 512;\n";

  $sql_string .= "ALTER SYSTEM ARCHIVE LOG START;\n";
  $sql_string .= "ALTER SYSTEM ARCHIVE LOG CURRENT;\n";

  $sql_string .= "variable max_seq number;\n";
  $sql_string .= "variable rowcount number;\n";
  $sql_string .= "variable spfile_val varchar2(256);\n";
  $sql_string .= "variable db_name varchar2(9);\n";

  $sql_string .= "variable max_stamp number;\n";

  $sql_string .= "declare\n";
  $sql_string .= "  mlogf  binary_integer;\n";
  $sql_string .= "  mlogm  binary_integer;\n";
  $sql_string .= "  mdatf  binary_integer;\n";
  $sql_string .= "  minst  binary_integer;\n";
  $sql_string .= "  mlogh  binary_integer;\n";
  $sql_string .= "  chset  varchar2(256);\n";

  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_output.enable(2000000);\n";
  $sql_string .= "  select checkpoint_change# INTO :max_seq from v\$database;\n";
  $sql_string .= "  dbms_output.put_line('Start printing max_seq number: ');\n";
  $sql_string .= "  dbms_output.put_line('max_seq# '||:max_seq);\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 .= "  select name INTO :db_name from v\$database;\n";
  $sql_string .= "  dbms_output.put_line('db_name# '||:db_name);\n";

  $sql_string .= "  select MAX(stamp) INTO :max_stamp from v\$datafile_copy;\n";
  $sql_string .= "  dbms_output.put_line('max_stamp# '||:max_stamp);\n";

  $sql_string .= "  dbms_backup_restore.getMaxInfo(mlogf,\n";
  $sql_string .= "                                 mlogm,\n";
  $sql_string .= "                                 mdatf,\n";
  $sql_string .= "                                 minst,\n";
  $sql_string .= "                                 mlogh,\n";
  $sql_string .= "                                 chset);\n";
  $sql_string .= "  dbms_output.put_line('mlogf# '||mlogf);\n";
  $sql_string .= "  dbms_output.put_line('mlogm# '||mlogm);\n";
  $sql_string .= "  dbms_output.put_line('mdatf# '||mdatf);\n";
  $sql_string .= "  dbms_output.put_line('minst# '||minst);\n";
  $sql_string .= "  dbms_output.put_line('mlogh# '||mlogh);\n";
  $sql_string .= "  dbms_output.put_line('chset# '||chset);\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

  my $hideOutput = "";
  (my $fh, my $filename) = &runSqlOnSource($sql_string, $hideOutput);

  my $maxSeq;
  my $spfile;
  my $dbName;
  my $maxStamp;
  my ($mlogf, $mlogm, $mdatf, $minst, $mlogh, $chset);
  my $maxInfo;

  open (MAX_S, "$filename") || die "Unable to open tempfile for MAX_S\n";
  while (<MAX_S>)
  {
    if (($_=~/\d/) && ($_=~/max_seq#/))
    {
      chomp($_);
      $maxSeq = substr $_, 9; #maxSeq starts from position 9
    }
    if ($_=~/\bspfile#/)
    {
      chomp($_);
      $spfile = substr $_, 8; #spfile starts from position 8
    }
    if ($_=~/\bdb_name#/)
    {
      chomp($_);
      $dbName = substr $_, 9; #db_name starts from position 9
    }
    if (($_=~/\d/) && ($_=~/max_stamp#/))
    {
      chomp($_);
      $maxStamp = substr $_, 11; #maxStamp starts from position 11
    }
    if ($_=~/\bmlogf#/)
    {
      chomp($_);
      $mlogf = substr $_, 7; # value starts from position 7
      $maxInfo .= ${mlogf}.${DELIMITER};
    }
    if ($_=~/\bmlogm#/)
    {
      chomp($_);
      $mlogm = substr $_, 7; # value starts from position 7
      $maxInfo .= ${mlogm}.${DELIMITER};
    }
    if ($_=~/\bmdatf#/)
    {
      chomp($_);
      $mdatf = substr $_, 7; # value starts from position 7
      $maxInfo .= ${mdatf}.${DELIMITER};
    }
    if ($_=~/\bminst#/)
    {
      chomp($_);
      $minst = substr $_, 7; # value starts from position 7
      $maxInfo .= ${minst}.${DELIMITER};
    }
    if ($_=~/\bmlogh#/)
    {
      chomp($_);
      $mlogh = substr $_, 7; # value starts from position 7
      $maxInfo .= ${mlogh}.${DELIMITER};
    }
    if ($_=~/\bchset#/)
    {
      chomp($_);
      $chset = substr $_, 7; # value starts from position 7
      $maxInfo .= ${chset}.${DELIMITER};
    }
  }

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

  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): max sequence: $maxSeq");
  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): spfile: $spfile");
  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): db name: $dbName");
  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): max stamp: $maxStamp");
  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): max info: $maxInfo");

  EMD_PERL_DEBUG("db_clone_10_2.getMaxs(): *** END ***");

  return ($maxSeq, $spfile, $dbName, $maxStamp, $maxInfo);
}

# Drop old (non-OMF) logfile names from controlfile, and readd
#  identical logfiles as OMF files
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# addLempfilesOmf
sub addLogfilesOmf
{
  EMD_PERL_DEBUG("db_clone_10_2.addLogfilesOmf(): *** START ***");

  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  dbms_backup_restore.clearOnlineLogNames();\n";
  $sql_string .= "  FOR cfrec IN (SELECT unique(group#) FROM v\$logfile)\n";
  $sql_string .= "  LOOP\n";
  $sql_string .= "    EXECUTE IMMEDIATE 'ALTER DATABASE CLEAR LOGFILE GROUP ' || cfrec.group#;\n";
  $sql_string .= "  END LOOP;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.addLogfilesOmf(): *** END ***");
}


# Run specified SQL script file or text
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# runCustomerScript(script)
sub runCustomerScript
{
  EMD_PERL_DEBUG("db_clone_10_2.runCustomerScript(): *** START ***");

  my ($script) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.runCustomerScript(): script: $script");

  my $sql_string = "";
  $sql_string .= "set echo on\n";
  $sql_string .= "$script\n";
  $sql_string .= "exit;\n";

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

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

  EMD_PERL_DEBUG("db_clone_10_2.runCustomerScript(): *** END ***");
}

############# end helper methods for testing purpose ########


############# methods for using RMAN backup #########

# Restore multiple datafiles
# If OMF, passin datafile names are not used.
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# restoreMultipleDatafilesOmf(sameHost, pieceNames, archPieceName, archPrefix, fileNums, fileNames, omfFlag, asmFlag)
sub restoreMultipleDatafilesOmf
{
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): *** START ***");

  my ($sameHost, $pieceNames, $archPieceName, $archPrefix, $fileNums, $fileNames, $omfFlag, $asmFlag) = @_;

  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): Is same host: $sameHost");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): Backup piece names: $pieceNames");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): archPieceName: $archPieceName");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): archPrefix: $archPrefix");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): File numbers to be restored: $fileNums");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): The restored file names: $fileNames");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): omfFlag: $omfFlag");
  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): asmFlag: $asmFlag");

  my @backupPieceNames = split /$DELIMITER/, $pieceNames;
  my @datafileNums = split /$DELIMITER/, $fileNums;
  my @datafileNames = split /$DELIMITER/, $fileNames;

  my $datafileNum;
  my $index = 0;
  my $keepPieceFlag = ""; #define this to keep the backup piece

  foreach $datafileNum (@datafileNums)
  {
    if($sameHost ne "Y")
    {
      restoreOneDatafileOmf($backupPieceNames[$index], $datafileNums[$index], $datafileNames[$index], $omfFlag, $asmFlag, $keepPieceFlag);
    }
    else
    {
      restoreOneDatafileOmfSameHost($backupPieceNames[$index], $datafileNums[$index], $datafileNames[$index], $omfFlag, $asmFlag);
    }
    $index ++;
  }

  if($archPrefix eq "REC_AREA")
  {
      $archPrefix = '';
  }

  if($sameHost eq "Y")
  {
    restoreLogSameHostExistingBS($archPieceName, $archPrefix);
  }
  else
  {
    restoreLog($archPieceName, $archPrefix);
  }

  EMD_PERL_DEBUG("db_clone_10_2.restoreMultipleDatafilesOmf(): *** END ***");
}

############# end methods for using RMAN backup #########


############# methods for using RMAN duplicate #########
# Modify database after using RMAN duplicate
# modifyDatabaseAfterDuplicate(pfileFullName, spfile, omfFlag, asmFlag,
#                              adminInitFile, spfileFullName)
sub modifyDatabaseAfterDuplicate
{
  EMD_PERL_DEBUG("db_clone_10_2.modifyDatabaseAfterDuplicate(): *** START ***");

  if($clonePurpose eq "STANDBY_NO_RECOVERY")
  {
  EMD_PERL_DEBUG("db_clone_10_2.modifyDatabaseAfterDuplicate(): Do not modify database as clone purpose is: $clonePurpose");
    EMD_PERL_DEBUG("db_clone_10_2.modifyDatabaseAfterDuplicate(): *** END ***");
    return;
  }

  my ($pfileFullName, $spfile, $omfFlag, $asmFlag,
      $adminInitFile, $spfileFullName) = @_;

  if(($omfFlag eq "Y") || ($asmFlag eq "Y"))
  {
    &addControlFileNamesInInitFile($pfileFullName, $spfile);
  }

  &copyInitFile($pfileFullName, $adminInitFile, $spfile);

  if(($spfile eq "Y") && ($asmFlag eq "Y"))
  {
    #disable for now since the ASM spfile does not work now
    #&createSpfile($pfileFullName, $spfileFullName);
  }

  &openDBOMS($pfileFullName, $spfile);

  EMD_PERL_DEBUG("db_clone_10_2.modifyDatabaseAfterDuplicate(): *** END ***");
}

# Open the cloned database
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# openDBOMS(pfileFullName, spfile)
sub openDBOMS
{
  EMD_PERL_DEBUG("db_clone.openDBOMS(): *** START ***");

  my ($pfileFullName, $spfile) = @_;

  my $sql_string = "";
  $sql_string .= "set echo off\n";

  if($spfile eq "Y")
  {
    $sql_string .= "startup force mount;\n";
  }
  else
  {
    $sql_string .= "startup force mount pfile='$pfileFullName';\n";
  }

  $sql_string .= "alter database open;\n";
  $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";

  if($clodClone eq "Y")
  {
    $sql_string .= "shutdown immediate;\n";
    if($spfile eq "Y")
    {
      $sql_string .= "startup mount;\n";
    }
    else
    {
      $sql_string .= "startup mount pfile='$pfileFullName';\n";
    }
    $sql_string .= "alter database NOARCHIVELOG;\n";
    $sql_string .= "alter database open;\n";
    $sql_string .= "SELECT STATUS FROM V\$INSTANCE;\n";
  }

  $sql_string .= "exit;\n";

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

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

  EMD_PERL_DEBUG("db_clone.openDBOMS(): *** END ***");
}
############# end methods for using RMAN duplicate #####

# Check whether OCM Directory exists, if yes reset it
# Call &set_env($oracleHome, $oracleSid) before calling this method.
# resetOCMDirObject
sub resetOCMDirObject
{
  EMD_PERL_DEBUG("db_clone_10_2.resetOCMDirObject(): *** START ***");
  my $sql_string = "";
  $sql_string .= "set echo off\n";
  $sql_string .= "set serveroutput on;\n\n";
  $sql_string .= "set linesize 512;\n";
  $sql_string .= "variable rowcount number;\n";
  $sql_string .= "BEGIN\n";
  $sql_string .= "  select count(*) INTO :rowcount from dba_directories where directory_name = 'ORACLE_OCM_CONFIG_DIR';\n";
  $sql_string .= "  dbms_output.put_line('Row count: '||:rowcount);\n";
  $sql_string .= "  IF (:rowcount > 0) then\n";
  $sql_string .= "      dbms_output.put_line('Reset ORACLE_OCM_CONFIG_DIR');\n";
  $sql_string .= "      ORACLE_OCM.MGMT_CONFIG_UTL.create_replace_dir_obj;\n";
  $sql_string .= "  end if;\n";
  $sql_string .= "END;\n";
  $sql_string .= "/\n";
  $sql_string .= "EXIT;\n";
  (my $fh, my $filename) = &runSqlOnDestination($sql_string);

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

1;

#Tests
#removed main_dbclone_10_2
