From 1480379b0e9907c0d41e8a782468c30f0ee83196 Mon Sep 17 00:00:00 2001 From: Jim Hahn Date: Thu, 12 Jul 2018 17:47:09 -0400 Subject: Distinguish lock from refresh This is the first step of separating the lock "refresh" operation from the original "lock" operation. This step entails adding the refresh() method to both the default and the feature-distriubted locking mechanisms. Change method call, in junit test, from lock to refresh. Change branch name in git review. Change-Id: I506de7a96cb3ee786839aca04ad67cdd7378832c Issue-ID: POLICY-872 Signed-off-by: Jim Hahn --- .../core/lock/PolicyResourceLockFeatureAPI.java | 28 ++++++++++++++ .../core/lock/PolicyResourceLockManager.java | 22 +++++++++++ .../policy/drools/core/lock/SimpleLockManager.java | 43 ++++++++++++++++++++++ 3 files changed, 93 insertions(+) (limited to 'policy-core/src/main') diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockFeatureAPI.java b/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockFeatureAPI.java index 683dd83d..ba6fe856 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockFeatureAPI.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockFeatureAPI.java @@ -97,6 +97,34 @@ public interface PolicyResourceLockFeatureAPI extends OrderedService { return false; } + /** + * This method is called before a lock is refreshed on a resource. It may be invoked + * repeatedly to extend the time that a lock is held. + * + * @param resourceId + * @param owner + * @param holdSec the amount of time, in seconds, that the lock should be held + * @return the result, where OPER_DENIED indicates that the resource is not + * currently locked by the given owner + */ + public default OperResult beforeRefresh(String resourceId, String owner, int holdSec) { + return OperResult.OPER_UNHANDLED; + } + + /** + * This method is called after a lock for a resource has been refreshed (or after the + * refresh has been denied). + * + * @param resourceId + * @param owner + * @param locked {@code true} if the lock was acquired, {@code false} if it was denied + * @return {@code true} if the implementer handled the request, {@code false} + * otherwise + */ + public default boolean afterRefresh(String resourceId, String owner, boolean locked) { + return false; + } + /** * This method is called before a lock on a resource is released. * diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockManager.java b/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockManager.java index 1a94a531..8e13ced4 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockManager.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/lock/PolicyResourceLockManager.java @@ -89,6 +89,28 @@ public class PolicyResourceLockManager extends SimpleLockManager { }); } + @Override + public boolean refresh(String resourceId, String owner, int holdSec) { + if (resourceId == null) { + throw makeNullArgException(MSG_NULL_RESOURCE_ID); + } + + if (owner == null) { + throw makeNullArgException(MSG_NULL_OWNER); + } + + + return doBoolIntercept(impl -> impl.beforeRefresh(resourceId, owner, holdSec), () -> { + + // implementer didn't do the work - defer to the superclass + boolean refreshed = super.refresh(resourceId, owner, holdSec); + + doIntercept(false, impl -> impl.afterRefresh(resourceId, owner, refreshed)); + + return refreshed; + }); + } + @Override public boolean unlock(String resourceId, String owner) { if (resourceId == null) { diff --git a/policy-core/src/main/java/org/onap/policy/drools/core/lock/SimpleLockManager.java b/policy-core/src/main/java/org/onap/policy/drools/core/lock/SimpleLockManager.java index 2a44ddcd..081ad4c1 100644 --- a/policy-core/src/main/java/org/onap/policy/drools/core/lock/SimpleLockManager.java +++ b/policy-core/src/main/java/org/onap/policy/drools/core/lock/SimpleLockManager.java @@ -117,6 +117,49 @@ public class SimpleLockManager { return locked; } + /** + * Attempts to refresh a lock on a resource. + * + * @param resourceId + * @param owner + * @param holdSec the amount of time, in seconds, that the lock should be held + * @return {@code true} if locked, {@code false} if the resource is not currently + * locked by the given owner + * @throws IllegalArgumentException if the resourceId or owner is {@code null} + */ + public boolean refresh(String resourceId, String owner, int holdSec) { + + if (resourceId == null) { + throw makeNullArgException(MSG_NULL_RESOURCE_ID); + } + + if (owner == null) { + throw makeNullArgException(MSG_NULL_OWNER); + } + + boolean refreshed = false; + + synchronized(locker) { + cleanUpLocks(); + + Data existingLock = resource2data.get(resourceId); + if (existingLock != null && existingLock.getOwner().equals(owner)) { + // MUST remove the existing lock from the set + locks.remove(existingLock); + + refreshed = true; + + Data data = new Data(owner, resourceId, currentTime.getMillis() + TimeUnit.SECONDS.toMillis(holdSec)); + resource2data.put(resourceId, data); + locks.add(data); + } + } + + logger.info("refresh lock {} for resource {} owner {}", refreshed, resourceId, owner); + + return refreshed; + } + /** * Unlocks a resource. * -- cgit 1.2.3-korg