From 99dbede9a263e23a9f526a6a9ad5a7004ad5bec7 Mon Sep 17 00:00:00 2001 From: Ralph Straubs Date: Tue, 9 May 2017 03:43:22 -0500 Subject: Batch submit [US866186 1710] Add the state_audit_interval_ms to the IntegrityMonitor.properties [US866186 1710] Added comments to the state audit property (state_audit_interval_ms) which clarify how to turn it off. [ECOMPD2TD-000] Update version.properties and pom.xml for iter 41 [ECOMPD2TD-000] Update version.properties and pom.xml for iter 41 Revert "[ECOMPD2TD-000] Update version.properties and pom.xml for iter 41" This reverts commit 61367d4c87fa6b153f707361537d9f802fb95a6e. [US250837 1710] Completed first cut of logic changes to PMStandbyStateChangeNotifier so that each segment of logic is only executed if a state change actually occurred. [US250837 1710] First cut on the JUnit for PMStandbyStateChangeNotifier. At this point I am simply checking the operation by inspecting the logs. [US250837 1710] Fixed the JUnit so it is not failing and added a note on how to run the JUnit. [US250837 1710] Added a method to get previousStandbyStatus from PMStandbyStateChangeHandler and began using it in JUnit tests. [US250837 1710] Finished the StandbyStateManagementTest. This uses the previousStandbyStatus value to test the function. [US250837 1710] Clean up of PMStandbyStateChangeNotifier and JUnit test to make static string values that are used throughout. [US250837 1710] Found a couple strings that I missed when converting to static variables. [US250837 1710] Updated PMStandbyStateChangeNotifier and StandbyStateManagementTest [US250837 1710] Added a dedicated db audit persistence unit auditDroolsPU to taylor the classes which will be audited. [ECOMPD2TD-1309] Clean up old persistence data This is an addition to 'policy-persistence' that cleans up 'sessioninfo' records with a 'lastmodificationdate' that is older than a specified time (default = 900 seconds = 15 minutes). [ECOMPD2TD-000] Correction to pom.xml versions Conflicts: version.properties Change-Id: I810d358c07e05fd36fa435a6fbb9e538e78b5011 Signed-off-by: Ralph Straubs --- .../drools/im/PMStandbyStateChangeNotifier.java | 171 +++++++++++++++------ .../drools/persistence/PersistenceFeature.java | 110 ++++++++++++- 2 files changed, 233 insertions(+), 48 deletions(-) (limited to 'policy-persistence/src/main') diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java index 46e5a5e6..363e43c4 100644 --- a/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/im/PMStandbyStateChangeNotifier.java @@ -84,7 +84,11 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { private long startTimeWaitingForActivationMs; private long waitInterval; private boolean isNowActivating; - + private String previousStandbyStatus; + public static String NONE = "none"; + public static String UNSUPPORTED = "unsupported"; + public static String HOTSTANDBY_OR_COLDSTANDBY = "hotstandby_or_coldstandby"; + public PMStandbyStateChangeNotifier(){ pdpUpdateInterval = Integer.parseInt(IntegrityMonitorProperties.getProperty(IntegrityMonitorProperties.PDP_UPDATE_INTERVAL)); isWaitingForActivation = false; @@ -92,6 +96,7 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { //delay the activate so the DesignatedWaiter can run twice - give it an extra 2 seconds waitInterval = 2*pdpUpdateInterval + 2000; isNowActivating=false; + previousStandbyStatus = PMStandbyStateChangeNotifier.NONE; } @Override @@ -101,99 +106,141 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { * has synchronize all of its methods. Only one stateManagement operation can occur at a time. Thus, * only one handleStateChange() call will ever be made at a time. */ - - logger.info("handleStateChange: Entering, message='" + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: Entering, message='" + super.getMessage() + "', standbyStatus='" + super.getStateManagement().getStandbyStatus() + "'"); - + } String standbyStatus = super.getStateManagement().getStandbyStatus(); String pdpId = IntegrityMonitorProperties .getProperty(IntegrityMonitorProperties.PDP_INSTANCE_ID); DroolsPdpsConnector conn = PersistenceFeature .getDroolsPdpsConnector("ncompPU"); - if (standbyStatus == null) { - logger.info("handleStateChange: standbyStatus is null; standing down PDP=" + pdpId); - isWaitingForActivation = false; - try{ - try{ - logger.info("handleStateChange: null: cancelling delayActivationTimer."); - delayActivateTimer.cancel(); - }catch(Exception e){ - logger.info("handleStateChange: null no delayActivationTimer existed."); - //If you end of here, there was no active timer + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: previousStandbyStatus = " + previousStandbyStatus + + "; standbyStatus = " + standbyStatus); + } + + if (standbyStatus == null || standbyStatus.equals(StateManagement.NULL_VALUE)) { + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: standbyStatus is null; standing down PDP=" + pdpId); + } + if(previousStandbyStatus.equals(StateManagement.NULL_VALUE)){ + //We were just here and did this successfully + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: Is returning because standbyStatus is null and was previously 'null'; PDP=" + pdpId); } - conn.standDownPdp(pdpId); - //Only want to lock the endpoints, not the controllers. - PolicyEngine.manager.deactivate(); - }catch(Exception e){ - logger.warn("handleStateChange: standbyStatus == null caught exception: " + e); - e.printStackTrace(); + return; } - - } else if (standbyStatus.equals("null")) { - logger.info("handleStateChange: standbyStatus equals 'null'; standing down PDP=" + pdpId); isWaitingForActivation = false; try{ try{ - logger.info("handleStateChange: NULL_VALUE: cancelling delayActivationTimer."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: null: cancelling delayActivationTimer."); + } delayActivateTimer.cancel(); }catch(Exception e){ - logger.info("handleStateChange: NULL_VALUE no delayActivationTimer existed."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: null no delayActivationTimer existed."); + } //If you end of here, there was no active timer } conn.standDownPdp(pdpId); //Only want to lock the endpoints, not the controllers. PolicyEngine.manager.deactivate(); + //The operation was fully successful, but you cannot assign it a real null value + //because later we might try to execute previousStandbyStatus.equals() and get + //a null pointer exception. + previousStandbyStatus = StateManagement.NULL_VALUE; }catch(Exception e){ - logger.warn("handleStateChange: standbyStatus == \"null\" caught exception: " + e); + logger.warn("handleStateChange: standbyStatus == null caught exception: " + e); e.printStackTrace(); } } else if (standbyStatus.equals(StateManagement.HOT_STANDBY) || standbyStatus.equals(StateManagement.COLD_STANDBY)) { - logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; standing down PDP=" + pdpId); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; standing down PDP=" + pdpId); + } + if(previousStandbyStatus.equals(PMStandbyStateChangeNotifier.HOTSTANDBY_OR_COLDSTANDBY)){ + //We were just here and did this successfully + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: Is returning because standbyStatus is " + + standbyStatus + " and was previously " + previousStandbyStatus + + "; PDP=" + pdpId); + } + return; + } isWaitingForActivation = false; try{ try{ - logger.info("handleStateChange: HOT_STNDBY || COLD_STANDBY: cancelling delayActivationTimer."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: HOT_STNDBY || COLD_STANDBY: cancelling delayActivationTimer."); + } delayActivateTimer.cancel(); }catch(Exception e){ - logger.info("handleStateChange: HOT_STANDBY || COLD_STANDBY no delayActivationTimer existed."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: HOT_STANDBY || COLD_STANDBY no delayActivationTimer existed."); + } //If you end of here, there was no active timer } //Only want to lock the endpoints, not the controllers. conn.standDownPdp(pdpId); PolicyEngine.manager.deactivate(); + //The operation was fully successful + previousStandbyStatus = PMStandbyStateChangeNotifier.HOTSTANDBY_OR_COLDSTANDBY; }catch(Exception e){ logger.warn("handleStateChange: standbyStatus == " + standbyStatus + " caught exception: " + e); e.printStackTrace(); } } else if (standbyStatus.equals(StateManagement.PROVIDING_SERVICE)) { + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; scheduling activation of PDP=" + pdpId); + } + if(previousStandbyStatus.equals(StateManagement.PROVIDING_SERVICE)){ + //We were just here and did this successfully + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: Is returning because standbyStatus is " + + standbyStatus + " and was previously " + previousStandbyStatus + + "; PDP=" + pdpId); + } + return; + } try{ //UnLock all the endpoints - logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; controllers must be unlocked."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: standbyStatus=" + standbyStatus + "; controllers must be unlocked."); + } /* * Only endpoints should be unlocked. Controllers have not been locked. * Because, sometimes, it is possible for more than one PDP-D to become active (race conditions) * we need to delay the activation of the topic endpoint interfaces to give the election algorithm * time to resolve the conflict. */ - logger.info("handleStateChange: PROVIDING_SERVICE isWaitingForActivation= " +isWaitingForActivation); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE isWaitingForActivation= " +isWaitingForActivation); + } //Delay activation for 2*pdpUpdateInterval+2000 ms in case of an election handler conflict. //You could have multiple election handlers thinking they can take over. // First let's check that the timer has not died if(isWaitingForActivation){ - logger.info("handleStateChange: PROVIDING_SERVICE isWaitingForActivation = " + isWaitingForActivation); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE isWaitingForActivation = " + isWaitingForActivation); + } long now = new Date().getTime(); long waitTimeMs = now - startTimeWaitingForActivationMs; if(waitTimeMs > 3*waitInterval){ - logger.info("handleStateChange: PROVIDING_SERVICE looks like the activation wait timer may be hung," + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE looks like the activation wait timer may be hung," + " waitTimeMs = " + waitTimeMs + " and allowable waitInterval = " + waitInterval + " Checking whether it is currently in activation. isNowActivating = " + isNowActivating); + } //Now check that it is not currently executing an activation if(!isNowActivating){ - logger.info("handleStateChange: PROVIDING_SERVICE looks like the activation wait timer died"); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE looks like the activation wait timer died"); + } // This will assure the timer is cancelled and rescheduled. isWaitingForActivation = false; } @@ -204,10 +251,14 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { if(!isWaitingForActivation){ try{ //Just in case there is an old timer hanging around - logger.info("handleStateChange: PROVIDING_SERVICE cancelling delayActivationTimer."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE cancelling delayActivationTimer."); + } delayActivateTimer.cancel(); }catch(Exception e){ - logger.info("handleStateChange: PROVIDING_SERVICE no delayActivationTimer existed."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE no delayActivationTimer existed."); + } //If you end of here, there was no active timer } delayActivateTimer = new Timer(); @@ -215,9 +266,13 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { delayActivateTimer.schedule(new DelayActivateClass(), waitInterval); isWaitingForActivation = true; startTimeWaitingForActivationMs = new Date().getTime(); - logger.info("handleStateChange: PROVIDING_SERVICE scheduling delayActivationTimer in " + waitInterval + " ms"); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE scheduling delayActivationTimer in " + waitInterval + " ms"); + } }else{ - logger.info("handleStateChange: PROVIDING_SERVICE delayActivationTimer is waiting for activation."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: PROVIDING_SERVICE delayActivationTimer is waiting for activation."); + } } }catch(Exception e){ @@ -227,27 +282,41 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { } else { logger.error("handleStateChange: Unsupported standbyStatus=" + standbyStatus + "; standing down PDP=" + pdpId); + if(previousStandbyStatus.equals(PMStandbyStateChangeNotifier.UNSUPPORTED)){ + //We were just here and did this successfully + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: Is returning because standbyStatus is " + + "UNSUPPORTED and was previously " + previousStandbyStatus + + "; PDP=" + pdpId); + } + return; + } //Only want to lock the endpoints, not the controllers. isWaitingForActivation = false; try{ try{ - logger.info("handleStateChange: unsupported standbystatus: cancelling delayActivationTimer."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: unsupported standbystatus: cancelling delayActivationTimer."); + } delayActivateTimer.cancel(); }catch(Exception e){ - logger.info("handleStateChange: unsupported standbystatus: no delayActivationTimer existed."); + if(logger.isInfoEnabled()){ + logger.info("handleStateChange: unsupported standbystatus: no delayActivationTimer existed."); + } //If you end of here, there was no active timer } conn.standDownPdp(pdpId); PolicyEngine.manager.deactivate(); + //We know the standbystatus is unsupported + previousStandbyStatus = PMStandbyStateChangeNotifier.UNSUPPORTED; }catch(Exception e){ logger.warn("handleStateChange: Unsupported standbyStatus == " + standbyStatus + "caught exception: " + e); e.printStackTrace(); } } - - //if (logger.isDebugEnabled()) { - logger.info("handleStateChange: Exiting"); - //} + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: Exiting"); + } } private class DelayActivateClass extends TimerTask{ @@ -259,14 +328,20 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { public void run() { isNowActivating = true; try{ - logger.info("DelayActivateClass.run: entry"); + if(logger.isInfoEnabled()){ + logger.info("DelayActivateClass.run: entry"); + } synchronized(delayActivateLock){ PolicyEngine.manager.activate(); + // The state change fully succeeded + previousStandbyStatus = StateManagement.PROVIDING_SERVICE; // We want to set this to false here because the activate call can take a while isWaitingForActivation = false; isNowActivating = false; } - logger.info("DelayActivateClass.run.exit"); + if(logger.isInfoEnabled()){ + logger.info("DelayActivateClass.run.exit"); + } }catch(Exception e){ isWaitingForActivation = false; isNowActivating = false; @@ -277,4 +352,8 @@ public class PMStandbyStateChangeNotifier extends StateChangeNotifier { } } } + + public String getPreviousStandbyStatus(){ + return previousStandbyStatus; + } } diff --git a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java index e592220e..b7695ab4 100644 --- a/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java +++ b/policy-persistence/src/main/java/org/openecomp/policy/drools/persistence/PersistenceFeature.java @@ -21,6 +21,10 @@ package org.openecomp.policy.drools.persistence; import java.io.IOException; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.SQLException; import java.util.Date; import java.util.HashMap; import java.util.Map; @@ -255,7 +259,109 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine * {@inheritDoc} */ @Override - public boolean beforeActivate(PolicyEngine engine) {return false;} + public boolean beforeActivate(PolicyEngine engine) + { + if (persistenceDisabled) + { + return(false); + } + + // The following code will remove "old" Drools 'sessioninfo' records, so + // they aren't used to restore data to Drools sessions. This also has the + // useful side-effect of removing abandoned records as well. + + // Fetch the timeout value, in seconds. If it is not specified or is + // less than or equal to 0, no records are removed. + + String timeoutString = null; + int timeout = 0; + try + { + timeoutString = DroolsPersistenceProperties.getProperty + ("persistence.sessioninfo.timeout"); + if (timeoutString != null) + { + // timeout parameter is specified + timeout = Integer.valueOf(timeoutString); + } + } + catch (NumberFormatException e) + { + logger.error("Invalid value for Drools persistence property " + + "persistence.sessioninfo.timeout: " + + timeoutString); + } + if (timeout <= 0) + { + // parameter is not specified, is <= 0, or is an invalid number + return(false); + } + + // if we reach this point, we are ready to remove old records from + // the database + + Connection connection = null; + PreparedStatement statement = null; + try + { + // fetch database parameters from properties + + String url = DroolsPersistenceProperties.getProperty + (DroolsPersistenceProperties.DB_URL); + String user = DroolsPersistenceProperties.getProperty + (DroolsPersistenceProperties.DB_USER); + String password = DroolsPersistenceProperties.getProperty + (DroolsPersistenceProperties.DB_PWD); + + if (url != null && user != null && password != null) + { + // get DB connection + connection = DriverManager.getConnection(url, user, password); + + // create statement to delete old records + statement = connection.prepareStatement + ("DELETE FROM sessioninfo WHERE " + + "timestampdiff(second,lastmodificationdate,now()) > ?"); + statement.setInt(1,timeout); + + // execute statement + int count = statement.executeUpdate(); + logger.info("Cleaning up sessioninfo table -- " + + count + " records removed"); + } + } + catch (SQLException e) + { + logger.error("Clean up of sessioninfo table failed", e); + } + finally + { + // cleanup + if (statement != null) + { + try + { + statement.close(); + } + catch (SQLException e) + { + logger.error("SQL connection close failed", e); + } + } + if (connection != null) + { + try + { + connection.close(); + } + catch (SQLException e) + { + logger.error("SQL connection close failed", e); + } + } + } + return(false); + } /** * {@inheritDoc} @@ -468,7 +574,7 @@ public class PersistenceFeature implements PolicySessionFeatureAPI, PolicyEngine * Start audit for Drools DB. */ integrityAudit = new IntegrityAudit( - resourceName, "ncompPU", droolsPia); + resourceName, "auditDroolsPU", droolsPia); integrityAudit.startAuditThread(); } catch (IOException e1) { -- cgit 1.2.3-korg