# $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 - # # 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 # # # 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); ©File($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 () { 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 () { 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 () { 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 () { 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 () { 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 () { 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 = ; 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 = ; 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 () { 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 = ; 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); } ©InitFile($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); } ©InitFile($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 () { 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 () { 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 = ; 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 () { 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"); ©File($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 () { 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 () { 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 () { 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); } ©InitFile($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