Rem drv: Rem Rem $Header: emdb/source/oracle/sysman/emdrep/sql/db/latest/rec/rec_pkgbodys.sql /st_emdbsa_11.2/2 2009/02/26 12:19:48 nzhao Exp $ Rem Rem rec_pkgbodys.sql Rem Rem Copyright (c) 2003, 2009, Oracle and/or its affiliates. Rem All rights reserved. Rem Rem NAME Rem rec_pkgbodys.sql Rem Rem DESCRIPTION Rem Backup and Recovery PL/SQL procedures and functions. Rem - Submit an oracle-suggested recurring backup job (DB Control only). Rem - PL/SQL ROWSET handlers. Rem - Callback for restartable backups. Rem Rem NOTES Rem Rem Rem MODIFIED (MM/DD/YY) Rem pbantis 12/05/08 - Bug 7344865 change retry_backup_job(). Rem nzhao 11/05/08 - Change the tag name for OSS to support 11.2 DB. Rem pbantis 09/02/05 - Change retrieval of large parameter. Rem pbantis 09/01/05 - Restartable backups - handle db target version. Rem pbantis 08/30/05 - Add retry_backup_job(). Rem pbantis 08/29/05 - More default param values. Rem pbantis 08/19/05 - Default param values for update_mgmt_ha_backup(). Rem pbantis 07/28/05 - Remove commits from plsql rowset handlers. Rem pbantis 07/25/05 - Add update_mgmt_ha_* procedures. Rem chyu 06/28/05 - New repmgr header impl Rem hying 02/14/05 - Fix merge conflict Rem hying 02/09/05 - add db_name Rem dsahrawa 11/04/04 - use mgmt_jobs.get_job_schedule_record Rem pbantis 11/03/04 - Turn DEFINE back on. Rem pbantis 10/27/04 - Support OMS-side perl. Rem dsahrawa 06/22/04 - use MGMT_JOBS.get_job_schedule_record Rem hying 12/16/03 - 3316974, commit Rem ysun 12/02/03 - modify cred params for do_blackout Rem hying 12/01/03 - do_blackout Rem pbantis 10/09/03 - Override credentials Rem pbantis 09/29/03 - Escape perl special characters in the rman. Rem Support for large parameter. Rem skini 09/09/03 - Change in schedule_record structure Rem hying 08/08/03 - Fix extend Rem hying 08/07/03 - Fix bug 3086483 Rem hying 07/07/03 - Fix schema 0706 Rem hying 07/03/03 - Change package name Rem hying 06/05/03 - hying_oss Rem hying 06/05/03 - Created Rem -- This forces sqlplus to ignore ampersand chars SET DEFINE OFF CREATE OR REPLACE PACKAGE BODY MGMT_REC as -- -- PROCEDURE: submit_out_of_box_backup -- for use by DBCA to create daily database backup to disk -- PROCEDURE submit_out_of_box_backup( p_host_username IN VARCHAR2, p_host_password IN VARCHAR2, p_db_username IN VARCHAR2, p_db_password IN VARCHAR2, p_db_role IN VARCHAR2, p_db_connect_string IN VARCHAR2, p_db_name IN VARCHAR2, p_target_name IN VARCHAR2, p_target_type IN VARCHAR2, p_job_name IN VARCHAR2, p_job_desc IN VARCHAR2, p_execution_hours IN NUMBER, p_execution_minutes IN NUMBER, p_noarchivelog_mode IN VARCHAR2) IS job_targets MGMT_JOB_TARGET_LIST; job_params MGMT_JOB_PARAM_LIST; job_id RAW(16); execution_id RAW(16); schedule MGMT_JOB_SCHEDULE_RECORD; rman_script VARCHAR2(256); large_param CLOB; large_param_value VARCHAR2(256); creds MGMT_JOB_CRED_ARRAY := MGMT_JOB_CRED_ARRAY(); l_cred_rows MGMT_CRED_ROW_ARRAY := MGMT_CRED_ROW_ARRAY(); l_cred_record MGMT_CRED_RECORD; role VARCHAR2(8); setName VARCHAR2(16); cred_columns MGMT_JOB_VECTOR_PARAMS := MGMT_JOB_VECTOR_PARAMS(); BEGIN job_targets := MGMT_JOB_TARGET_LIST(); job_targets.extend(1); job_targets(1) := MGMT_JOB_TARGET_RECORD(p_target_name, p_target_type); -- Submit the parameters for the job. All parameters that your job -- needs must be specified here job_params := MGMT_JOB_PARAM_LIST(); job_params.extend(13); rman_script := 'run { allocate channel oem_disk_backup device type disk; recover copy of database with tag ''ORA_OEM_LEVEL_0''; backup incremental level 1 cumulative copies=1 for recover of copy with tag ''ORA_OEM_LEVEL_0'' database;}'; job_params(1) := MGMT_JOB_PARAM_RECORD('backup_strategy', MGMT_JOBS.PARAM_TYPE_SCALAR, 'basic', null); job_params(2) := MGMT_JOB_PARAM_RECORD('device_type', MGMT_JOBS.PARAM_TYPE_SCALAR, 'disk', null); job_params(3) := MGMT_JOB_PARAM_RECORD('daily_backup_script', MGMT_JOBS.PARAM_TYPE_SCALAR, rman_script, null); job_params(4) := MGMT_JOB_PARAM_RECORD('is_cold_backup', MGMT_JOBS.PARAM_TYPE_SCALAR, p_noarchivelog_mode, null); job_params(5) := MGMT_JOB_PARAM_RECORD('blackout_target_name', MGMT_JOBS.PARAM_TYPE_SCALAR, p_target_name, null); job_params(6) := MGMT_JOB_PARAM_RECORD('blackout_target_type', MGMT_JOBS.PARAM_TYPE_SCALAR, p_target_type, null); job_params(7) := MGMT_JOB_PARAM_RECORD('db_connect_string', MGMT_JOBS.PARAM_TYPE_SCALAR, p_db_connect_string, null); job_params(8) := MGMT_JOB_PARAM_RECORD('use_rcvcat', MGMT_JOBS.PARAM_TYPE_SCALAR, 'NO', null); job_params(9) := MGMT_JOB_PARAM_RECORD('db_10_or_higher', MGMT_JOBS.PARAM_TYPE_SCALAR, 'YES', null); job_params(10) := MGMT_JOB_PARAM_RECORD('rman_perl_script', MGMT_JOBS.PARAM_TYPE_LARGE, null, null); job_params(11) := MGMT_JOB_PARAM_RECORD('do_blackout', MGMT_JOBS.PARAM_TYPE_SCALAR, 'NO', null); job_params(12) := MGMT_JOB_PARAM_RECORD('db_name', MGMT_JOBS.PARAM_TYPE_SCALAR, p_db_name, null); job_params(13) := MGMT_JOB_PARAM_RECORD('modified_rman_perl_script', MGMT_JOBS.PARAM_TYPE_LARGE, null, null); -- Always override the preferred credentials. creds.extend(2); l_cred_rows.extend(2); -- Database host credentials l_cred_rows(1) := MGMT_CRED_ROW_RECORD('HostUsername', p_host_username); l_cred_rows(2) := MGMT_CRED_ROW_RECORD('HostPassword', p_host_password); l_cred_record := MGMT_CRED_RECORD(MGMT_USER.get_current_em_user, 'DBHostCreds', l_cred_rows); creds(1) := MGMT_JOB_CRED_RECORD(null, p_target_type, null, l_cred_record); -- Database credentials l_cred_rows.extend(1); role := UPPER(p_db_role); IF role = 'NORMAL' THEN l_cred_rows(1) := MGMT_CRED_ROW_RECORD('username', p_db_username); l_cred_rows(2) := MGMT_CRED_ROW_RECORD('password', p_db_password); l_cred_rows(3) := MGMT_CRED_ROW_RECORD('role', role); setName := 'DBCredsNormal'; ELSE l_cred_rows(1) := MGMT_CRED_ROW_RECORD('sysDBAUserName', p_db_username); l_cred_rows(2) := MGMT_CRED_ROW_RECORD('sysDBAPassword', p_db_password); l_cred_rows(3) := MGMT_CRED_ROW_RECORD('sysDBARole', role); setName := 'DBCredsSYSDBA'; cred_columns.extend(3); cred_columns(1) := 'sysDBAUserName'; cred_columns(2) := 'sysDBAPassword'; cred_columns(3) := 'sysDBARole'; job_params.extend(2); job_params(14) := MGMT_JOB_PARAM_RECORD('db_credential_set_name', 1, setName, null); job_params(15) := MGMT_JOB_PARAM_RECORD('db_credential_columns', MGMT_JOBS.PARAM_TYPE_VECTOR, null, cred_columns); END IF; l_cred_record := MGMT_CRED_RECORD(MGMT_USER.get_current_em_user, setName, l_cred_rows); creds(2) := MGMT_JOB_CRED_RECORD(null, p_target_type, null, l_cred_record); -- Schedule schedule := MGMT_JOBS.get_job_schedule_record(MGMT_JOBS.DAILY_FREQUENCY_CODE, SYSDATE, null, p_execution_hours, p_execution_minutes, 0, null, null, MGMT_JOBS.TIMEZONE_REPOSITORY, 0,0, null); -- Submit the job. MGMT_JOBS.submit_job(p_job_name, p_job_desc, 'Backup', job_targets, job_params, schedule, job_id, execution_id, null, 0, creds); -- Set the 1st large parameter. large_param := MGMT_JOBS.get_large_param(job_id, execution_id, 'rman_perl_script'); large_param_value := '&br_save_agent_env(); ' || '&br_prebackup($l_db_connect_string, $l_is_cold_backup, $l_use_rcvcat, $l_db_10_or_higher, $l_backup_strategy); ' || 'my $result = &br_backup(); ' || 'exit($result);'; dbms_lob.write(large_param, LENGTH(large_param_value), 1, large_param_value); -- Set the 2nd large parameter. large_param := MGMT_JOBS.get_large_param(job_id, execution_id, 'modified_rman_perl_script'); large_param_value := ' '; dbms_lob.write(large_param, LENGTH(large_param_value), 1, large_param_value); commit; dbms_output.put_line('Oracle Suggested Backup Job ' || p_job_name || ' successfully inserted'); dbms_output.put_line('Job id is ' || job_id); dbms_output.put_line('Execution id is ' || execution_id); END submit_out_of_box_backup; -- PL/SQL Procedure used by loader to handle table inserts for mgmt_ha_backup. PROCEDURE update_mgmt_ha_backup( p_target_guid IN RAW, p_collection_timestamp IN DATE DEFAULT SYSDATE, p_end_time IN DATE DEFAULT NULL, p_status IN VARCHAR2 DEFAULT NULL, p_session_key IN NUMBER DEFAULT NULL, p_session_recid IN NUMBER DEFAULT NULL, p_session_stamp IN NUMBER DEFAULT NULL, p_command_id IN VARCHAR2 DEFAULT NULL, p_start_time in DATE DEFAULT NULL, p_time_taken_display IN VARCHAR2 DEFAULT NULL, p_input_type IN VARCHAR2 DEFAULT NULL, p_output_device_type IN VARCHAR2 DEFAULT NULL, p_input_bytes_display IN VARCHAR2 DEFAULT NULL, p_output_bytes_display IN VARCHAR2 DEFAULT NULL, p_output_bytes_per_sec_display IN VARCHAR2 DEFAULT NULL) IS BEGIN -- Insert the entry into mgmt_ha_backup table BEGIN INSERT INTO mgmt_ha_backup (target_guid, collection_timestamp, end_time, status, session_key, session_recid, session_stamp, command_id, start_time, time_taken_display, input_type, output_device_type, input_bytes_display, output_bytes_display, output_bytes_per_sec_display) VALUES (p_target_guid, p_collection_timestamp, p_end_time, p_status, p_session_key, p_session_recid, p_session_stamp, p_command_id, p_start_time, p_time_taken_display, p_input_type, p_output_device_type, p_input_bytes_display, p_output_bytes_display, p_output_bytes_per_sec_display); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN -- Entry already exists, update the entry UPDATE mgmt_ha_backup SET collection_timestamp = p_collection_timestamp, end_time = p_end_time, status = p_status, session_key = p_session_key, session_recid = p_session_recid, session_stamp = p_session_stamp, command_id = p_command_id, start_time = p_start_time, time_taken_display = p_time_taken_display, input_type = p_input_type, output_device_type = p_output_device_type, input_bytes_display = p_input_bytes_display, output_bytes_display = p_output_bytes_display, output_bytes_per_sec_display = p_output_bytes_per_sec_display WHERE target_guid = p_target_guid; END; EXCEPTION WHEN OTHERS THEN NULL; END update_mgmt_ha_backup; -- PL/SQL Procedure used by loader to handle table inserts for mgmt_ha_mttr. PROCEDURE update_mgmt_ha_mttr( p_target_guid IN RAW, p_collection_timestamp IN DATE DEFAULT SYSDATE, p_estimated_mttr IN NUMBER DEFAULT NULL) IS BEGIN -- Insert the entry into mgmt_ha_mttr table BEGIN INSERT INTO mgmt_ha_mttr (target_guid, collection_timestamp, estimated_mttr) VALUES (p_target_guid, p_collection_timestamp, p_estimated_mttr); EXCEPTION WHEN DUP_VAL_ON_INDEX THEN -- Entry already exists, update the entry UPDATE mgmt_ha_mttr SET collection_timestamp = p_collection_timestamp, estimated_mttr = p_estimated_mttr WHERE target_guid = p_target_guid; END; EXCEPTION WHEN OTHERS THEN NULL; END update_mgmt_ha_mttr; -- Restartable backup job. PROCEDURE retry_backup_job( p_reason IN NUMBER, p_status IN NUMBER, p_job_id IN RAW, p_execution_id IN RAW) IS -- Target version. l_dbversion_param VARCHAR2(64) := 'p_db_version'; l_dbversion_value MGMT_JOB_VECTOR_PARAMS; l_versionGTE9i BOOLEAN := false; l_decimalPosition NUMBER; l_versionNum NUMBER; -- Job start time. l_job_utc_start_time DATE := NULL; l_target_timezone VARCHAR2(64); l_job_target_start_time_date DATE; l_job_target_start_time_string VARCHAR2(64); -- Any format we want it to be. l_job_target_start_time_fmt VARCHAR(64) := 'MMDDYYHHMISS'; -- large input parameter: rman_perl_script l_script_param VARCHAR2(64) := 'rman_perl_script'; l_script_value_update_clob CLOB; -- large input parameter: retry_rman_perl_script l_retryscript_param VARCHAR2(64) := 'retry_rman_perl_script'; l_retryscript_param_found NUMBER := 1; l_retryscript_value_id RAW(16); l_retryscript_value_clob CLOB; -- parameter: exec_rman_perl_script l_execscript_param VARCHAR2(64) := 'exec_rman_perl_script'; l_backup_index NUMBER; l_semicolon_index NUMBER; l_not_backed_up_index NUMBER; l_backup_clause VARCHAR2(512); l_chunk_size INTEGER; l_buffer VARCHAR2(32767); l_read_offset INTEGER; BEGIN -- Determine the target version. SELECT vector_value INTO l_dbversion_value FROM MGMT_JOB_PARAMETER WHERE job_id=p_job_id AND execution_id=p_execution_id AND parameter_name=l_dbversion_param; IF ((l_dbversion_value IS NOT NULL) AND (l_dbversion_value.count > 0)) THEN l_decimalPosition := INSTR(l_dbversion_value(1), '.'); IF (l_decimalPosition > 0) THEN l_versionNum := TO_NUMBER(SUBSTR(l_dbversion_value(1), 0, l_decimalPosition)); IF (l_versionNum >= 9) THEN l_versionGTE9i := true; END IF; END IF; END IF; -- Restartable backups are only supported for db version 9i or higher. IF (l_versionGTE9i) THEN -- Get the start time (UTC) of the first execution in this chain. l_job_utc_start_time := getStartTimeOfFirstInChain(p_job_id, p_execution_id); IF (l_job_utc_start_time IS NULL) THEN RETURN; END IF; -- Get the target's timezone region. SELECT timezone_region INTO l_target_timezone FROM MGMT_TARGETS WHERE target_guid= (SELECT target_guid FROM MGMT_JOB_TARGET WHERE job_id=p_job_id AND execution_id=p_execution_id); -- Convert the start time (UTC) to that of the target timezone region. l_job_target_start_time_date := MGMT_GLOBAL.FROM_UTC(l_job_utc_start_time, l_target_timezone); -- Convert the date to a VARCHAR2 for RMAN 'backup ... TO_DATE()'. l_job_target_start_time_string := TO_CHAR(l_job_target_start_time_date, l_job_target_start_time_fmt); IF EMDW_LOG.p_is_debug_set THEN EMDW_LOG.debug('retry_backup_job: l_job_target_start_time_string ' || l_job_target_start_time_string, LOG_NAME); END IF; -- Get the 'rman_perl_script' large parameter value. l_script_value_update_clob := MGMT_JOB_ENGINE.GET_LARGE_PARAM(p_job_id, p_execution_id, l_script_param); -- Find the 'backup' command in the 'rman_perl_script' large parameter value. l_backup_index := DBMS_LOB.INSTR(l_script_value_update_clob, 'backup '); IF (l_backup_index > 0) THEN -- Find the trailing semicolon in the backup command. l_semicolon_index := DBMS_LOB.INSTR(l_script_value_update_clob, ';', l_backup_index); IF (l_semicolon_index > 0) THEN -- Ensure that there's not already a 'not backed up' clause -- between the 'backup' and ';'. l_not_backed_up_index := DBMS_LOB.INSTR(l_script_value_update_clob, 'not backed up'); -- Clause not found, or found after the semicolon. IF ((l_not_backed_up_index = 0) OR (l_not_backed_up_index > l_semicolon_index)) THEN -- Find the large input parameter 'retry_rman_perl_script' for this job. SELECT count(*) INTO l_retryscript_param_found FROM MGMT_JOB_PARAMETER WHERE job_id=p_job_id AND parameter_name=l_retryscript_param; -- CREATE parameter 'retry_rman_perl_script'. IF (l_retryscript_param_found = 0) THEN -- Create the parameter for this execution. INSERT INTO MGMT_JOB_PARAMETER(job_id, execution_id, parameter_name, parameter_type) VALUES (p_job_id, p_execution_id, l_retryscript_param, MGMT_JOB_ENGINE.PARAM_TYPE_LARGE) RETURNING large_value INTO l_retryscript_value_id; l_retryscript_value_clob := MGMT_JOB_ENGINE.GET_LARGE_PARAM(p_job_id, p_execution_id, l_retryscript_param, 1); -- UPDATE parameter 'retry_rman_perl_script'. ELSE -- Get the large value (id) for the existing 'retry_rman_perl_script' large parameter. SELECT large_value INTO l_retryscript_value_id FROM MGMT_JOB_PARAMETER WHERE job_id=p_job_id AND parameter_name=l_retryscript_param AND rownum=1; -- Associate the parameter to this execution. INSERT INTO MGMT_JOB_PARAMETER(job_id, execution_id, parameter_name, parameter_type, large_value) VALUES (p_job_id, p_execution_id, l_retryscript_param, MGMT_JOB_ENGINE.PARAM_TYPE_LARGE, l_retryscript_value_id); -- Get the 'retry_rman_perl_script' large parameter value. l_retryscript_value_clob := MGMT_JOB_ENGINE.GET_LARGE_PARAM(p_job_id, p_execution_id, l_retryscript_param, 1); -- Trim the original large parameter value. DBMS_LOB.TRIM(l_retryscript_value_clob, 0); END IF; -- Write to the 'retry_rman_perl_script' large parameter value. -- Copy 'rman_perl_script' data from the beginning up to the semicolon. DBMS_LOB.COPY(l_retryscript_value_clob, l_script_value_update_clob, l_semicolon_index-1, 1, 1); -- Use the chunk size for better read/write performance. l_chunk_size := DBMS_LOB.GETCHUNKSIZE(l_script_value_update_clob); -- Construct the 'not backed up' clause. l_backup_clause := ' not backed up since time \"TO_DATE(''' || l_job_target_start_time_string || ''', ''' || l_job_target_start_time_fmt || ''')\"'; -- Append the 'not backed up' clause. DBMS_LOB.WRITEAPPEND(l_retryscript_value_clob, LENGTH(l_backup_clause), l_backup_clause); -- Trim everything after the 'not backed up' clause. DBMS_LOB.TRIM(l_retryscript_value_clob, l_semicolon_index + LENGTH(l_backup_clause) - 1); BEGIN -- Start reading from the semicolon. l_read_offset := l_semicolon_index; LOOP -- Read from the copied clob value. DBMS_LOB.READ(l_script_value_update_clob, l_chunk_size, l_read_offset, l_buffer); l_read_offset := l_read_offset + l_chunk_size; -- Write to the original clob value. DBMS_LOB.WRITEAPPEND(l_retryscript_value_clob, l_chunk_size, l_buffer); END LOOP; EXCEPTION WHEN OTHERS THEN NULL; END; -- For this execution, update parameter 'exec_rman_perl_script' to contain 'retry_rman_perl_script'. UPDATE MGMT_JOB_PARAMETER SET scalar_value=l_retryscript_param WHERE job_id=p_job_id AND execution_id=p_execution_id AND parameter_name=l_execscript_param; -- COMMMIT will be made by caller of retry_backup_job. END IF; END IF; END IF; END IF; EXCEPTION WHEN OTHERS THEN EMDW_LOG.error('retry_backup_job: Exception occured while retrying Backup job', LOG_NAME); EMDW_LOG.error('retry_backup_job: Job id ' || p_job_id || ' and execution id ' || p_execution_id || ', SQLCODE: ' || SQLCODE || ', SQLERRM: ' || SQLERRM, LOG_NAME); END retry_backup_job; -- Function to return the start time of the first execution in the chain. -- Job 123, Day 1, Execution 123-1, Execution 123-2 -- Job 123, Day 2, Execution 123-11, Execution 123-21 -- e.g. Give Execution 123-21, you want the start time of Execution 123-11. FUNCTION getStartTimeOfFirstInChain( p_job_id IN RAW, p_execution_id IN RAW) RETURN DATE IS -- Job start time. l_utc_start_time DATE := NULL; -- Source execution id. l_source_execution_id MGMT_JOB_EXEC_SUMMARY.execution_id%TYPE := NULL; BEGIN SELECT start_time, source_execution_id INTO l_utc_start_time, l_source_execution_id FROM MGMT_JOB_EXEC_SUMMARY WHERE job_id=p_job_id AND execution_id=p_execution_id; IF ((l_source_execution_id IS NOT NULL) AND (p_execution_id != l_source_execution_id)) THEN -- Recursive call. l_utc_start_time := getStartTimeOfFirstInChain(p_job_id, l_source_execution_id); END IF; RETURN l_utc_start_time; EXCEPTION WHEN OTHERS THEN EMDW_LOG.error('getStartTimeOfFirstInChain: Exception occured while getting job execution start time', LOG_NAME); EMDW_LOG.error('getStartTimeOfFirstInChain: Job id ' || p_job_id || ' and execution id ' || p_execution_id || ', SQLCODE: ' || SQLCODE || ', SQLERRM: ' || SQLERRM, LOG_NAME); RETURN l_utc_start_time; END getStartTimeOfFirstInChain; END MGMT_REC; / SET DEFINE ON show errors;