diff options
Diffstat (limited to 'feature-distributed-locking')
6 files changed, 525 insertions, 494 deletions
diff --git a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java index f1c8b687..17f65459 100644 --- a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java +++ b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeature.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.distributed.locking; import java.sql.Connection; @@ -35,102 +36,105 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DistributedLockingFeature implements PolicyEngineFeatureAPI, PolicyResourceLockFeatureAPI { - - /** - * Logger instance - */ - private static final Logger logger = LoggerFactory.getLogger(DistributedLockingFeature.class); - - /** - * Properties Configuration Name - */ - public static final String CONFIGURATION_PROPERTIES_NAME = "feature-distributed-locking"; - - /** - * Properties for locking feature - */ - private DistributedLockingProperties lockProps; - - /** - * Data source used to connect to the DB containing locks. - */ - private BasicDataSource dataSource; - - /** - * UUID - */ - private static final UUID uuid = UUID.randomUUID(); - - @Override - public int getSequenceNumber() { + + /** + * Logger instance. + */ + private static final Logger logger = LoggerFactory.getLogger(DistributedLockingFeature.class); + + /** + * Properties Configuration Name. + */ + public static final String CONFIGURATION_PROPERTIES_NAME = "feature-distributed-locking"; + + /** + * Properties for locking feature. + */ + private DistributedLockingProperties lockProps; + + /** + * Data source used to connect to the DB containing locks. + */ + private BasicDataSource dataSource; + + /** + * UUID. + */ + private static final UUID uuid = UUID.randomUUID(); + + @Override + public int getSequenceNumber() { return 1000; - } - - @Override + } + + @Override public OperResult beforeLock(String resourceId, String owner, int holdSec) { - - TargetLock tLock = new TargetLock(resourceId, uuid, owner, dataSource); - return(tLock.lock(holdSec) ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); - } - + TargetLock lock = new TargetLock(resourceId, uuid, owner, dataSource); + + return (lock.lock(holdSec) ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); + } + @Override public OperResult beforeRefresh(String resourceId, String owner, int holdSec) { - - TargetLock tLock = new TargetLock(resourceId, uuid, owner, dataSource); - return(tLock.refresh(holdSec) ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); + TargetLock lock = new TargetLock(resourceId, uuid, owner, dataSource); + + return (lock.refresh(holdSec) ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); + } + + @Override + public OperResult beforeUnlock(String resourceId, String owner) { + TargetLock lock = new TargetLock(resourceId, uuid, owner, dataSource); + + return (lock.unlock() ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); + } + + @Override + public OperResult beforeIsLockedBy(String resourceId, String owner) { + TargetLock lock = new TargetLock(resourceId, uuid, owner, dataSource); + + return (lock.isActive() ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); + } + + @Override + public OperResult beforeIsLocked(String resourceId) { + TargetLock lock = new TargetLock(resourceId, uuid, "dummyOwner", dataSource); + + return (lock.isLocked() ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); } - @Override - public OperResult beforeUnlock(String resourceId, String owner) { - TargetLock tLock = new TargetLock(resourceId, uuid, owner, dataSource); - - return(tLock.unlock() ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); - } - - @Override - public OperResult beforeIsLockedBy(String resourceId, String owner) { - TargetLock tLock = new TargetLock(resourceId, uuid, owner, dataSource); - - return(tLock.isActive() ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); - } - - @Override - public OperResult beforeIsLocked(String resourceId) { - TargetLock tLock = new TargetLock(resourceId, uuid, "dummyOwner", dataSource); - - return(tLock.isLocked() ? OperResult.OPER_ACCEPTED : OperResult.OPER_DENIED); - } - - @Override - public boolean afterStart(PolicyEngine engine) { - - try { - this.lockProps = new DistributedLockingProperties(SystemPersistence.manager.getProperties(DistributedLockingFeature.CONFIGURATION_PROPERTIES_NAME)); - this.dataSource = makeDataSource(); - } catch (PropertyException e) { - logger.error("DistributedLockingFeature feature properies have not been loaded", e); - throw new DistributedLockingFeatureException(e); - } catch(InterruptedException e) { + @Override + public boolean afterStart(PolicyEngine engine) { + + try { + this.lockProps = new DistributedLockingProperties( + SystemPersistence.manager.getProperties(DistributedLockingFeature.CONFIGURATION_PROPERTIES_NAME)); + this.dataSource = makeDataSource(); + } catch (PropertyException e) { + logger.error("DistributedLockingFeature feature properies have not been loaded", e); + throw new DistributedLockingFeatureException(e); + } catch (InterruptedException e) { logger.error("DistributedLockingFeature failed to create data source", e); - Thread.currentThread().interrupt(); + Thread.currentThread().interrupt(); throw new DistributedLockingFeatureException(e); - } catch(Exception e) { + } catch (Exception e) { logger.error("DistributedLockingFeature failed to create data source", e); throw new DistributedLockingFeatureException(e); - } - - cleanLockTable(); - - return false; - } - - /** - * @return a new, pooled data source - * @throws Exception - */ - private BasicDataSource makeDataSource() throws Exception { + } + + cleanLockTable(); + + return false; + } + + /** + * Make data source. + * + * @return a new, pooled data source + * @throws Exception exception + */ + private BasicDataSource makeDataSource() throws Exception { Properties props = new Properties(); props.put("driverClassName", lockProps.getDbDriver()); props.put("url", lockProps.getDbUrl()); @@ -140,36 +144,36 @@ public class DistributedLockingFeature implements PolicyEngineFeatureAPI, Policy props.put("poolPreparedStatements", "true"); // additional properties are listed in the GenericObjectPool API - + return BasicDataSourceFactory.createDataSource(props); } /** - * This method kills the heartbeat thread and calls refreshLockTable which removes - * any records from the db where the current host is the owner. - */ - @Override - public boolean beforeShutdown(PolicyEngine engine) { - cleanLockTable(); - return false; - } - - /** - * This method removes all records owned by the current host from the db. - */ - private void cleanLockTable() { - - try (Connection conn = dataSource.getConnection(); - PreparedStatement statement = conn.prepareStatement( - "DELETE FROM pooling.locks WHERE host = ? OR expirationTime < now()"); - ){ - - statement.setString(1, uuid.toString()); - statement.executeUpdate(); - - } catch (SQLException e) { - logger.error("error in refreshLockTable()", e); - } - - } + * This method kills the heartbeat thread and calls refreshLockTable which removes + * any records from the db where the current host is the owner. + */ + @Override + public boolean beforeShutdown(PolicyEngine engine) { + cleanLockTable(); + return false; + } + + /** + * This method removes all records owned by the current host from the db. + */ + private void cleanLockTable() { + + try (Connection conn = dataSource.getConnection(); + PreparedStatement statement = conn.prepareStatement( + "DELETE FROM pooling.locks WHERE host = ? OR expirationTime < now()"); + ) { + + statement.setString(1, uuid.toString()); + statement.executeUpdate(); + + } catch (SQLException e) { + logger.error("error in refreshLockTable()", e); + } + + } } diff --git a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeatureException.java b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeatureException.java index f28ccbc9..55fc4fab 100644 --- a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeatureException.java +++ b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingFeatureException.java @@ -21,14 +21,14 @@ package org.onap.policy.distributed.locking; public class DistributedLockingFeatureException extends RuntimeException { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - /** - * - * @param e - * exception to be wrapped - */ - public DistributedLockingFeatureException(Exception e) { - super(e); - } + /** + * Constructor. + * + * @param ex exception to be wrapped + */ + public DistributedLockingFeatureException(Exception ex) { + super(ex); + } } diff --git a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingProperties.java b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingProperties.java index 1f55a4cb..00db5733 100644 --- a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingProperties.java +++ b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/DistributedLockingProperties.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.distributed.locking; import java.util.Properties; @@ -42,25 +43,25 @@ public class DistributedLockingProperties extends PropertyConfiguration { private Properties source; /** - * Database driver + * Database driver. */ @Property(name = DB_DRIVER) private String dbDriver; /** - * Database url + * Database url. */ @Property(name = DB_URL) private String dbUrl; /** - * Database user + * Database user. */ @Property(name = DB_USER) private String dbUser; /** - * Database password + * Database password. */ @Property(name = DB_PWD) private String dbPwd; diff --git a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/TargetLock.java b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/TargetLock.java index 0652897c..42e1f92f 100644 --- a/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/TargetLock.java +++ b/feature-distributed-locking/src/main/java/org/onap/policy/distributed/locking/TargetLock.java @@ -17,6 +17,7 @@ * limitations under the License. * ============LICENSE_END========================================================= */ + package org.onap.policy.distributed.locking; import java.sql.Connection; @@ -29,145 +30,149 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TargetLock { - - private static final Logger logger = LoggerFactory.getLogger(TargetLock.class); - - /** - * The Target resource we want to lock - */ - private String resourceId; - + + private static final Logger logger = LoggerFactory.getLogger(TargetLock.class); + + /** + * The Target resource we want to lock. + */ + private String resourceId; + /** * Data source used to connect to the DB containing locks. */ private BasicDataSource dataSource; - /** - * UUID - */ - private UUID uuid; - - /** - * Owner - */ - private String owner; - - /** - * Constructs a TargetLock object. - * - * @param resourceId ID of the entity we want to lock - * @param dataSource used to connect to the DB containing locks - */ - public TargetLock (String resourceId, UUID uuid, String owner, BasicDataSource dataSource) { - this.resourceId = resourceId; - this.uuid = uuid; - this.owner = owner; - this.dataSource = dataSource; - } - - /** - * obtain a lock + /** + * UUID . + */ + private UUID uuid; + + /** + * Owner. + */ + private String owner; + + /** + * Constructs a TargetLock object. + * + * @param resourceId ID of the entity we want to lock + * @param dataSource used to connect to the DB containing locks + */ + public TargetLock(String resourceId, UUID uuid, String owner, BasicDataSource dataSource) { + this.resourceId = resourceId; + this.uuid = uuid; + this.owner = owner; + this.dataSource = dataSource; + } + + /** + * Obtain a lock. * @param holdSec the amount of time, in seconds, that the lock should be held - */ - public boolean lock(int holdSec) { - - return grabLock(holdSec); - } + */ + public boolean lock(int holdSec) { + + return grabLock(holdSec); + } /** - * refresh a lock + * Refresh a lock. * * @param holdSec the amount of time, in seconds, that the lock should be held * @return {@code true} if the lock was refreshed, {@code false} if the resource is * not currently locked by the given owner */ - public boolean refresh(int holdSec) { - return updateLock(holdSec); - } - - /** - * Unlock a resource by deleting it's associated record in the db - */ - public boolean unlock() { - return deleteLock(); - } - - /** - * "Grabs" lock by attempting to insert a new record in the db. - * If the insert fails due to duplicate key error resource is already locked - * so we call secondGrab. - * @param holdSec the amount of time, in seconds, that the lock should be held - */ - private boolean grabLock(int holdSec) { - - // try to insert a record into the table(thereby grabbing the lock) - try (Connection conn = dataSource.getConnection(); - - PreparedStatement statement = conn.prepareStatement( - "INSERT INTO pooling.locks (resourceId, host, owner, expirationTime) values (?, ?, ?, timestampadd(second, ?, now()))")) { - - int i = 1; - statement.setString(i++, this.resourceId); - statement.setString(i++, this.uuid.toString()); - statement.setString(i++, this.owner); - statement.setInt(i++, holdSec); - statement.executeUpdate(); - } - - catch (SQLException e) { - logger.error("error in TargetLock.grabLock()", e); - return secondGrab(holdSec); - } - - return true; - } - - /** - * A second attempt at grabbing a lock. It first attempts to update the lock in case it is expired. - * If that fails, it attempts to insert a new record again + public boolean refresh(int holdSec) { + return updateLock(holdSec); + } + + /** + * Unlock a resource by deleting it's associated record in the db. + */ + public boolean unlock() { + return deleteLock(); + } + + /** + * "Grabs" lock by attempting to insert a new record in the db. + * If the insert fails due to duplicate key error resource is already locked + * so we call secondGrab. * @param holdSec the amount of time, in seconds, that the lock should be held - */ - private boolean secondGrab(int holdSec) { + */ + private boolean grabLock(int holdSec) { - try (Connection conn = dataSource.getConnection(); + // try to insert a record into the table(thereby grabbing the lock) + try (Connection conn = dataSource.getConnection(); - PreparedStatement updateStatement = conn.prepareStatement( - "UPDATE pooling.locks SET host = ?, owner = ?, expirationTime = timestampadd(second, ?, now()) WHERE resourceId = ? AND expirationTime < now()"); + PreparedStatement statement = conn.prepareStatement( + "INSERT INTO pooling.locks (resourceId, host, owner, expirationTime) " + + "values (?, ?, ?, timestampadd(second, ?, now()))")) { - PreparedStatement insertStatement = conn.prepareStatement( - "INSERT INTO pooling.locks (resourceId, host, owner, expirationTime) values (?, ?, ?, timestampadd(second, ?, now()))");) { + int index = 1; + statement.setString(index++, this.resourceId); + statement.setString(index++, this.uuid.toString()); + statement.setString(index++, this.owner); + statement.setInt(index++, holdSec); + statement.executeUpdate(); + } - int i = 1; - updateStatement.setString(i++, this.uuid.toString()); - updateStatement.setString(i++, this.owner); - updateStatement.setInt(i++, holdSec); - updateStatement.setString(i++, this.resourceId); + catch (SQLException e) { + logger.error("error in TargetLock.grabLock()", e); + return secondGrab(holdSec); + } + + return true; + } - // The lock was expired and we grabbed it. - // return true - if (updateStatement.executeUpdate() == 1) { - return true; - } + /** + * A second attempt at grabbing a lock. It first attempts to update the lock in case it is expired. + * If that fails, it attempts to insert a new record again + * @param holdSec the amount of time, in seconds, that the lock should be held + */ + private boolean secondGrab(int holdSec) { - // If our update does not return 1 row, the lock either has not expired - // or it was removed. Try one last grab - else { - i = 1; - insertStatement.setString(i++, this.resourceId); - insertStatement.setString(i++, this.uuid.toString()); - insertStatement.setString(i++, this.owner); - insertStatement.setInt(i++, holdSec); + try (Connection conn = dataSource.getConnection(); - // If our insert returns 1 we successfully grabbed the lock - return (insertStatement.executeUpdate() == 1); - } + PreparedStatement updateStatement = conn.prepareStatement( + "UPDATE pooling.locks SET host = ?, owner = ?, " + + "expirationTime = timestampadd(second, ?, now()) " + + "WHERE resourceId = ? AND expirationTime < now()"); + + PreparedStatement insertStatement = conn.prepareStatement( + "INSERT INTO pooling.locks (resourceId, host, owner, expirationTime) " + + "values (?, ?, ?, timestampadd(second, ?, now()))");) { + + int index = 1; + updateStatement.setString(index++, this.uuid.toString()); + updateStatement.setString(index++, this.owner); + updateStatement.setInt(index++, holdSec); + updateStatement.setString(index++, this.resourceId); + + // The lock was expired and we grabbed it. + // return true + if (updateStatement.executeUpdate() == 1) { + return true; + } + + // If our update does not return 1 row, the lock either has not expired + // or it was removed. Try one last grab + else { + index = 1; + insertStatement.setString(index++, this.resourceId); + insertStatement.setString(index++, this.uuid.toString()); + insertStatement.setString(index++, this.owner); + insertStatement.setInt(index++, holdSec); + + // If our insert returns 1 we successfully grabbed the lock + return (insertStatement.executeUpdate() == 1); + } - } catch (SQLException e) { - logger.error("error in TargetLock.secondGrab()", e); - return false; - } + } catch (SQLException e) { + logger.error("error in TargetLock.secondGrab()", e); + return false; + } - } + } /** * Updates the DB record associated with the lock. @@ -179,15 +184,17 @@ public class TargetLock { try (Connection conn = dataSource.getConnection(); - PreparedStatement updateStatement = conn.prepareStatement( - "UPDATE pooling.locks SET host = ?, owner = ?, expirationTime = timestampadd(second, ?, now()) WHERE resourceId = ? AND owner = ? AND expirationTime >= now()")) { + PreparedStatement updateStatement = conn.prepareStatement( + "UPDATE pooling.locks SET host = ?, owner = ?, " + + "expirationTime = timestampadd(second, ?, now()) " + + "WHERE resourceId = ? AND owner = ? AND expirationTime >= now()")) { - int i = 1; - updateStatement.setString(i++, this.uuid.toString()); - updateStatement.setString(i++, this.owner); - updateStatement.setInt(i++, holdSec); - updateStatement.setString(i++, this.resourceId); - updateStatement.setString(i++, this.owner); + int index = 1; + updateStatement.setString(index++, this.uuid.toString()); + updateStatement.setString(index++, this.owner); + updateStatement.setInt(index++, holdSec); + updateStatement.setString(index++, this.resourceId); + updateStatement.setString(index++, this.owner); // refresh succeeded iff a record was updated return (updateStatement.executeUpdate() == 1); @@ -198,80 +205,78 @@ public class TargetLock { } } - - /** - *To remove a lock we simply delete the record from the db - */ - private boolean deleteLock() { - - try (Connection conn = dataSource.getConnection(); - - PreparedStatement deleteStatement = conn.prepareStatement( - "DELETE FROM pooling.locks WHERE resourceId = ? AND owner = ? AND host = ?")) { - - deleteStatement.setString(1, this.resourceId); - deleteStatement.setString(2, this.owner); - deleteStatement.setString(3, this.uuid.toString()); - - return (deleteStatement.executeUpdate() == 1); - - } catch (SQLException e) { - logger.error("error in TargetLock.deleteLock()", e); - return false; - } - - } - - /** - * Is the lock active - */ - public boolean isActive() { - try (Connection conn = dataSource.getConnection(); - - PreparedStatement selectStatement = conn.prepareStatement( - "SELECT * FROM pooling.locks WHERE resourceId = ? AND host = ? AND owner= ? AND expirationTime >= now()")) { - - selectStatement.setString(1, this.resourceId); - selectStatement.setString(2, this.uuid.toString()); - selectStatement.setString(3, this.owner); - try (ResultSet result = selectStatement.executeQuery()) { - - // This will return true if the - // query returned at least one row - return result.first(); - } - - } - - catch (SQLException e) { - logger.error("error in TargetLock.isActive()", e); - return false; - } - - } - - /** - * Is the resource locked - */ - public boolean isLocked() { - - try (Connection conn = dataSource.getConnection(); - - PreparedStatement selectStatement = conn - .prepareStatement("SELECT * FROM pooling.locks WHERE resourceId = ? AND expirationTime >= now()")) { - - selectStatement.setString(1, this.resourceId); - try (ResultSet result = selectStatement.executeQuery()) { - // This will return true if the - // query returned at least one row - return result.first(); - } - } - - catch (SQLException e) { - logger.error("error in TargetLock.isActive()", e); - return false; - } - } + + /** + *To remove a lock we simply delete the record from the db . + */ + private boolean deleteLock() { + + try (Connection conn = dataSource.getConnection(); + + PreparedStatement deleteStatement = conn.prepareStatement( + "DELETE FROM pooling.locks WHERE resourceId = ? AND owner = ? AND host = ?")) { + + deleteStatement.setString(1, this.resourceId); + deleteStatement.setString(2, this.owner); + deleteStatement.setString(3, this.uuid.toString()); + + return (deleteStatement.executeUpdate() == 1); + + } catch (SQLException e) { + logger.error("error in TargetLock.deleteLock()", e); + return false; + } + + } + + /** + * Is the lock active. + */ + public boolean isActive() { + try (Connection conn = dataSource.getConnection(); + + PreparedStatement selectStatement = conn.prepareStatement( + "SELECT * FROM pooling.locks " + + "WHERE resourceId = ? AND host = ? AND owner= ? AND expirationTime >= now()")) { + + selectStatement.setString(1, this.resourceId); + selectStatement.setString(2, this.uuid.toString()); + selectStatement.setString(3, this.owner); + try (ResultSet result = selectStatement.executeQuery()) { + + // This will return true if the + // query returned at least one row + return result.first(); + } + + } + + catch (SQLException e) { + logger.error("error in TargetLock.isActive()", e); + return false; + } + + } + + /** + * Is the resource locked. + */ + public boolean isLocked() { + + try (Connection conn = dataSource.getConnection(); + PreparedStatement selectStatement = conn + .prepareStatement("SELECT * FROM pooling.locks WHERE resourceId = ? AND expirationTime >= now()")) { + + selectStatement.setString(1, this.resourceId); + try (ResultSet result = selectStatement.executeQuery()) { + // This will return true if the + // query returned at least one row + return result.first(); + } + } catch (SQLException e) { + logger.error("error in TargetLock.isActive()", e); + return false; + } + } } diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureExceptionTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureExceptionTest.java index 5bc3ae5e..7ba2384a 100644 --- a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureExceptionTest.java +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/DistributedLockingFeatureExceptionTest.java @@ -26,11 +26,11 @@ import org.junit.Test; import org.onap.policy.common.utils.test.ExceptionsTester; import org.onap.policy.distributed.locking.DistributedLockingFeatureException; -public class DistributedLockingFeatureExceptionTest extends ExceptionsTester{ - - @Test - public void test() { - assertEquals(1, test(DistributedLockingFeatureException.class)); - } +public class DistributedLockingFeatureExceptionTest extends ExceptionsTester { + + @Test + public void test() { + assertEquals(1, test(DistributedLockingFeatureException.class)); + } } diff --git a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java index 42c8a742..60a721b7 100644 --- a/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java +++ b/feature-distributed-locking/src/test/java/org/onap/policy/distributed/locking/TargetLockTest.java @@ -7,9 +7,9 @@ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,6 +21,7 @@ package org.onap.policy.distributed.locking; import static org.junit.Assert.assertEquals; + import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; @@ -36,191 +37,211 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TargetLockTest { - private static final Logger logger = LoggerFactory.getLogger(TargetLockTest.class); + private static final Logger logger = LoggerFactory.getLogger(TargetLockTest.class); private static final int MAX_AGE_SEC = 4 * 60; - private static final String DB_CONNECTION = "jdbc:h2:mem:pooling;INIT=CREATE SCHEMA IF NOT EXISTS pooling\\;SET SCHEMA pooling"; - private static final String DB_USER = "user"; - private static final String DB_PASSWORD = "password"; - private static Connection conn = null; - private static DistributedLockingFeature distLockFeat; - - @BeforeClass - public static void setup() { - getDBConnection(); - createTable(); - SystemPersistence.manager.setConfigurationDir("src/test/resources"); - distLockFeat = new DistributedLockingFeature(); - distLockFeat.afterStart(null); - - } - - @AfterClass - public static void cleanUp() { - distLockFeat.beforeShutdown(null); - try { - conn.close(); - } catch (SQLException e) { - logger.error("Error in TargetLockTest.cleanUp()", e); - } - } - - @Before - public void wipeDb() { - try (PreparedStatement lockDelete = conn.prepareStatement("DELETE FROM pooling.locks");){ - lockDelete.executeUpdate(); - } catch (SQLException e) { - logger.error("Error in TargetLockTest.wipeDb()", e); - throw new RuntimeException(e); - } - - } - - @Test - public void testGrabLockSuccess() throws InterruptedException, ExecutionException { - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); - - //attempt to grab expiredLock - try (PreparedStatement updateStatement = conn.prepareStatement("UPDATE pooling.locks SET expirationTime = timestampadd(second, -1, now()) WHERE resourceId = ?");) - { - updateStatement.setString(1, "resource1"); - updateStatement.executeUpdate(); - - } catch (SQLException e) { - logger.error("Error in TargetLockTest.testGrabLockSuccess()", e); - throw new RuntimeException(e); - } - - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); - - // cannot re-lock - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); + private static final String DB_CONNECTION = + "jdbc:h2:mem:pooling;INIT=CREATE SCHEMA IF NOT EXISTS pooling\\;SET SCHEMA pooling"; + private static final String DB_USER = "user"; + private static final String DB_PASSWORD = "password"; + private static Connection conn = null; + private static DistributedLockingFeature distLockFeat; + + /** + * Setup the database. + */ + @BeforeClass + public static void setup() { + getDbConnection(); + createTable(); + SystemPersistence.manager.setConfigurationDir("src/test/resources"); + distLockFeat = new DistributedLockingFeature(); + distLockFeat.afterStart(null); + } + + /** + * Cleanup the lock. + */ + @AfterClass + public static void cleanUp() { + distLockFeat.beforeShutdown(null); + try { + conn.close(); + } catch (SQLException e) { + logger.error("Error in TargetLockTest.cleanUp()", e); + } + } + + /** + * Wipe the database. + */ + @Before + public void wipeDb() { + try (PreparedStatement lockDelete = conn.prepareStatement("DELETE FROM pooling.locks"); ) { + lockDelete.executeUpdate(); + } catch (SQLException e) { + logger.error("Error in TargetLockTest.wipeDb()", e); + throw new RuntimeException(e); + } + } + + @Test + public void testGrabLockSuccess() throws InterruptedException, ExecutionException { + assertEquals( + OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); + + // attempt to grab expiredLock + try (PreparedStatement updateStatement = + conn.prepareStatement( + "UPDATE pooling.locks SET expirationTime = timestampadd(second, -1, now()) WHERE resourceId = ?"); ) { + updateStatement.setString(1, "resource1"); + updateStatement.executeUpdate(); + + } catch (SQLException e) { + logger.error("Error in TargetLockTest.testGrabLockSuccess()", e); + throw new RuntimeException(e); + } + + assertEquals( + OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); + + // cannot re-lock + assertEquals( + OperResult.OPER_DENIED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); - } - - @Test - public void testExpiredLocks() throws Exception { - - //grab lock - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - - //force lock to expire - try (PreparedStatement lockExpire = conn.prepareStatement("UPDATE pooling.locks SET expirationTime = timestampadd(second, -?, now())");) { + } + + @Test + public void testExpiredLocks() throws Exception { + + // grab lock + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + + // force lock to expire + try (PreparedStatement lockExpire = + conn.prepareStatement( + "UPDATE pooling.locks SET expirationTime = timestampadd(second, -?, now())"); ) { lockExpire.setInt(1, MAX_AGE_SEC + 1); lockExpire.executeUpdate(); } - - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); - } - - @Test - public void testGrabLockFail() throws InterruptedException, ExecutionException { - - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); - - } - + + assertEquals( + OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); + } + + @Test + public void testGrabLockFail() throws InterruptedException, ExecutionException { + + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + + assertEquals( + OperResult.OPER_DENIED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); + } + @Test public void testUpdateLock() throws InterruptedException, ExecutionException { // not locked yet - refresh should fail - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); - + assertEquals( + OperResult.OPER_DENIED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); + // now lock it - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); + assertEquals( + OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC)); // refresh should work now - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); - + assertEquals( + OperResult.OPER_ACCEPTED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); + assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); - + // expire the lock - try (PreparedStatement updateStatement = conn.prepareStatement("UPDATE pooling.locks SET expirationTime = timestampadd(second, -1, now()) WHERE resourceId = ?");) - { + try (PreparedStatement updateStatement = + conn.prepareStatement( + "UPDATE pooling.locks SET expirationTime = timestampadd(second, -1, now()) WHERE resourceId = ?"); ) { updateStatement.setString(1, "resource1"); updateStatement.executeUpdate(); - + } catch (SQLException e) { logger.error("Error in TargetLockTest.testGrabLockSuccess()", e); throw new RuntimeException(e); } - + // refresh should fail now - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); + assertEquals( + OperResult.OPER_DENIED, distLockFeat.beforeRefresh("resource1", "owner1", MAX_AGE_SEC)); assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); } - - - @Test - public void testUnlock() throws InterruptedException, ExecutionException { - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeUnlock("resource1", "owner1")); - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); - } - - @Test - public void testIsActive() { - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner2")); - - // isActive on expiredLock - try (PreparedStatement updateStatement = conn - .prepareStatement("UPDATE pooling.locks SET expirationTime = timestampadd(second, -5, now()) WHERE resourceId = ?");) { - updateStatement.setString(1, "resource1"); - updateStatement.executeUpdate(); - - } catch (SQLException e) { - logger.error("Error in TargetLockTest.testIsActive()", e); - throw new RuntimeException(e); - } - - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); - - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - //Unlock record, next isActive attempt should fail - distLockFeat.beforeUnlock("resource1", "owner1"); - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); - - } - - @Test - public void unlockBeforeLock() { - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeUnlock("resource1", "owner1")); - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeUnlock("resource1", "owner1")); - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeUnlock("resource1", "owner1")); - } - - @Test - public void testIsLocked() { - assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLocked("resource1")); - distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); - assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLocked("resource1")); - - } - - private static void getDBConnection() { - try { - conn = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD); - } catch (SQLException e) { - logger.error("Error in TargetLockTest.getDBConnection()", e); - } - } - - private static void createTable() { - String createString = "create table if not exists pooling.locks (resourceId VARCHAR(128), host VARCHAR(128), owner VARCHAR(128), expirationTime TIMESTAMP DEFAULT 0, PRIMARY KEY (resourceId))"; - try (PreparedStatement createStmt = conn.prepareStatement(createString);) { - createStmt.executeUpdate(); - - } catch (SQLException e) { - logger.error("Error in TargetLockTest.createTable()", e); - } - } - + @Test + public void testUnlock() throws InterruptedException, ExecutionException { + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + + assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeUnlock("resource1", "owner1")); + assertEquals( + OperResult.OPER_ACCEPTED, distLockFeat.beforeLock("resource1", "owner2", MAX_AGE_SEC)); + } + + @Test + public void testIsActive() { + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner2")); + + // isActive on expiredLock + try (PreparedStatement updateStatement = + conn.prepareStatement( + "UPDATE pooling.locks SET expirationTime = timestampadd(second, -5, now()) WHERE resourceId = ?"); ) { + updateStatement.setString(1, "resource1"); + updateStatement.executeUpdate(); + + } catch (SQLException e) { + logger.error("Error in TargetLockTest.testIsActive()", e); + throw new RuntimeException(e); + } + + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); + + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + // Unlock record, next isActive attempt should fail + distLockFeat.beforeUnlock("resource1", "owner1"); + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLockedBy("resource1", "owner1")); + } + + @Test + public void unlockBeforeLock() { + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeUnlock("resource1", "owner1")); + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeUnlock("resource1", "owner1")); + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeUnlock("resource1", "owner1")); + } + + @Test + public void testIsLocked() { + assertEquals(OperResult.OPER_DENIED, distLockFeat.beforeIsLocked("resource1")); + distLockFeat.beforeLock("resource1", "owner1", MAX_AGE_SEC); + assertEquals(OperResult.OPER_ACCEPTED, distLockFeat.beforeIsLocked("resource1")); + } + + private static void getDbConnection() { + try { + conn = DriverManager.getConnection(DB_CONNECTION, DB_USER, DB_PASSWORD); + } catch (SQLException e) { + logger.error("Error in TargetLockTest.getDBConnection()", e); + } + } + + private static void createTable() { + String createString = + "create table if not exists pooling.locks " + + "(resourceId VARCHAR(128), host VARCHAR(128), owner VARCHAR(128), " + + "expirationTime TIMESTAMP DEFAULT 0, PRIMARY KEY (resourceId))"; + try (PreparedStatement createStmt = conn.prepareStatement(createString); ) { + createStmt.executeUpdate(); + + } catch (SQLException e) { + logger.error("Error in TargetLockTest.createTable()", e); + } + } } |