Rem drv: Rem Rem $Header: emcore/source/oracle/sysman/emdrep/sql/core/latest/failover/failover_pkgbody.sql /st_emcore_10.2.0.4.2db11.2/1 2008/09/26 14:26:37 jsadras Exp $ Rem Rem failover_pkgbody.sql Rem Rem Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. Rem Rem NAME Rem failover_pkgbody.sql - Manages failover of middle-tier components Rem Rem DESCRIPTION Rem Rem Rem NOTES Rem Rem Rem MODIFIED (MM/DD/YY) Rem jsadras 09/23/08 - Bug:7426001, add dbms_assert calls Rem sradhakr 05/19/07 - Backport sradhakr_rfi_backport_5873907_10.2.4.0.0 Rem from st_emcore_10.2.0.1.0 Rem sradhakr 03/09/07 - incorporating review comments for Bug#5873907. Rem sradhakr 03/07/07 - Bug#5873907 - OMS FAILOVER CODE DOES NOT HANDLE Rem DST CHANGES. Rem sradhakr 04/05/07 - Backport sradhakr_dummy2 from main Rem neearora 08/25/05 - Fetch heartbeat_interval_factor from mgmt_parameters Rem rmaggarw 07/29/05 - handle callback errors Rem gsbhatia 07/01/05 - New repmgr header impl Rem skini 06/23/05 - Do not keep failvoer entry on error Rem skini 06/23/05 - Catch errors if callbacks fail Rem aholser 06/09/05 - add host name to register proc Rem rmaggarw 01/27/05 - introduce sticky omsid Rem gan 08/19/04 - add get_active_mt_count Rem gan 11/21/03 - increase the time interval for failover Rem skini 06/06/03 - Prevent unnecessary locking Rem skini 04/23/03 - Add column for hb interval Rem rpinnama 09/16/02 - Use Ping API Rem mbhoopat 07/30/02 - Add support for OMS_URL parameter Rem aholser 05/29/02 - insert mgmt_oms_parameters entry. Rem rpinnama 05/15/02 - rpinnama_reorg_rep_scripts Rem rpinnama 05/15/02 - Restructured. Rem aholser 03/28/02 - monitoring the monitor. Rem skini 01/30/02 - Increase failover interval Rem rpinnama 01/21/02 - Lock during inserting. Rem rpinnama 01/18/02 - Add a method to get the count of entries.. Rem skini 11/21/01 - Merged skini_js_stability Rem skini 11/19/01 - fix typo Rem skini 11/18/01 - Created Rem CREATE OR REPLACE PACKAGE BODY MGMT_FAILOVER AS --Forward declaration for private function FUNCTION get_oms_id(p_host_url IN VARCHAR2) RETURN INTEGER; FUNCTION register(p_host_url IN VARCHAR2, p_oms_url IN VARCHAR2, p_host_name IN VARCHAR2, p_heartbeat_interval IN NUMBER) RETURN INTEGER IS l_mt_cnt INTEGER := 0; l_new_id INTEGER; l_old_hosturl VARCHAR2(256); l_value VARCHAR2(256); l_oms_id INTEGER; BEGIN -- Lock the table before getting the count.. LOCK TABLE MGMT_FAILOVER_TABLE IN EXCLUSIVE MODE; l_mt_cnt := get_active_mt_count; -- If this is no active middle tier system yet, -- start the ping sub system. IF (l_mt_cnt = 0) THEN -- We have to implement a callback mechanism here.. EM_PING.start_ping_system; END IF; INSERT INTO MGMT_FAILOVER_TABLE(failover_id, last_time_stamp, host_url, heartbeat_interval, last_time_stamp_utc) VALUES(MGMT_FAILOVER_SEQUENCE.NEXTVAL, SYSDATE, p_host_url, p_heartbeat_interval, sys_extract_utc(SYSTIMESTAMP)) RETURNING failover_id INTO l_new_id; BEGIN SELECT value INTO l_value FROM MGMT_OMS_PARAMETERS WHERE host_url=p_host_url AND name='TIMESTAMP'; UPDATE MGMT_OMS_PARAMETERS SET value=TO_CHAR(SYSDATE, 'DD-Mon-YYYY HH24:MI:SS') WHERE host_url=p_host_url AND name='TIMESTAMP'; UPDATE MGMT_OMS_PARAMETERS SET value=p_oms_url WHERE host_url=p_host_url AND name='OMS_URL'; EXCEPTION WHEN NO_DATA_FOUND THEN INSERT INTO mgmt_oms_parameters(host_url, name, value) VALUES (p_host_url, 'TIMESTAMP', TO_CHAR(SYSDATE, 'DD-Mon-YYYY HH24:MI:SS')); INSERT INTO mgmt_oms_parameters(host_url, name, value) VALUES (p_host_url, 'OMS_URL', p_oms_url); INSERT INTO mgmt_oms_parameters(host_url, name, value) VALUES (p_host_url, 'HOST_NAME', p_host_name); l_oms_id := get_oms_id(p_host_url); INSERT INTO mgmt_oms_parameters(host_url, name, value) VALUES (p_host_url, 'OMS_ID', TO_CHAR(l_oms_id)); END; RETURN l_new_id; END; FUNCTION get_middle_tier_count RETURN INTEGER IS l_cnt INTEGER; BEGIN SELECT count(failover_id) INTO l_cnt FROM MGMT_FAILOVER_TABLE; return l_cnt; END; FUNCTION get_active_mt_count RETURN INTEGER IS l_oms_grace NUMBER; l_cnt INTEGER; BEGIN BEGIN SELECT to_number(parameter_value) INTO l_oms_grace FROM mgmt_parameters WHERE parameter_name = G_ACTIVE_OMS_GRACE_PROP; EXCEPTION WHEN OTHERS THEN l_oms_grace := G_DEFAULT_OMS_GRACE; END; IF l_oms_grace < G_MIN_OMS_GRACE THEN l_oms_grace := G_MIN_OMS_GRACE; END IF; SELECT count(failover_id) INTO l_cnt FROM MGMT_FAILOVER_TABLE WHERE SYSDATE-last_time_stamp < l_oms_grace/(24*60*60); return l_cnt; END; PROCEDURE register_callback(p_callback_name VARCHAR2) IS BEGIN INSERT INTO MGMT_FAILOVER_CALLBACKS(callback_name) VALUES(p_callback_name); END; FUNCTION heartbeat(p_id IN NUMBER) RETURN INTEGER IS BEGIN UPDATE MGMT_FAILOVER_TABLE SET last_time_stamp=SYSDATE, last_time_stamp_utc=sys_extract_utc(SYSTIMESTAMP) WHERE failover_id=p_id; RETURN SQL%ROWCOUNT; END; PROCEDURE check_failure IS l_host_url VARCHAR2(256); l_count NUMBER; l_skip BOOLEAN; l_heartbeat_interval_factor NUMBER; BEGIN BEGIN SELECT to_number(parameter_value) INTO l_heartbeat_interval_factor FROM mgmt_parameters WHERE parameter_name = G_HEARTBEAT_INTERVAL_FACTOR; EXCEPTION WHEN OTHERS THEN l_heartbeat_interval_factor := G_DEFAULT_HB_INTERVAL_FACTOR; END; SELECT COUNT(*) INTO l_count FROM MGMT_FAILOVER_TABLE WHERE sys_extract_utc(SYSTIMESTAMP)-last_time_stamp_utc > numtodsinterval(heartbeat_interval*l_heartbeat_interval_factor, 'SECOND'); -- Prevent unnecesary locking IF l_count=0 THEN RETURN; END IF; -- If we're here, there is at least one dead oms LOCK TABLE MGMT_FAILOVER_TABLE IN EXCLUSIVE MODE; FOR crec IN (SELECT failover_id, last_time_stamp FROM MGMT_FAILOVER_TABLE WHERE sys_extract_utc(SYSTIMESTAMP)-last_time_stamp_utc > numtodsinterval(heartbeat_interval*l_heartbeat_interval_factor, 'SECOND')) LOOP l_skip := FALSE; SAVEPOINT oms_iteration; -- This middle-tier is considered to have died. Call -- all the callbacks for this middle-tier FOR C in (SELECT callback_name FROM MGMT_FAILOVER_CALLBACKS ORDER BY callback_name) LOOP SAVEPOINT callback_iteration; BEGIN EXECUTE IMMEDIATE 'BEGIN ' || DBMS_ASSERT.SQL_OBJECT_NAME(C.callback_name) || '(:1, :2); END;' USING crec.failover_id, crec.last_time_stamp; EXCEPTION WHEN OTHERS THEN IF (em_check.is_recoverable_error(SQLCODE)) THEN MGMT_LOG.log_error(G_MODULE_NAME, SQLCODE, 'OMS failover: Recoverable error encountered when running callback ' || C.callback_name || ' for OMS: '|| crec.failover_id || '. Will try again: ' || SQLERRM); -- Rollback all callbacks for this OMS and continue with next oms ROLLBACK TO oms_iteration; l_skip := TRUE; EXIT; ELSE MGMT_LOG.log_error(G_MODULE_NAME, SQLCODE, 'OMS failover: error encountered when running callback ' || C.callback_name || ' for OMS: '|| crec.failover_id || '. Skipping callback: ' || SQLERRM); -- Rollback current callback and continue with next callback ROLLBACK TO callback_iteration; END IF; END; END LOOP; IF (l_skip = FALSE) THEN -- Update the timestamp for the 'down since'. If the entry doesn't exist, -- it is considered removed BEGIN SELECT host_url INTO l_host_url FROM mgmt_failover_table WHERE failover_id=crec.failover_id; UPDATE mgmt_oms_parameters SET value=TO_CHAR(SYSDATE, 'DD-Mon-YYYY HH24:MI:SS') WHERE host_url=l_host_url AND name='TIMESTAMP'; EXCEPTION WHEN NO_DATA_FOUND THEN NULL; END; -- Delete the entry for this middle-tier DELETE FROM MGMT_FAILOVER_TABLE WHERE failover_id=crec.failover_id; END IF; END LOOP; END; FUNCTION get_oms_id(p_host_url IN VARCHAR2) RETURN INTEGER IS oms_id INTEGER; BEGIN --return existing SELECT to_number(value) INTO oms_id FROM MGMT_OMS_PARAMETERS WHERE NAME = 'OMS_ID' AND HOST_URL = p_host_url; RETURN oms_id; EXCEPTION WHEN NO_DATA_FOUND THEN --generate new SELECT nvl(max(to_number(value)),0)+1 INTO oms_id FROM MGMT_OMS_PARAMETERS WHERE NAME = 'OMS_ID'; RETURN oms_id; END; END MGMT_FAILOVER; / show errors;