diff options
Diffstat (limited to 'feature-active-standby-management')
8 files changed, 81 insertions, 79 deletions
diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ActiveStandbyFeature.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ActiveStandbyFeature.java index d2c542fb..932ebb2d 100644 --- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ActiveStandbyFeature.java +++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ActiveStandbyFeature.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * feature-active-standby-management * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -80,7 +80,7 @@ public class ActiveStandbyFeature implements ActiveStandbyFeatureAPI, * {@inheritDoc} */ @Override - public void globalInit(String args[], String configDir) + public void globalInit(String[] args, String configDir) { // This must come first since it initializes myPdp initializePersistence(configDir); @@ -164,7 +164,7 @@ public class ActiveStandbyFeature implements ActiveStandbyFeatureAPI, */ DroolsPdp existingPdp = conn.getPdp(resourceName); if (existingPdp != null) { - System.out.println("Found existing PDP record, pdpId=" + logger.info("Found existing PDP record, pdpId=" + existingPdp.getPdpId() + ", isDesignated=" + existingPdp.isDesignated() + ", updatedDate=" + existingPdp.getUpdatedDate()); @@ -176,18 +176,17 @@ public class ActiveStandbyFeature implements ActiveStandbyFeatureAPI, myPdp = new DroolsPdpImpl(resourceName,false,4,new Date()); } - String site_name = ActiveStandbyProperties.getProperty(ActiveStandbyProperties.SITE_NAME); - if (site_name == null) { - site_name = ""; + String siteName = ActiveStandbyProperties.getProperty(ActiveStandbyProperties.SITE_NAME); + if (siteName == null) { + siteName = ""; }else{ - site_name = site_name.trim(); + siteName = siteName.trim(); } - myPdp.setSiteName(site_name); + myPdp.setSiteName(siteName); if(electionHandler == null){ electionHandler = new DroolsPdpsElectionHandler(conn,myPdp); } } - System.out.println("\n\nThis controller is a standby, waiting to be chosen as primary...\n\n"); logger.info("\n\nThis controller is a standby, waiting to be chosen as primary...\n\n"); } @@ -199,7 +198,7 @@ public class ActiveStandbyFeature implements ActiveStandbyFeatureAPI, */ public static DroolsPdpsConnector getDroolsPdpsConnector(String pu) { - Map<String, Object> propMap = new HashMap<String, Object>(); + Map<String, Object> propMap = new HashMap<>(); propMap.put("javax.persistence.jdbc.driver", ActiveStandbyProperties .getProperty(ActiveStandbyProperties.DB_DRIVER)); propMap.put("javax.persistence.jdbc.url", @@ -211,9 +210,7 @@ public class ActiveStandbyFeature implements ActiveStandbyFeatureAPI, EntityManagerFactory emf = Persistence.createEntityManagerFactory( pu, propMap); - DroolsPdpsConnector conn = new JpaDroolsPdpsConnector(emf); - - return conn; + return new JpaDroolsPdpsConnector(emf); } /** diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java index 8c1d9f2e..690b260c 100644 --- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java +++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpObject.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * feature-active-standby-management * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,7 +65,7 @@ public abstract class DroolsPdpObject implements DroolsPdp{ } @Override public int comparePriority(DroolsPdp other, String previousSite){ - if(previousSite == null || previousSite.equals("")){ + if(previousSite == null || previousSite.isEmpty()){ return comparePriority(other); } if(nullSafeCompare(this.getSiteName(),other.getSiteName()) == 0){ diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpsElectionHandler.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpsElectionHandler.java index 2836f92f..1a09d920 100644 --- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpsElectionHandler.java +++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/DroolsPdpsElectionHandler.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * feature-active-standby-management * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ package org.onap.policy.drools.activestandby; import java.util.ArrayList; import java.util.Collection; import java.util.Date; +import java.util.List; import java.util.Timer; import java.util.TimerTask; @@ -33,7 +34,7 @@ import org.onap.policy.drools.statemanagement.StateManagementFeatureAPI; public class DroolsPdpsElectionHandler implements ThreadRunningChecker { // get an instance of logger - private final static Logger logger = LoggerFactory.getLogger(DroolsPdpsElectionHandler.class); + private static final Logger logger = LoggerFactory.getLogger(DroolsPdpsElectionHandler.class); private DroolsPdpsConnector pdpsConnector; private Object checkWaitTimerLock = new Object(); private Object designationWaiterLock = new Object(); @@ -70,13 +71,7 @@ public class DroolsPdpsElectionHandler implements ThreadRunningChecker { private StateManagementFeatureAPI stateManagementFeature; private static boolean isUnitTesting = false; - public static void setIsUnitTesting(boolean val){ - isUnitTesting = val; - } private static boolean isStalled = false; - public static void setIsStalled(boolean val){ - isStalled = val; - } public DroolsPdpsElectionHandler(DroolsPdpsConnector pdps, DroolsPdp myPdp){ if (pdps == null) { @@ -152,6 +147,13 @@ public class DroolsPdpsElectionHandler implements ThreadRunningChecker { } } + public static void setIsUnitTesting(boolean val){ + isUnitTesting = val; + } + public static void setIsStalled(boolean val){ + isStalled = val; + } + /* * When the JpaDroolsPdpsConnector.standDown() method is invoked, it needs * access to myPdp, so it can keep its designation status in sync with the @@ -194,7 +196,7 @@ public class DroolsPdpsElectionHandler implements ThreadRunningChecker { //It is possible that multiple PDPs are designated lead. So, we will make a list of all designated //PDPs and then decide which one really should be designated at the end. - ArrayList<DroolsPdp> listOfDesignated = new ArrayList<DroolsPdp>(); + ArrayList<DroolsPdp> listOfDesignated = new ArrayList<>(); Collection<DroolsPdp> pdps = pdpsConnector.getDroolsPdps(); DroolsPdp designatedPdp = null; @@ -767,7 +769,7 @@ public class DroolsPdpsElectionHandler implements ThreadRunningChecker { return mostRecentPrimary; } - public DroolsPdp computeDesignatedPdp(ArrayList<DroolsPdp> listOfDesignated, DroolsPdp mostRecentPrimary){ + public DroolsPdp computeDesignatedPdp(List<DroolsPdp> listOfDesignated, DroolsPdp mostRecentPrimary){ DroolsPdp designatedPdp = null; DroolsPdp lowestPriorityPdp = null; if(listOfDesignated.size() > 1){ diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/JpaDroolsPdpsConnector.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/JpaDroolsPdpsConnector.java index 0d931acc..dc907b27 100644 --- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/JpaDroolsPdpsConnector.java +++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/JpaDroolsPdpsConnector.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * feature-active-standby-management * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -53,7 +53,7 @@ public class JpaDroolsPdpsConnector implements DroolsPdpsConnector { em.getTransaction().begin(); Query droolsPdpsListQuery = em.createQuery("SELECT p FROM DroolsPdpEntity p"); List<?> droolsPdpsList = droolsPdpsListQuery.setLockMode(LockModeType.NONE).setFlushMode(FlushModeType.COMMIT).getResultList(); - LinkedList<DroolsPdp> droolsPdpsReturnList = new LinkedList<DroolsPdp>(); + LinkedList<DroolsPdp> droolsPdpsReturnList = new LinkedList<>(); for(Object o : droolsPdpsList){ if(o instanceof DroolsPdp){ //Make sure it is not a cached version @@ -613,24 +613,22 @@ public class JpaDroolsPdpsConnector implements DroolsPdpsConnector { */ private static void cleanup(EntityManager em, String method) { - if (em != null) { - if (em.isOpen()) { - if (em.getTransaction().isActive()) { - // there is an active EntityTransaction -- roll it back - try { - em.getTransaction().rollback(); - } catch (Exception e) { - logger.error(method + ": Caught Exception attempting to rollback EntityTransaction,", e); - } - } - - // now, close the EntityManager + if (em != null && em.isOpen()) { + if (em.getTransaction().isActive()) { + // there is an active EntityTransaction -- roll it back try { - em.close(); + em.getTransaction().rollback(); } catch (Exception e) { - logger.error(method + ": Caught Exception attempting to close EntityManager, ", e); + logger.error(method + ": Caught Exception attempting to rollback EntityTransaction,", e); } } + + // now, close the EntityManager + try { + em.close(); + } catch (Exception e) { + logger.error(method + ": Caught Exception attempting to close EntityManager, ", e); + } } } } diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/PMStandbyStateChangeNotifier.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/PMStandbyStateChangeNotifier.java index 5a6dd8fa..84cc8dbd 100644 --- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/PMStandbyStateChangeNotifier.java +++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/PMStandbyStateChangeNotifier.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * feature-active-standby-management * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -101,11 +101,9 @@ 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. */ - if(logger.isInfoEnabled()){ - if(logger.isDebugEnabled()){ - logger.debug("handleStateChange: Entering, message={}, standbyStatus={}", - super.getMessage(), super.getStateManagement().getStandbyStatus()); - } + if(logger.isDebugEnabled()){ + logger.debug("handleStateChange: Entering, message={}, standbyStatus={}", + super.getMessage(), super.getStateManagement().getStandbyStatus()); } String standbyStatus = super.getStateManagement().getStandbyStatus(); String pdpId = ActiveStandbyProperties diff --git a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ThreadRunningChecker.java b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ThreadRunningChecker.java index db848ebb..b5fe3071 100644 --- a/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ThreadRunningChecker.java +++ b/feature-active-standby-management/src/main/java/org/onap/policy/drools/activestandby/ThreadRunningChecker.java @@ -1,8 +1,8 @@ -/*- +/* * ============LICENSE_START======================================================= * feature-active-standby-management * ================================================================================ - * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ package org.onap.policy.drools.activestandby; +@FunctionalInterface public interface ThreadRunningChecker { public void checkThreadStatus(); diff --git a/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/AllSeemsWellTest.java b/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/AllSeemsWellTest.java index 0318bed6..19265206 100644 --- a/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/AllSeemsWellTest.java +++ b/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/AllSeemsWellTest.java @@ -37,7 +37,6 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.common.im.StateManagement; import org.onap.policy.drools.activestandby.ActiveStandbyFeatureAPI; @@ -264,7 +263,7 @@ public class AllSeemsWellTest { logger.debug("testAllSeemsWell: Sleeping {} ms, to allow JpaDroolsPdpsConnector " + "time to check droolspdpentity table", sleepTime); - Thread.sleep(sleepTime); + sleep(sleepTime); // Verify that this formerly un-designated PDP in HOT_STANDBY is now designated and providing service. @@ -292,7 +291,7 @@ public class AllSeemsWellTest { //It takes 10x the update interval (1 sec) before the watcher will declare the election handler dead //and that just stops forward progress counter. So, the fp monitor must then run to determine //if the fpc has stalled. That will take about another 5 sec. - Thread.sleep(stalledElectionHandlerSleepTime); + sleep(stalledElectionHandlerSleepTime); logger.debug("testAllSeemsWell: After isStalled=true, PDP= {} " + "has standbyStatus= {}", thisPdpId, smf.getStandbyStatus(thisPdpId)); @@ -302,7 +301,7 @@ public class AllSeemsWellTest { //Now lets resume the election handler DroolsPdpsElectionHandler.setIsStalled(false); - Thread.sleep(resumedElectionHandlerSleepTime); + sleep(resumedElectionHandlerSleepTime); logger.debug("testAllSeemsWell: After isStalled=false, PDP= {} " + "has standbyStatus= {}", thisPdpId, smf.getStandbyStatus(thisPdpId)); @@ -313,4 +312,8 @@ public class AllSeemsWellTest { logger.debug("\n\ntestAllSeemsWell: Exiting\n\n"); } + + private void sleep(long sleepms) throws InterruptedException { + Thread.sleep(sleepms); + } } diff --git a/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/StandbyStateManagementTest.java b/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/StandbyStateManagementTest.java index 876cd99a..66af3eaa 100644 --- a/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/StandbyStateManagementTest.java +++ b/feature-active-standby-management/src/test/java/org/onap/policy/drools/controller/test/StandbyStateManagementTest.java @@ -38,7 +38,6 @@ import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; -import org.junit.Ignore; import org.junit.Test; import org.onap.policy.common.im.AdministrativeStateException; import org.onap.policy.common.im.IntegrityMonitor; @@ -274,7 +273,7 @@ public class StandbyStateManagementTest { assertTrue(pmNotifier.getPreviousStandbyStatus().equals(PMStandbyStateChangeNotifier.HOTSTANDBY_OR_COLDSTANDBY)); //Sleep long enough for the delayActivationTimer to run - Thread.sleep(5000); + sleep(5000); assertTrue(pmNotifier.getPreviousStandbyStatus().equals(StateManagement.PROVIDING_SERVICE)); //standbystatus = providingservice @@ -790,7 +789,7 @@ public class StandbyStateManagementTest { logger.debug("testColdStandby: Runner started; Sleeping " + interruptRecoveryTime + "ms before promoting PDP= {}", thisPdpId); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); logger.debug("testColdStandby: Promoting PDP={}", thisPdpId); smf.promote(); @@ -802,7 +801,7 @@ public class StandbyStateManagementTest { logger.debug("testColdStandby: Locking smf"); smf.lock(); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); // Verify that the PDP is no longer designated. @@ -812,7 +811,7 @@ public class StandbyStateManagementTest { assertTrue(droolsPdpEntity.isDesignated() == false); logger.debug("\n\ntestColdStandby: Exiting\n\n"); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); } @@ -918,7 +917,7 @@ public class StandbyStateManagementTest { logger.debug("testHotStandby1: Sleeping {} ms, to allow JpaDroolsPdpsConnector " + "time to check droolspdpentity table", sleepTime); - Thread.sleep(sleepTime); + sleep(sleepTime); // Verify that this formerly un-designated PDP in HOT_STANDBY is now designated and providing service. @@ -936,7 +935,7 @@ public class StandbyStateManagementTest { //policyManagementRunner.stopRunner(); logger.debug("\n\ntestHotStandby1: Exiting\n\n"); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); } @@ -1066,7 +1065,7 @@ public class StandbyStateManagementTest { logger.info("testHotStandby2: Runner started; Sleeping {} " + "ms before promoting/demoting", interruptRecoveryTime); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); logger.info("testHotStandby2: Runner started; promoting PDP={}", activePdpId); //At this point, the newly created pdp will have set the state to disabled/failed/cold standby @@ -1085,7 +1084,7 @@ public class StandbyStateManagementTest { logger.info("testHotStandby2: Sleeping {} ms, to allow JpaDroolsPdpsConnector " + "time to check droolspdpentity table", sleepTime); - Thread.sleep(sleepTime); + sleep(sleepTime); /* * Verify that this PDP, demoted to HOT_STANDBY, is now @@ -1108,7 +1107,7 @@ public class StandbyStateManagementTest { //policyManagementRunner.stopRunner(); logger.info("\n\ntestHotStandby2: Exiting\n\n"); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); } @@ -1221,7 +1220,7 @@ public class StandbyStateManagementTest { logger.debug("testLocking1: Runner started; Sleeping " + interruptRecoveryTime + "ms before promoting PDP={}", thisPdpId); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); logger.debug("testLocking1: Promoting PDP={}", thisPdpId); sm.promote(); @@ -1229,7 +1228,7 @@ public class StandbyStateManagementTest { logger.debug("testLocking1: Sleeping {} ms, to allow time for " + "policy-management.Main class to come up, designated= {}", sleepTime, conn.getPdp(thisPdpId).isDesignated()); - Thread.sleep(sleepTime); + sleep(sleepTime); logger.debug("testLocking1: Waking up and invoking startTransaction on active PDP={}" + ", designated= {}",thisPdpId, conn.getPdp(thisPdpId).isDesignated()); @@ -1258,7 +1257,7 @@ public class StandbyStateManagementTest { logger.debug("testLocking1: sleeping" + electionWaitSleepTime + " to allow election handler to re-promote PDP={}", thisPdpId); - Thread.sleep(electionWaitSleepTime); + sleep(electionWaitSleepTime); logger.debug("testLocking1: Invoking startTransaction on re-promoted PDP={}" + ", designated={}", thisPdpId, conn.getPdp(thisPdpId).isDesignated()); @@ -1283,7 +1282,7 @@ public class StandbyStateManagementTest { // Just to avoid any race conditions, sleep a little after locking logger.debug("testLocking1: Sleeping a few millis after locking, to avoid race condition"); - Thread.sleep(100); + sleep(100); logger.debug("testLocking1: Invoking startTransaction on locked PDP= {}" + ", designated= {}",thisPdpId, conn.getPdp(thisPdpId).isDesignated()); @@ -1309,7 +1308,7 @@ public class StandbyStateManagementTest { // Just to avoid any race conditions, sleep a little after locking logger.debug("testLocking1: Sleeping a few millis after unlocking, to avoid race condition"); - Thread.sleep(electionWaitSleepTime); + sleep(electionWaitSleepTime); logger.debug("testLocking1: Invoking startTransaction on unlocked PDP=" + thisPdpId @@ -1337,7 +1336,7 @@ public class StandbyStateManagementTest { // Just to avoid any race conditions, sleep a little after promoting logger.debug("testLocking1: Sleeping a few millis after demoting, to avoid race condition"); - Thread.sleep(100); + sleep(100); logger.debug("testLocking1: Invoking startTransaction on demoted PDP={}" + ", designated={}", thisPdpId, conn.getPdp(thisPdpId).isDesignated()); @@ -1357,7 +1356,7 @@ public class StandbyStateManagementTest { } logger.debug("\n\ntestLocking1: Exiting\n\n"); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); } @@ -1483,7 +1482,7 @@ public class StandbyStateManagementTest { logger.debug("testLocking2: Runner started; Sleeping {} ms " + "before promoting/demoting", interruptRecoveryTime); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); logger.debug("testLocking2: Promoting PDP= {}", thisPdpId); sm.promote(); @@ -1493,7 +1492,7 @@ public class StandbyStateManagementTest { sm2.demote(); logger.debug("testLocking2: Sleeping {} ms, to allow time for to come up", sleepTime); - Thread.sleep(sleepTime); + sleep(sleepTime); logger.debug("testLocking2: Waking up and invoking startTransaction on active PDP={}" + ", designated= {}", thisPdpId, conn.getPdp(thisPdpId).isDesignated()); @@ -1521,7 +1520,7 @@ public class StandbyStateManagementTest { logger.debug("testLocking2: sleeping {}" + " to allow election handler to re-promote PDP={}", electionWaitSleepTime, thisPdpId); - Thread.sleep(electionWaitSleepTime); + sleep(electionWaitSleepTime); logger.debug("testLocking2: Waking up and invoking startTransaction " + "on re-promoted PDP= {}, designated= {}", @@ -1546,6 +1545,10 @@ public class StandbyStateManagementTest { assertTrue(standbyPdpDesignated == false); logger.debug("\n\ntestLocking2: Exiting\n\n"); - Thread.sleep(interruptRecoveryTime); + sleep(interruptRecoveryTime); + } + + private void sleep(long sleepms) throws InterruptedException { + Thread.sleep(sleepms); } } |