Rem drv: Rem Rem $Header: emcore/source/oracle/sysman/emdrep/sql/core/latest/admin/admin_maint_util_pkgbody.sql /st_emcore_10.2.0.4.2db11.2/1 2008/09/26 14:26:37 jsadras Exp $ Rem Rem admin_maint_util_pkgbody.sql Rem Rem Copyright (c) 2006, 2008, Oracle and/or its affiliates. All rights reserved. Rem Rem NAME Rem admin_maint_util_pkgbody.sql - Rem Rem DESCRIPTION Rem Maintenance Utility to do the following Rem 1. Recompile Invalid Objects Rem 2. Partition Maintenance Rem **Note: Rem This Package spec should not depend on any EM related Rem Objects Rem The package body should not depend on any EM related Rem objects other than MGMT_VERSIONS, MGMT_LOG, Rem MGMT_PARAMETERS Rem Rem NOTES Rem Rem Rem MODIFIED (MM/DD/YY) Rem jsadras 09/23/08 - Bug:7425931, add dbms_assert Rem edemembe 07/17/07 - Backport edemembe_bug-6157164 from main Rem edemembe 07/11/07 - Bug 6157164 Rem minfan 05/23/07 - Bug 5894442 Rem minfan 05/23/07 - Bug 5894442 Rem minfan 05/23/07 - Bug 5894442 Rem minfan 05/23/07 - Bug 5894442 Rem rrawat 05/21/07 - Backport rrawat_bug-5502664 from main Rem rrawat 09/06/06 - Bug-5502664 Rem jsadras 08/09/06 - Created Rem CREATE OR REPLACE PACKAGE BODY EMD_MAINT_UTIL AS p_ErrMsg VARCHAR(2048); p_Module VARCHAR(128); p_Action VARCHAR(128); -- -- Names of basic tables which have partition maintenance enabled -- METRICS_RAW_TABLE CONSTANT VARCHAR(30) := 'MGMT_METRICS_RAW'; METRICS_1HOUR_TABLE CONSTANT VARCHAR(30) := 'MGMT_METRICS_1HOUR'; METRICS_1DAY_TABLE CONSTANT VARCHAR(30) := 'MGMT_METRICS_1DAY'; -- Variable to control the retention in metrics_raw/1hour/1day tables -- Days of partitions to keep PART_RETENTION_RAW CONSTANT PLS_INTEGER := 7; PART_RETENTION_1HOUR CONSTANT PLS_INTEGER := 31; PART_RETENTION_1DAY CONSTANT PLS_INTEGER := 365; -- Component modes COMPONENT_MODE_CENTRAL CONSTANT VARCHAR2(16) := 'CENTRAL'; MAX_RECOMPILES CONSTANT NUMBER := 5 ; -- -- Get central mode -- FUNCTION is_central_mode (p_comp_name VARCHAR2 DEFAULT 'CORE') RETURN NUMBER IS l_is_central NUMBER := 0; BEGIN SELECT COUNT(1) INTO l_is_central FROM MGMT_VERSIONS WHERE component_name = UPPER(p_comp_name) AND component_mode = COMPONENT_MODE_CENTRAL; RETURN l_is_central; END is_central_mode; -- -- Check if the table has partitioning enabled -- FUNCTION partitions_enabled(v_table_name IN VARCHAR2) RETURN BOOLEAN IS v_partitioned VARCHAR2(3); BEGIN -- -- Check for partitions on a core repository table. -- SELECT decode(bitand(t.property, 32), 32, 'YES', 'NO') INTO v_partitioned FROM sys.obj$ o,sys.tab$ t WHERE o.owner# = USERENV('SCHEMAID') AND o.name = UPPER(v_table_name) AND o.obj#=t.obj#; IF v_partitioned = 'YES' THEN RETURN TRUE; ELSE RETURN FALSE; END IF; END partitions_enabled ; --- --- Gets the retention period for fetching raw data from repository --- FUNCTION GET_RAW_RETENTION_WINDOW RETURN NUMBER IS l_custom_raw_window NUMBER; l_dflt_value NUMBER; BEGIN l_custom_raw_window:=NULL; -- Get the default custom raw value, into l_dflt_value, based on mode.. IF (is_central_mode > 0) THEN l_dflt_value := PART_RETENTION_RAW; ELSE l_dflt_value := (DEFAULT_RAW_KEEP/24); END IF; BEGIN SELECT NVL(TO_NUMBER(parameter_value), l_dflt_value) INTO l_custom_raw_window FROM mgmt_parameters WHERE parameter_name = RAW_KEEP_PARAM; EXCEPTION WHEN OTHERS THEN l_custom_raw_window := l_dflt_value; END; RETURN l_custom_raw_window; END GET_RAW_RETENTION_WINDOW; ---------------------------------------------------------------------- --- --- Gets the retention period for fetching 1 hour data from repository --- FUNCTION GET_1HOUR_RETENTION_WINDOW RETURN NUMBER IS l_custom_hour_window NUMBER; l_dflt_value NUMBER; BEGIN l_custom_hour_window:=NULL; -- Get the default custom 1hour value, into l_dflt_value, based on mode.. IF (is_central_mode > 0) THEN l_dflt_value := PART_RETENTION_1HOUR; ELSE l_dflt_value := (DEFAULT_HOUR_KEEP/24); END IF; BEGIN SELECT NVL(TO_NUMBER(parameter_value), l_dflt_value) INTO l_custom_hour_window FROM mgmt_parameters WHERE parameter_name = HOUR_KEEP_PARAM; EXCEPTION WHEN OTHERS THEN l_custom_hour_window := l_dflt_value; END; RETURN l_custom_hour_window; END GET_1HOUR_RETENTION_WINDOW; ---------------------------------------------------------------------- --- --- Gets the retention period for fetching 1 day data from repository --- FUNCTION GET_1DAY_RETENTION_WINDOW RETURN NUMBER IS l_custom_day_window NUMBER; l_dflt_value NUMBER; BEGIN l_custom_day_window :=null; -- Get the default custom 1day value, into l_dflt_value, based on mode.. IF (is_central_mode > 0) THEN l_dflt_value := PART_RETENTION_1DAY; ELSE l_dflt_value := DEFAULT_DAY_KEEP; END IF; BEGIN SELECT NVL(TO_NUMBER(parameter_value), l_dflt_value) INTO l_custom_day_window FROM mgmt_parameters WHERE parameter_name = DAY_KEEP_PARAM; EXCEPTION WHEN OTHERS THEN l_custom_day_window := l_dflt_value; END; RETURN l_custom_day_window; END GET_1DAY_RETENTION_WINDOW; -- -- Recreate Public Synonyms for views that start with MGMT$ -- and public synonyms for mgmt_metrics_raw,1hour,1day tables if present -- PROCEDURE recreate_synonyms IS BEGIN -- drop and recreate invalid public synonyms pointing to repository owner -- to make them valid. FOR rec IN ( SELECT syn.synonym_name,syn.table_name,syn.table_owner FROM all_objects ao, all_synonyms syn WHERE ao.status = 'INVALID' AND ao.owner = 'PUBLIC' AND ao.object_type = 'SYNONYM' AND syn.owner = 'PUBLIC' AND syn.table_owner = USER AND syn.synonym_name = ao.object_name) LOOP BEGIN EXECUTE IMMEDIATE 'CREATE OR REPLACE PUBLIC SYNONYM '||DBMS_ASSERT.ENQUOTE_NAME(rec.synonym_name,FALSE) ||' FOR '|| DBMS_ASSERT.ENQUOTE_NAME(rec.table_owner,FALSE)||'.'|| DBMS_ASSERT.ENQUOTE_NAME(rec.synonym_name,FALSE) ; EXCEPTION WHEN OTHERS THEN MGMT_LOG.LOG_ERROR('MAINT', null, 'Error during recreate_synoyms:'||sqlerrm) ; END ; END LOOP ; END recreate_synonyms; -- -- Private procedure -- Recompile the invalid objects -- p_recompile_no contains the number of times this procedure has been called -- if it is greater then MAX_RECOMPILE_TIMES then return -- PROCEDURE recompile_invalid_objects (p_recompile_no IN NUMBER) IS l_invalid_count NUMBER ; l_object_name all_objects.object_name%TYPE ; BEGIN -- -- If the recompiles have been done more than MAX_RECOMPILES -- times then exit -- IF p_recompile_no < 0 OR p_recompile_no > MAX_RECOMPILES THEN RETURN ; END IF ; dbms_utility.compile_schema(USER,FALSE); -- Compile any invalids left over by dbms_utility FOR crec IN (SELECT object_name, object_type, DECODE(object_type, 'TYPE', 1, 'FUNCTION', 2, 'PROCEDURE', 3, 'TRIGGER', 4, 'VIEW', 5, 'PACKAGE', 6, 'TYPE BODY', 7, 'PACKAGE BODY', 8, 'MATERIALIZED VIEW', 9, 10) object_type_seq FROM all_objects WHERE status ='INVALID' AND owner = USER AND object_type IN ('FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'TRIGGER', 'VIEW', 'TYPE BODY', 'TYPE', 'MATERIALIZED VIEW') ORDER BY object_type_seq, object_type, created) LOOP BEGIN l_object_name := DBMS_ASSERT.ENQUOTE_NAME(crec.object_name,FALSE); IF (crec.object_type = 'PACKAGE BODY') THEN -- If package body is invalid, just compile the body and not -- the specification EXECUTE IMMEDIATE 'ALTER PACKAGE ' || l_object_name || ' compile body'; ELSIF (crec.object_type = 'TYPE') THEN -- If type spec is invalid, just compile the specification and not -- the body EXECUTE IMMEDIATE 'ALTER TYPE ' || l_object_name || ' compile specification'; ELSIF (crec.object_type = 'TYPE BODY') THEN -- If type body is invalid, just compile the body and not -- the specification EXECUTE IMMEDIATE 'ALTER TYPE ' || l_object_name || ' compile body'; ELSIF (crec.object_type = 'MATERIALIZED VIEW') THEN EXECUTE IMMEDIATE 'ALTER MATERIALIZED VIEW '||l_object_name||' compile' ; ELSE EXECUTE IMMEDIATE 'ALTER ' || DBMS_ASSERT.SIMPLE_SQL_NAME(crec.object_type) || ' ' || l_object_name || ' compile'; END IF; EXCEPTION WHEN OTHERS THEN NULL; -- No action on failure. Continue to next object. END; END LOOP; -- Check if there are any more invalids SELECT COUNT(*) INTO l_invalid_count FROM user_objects WHERE status = 'INVALID' AND object_type IN ('FUNCTION', 'PACKAGE', 'PACKAGE BODY', 'PROCEDURE', 'TRIGGER', 'VIEW', 'TYPE BODY', 'TYPE', 'MATERIALIZED VIEW'); IF l_invalid_count > 0 THEN -- recursively call recompile recompile_invalid_objects(p_recompile_no+1); END IF ; EXCEPTION -- No action on failure WHEN OTHERS THEN NULL ; END recompile_invalid_objects; -- -- Recompile Invalid Objects -- PROCEDURE recompile_invalid_objects IS BEGIN recompile_invalid_objects(1); -- recreate the invalid public synonyms recreate_synonyms ; END recompile_invalid_objects; -- Do Partition maintenance on the following tables -- MGMT_METRICS_RAW -- MGMT_METRICS_1HOUR -- MGMT_METRICS_1DAY -- PROCEDURE partition_maintenance ( p_stop_job BOOLEAN DEFAULT TRUE ) IS -- -- Drop partitions for the table older than retention days -- This has been made a local procedure because the -- drop partitions accept table name as input, we need to -- call em_check procedure. By making this local, we are -- not accepting parameters from outside. -- If we call em_check then em_check will become a dependency -- and we want to avoid dependencies PROCEDURE drop_partitions(v_table_name IN VARCHAR2, v_retention_days IN PLS_INTEGER) IS CURSOR old_partition_cursor (c_table_name VARCHAR2, c_keep_date DATE) IS SELECT partition_name FROM user_tab_partitions WHERE table_name = UPPER(c_table_name) AND partition_name < TO_CHAR(c_keep_date,'YYYY-MM-DD HH24:MI') ORDER BY partition_name DESC; TYPE local_string_table IS TABLE OF user_tab_partitions.partition_name%TYPE INDEX BY BINARY_INTEGER ; v_partitionDate DATE; v_keepDate DATE; v_part_names local_string_table ; BEGIN v_keepDate := TRUNC((SYSDATE - v_retention_days), 'HH24'); IF NOT (partitions_enabled(v_table_name)) THEN RETURN; END IF; -- Doing bulk collect up front to avoid snapshot too old OPEN old_partition_cursor(v_table_name,v_keepDate) ; FETCH old_partition_cursor BULK COLLECT INTO v_part_names ; CLOSE old_partition_cursor ; IF v_part_names IS NULL or v_part_names.COUNT = 0 THEN RETURN ; END IF ; FOR part_rec IN v_part_names.FIRST..v_part_names.LAST LOOP EXECUTE IMMEDIATE 'ALTER TABLE '||v_table_name ||' DROP PARTITION "' ||v_part_names(part_rec) || '"'; END LOOP; EXCEPTION WHEN OTHERS THEN p_ErrMsg := SUBSTR(SQLERRM, 1, 2048); DBMS_APPLICATION_INFO.READ_MODULE(p_Module,p_Action); MGMT_LOG.LOG_ERROR('MAINT', null, 'Error during ' || p_Module || ' : ' || p_ErrMsg,p_Action); END drop_partitions ; BEGIN DBMS_APPLICATION_INFO.SET_MODULE( module_name => 'Oracle Enterprise Manager.Partition Maintenance', action_name => 'start'); -- Starting 102DB, we do not need to stop job before dropping -- partition. -- Stop/Remove all the EM jobs -- Execute Immediate is called instead of direct call to avoid -- making this package a dependent of emd_maintenance which gets -- invalidated by dropping of partitions -- IF p_stop_job THEN EXECUTE IMMEDIATE 'CALL emd_maintenance.remove_em_dbms_jobs()'; END IF; -- Drop old partitions --get_%_retention_window will get the retention days, if set in --mgmt_parameters else default value drop_partitions(metrics_raw_table, get_raw_retention_window); drop_partitions(metrics_1hour_table, get_1hour_retention_window); drop_partitions(metrics_1day_table, get_1day_retention_window); -- Recompile all the invalidated repository objects. recompile_invalid_objects; -- Submit all the EM jobs IF p_stop_job THEN EXECUTE IMMEDIATE 'CALL emd_maintenance.submit_em_dbms_jobs() ' ; END IF; DBMS_APPLICATION_INFO.SET_MODULE( module_name => ' ', action_name => ' '); EXCEPTION WHEN OTHERS THEN p_ErrMsg := SUBSTR(SQLERRM, 1, 2048); DBMS_APPLICATION_INFO.READ_MODULE(p_Module,p_Action); MGMT_LOG.LOG_ERROR('MAINT', null, 'Error during ' || p_Module || ' : ' || p_ErrMsg,p_Action); DBMS_APPLICATION_INFO.SET_MODULE( module_name => ' ', action_name => ' '); END partition_maintenance; END EMD_MAINT_UTIL ; /