Modify drools-applications to use new Lock API 37/97437/1
authorJim Hahn <jrh3@att.com>
Fri, 27 Sep 2019 15:22:47 +0000 (11:22 -0400)
committerJim Hahn <jrh3@att.com>
Tue, 22 Oct 2019 20:06:10 +0000 (16:06 -0400)
Modified code to use new Lock API.
Also deleted TargetLock and PolicyGuard, as they are no longer needed.

Issue-ID: POLICY-2113
Signed-off-by: Jim Hahn <jrh3@att.com>
Change-Id: I5bc9b7732f9cfc6056789b2902d9f6f838b560be

16 files changed:
controlloop/common/controller-usecases/src/main/resources/usecases.drl
controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManager.java
controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/ControlLoopOperationManager.java
controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/LockCallbackWorkingMemory.java [new file with mode: 0644]
controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/ControlLoopEventManagerTest.java
controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/LockCallbackWorkingMemoryTest.java [new file with mode: 0644]
controlloop/common/guard/src/main/java/org/onap/policy/guard/LockCallback.java [deleted file]
controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuard.java [deleted file]
controlloop/common/guard/src/main/java/org/onap/policy/guard/TargetLock.java [deleted file]
controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/PnfTargetLock.java [deleted file]
controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/TargetLockImpl.java [deleted file]
controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/VmTargetLock.java [deleted file]
controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/VnfTargetLock.java [deleted file]
controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardTest.java [deleted file]
controlloop/templates/archetype-cl-amsterdam/src/main/resources/archetype-resources/src/main/resources/__closedLoopControlName__.drl
controlloop/templates/template.demo/src/test/java/org/onap/policy/template/demo/ControlLoopFailureTest.java

index 4adf740..fb6812a 100644 (file)
@@ -35,6 +35,7 @@ import org.onap.policy.controlloop.policy.Policy;
 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NewEventStatus;
 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
+import org.onap.policy.controlloop.eventmanager.LockCallbackWorkingMemory;
 import org.onap.policy.controlloop.utils.ControlLoopUtils;
 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider;
@@ -53,6 +54,7 @@ import org.onap.policy.appclcm.LcmCommonHeader;
 import org.onap.policy.cds.CdsResponse;
 import org.onap.policy.cds.client.CdsProcessorGrpcClient;
 import org.onap.policy.cds.properties.CdsServerProperties;
+import org.onap.policy.drools.utils.Pair;
 import org.onap.policy.sdnr.PciRequestWrapper;
 import org.onap.policy.sdnr.PciResponseWrapper;
 import org.onap.policy.sdnr.PciRequest;
@@ -66,10 +68,7 @@ import org.onap.policy.so.SoResponseWrapper;
 import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncManager;
 import org.onap.policy.sdnc.SdncResponse;
-import org.onap.policy.guard.PolicyGuard;
-import org.onap.policy.guard.PolicyGuard.LockResult;
-import org.onap.policy.guard.TargetLock;
-import org.onap.policy.guard.GuardResult;
+import org.onap.policy.drools.core.lock.Lock;
 import org.onap.policy.guard.PolicyGuardRequest;
 import org.onap.policy.guard.PolicyGuardResponse;
 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
@@ -113,7 +112,7 @@ rule "INSERT.PARAMS"
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "." 
+    logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), $params.getPolicyName() + "."
         + drools.getRule().getName(), $params.getControlLoopYaml());
 end
 
@@ -164,7 +163,7 @@ rule "EVENT"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
-        not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() ) )
     then
 
@@ -204,7 +203,7 @@ rule "EVENT"
             //
             ControlLoopEventManager manager = new ControlLoopEventManager($clName, $event.getRequestId());
             //
-            // Determine if EventManager can actively process the event 
+            // Determine if EventManager can actively process the event
             // (i.e. syntax, is_closed_loop_disabled checks etc.)
             //
             VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
@@ -283,9 +282,9 @@ rule "EVENT.MANAGER"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
     then
 
@@ -362,10 +361,10 @@ rule "EVENT.MANAGER"
                 //
                 // Unlock the target
                 //
-                TargetLock lock = $manager.unlockCurrentOperation();
-                if (lock != null) {
-                    logger.debug("{}: {}: retracting lock=", $clName,
-                                 $params.getPolicyName() + "." + drools.getRule().getName(), lock);
+                Lock lock = $manager.unlockCurrentOperation();
+                if(lock != null) {
+                    logger.debug("{}: {}.{}: retracting lock={}", $clName,
+                                 $params.getPolicyName(), drools.getRule().getName(), lock);
                     retract(lock);
                 }
                 //
@@ -375,9 +374,9 @@ rule "EVENT.MANAGER"
                             $clName, $params.getPolicyName() + "." + drools.getRule().getName());
 
                 retract($manager.getOnsetEvent());
-                
+
                 // don't retract manager, etc. - a clean-up rule will do that
-                
+
                 //
                 // TODO - what if we get subsequent Events for this RequestId?
                 // By default, it will all start over again. May be confusing for Ruby.
@@ -407,10 +406,10 @@ rule "EVENT.MANAGER"
                   //
                   // Unlock the target
                   //
-                  TargetLock lock = $manager.unlockCurrentOperation();
-                  if (lock != null) {
-                      logger.debug("{}: {}: retracting lock=", $clName,
-                                  $params.getPolicyName() + "." + drools.getRule().getName(), lock);
+                  Lock lock = $manager.unlockCurrentOperation();
+                  if(lock != null) {
+                      logger.debug("{}: {}.{}: retracting lock={}", $clName,
+                                  $params.getPolicyName(), drools.getRule().getName(), lock);
                       retract(lock);
                   }
                   //
@@ -420,7 +419,7 @@ rule "EVENT.MANAGER"
                               $clName, $params.getPolicyName() + "." + drools.getRule().getName());
 
                   retract($manager.getOnsetEvent());
-                
+
                   // don't retract manager, etc. - a clean-up rule will do that
                 }
             }
@@ -433,57 +432,39 @@ rule "EVENT.MANAGER"
               //
               // Let's ask for a lock right away
               //
-              LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
-              logger.info("{}: {}: guard lock acquired={}",
-                            $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                            result.getB());
-              if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
-                  //
-                  // insert the operation into memory
-                  //
-                  insert(operation);
-
-                  //
-                  // insert operation timeout object
-                  //
-                  ControlLoopTimer opTimer = new ControlLoopTimer();
-                  opTimer.setTimerType("Operation");
-                  opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
-                  opTimer.setRequestId($event.getRequestId().toString());
-                  Integer timeout = operation.getOperationTimeout();
-                  opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
-                  insert(opTimer);
-
-                  //
-                  // Insert lock into memory
-                  //
-                  insert(result.getB());
+              logger.info("{}: {}.{}: requesting lock for operation={}",
+                            $clName, $params.getPolicyName(), drools.getRule().getName(),
+                            operation);
+
+              Pair<Lock,Lock> oldNew = $manager.lockCurrentOperation(
+                        new LockCallbackWorkingMemory($params.getClosedLoopControlName(), drools.getWorkingMemory()));
+              if(oldNew.first() != null) {
+                  logger.debug("{}: {}.{}: retracting lock={}", $clName,
+                              $params.getPolicyName(), drools.getRule().getName(), oldNew.first());
+                  retract(oldNew.first());
+              }
+              if(oldNew.second() != null) {
+                  logger.debug("{}: {}.{}: inserting lock={}", $clName,
+                              $params.getPolicyName(), drools.getRule().getName(), oldNew.second());
+                  insert(oldNew.second());
               }
-              else {
-                  logger.debug("The target resource {} is already processing",
-                                $event.getAai().get($event.getTarget()));
-                  notification = new VirtualControlLoopNotification($event);
-                  notification.setNotification(ControlLoopNotificationType.REJECTED);
-                  notification.setMessage("The target " + $event.getAai().get($event.getTarget()) 
-                      + " is already locked");
-                  notification.setFrom("policy");
-                  notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
-                  notification.setPolicyScope($params.getPolicyScope());
-                  notification.setPolicyVersion($params.getPolicyVersion());
 
-                  PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
+              //
+              // insert the operation into memory
+              //
+              insert(operation);
 
-                  retract($event);
-                
-                  // don't retract manager, etc. - a clean-up rule will do that
+              //
+              // insert operation timeout object
+              //
+              ControlLoopTimer opTimer = new ControlLoopTimer();
+              opTimer.setTimerType("Operation");
+              opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
+              opTimer.setRequestId($event.getRequestId().toString());
+              Integer timeout = operation.getOperationTimeout();
+              opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
+              insert(opTimer);
 
-                if(result.getB() != null) {
-                  retract(result.getB());
-                }
-              }
-              logger.info("{}: {}: starting operation={}",
-                          $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                          operation);
             } else {
               //
               // Probably waiting for abatement
@@ -508,12 +489,49 @@ rule "EVENT.MANAGER"
         PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
 
         retract($event);
-                
+
         // don't retract manager, etc. - a clean-up rule will do that
     }
 
 end
 
+/*
+*
+* Lock denied
+*
+*/
+rule "EVENT.MANAGER.OPERATION.LOCK.DENIED"
+    when
+        $params : ControlLoopParams( $clName : getClosedLoopControlName() )
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
+            requestId == $event.getRequestId() )
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
+            onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
+        $lock : Lock (ownerKey == $event.getRequestId().toString(), isUnavailable())
+    then
+
+    Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
+    logger.info("{}: {}.{}: event={} manager={} operation={} lock={}",
+            $clName, $params.getPolicyName(), drools.getRule().getName(),
+            $event, $manager, $operation, $lock);
+
+    logger.debug("The target resource {} is already processing", $event.getAai().get($event.getTarget()));
+    VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
+    notification.setNotification(ControlLoopNotificationType.REJECTED);
+    notification.setMessage("The target " + $event.getAai().get($event.getTarget()) + " is already locked");
+    notification.setFrom("policy");
+    notification.setPolicyName($params.getPolicyName() + "." + drools.getRule().getName());
+    notification.setPolicyScope($params.getPolicyScope());
+    notification.setPolicyVersion($params.getPolicyVersion());
+
+    PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
+
+    retract($event);
+
+    // don't retract manager, etc. - a clean-up rule will do that
+end
+
 /*
 *
 * Guard Permitted, let's send request to the actor.
@@ -523,19 +541,18 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
-        $lock : TargetLock (requestId == $event.getRequestId())
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {}: event={} manager={} operation={} lock={}",
+    logger.info("{}: {}: event={} manager={} operation={}",
                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                $event, $manager, $operation, $lock);
+                $event, $manager, $operation);
 
     Object request = null;
     boolean caughtException = false;
@@ -573,7 +590,7 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                   }
                   break;
               case "SO":
-                  // at this point the AAI named query request should have already been made, the response 
+                  // at this point the AAI named query request should have already been made, the response
                   // recieved and used in the construction of the SO Request which is stored in operationRequest
 
                   if(request instanceof SoRequest) {
@@ -583,8 +600,8 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                               drools.getWorkingMemory().insert(wrapper);
                           }
                       }
-                      SoActorServiceProvider.sendRequest($event.getRequestId().toString(), 
-                          new mySoCallback(), 
+                      SoActorServiceProvider.sendRequest($event.getRequestId().toString(),
+                          new mySoCallback(),
                           request,
                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.url"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.username"),
@@ -594,7 +611,7 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
               case "VFC":
                   if (request instanceof VfcRequest) {
                       class myVfcCallback implements VfcManager.VfcCallback {
-                          
+
                           public void onResponse(VfcResponse responseError) {
                               drools.getWorkingMemory().insert(responseError);
                           }
@@ -613,23 +630,23 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                       PolicyEngineConstants.getManager().deliver("SDNR-CL", request);
                   }
                   break;
-              
+
               case "SDNC":
                   if (request instanceof SdncRequest) {
                       class mySdncCallback implements SdncManager.SdncCallback {
                           public void onCallback(SdncResponse response) {
                               drools.getWorkingMemory().insert(response);
                           }
-                      }  
+                      }
                       // Start SDNC thread
-                      Thread t = new Thread(new SdncManager(new mySdncCallback(), 
+                      Thread t = new Thread(new SdncManager(new mySdncCallback(),
                           (SdncRequest)request,
                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.url"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.username"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.password")));
                       t.start();
                   }
-                  break;                 
+                  break;
 
               case "CDS":
 
@@ -656,7 +673,6 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                       }
                   }
                   break;
-
           }
         } else {
           //
@@ -728,11 +744,11 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
-            onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
-        $lock : TargetLock (requestId == $event.getRequestId())
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
+            onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
+        $lock : Lock (ownerKey == $event.getRequestId().toString(), isActive())
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
@@ -745,7 +761,7 @@ rule "EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
     //
     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
     notification.setNotification(ControlLoopNotificationType.OPERATION);
-    notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " " 
+    notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
         + $operation.policy.getRecipe());
     notification.setHistory($operation.getHistory());
     notification.setFrom("policy");
@@ -813,22 +829,21 @@ end
 rule "GUARD.RESPONSE"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $lock : TargetLock (requestId == $event.getRequestId())
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
         $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}",
+    logger.info("{}: {}: event={} manager={} operation={} opTimer={} guardResponse={}",
                  $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                 $event, $manager, $operation, $lock, $opTimer, $guardResponse);
+                 $event, $manager, $operation, $opTimer, $guardResponse);
 
 
     //we will permit the operation if there was no Guard for it
@@ -882,23 +897,22 @@ end
 rule "APPC.RESPONSE"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                  $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                 $event, $manager, $operation, $lock, $opTimer, $response);
+                 $event, $manager, $operation, $opTimer, $response);
     //
     // Get the result of the operation
     //
@@ -1000,23 +1014,22 @@ end
 rule "APPC.LCM.RESPONSE"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                $event, $manager, $operation, $operation, $opTimer, $response);
 
     //
     // Get the result of the operation
@@ -1109,23 +1122,22 @@ end
 rule "SO.RESPONSE"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                $event, $manager, $operation, $operation, $opTimer, $response);
 
     // Get the result of the operation
     //
@@ -1197,22 +1209,21 @@ end
 rule "VFC.RESPONSE"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
     then
         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
         logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-        logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+        logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                     $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                    $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                    $event, $manager, $operation, $operation, $opTimer, $response);
 
         // Get the result of the operation
         //
@@ -1276,16 +1287,15 @@ rule "SDNC.RESPONSE"
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName, closedLoopEventStatus == ControlLoopEventStatus.ONSET )
         $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), requestId == $event.getRequestId() )
         $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
     then
         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
         logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-        logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+        logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                        $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                       $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                       $event, $manager, $operation, $operation, $opTimer, $response);
 
         // Get the result of the operation
         //
@@ -1353,16 +1363,15 @@ rule "${policyName}.CDS.RESPONSE"
             onset.getRequestId() == $event.getRequestId() )
         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : CdsResponse( requestId == $event.getRequestId().toString() )
 
     then
 
         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
         logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-        logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+        logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
-                    $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                    $event, $manager, $operation, $operation, $opTimer, $response);
 
         // Get the result of the operation
         PolicyResult policyResult = $operation.onResponse($response);
@@ -1444,20 +1453,19 @@ rule "EVENT.MANAGER.OPERATION.TIMEOUT"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}",
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={}",
                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer);
+                $event, $manager, $operation, $operation, $opTimer);
 
     //
     // Tell it its timed out
@@ -1511,9 +1519,9 @@ rule "EVENT.MANAGER.TIMEOUT"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
         $event : VirtualControlLoopEvent( closedLoopControlName == $clName )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", expired )
     then
 
@@ -1553,13 +1561,11 @@ rule "EVENT.MANAGER.CLEANUP"
     when
         $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
         $operations : LinkedList()
-                        from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName, 
+                        from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
                             onset.getRequestId() == $requestId ) )
         $timers : LinkedList()
-                        from collect( ControlLoopTimer( closedLoopControlName == $clName, 
+                        from collect( ControlLoopTimer( closedLoopControlName == $clName,
                             requestId == $requestId.toString() ) )
-        $locks : LinkedList()
-                        from collect( TargetLock (requestId == $requestId) )
         not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
     then
 
@@ -1570,6 +1576,14 @@ rule "EVENT.MANAGER.CLEANUP"
               $clName, drools.getRule().getName(),
               $manager, $timers.size(), $operations.size());
 
+    //
+    // Retract lock by invoking unlock()
+    //
+    Lock lock = $manager.unlockCurrentOperation();
+    if(lock != null) {
+        retract(lock);
+    }
+
     //
     // Retract EVERYTHING
     //
@@ -1581,14 +1595,6 @@ rule "EVENT.MANAGER.CLEANUP"
     for(Object timer: $timers) {
         retract((ControlLoopTimer) timer);
     }
-    for(Object lock: $locks) {
-        TargetLock tgt = (TargetLock) lock;
-        //
-        // Ensure we release the lock
-        //
-        PolicyGuard.unlockTarget(tgt);
-        retract(tgt);
-    }
 end
 
 /*
@@ -1619,23 +1625,22 @@ end
 rule "SDNR.RESPONSE"
     when
         $params : ControlLoopParams( $clName : getClosedLoopControlName() )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $clName, 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $clName,
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, $params.getPolicyName() + "." + drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                 $clName, $params.getPolicyName() + "." + drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                $event, $manager, $operation, $operation, $opTimer, $response);
 
     //
     // Get the result of the operation
index f6cfe55..6afb08d 100644 (file)
@@ -58,18 +58,18 @@ import org.onap.policy.controlloop.VirtualControlLoopNotification;
 import org.onap.policy.controlloop.policy.FinalResult;
 import org.onap.policy.controlloop.policy.Policy;
 import org.onap.policy.controlloop.processor.ControlLoopProcessor;
+import org.onap.policy.drools.core.lock.Lock;
+import org.onap.policy.drools.core.lock.LockCallback;
+import org.onap.policy.drools.core.lock.LockImpl;
+import org.onap.policy.drools.core.lock.LockState;
 import org.onap.policy.drools.system.PolicyEngineConstants;
-import org.onap.policy.guard.GuardResult;
-import org.onap.policy.guard.LockCallback;
-import org.onap.policy.guard.PolicyGuard;
-import org.onap.policy.guard.PolicyGuard.LockResult;
-import org.onap.policy.guard.TargetLock;
+import org.onap.policy.drools.utils.Pair;
 import org.onap.policy.rest.RestManager;
 import org.onap.policy.so.util.Serialization;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ControlLoopEventManager implements LockCallback, Serializable {
+public class ControlLoopEventManager implements Serializable {
     public static final String PROV_STATUS_ACTIVE = "ACTIVE";
     private static final String VM_NAME = "VM_NAME";
     private static final String VNF_NAME = "VNF_NAME";
@@ -121,7 +121,7 @@ public class ControlLoopEventManager implements LockCallback, Serializable {
     private LinkedList<ControlLoopOperation> controlLoopHistory = new LinkedList<>();
     private ControlLoopOperationManager currentOperation = null;
     private ControlLoopOperationManager lastOperationManager = null;
-    private transient TargetLock targetLock = null;
+    private transient Lock targetLock = null;
     private AaiGetVnfResponse vnfResponse = null;
     private AaiGetVserverResponse vserverResponse = null;
     private boolean useTargetLock = true;
@@ -140,6 +140,12 @@ public class ControlLoopEventManager implements LockCallback, Serializable {
         requiredAAIKeys.add(VM_NAME);
     }
 
+    /**
+     * Constructs the object.
+     *
+     * @param closedLoopControlName name of the control loop
+     * @param requestId ID of the request with which this manager is associated
+     */
     public ControlLoopEventManager(String closedLoopControlName, UUID requestId) {
         this.closedLoopControlName = closedLoopControlName;
         this.requestId = requestId;
@@ -472,9 +478,11 @@ public class ControlLoopEventManager implements LockCallback, Serializable {
                 //
                 this.lastOperationManager = this.currentOperation;
                 this.currentOperation = null;
+
                 //
-                // TODO: Release our lock
+                // Don't release the lock - it may be re-used by the next operation
                 //
+
                 return;
             }
             logger.debug("Cannot finish current operation {} does not match given operation {}",
@@ -487,77 +495,75 @@ public class ControlLoopEventManager implements LockCallback, Serializable {
     /**
      * Obtain a lock for the current operation.
      *
-     * @return the lock result
+     * @param callback call-back to be invoked when the lock state changes
+     * @return a pair containing the old lock and the new lock, either of which may be null
      * @throws ControlLoopException if an error occurs
      */
-    public synchronized LockResult<GuardResult, TargetLock> lockCurrentOperation() throws ControlLoopException {
+    public synchronized Pair<Lock, Lock> lockCurrentOperation(LockCallback callback) throws ControlLoopException {
         //
         // Sanity check
         //
         if (this.currentOperation == null) {
             throw new ControlLoopException("Do not have a current operation.");
         }
+
         //
-        // Not using target locks? Create and return a lock w/o actually locking.
+        // Release the old lock if it's for a different resource.
         //
-        if (!this.useTargetLock) {
-            TargetLock lock = PolicyGuard.createTargetLock(this.currentOperation.policy.getTarget().getType(),
-                    this.currentOperation.getTargetEntity(), this.onset.getRequestId(), this);
-            this.targetLock = lock;
-            return LockResult.createLockResult(GuardResult.LOCK_ACQUIRED, lock);
+        Lock oldLock = null;
+        if (this.targetLock != null
+                        && !this.targetLock.getResourceId().equals(this.currentOperation.getTargetEntity())) {
+            logger.debug("{}: different resource - releasing old lock", getClosedLoopControlName());
+            oldLock = this.targetLock;
+            this.targetLock = null;
         }
+
+        // keep the lock a little longer than the operation, including retries
+        int optimeout = Math.max(1, this.currentOperation.getOperationTimeout());
+        int nattempts = 1 + Math.max(0, this.currentOperation.getMaxRetries());
+        int holdSec = optimeout * nattempts + ADDITIONAL_LOCK_SEC;
+
         //
         // Have we acquired it already?
         //
         if (this.targetLock != null) {
-            //
-            // TODO: Make sure the current lock is for the same target.
-            // Currently, it should be. But in the future it may not.
-            //
-            GuardResult result = PolicyGuard.lockTarget(targetLock,
-                    this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
-            return new LockResult<>(result, this.targetLock);
+            // we have the lock - just extend it
+            this.targetLock.extend(holdSec, callback);
+            return new Pair<>(oldLock, null);
+
+        } else if (this.useTargetLock) {
+            this.targetLock = createRealLock(this.currentOperation.getTargetEntity(), this.onset.getRequestId(),
+                            holdSec, callback);
+            return new Pair<>(oldLock, this.targetLock);
+
         } else {
-            //
-            // Ask the Guard
-            //
-            LockResult<GuardResult, TargetLock> lockResult = PolicyGuard.lockTarget(
-                    this.currentOperation.policy.getTarget().getType(), this.currentOperation.getTargetEntity(),
-                    this.onset.getRequestId(), this, this.currentOperation.getOperationTimeout() + ADDITIONAL_LOCK_SEC);
-            //
-            // Was it acquired?
-            //
-            if (lockResult.getA().equals(GuardResult.LOCK_ACQUIRED)) {
-                //
-                // Yes, let's save it
-                //
-                this.targetLock = lockResult.getB();
-            }
-            return lockResult;
+            // Not using target locks - create a lock w/o actually locking.
+            logger.debug("{}: not using target locking; using pseudo locks", getClosedLoopControlName());
+            this.targetLock = createPseudoLock(this.currentOperation.getTargetEntity(), this.onset.getRequestId(),
+                            holdSec, callback);
+
+            // Note: no need to invoke callback, as the lock is already ACTIVE
+
+            return new Pair<>(oldLock, this.targetLock);
         }
     }
 
     /**
-     * Release the lock for the current operation.
+     * Releases the lock for the current operation, deleting it from working memory.
      *
-     * @return the target lock
+     * @return the lock, if the operation was locked, {@code null} otherwise
      */
-    public synchronized TargetLock unlockCurrentOperation() {
+    public synchronized Lock unlockCurrentOperation() {
         if (this.targetLock == null) {
             return null;
         }
 
-        TargetLock returnLock = this.targetLock;
+        Lock lock = this.targetLock;
         this.targetLock = null;
-        //
-        // if using target locking unlock before returning
-        //
-        if (this.useTargetLock) {
-            PolicyGuard.unlockTarget(returnLock);
-        }
 
-        // always return the old target lock so rules can retract it
-        return returnLock;
+        lock.free();
+
+        return lock;
     }
 
     public enum NewEventStatus {
@@ -1032,18 +1038,6 @@ public class ControlLoopEventManager implements LockCallback, Serializable {
         return enginePropertyValue;
     }
 
-    @Override
-    public boolean isActive() {
-        // TODO
-        return true;
-    }
-
-    @Override
-    public boolean releaseLock() {
-        // TODO
-        return false;
-    }
-
     @Override
     public String toString() {
         return "ControlLoopEventManager [closedLoopControlName=" + closedLoopControlName + ", requestId=" + requestId
@@ -1097,4 +1091,17 @@ public class ControlLoopEventManager implements LockCallback, Serializable {
 
     }
 
+
+    // the following methods may be overridden by junit tests
+
+    protected Lock createRealLock(String targetEntity, UUID requestId, int holdSec, LockCallback callback) {
+        return PolicyEngineConstants.getManager().createLock(targetEntity, requestId.toString(), holdSec, callback,
+                        false);
+    }
+
+    // note: the "callback" is required, because it will be invoked when lock.extend() is
+    // invoked
+    protected Lock createPseudoLock(String targetEntity, UUID requestId, int holdSec, LockCallback callback) {
+        return new LockImpl(LockState.ACTIVE, targetEntity, requestId.toString(), holdSec, callback);
+    }
 }
index eb19019..62bd0c1 100644 (file)
@@ -963,7 +963,7 @@ public class ControlLoopOperationManager implements Serializable {
             //
             // Check if there were no retries specified
             //
-            if (policy.getRetry() == null || policy.getRetry() == 0) {
+            if (getMaxRetries() < 1) {
                 //
                 // The result is the failure
                 //
@@ -972,7 +972,7 @@ public class ControlLoopOperationManager implements Serializable {
             //
             // Check retries
             //
-            if (this.isRetriesMaxedOut()) {
+            if (this.attempts > getMaxRetries()) {
                 //
                 // No more attempts allowed, reset
                 // that our actual result is failure due to retries
@@ -1016,7 +1016,7 @@ public class ControlLoopOperationManager implements Serializable {
         //
         // Check if we have maxed out on retries
         //
-        if (this.policy.getRetry() == null || this.policy.getRetry() < 1) {
+        if (getMaxRetries() < 1) {
             //
             // No retries are allowed, so check have we even made
             // one attempt to execute the operation?
@@ -1037,7 +1037,7 @@ public class ControlLoopOperationManager implements Serializable {
             //
             // Have we maxed out on retries?
             //
-            if (this.attempts > this.policy.getRetry()) {
+            if (this.attempts > getMaxRetries()) {
                 if (this.policyResult == null) {
                     this.policyResult = PolicyResult.FAILURE_RETRIES;
                 }
@@ -1046,15 +1046,13 @@ public class ControlLoopOperationManager implements Serializable {
         }
     }
 
-    private boolean isRetriesMaxedOut() {
-        if (policy.getRetry() == null || policy.getRetry() == 0) {
-            //
-            // There were NO retries specified, so declare
-            // this as completed.
-            //
-            return (this.attempts > 0);
-        }
-        return (this.attempts > policy.getRetry());
+    /**
+     * Gets the maximum number of retries.
+     *
+     * @return the maximum number of retries, or {@code 0}, if not specified
+     */
+    public int getMaxRetries() {
+        return (policy.getRetry() != null ? policy.getRetry() : 0);
     }
 
     private void storeOperationInDataBase() {
diff --git a/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/LockCallbackWorkingMemory.java b/controlloop/common/eventmanager/src/main/java/org/onap/policy/controlloop/eventmanager/LockCallbackWorkingMemory.java
new file mode 100644 (file)
index 0000000..738d3b9
--- /dev/null
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.eventmanager;
+
+import lombok.Getter;
+import org.drools.core.WorkingMemory;
+import org.kie.api.runtime.rule.FactHandle;
+import org.onap.policy.drools.core.lock.Lock;
+import org.onap.policy.drools.core.lock.LockCallback;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Lock call-back that updates working memory.
+ */
+@Getter
+public class LockCallbackWorkingMemory implements LockCallback {
+    private static final Logger logger = LoggerFactory.getLogger(LockCallbackWorkingMemory.class);
+
+    /**
+     * Name to be logged when the lock is updated.
+     */
+    private final String name;
+
+    /**
+     * Working memory to be updated when the lock is notified.
+     */
+    private final WorkingMemory workingMemory;
+
+
+    /**
+     * Constructs the object.
+     *
+     * @param name name to be logged when the lock is updated
+     * @param workingMemory working memory to be updated when the lock is notified
+     */
+    public LockCallbackWorkingMemory(String name, WorkingMemory workingMemory) {
+        this.name = name;
+        this.workingMemory = workingMemory;
+    }
+
+    @Override
+    public void lockAvailable(Lock lock) {
+        notifySession(lock);
+    }
+
+    @Override
+    public void lockUnavailable(Lock lock) {
+        notifySession(lock);
+    }
+
+    /**
+     * Notifies the session that the lock has been updated.
+     */
+    private void notifySession(Lock lock) {
+        FactHandle fact = workingMemory.getFactHandle(lock);
+        if (fact != null) {
+            logger.debug("{}: updating lock={}", name, lock);
+            workingMemory.update(fact, lock);
+        }
+    }
+}
index 0b27ffa..8efdb1f 100644 (file)
@@ -25,12 +25,19 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.Serializable;
 import java.nio.charset.StandardCharsets;
 import java.time.Instant;
 import java.util.HashMap;
@@ -65,14 +72,14 @@ import org.onap.policy.controlloop.VirtualControlLoopNotification;
 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NewEventStatus;
 import org.onap.policy.controlloop.policy.ControlLoopPolicy;
 import org.onap.policy.controlloop.policy.PolicyResult;
+import org.onap.policy.drools.core.lock.Lock;
+import org.onap.policy.drools.core.lock.LockCallback;
 import org.onap.policy.drools.system.PolicyEngineConstants;
-import org.onap.policy.guard.GuardResult;
-import org.onap.policy.guard.PolicyGuard;
-import org.onap.policy.guard.PolicyGuard.LockResult;
-import org.onap.policy.guard.TargetLock;
+import org.onap.policy.drools.utils.Pair;
 import org.powermock.reflect.Whitebox;
 
 public class ControlLoopEventManagerTest {
+    private static final String TARGET_LOCK_FIELD = "targetLock";
     private static final String PROCESS_VSERVER_RESPONSE = "processVServerResponse";
     private static final String ONSET_ONE = "onsetOne";
     private static final String VSERVER_NAME = "vserver.vserver-name";
@@ -107,6 +114,7 @@ public class ControlLoopEventManagerTest {
     public ExpectedException thrown = ExpectedException.none();
 
     private VirtualControlLoopEvent onset;
+    private LockCallback callback;
 
     /**
      * Set up test class.
@@ -130,6 +138,8 @@ public class ControlLoopEventManagerTest {
      */
     @Before
     public void setUp() {
+        callback = mock(LockCallback.class);
+
         onset = new VirtualControlLoopEvent();
         onset.setClosedLoopControlName("ControlLoop-vUSP");
         onset.setRequestId(UUID.randomUUID());
@@ -414,8 +424,6 @@ public class ControlLoopEventManagerTest {
         assertNull(clem.getAbatementEvent());
         assertNull(clem.getProcessor());
 
-        assertEquals(true, clem.isActive());
-        assertEquals(false, clem.releaseLock());
         assertEquals(true, clem.isControlLoopTimedOut());
 
         assertNull(clem.unlockCurrentOperation());
@@ -441,11 +449,6 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testActivationYaml() throws IOException {
-        InputStream is = new FileInputStream(new File(TEST_YAML));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
-        InputStream isBad = new FileInputStream(new File("src/test/resources/notutf8.yaml"));
-        final String yamlStringBad = IOUtils.toString(isBad, StandardCharsets.UTF_8);
 
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
@@ -470,10 +473,17 @@ public class ControlLoopEventManagerTest {
         assertEquals(ControlLoopNotificationType.REJECTED, notificationEmpty.getNotification());
 
         // Bad YAML should fail
+        InputStream isBad = new FileInputStream(new File("src/test/resources/notutf8.yaml"));
+        final String yamlStringBad = IOUtils.toString(isBad, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notificationBad = manager.activate(yamlStringBad, event);
         assertNotNull(notificationBad);
         assertEquals(ControlLoopNotificationType.REJECTED, notificationBad.getNotification());
 
+
+        InputStream is = new FileInputStream(new File(TEST_YAML));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, event);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -486,9 +496,6 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testControlLoopFinal() throws Exception {
-        InputStream is = new FileInputStream(new File(TEST_YAML));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
         event.setClosedLoopControlName(TWO_ONSET_TEST);
@@ -509,6 +516,10 @@ public class ControlLoopEventManagerTest {
                         .hasMessage("No onset event for ControlLoopEventManager.");
 
         manager.setActivated(false);
+
+        InputStream is = new FileInputStream(new File(TEST_YAML));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, event);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -552,9 +563,6 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testProcessControlLoop() throws Exception {
-        InputStream is = new FileInputStream(new File(TEST_YAML));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent event = new VirtualControlLoopEvent();
         event.setClosedLoopControlName(TWO_ONSET_TEST);
@@ -575,6 +583,10 @@ public class ControlLoopEventManagerTest {
                         .hasMessage("No onset event for ControlLoopEventManager.");
 
         manager.setActivated(false);
+
+        InputStream is = new FileInputStream(new File(TEST_YAML));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, event);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -620,21 +632,10 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testFinishOperation() throws Exception {
-        InputStream is = new FileInputStream(new File("src/test/resources/testSOactor.yaml"));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
         InputStream isStd = new FileInputStream(new File(TEST_YAML));
         final String yamlStringStd = IOUtils.toString(isStd, StandardCharsets.UTF_8);
 
-        UUID requestId = UUID.randomUUID();
-        VirtualControlLoopEvent event = new VirtualControlLoopEvent();
-        event.setClosedLoopControlName(TWO_ONSET_TEST);
-        event.setRequestId(requestId);
-        event.setTarget(VNF_ID);
-        event.setClosedLoopAlarmStart(Instant.now());
-        event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
-        event.setAai(new HashMap<>());
-        event.getAai().put(VNF_ID, ONSET_ONE);
+        VirtualControlLoopEvent event = makeEvent();
 
         ControlLoopEventManager manager = makeManager(event);
         ControlLoopEventManager manager2 = manager;
@@ -646,15 +647,14 @@ public class ControlLoopEventManagerTest {
                         .hasMessage("No operation to finish.");
 
         manager.setActivated(false);
+
+        InputStream is = new FileInputStream(new File("src/test/resources/testSOactor.yaml"));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, event);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
 
-        assertThatThrownBy(manager2::lockCurrentOperation).isInstanceOf(ControlLoopException.class)
-                        .hasMessage("Do not have a current operation.");
-
-        assertNull(manager.unlockCurrentOperation());
-
         // serialize and de-serialize manager
         manager = Serializer.roundTrip(manager);
 
@@ -662,23 +662,6 @@ public class ControlLoopEventManagerTest {
         assertNotNull(clom);
         assertNull(clom.getOperationResult());
 
-        LockResult<GuardResult, TargetLock> lockLock = manager.lockCurrentOperation();
-        assertNotNull(lockLock);
-        assertEquals(GuardResult.LOCK_ACQUIRED, lockLock.getA());
-
-        LockResult<GuardResult, TargetLock> lockLockAgain = manager.lockCurrentOperation();
-        assertNotNull(lockLockAgain);
-        assertEquals(GuardResult.LOCK_ACQUIRED, lockLockAgain.getA());
-        assertEquals(lockLock.getB(), lockLockAgain.getB());
-
-        assertEquals(lockLock.getB(), manager.unlockCurrentOperation());
-        assertNull(manager.unlockCurrentOperation());
-
-        lockLock = manager.lockCurrentOperation();
-        assertNotNull(lockLock);
-        PolicyGuard.unlockTarget(lockLock.getB());
-        assertEquals(lockLock.getB(), manager.unlockCurrentOperation());
-
         clom.startOperation(event);
 
         // This call should be exception free
@@ -697,10 +680,98 @@ public class ControlLoopEventManagerTest {
     }
 
     @Test
-    public void testOnNewEvent() throws Exception {
-        InputStream is = new FileInputStream(new File(TEST_YAML));
+    public void testLockCurrentOperation_testUnlockCurrentOperation() throws Exception {
+        VirtualControlLoopEvent event = makeEvent();
+
+        ControlLoopEventManager manager = makeManager(event);
+
+        manager.setActivated(false);
+
+        InputStream is = new FileInputStream(new File("src/test/resources/testSOactor.yaml"));
         final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
 
+        VirtualControlLoopNotification notification = manager.activate(yamlString, event);
+        assertNotNull(notification);
+        assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
+
+        ControlLoopEventManager manager2 = manager;
+        assertThatThrownBy(() -> manager2.lockCurrentOperation(callback)).isInstanceOf(ControlLoopException.class)
+                        .hasMessage("Do not have a current operation.");
+
+        assertNull(manager.unlockCurrentOperation());
+
+        ControlLoopOperationManager clom = manager.processControlLoop();
+        assertNotNull(clom);
+        assertNull(clom.getOperationResult());
+
+        Pair<Lock, Lock> lockPair = manager.lockCurrentOperation(callback);
+        assertNull(lockPair.first());
+        assertNotNull(lockPair.second());
+
+        // pseudo lock - session should NOT have been notified of the change
+        verify(callback, never()).lockAvailable(any());
+        verify(callback, never()).lockUnavailable(any());
+
+        // repeat - should cause an extension
+        Lock lock = lockPair.second();
+        lockPair = manager.lockCurrentOperation(callback);
+
+        /*
+         * even with a pseudo lock, the session should have been notified that it was
+         * extended
+         */
+
+        verify(callback).lockAvailable(lock);
+
+        assertSame(lock, manager.unlockCurrentOperation());
+
+        assertNull(lockPair.first());
+        assertNull(lockPair.second());
+
+        // force it to use a pseudo lock
+        manager.setUseTargetLock(false);
+        lockPair = manager.lockCurrentOperation(callback);
+        assertNull(lockPair.first());
+        assertNotNull(lockPair.second());
+
+        lock = lockPair.second();
+
+        lockPair = manager.lockCurrentOperation(callback);
+        assertNull(lockPair.first());
+        assertNull(lockPair.second());
+
+        // first lock uses a pseudo lock, so it will only update when extended
+        verify(callback).lockAvailable(lock);
+
+        // force it to re-create the lock due to change in resource ID
+        lock = mock(Lock.class);
+        when(lock.getResourceId()).thenReturn("different");
+        Whitebox.setInternalState(manager, TARGET_LOCK_FIELD, lock);
+
+        lockPair = manager.lockCurrentOperation(callback);
+        assertSame(lock, lockPair.first());
+        assertNotNull(lockPair.second());
+
+        lock = lockPair.second();
+
+        lockPair = manager.lockCurrentOperation(callback);
+        assertNull(lockPair.first());
+        assertNull(lockPair.second());
+
+        // first lock uses a pseudo lock, so it won't do an update
+        verify(callback).lockAvailable(lock);
+
+        assertSame(lock, manager.unlockCurrentOperation());
+        assertNull(manager.unlockCurrentOperation());
+
+        // try again - this time don't return the fact handle- no change in count
+        lockPair = manager.lockCurrentOperation(callback);
+        assertNull(lockPair.first());
+        assertNotNull(lockPair.second());
+    }
+
+    @Test
+    public void testOnNewEvent() throws Exception {
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent();
         onsetEvent.setClosedLoopControlName(TWO_ONSET_TEST);
@@ -721,6 +792,10 @@ public class ControlLoopEventManagerTest {
         abatedEvent.getAai().put(VNF_NAME, ONSET_ONE);
 
         ControlLoopEventManager manager = makeManager(onsetEvent);
+
+        InputStream is = new FileInputStream(new File(TEST_YAML));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, onsetEvent);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -816,9 +891,6 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testControlLoopTimeout() throws IOException {
-        InputStream is = new FileInputStream(new File(TEST_YAML));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent();
         onsetEvent.setClosedLoopControlName(TWO_ONSET_TEST);
@@ -833,6 +905,9 @@ public class ControlLoopEventManagerTest {
         assertTrue(0 == manager.getControlLoopTimeout(null));
         assertTrue(120 == manager.getControlLoopTimeout(120));
 
+        InputStream is = new FileInputStream(new File(TEST_YAML));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, onsetEvent);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -842,9 +917,6 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testControlLoopTimeout_ZeroTimeout() throws IOException {
-        InputStream is = new FileInputStream(new File("src/test/resources/test-zero-timeout.yaml"));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent();
         onsetEvent.setClosedLoopControlName(TWO_ONSET_TEST);
@@ -857,6 +929,9 @@ public class ControlLoopEventManagerTest {
 
         ControlLoopEventManager manager = makeManager(onsetEvent);
 
+        InputStream is = new FileInputStream(new File("src/test/resources/test-zero-timeout.yaml"));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, onsetEvent);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -867,9 +942,6 @@ public class ControlLoopEventManagerTest {
 
     @Test
     public void testControlLoopTimeout_NullTimeout() throws IOException {
-        InputStream is = new FileInputStream(new File("src/test/resources/test-null-timeout.yaml"));
-        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
-
         UUID requestId = UUID.randomUUID();
         VirtualControlLoopEvent onsetEvent = new VirtualControlLoopEvent();
         onsetEvent.setClosedLoopControlName(TWO_ONSET_TEST);
@@ -882,6 +954,9 @@ public class ControlLoopEventManagerTest {
 
         ControlLoopEventManager manager = makeManager(onsetEvent);
 
+        InputStream is = new FileInputStream(new File("src/test/resources/test-null-timeout.yaml"));
+        final String yamlString = IOUtils.toString(is, StandardCharsets.UTF_8);
+
         VirtualControlLoopNotification notification = manager.activate(yamlString, onsetEvent);
         assertNotNull(notification);
         assertEquals(ControlLoopNotificationType.ACTIVE, notification.getNotification());
@@ -1258,8 +1333,33 @@ public class ControlLoopEventManagerTest {
         assertNotNull(aaiCqResponse);
     }
 
+    private VirtualControlLoopEvent makeEvent() {
+        UUID requestId = UUID.randomUUID();
+        VirtualControlLoopEvent event = new VirtualControlLoopEvent();
+        event.setClosedLoopControlName(TWO_ONSET_TEST);
+        event.setRequestId(requestId);
+        event.setTarget(VNF_ID);
+        event.setClosedLoopAlarmStart(Instant.now());
+        event.setClosedLoopEventStatus(ControlLoopEventStatus.ONSET);
+        event.setAai(new HashMap<>());
+        event.getAai().put(VNF_ID, ONSET_ONE);
+        return event;
+    }
 
     private ControlLoopEventManager makeManager(VirtualControlLoopEvent event) {
-        return new ControlLoopEventManager(event.getClosedLoopControlName(), event.getRequestId());
+        return new MyManager(event.getClosedLoopControlName(), event.getRequestId());
+    }
+
+    private static class MyManager extends ControlLoopEventManager implements Serializable {
+        private static final long serialVersionUID = 1L;
+
+        public MyManager(String closedLoopControlName, UUID requestId) {
+            super(closedLoopControlName, requestId);
+        }
+
+        @Override
+        protected Lock createRealLock(String targetEntity, UUID requestId, int holdSec, LockCallback callback) {
+            return createPseudoLock(targetEntity, requestId, holdSec, callback);
+        }
     }
 }
diff --git a/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/LockCallbackWorkingMemoryTest.java b/controlloop/common/eventmanager/src/test/java/org/onap/policy/controlloop/eventmanager/LockCallbackWorkingMemoryTest.java
new file mode 100644 (file)
index 0000000..18ab15b
--- /dev/null
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP
+ * ================================================================================
+ * Copyright (C) 2019 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.
+ * 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.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.controlloop.eventmanager;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import org.drools.core.WorkingMemory;
+import org.junit.Before;
+import org.junit.Test;
+import org.kie.api.runtime.rule.FactHandle;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.onap.policy.drools.core.lock.Lock;
+
+public class LockCallbackWorkingMemoryTest {
+    private static final String MY_NAME = "my-name";
+
+    @Mock
+    private WorkingMemory workingMemory;
+
+    @Mock
+    private Lock lock;
+
+    @Mock
+    private FactHandle fact;
+
+    private LockCallbackWorkingMemory callback;
+
+
+    /**
+     * Initializes mocks and creates a call-back.
+     */
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+
+        when(workingMemory.getFactHandle(lock)).thenReturn(fact);
+
+        callback = new LockCallbackWorkingMemory(MY_NAME, workingMemory);
+    }
+
+    @Test
+    public void testLockCallbackWorkingMemory() {
+        assertEquals(MY_NAME, callback.getName());
+        assertSame(workingMemory, callback.getWorkingMemory());
+    }
+
+    @Test
+    public void testLockAvailable() {
+        callback.lockAvailable(lock);
+        verify(workingMemory).update(fact, lock);
+
+        // "remove" from working memory
+        when(workingMemory.getFactHandle(lock)).thenReturn(null);
+        callback.lockAvailable(lock);
+
+        // should be no additional calls
+        verify(workingMemory).update(any(), any());
+    }
+
+    @Test
+    public void testLockUnavailable() {
+        callback.lockUnavailable(lock);
+        verify(workingMemory).update(fact, lock);
+
+        // "remove" from working memory
+        when(workingMemory.getFactHandle(lock)).thenReturn(null);
+        callback.lockUnavailable(lock);
+
+        // should be no additional calls
+        verify(workingMemory).update(any(), any());
+    }
+
+}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/LockCallback.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/LockCallback.java
deleted file mode 100644 (file)
index 2b33e0e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard;
-
-public interface LockCallback {
-
-    public boolean isActive();
-
-    public boolean releaseLock();
-
-}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuard.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/PolicyGuard.java
deleted file mode 100644 (file)
index 90e6e87..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
- * Modifications Copyright (C) 2019 Tech Mahindra
- * ================================================================================
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard;
-
-import java.util.UUID;
-import org.onap.policy.controlloop.policy.TargetType;
-import org.onap.policy.drools.core.lock.PolicyResourceLockManager;
-import org.onap.policy.guard.impl.PnfTargetLock;
-import org.onap.policy.guard.impl.VmTargetLock;
-import org.onap.policy.guard.impl.VnfTargetLock;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class PolicyGuard {
-
-    private static final Logger logger = LoggerFactory.getLogger(PolicyGuard.class);
-    
-    /**
-     * Factory to access various objects.  Can be changed for junit tests.
-     */
-    private static Factory factory = new Factory();
-
-    public static class LockResult<A, B> {
-        private A parameterA;
-        private B parameterB;
-
-        public LockResult(A parameterA, B parameterB) {
-            this.parameterA = parameterA;
-            this.parameterB = parameterB;
-        }
-
-        public A getA() {
-            return parameterA;
-        }
-
-        public B getB() {
-            return parameterB;
-        }
-        
-        public static <A, B> LockResult<A, B> createLockResult(A parameterA, B parameterB) {
-            return new LockResult<>(parameterA, parameterB);
-        }
-    }
-    
-    private PolicyGuard() {
-        // Cannot instantiate this static class
-    }
-
-    /**
-     * Get the factory.
-     * 
-     * @return the factory used to access various objects
-     */
-    protected static Factory getFactory() {
-        return factory;
-    }
-    
-    /**
-     * Sets the factory to be used by junit tests.
-     * @param factory factory
-     */
-    protected static void setFactory(Factory factory) {
-        PolicyGuard.factory = factory;
-    }
-
-    /**
-     * Create a lock.
-     * 
-     * @param targetType the target type
-     * @param targetInstance the target instance
-     * @param requestId the request Id
-     * @return the TargetLock
-     * @throws IllegalArgumentException if an argument is null
-     */
-    public static TargetLock createTargetLock(TargetType targetType, String targetInstance,
-            UUID requestId, LockCallback callback) {
-        switch (targetType) {
-            case PNF:
-                //
-                // Create the Lock object
-                //
-                return new PnfTargetLock(targetType, targetInstance, requestId, callback);
-            case VM:
-                //
-                // Create the Lock object
-                //
-                return new VmTargetLock(targetType, targetInstance, requestId, callback);
-            case VNF:
-                //
-                // Create the Lock object
-                //
-                return new VnfTargetLock(targetType, targetInstance, requestId, callback);
-                
-            case VFMODULE:
-                //
-                // Create the Lock object
-                //
-                return new VnfTargetLock(targetType, targetInstance, requestId, callback);
-            default:
-                logger.error("invalid target type {} for lock on {}", targetType, targetInstance);
-                return null;
-        }
-    }
-
-    /**
-     * Lock a target.
-     * 
-     * @param targetType the target type
-     * @param targetInstance the target instance
-     * @param requestId the request Id
-     * @param callback the LockCallback
-     * @param holdSec maximum number of seconds to hold the lock
-     * @return the LockResult
-     * @throws IllegalArgumentException if an argument is null
-     */
-    public static LockResult<GuardResult, TargetLock> lockTarget(TargetType targetType, String targetInstance,
-            UUID requestId, LockCallback callback, int holdSec) {
-        String owner = makeOwner(targetType, requestId);
-        boolean result = factory.getManager().lock(targetInstance, owner, holdSec);
-        if (!result) {
-            return LockResult.createLockResult(GuardResult.LOCK_DENIED, null);
-        }
-
-        TargetLock lock = createTargetLock(targetType, targetInstance, requestId, callback);
-        if (lock == null) {
-            //
-            // Bad lock type: unlock and return exception result
-            // 
-            factory.getManager().unlock(targetInstance, owner);
-            return LockResult.createLockResult(GuardResult.LOCK_EXCEPTION, null);
-        } else {
-            //
-            // Return result
-            //
-            logger.debug("Locked {}", lock);
-            return LockResult.createLockResult(GuardResult.LOCK_ACQUIRED, lock);
-        }
-    }
-        
-    /**
-     * Extends a lock on a target.
-     * @param lock      current lock
-     * @param holdSec maximum number of seconds to hold the lock
-     * @return the result: acquired or denied
-     */
-    public static GuardResult lockTarget(TargetLock lock, int holdSec) {
-        String owner = makeOwner(lock.getTargetType(), lock.getRequestId());
-        
-        boolean result = factory.getManager().refresh(lock.getTargetInstance(), owner, holdSec);
-        
-        logger.debug("Lock {} extend {}", lock, result);
-        return (result ? GuardResult.LOCK_ACQUIRED : GuardResult.LOCK_DENIED);
-    }
-
-    /**
-     * Unlock a target.
-     * 
-     * @param lock the target lock to unlock
-     * @return <code>true</code> if the target is successfully unlocked, <code>false</code>
-     *         otherwise
-     * @throws IllegalArgumentException if an argument is null
-     */
-    public static boolean unlockTarget(TargetLock lock) {
-        String owner = makeOwner(lock.getTargetType(), lock.getRequestId());
-        boolean result = factory.getManager().unlock(lock.getTargetInstance(), owner);
-        
-        if (result) {
-            logger.debug("Unlocked {}", lock);
-            return true;            
-        }
-        
-        return false;
-    }
-
-    /**
-     * Check if a target is locked.
-     * 
-     * @param targetType the target type
-     * @param targetInstance the target instance
-     * @param requestId the request Id
-     * @return <code>true</code> if the target is locked, <code>false</code> otherwise
-     * @throws IllegalArgumentException if an argument is null
-     */
-    public static boolean isLocked(TargetType targetType, String targetInstance, UUID requestId) {
-        String owner = makeOwner(targetType, requestId);
-        return factory.getManager().isLockedBy(targetInstance, owner);
-    }
-
-    /**
-     * Combines the target type and request ID to yield a single, "owner" string.
-     * @param targetType target type
-     * @param requestID request id
-     * @return the "owner" of a resource
-     * @throws IllegalArgumentException if either argument is null
-     */
-    private static String makeOwner(TargetType targetType, UUID requestId) {
-        if (targetType == null) {
-            throw new IllegalArgumentException("null targetType for lock request id " + requestId);
-        }
-
-        if (requestId == null) {
-            throw new IllegalArgumentException("null requestID for lock type " + targetType);
-        }
-        
-        return targetType + ":" + requestId;
-    }
-    
-    /**
-     * Factory to access various objects.
-     */
-    public static class Factory {
-
-        /**
-         * Get the manager.
-         * 
-         * @return the lock manager to be used
-         */
-        public PolicyResourceLockManager getManager() {
-            return PolicyResourceLockManager.getInstance();
-        }
-    }
-}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/TargetLock.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/TargetLock.java
deleted file mode 100644 (file)
index eea46c3..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2017, 2019 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard;
-
-import java.util.UUID;
-
-import org.onap.policy.controlloop.policy.TargetType;
-
-public interface TargetLock {
-
-    public UUID getLockId();
-
-    public TargetType getTargetType();
-
-    public String getTargetInstance();
-
-    public UUID getRequestId();
-
-}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/PnfTargetLock.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/PnfTargetLock.java
deleted file mode 100644 (file)
index 8ddb5ff..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2017-2019 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard.impl;
-
-import java.util.UUID;
-import org.onap.policy.controlloop.policy.TargetType;
-import org.onap.policy.guard.LockCallback;
-
-public class PnfTargetLock extends TargetLockImpl {
-
-    private static final long serialVersionUID = 2335897394577202732L;
-
-    /**
-     * Construct an instance.
-     *
-     * @param type the target type
-     * @param target the target
-     * @param requestId the request Id
-     * @param callback the callback
-     */
-    public PnfTargetLock(TargetType type, String target, UUID requestId, LockCallback callback) {
-        super(type, target, requestId, callback);
-    }
-
-    @Override
-    public String toString() {
-        return "PnfTargetLock [" + super.toString() + "]";
-    }
-}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/TargetLockImpl.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/TargetLockImpl.java
deleted file mode 100644 (file)
index d406999..0000000
+++ /dev/null
@@ -1,86 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2019 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard.impl;
-
-import java.io.Serializable;
-import java.util.UUID;
-
-import org.onap.policy.controlloop.policy.TargetType;
-import org.onap.policy.guard.LockCallback;
-import org.onap.policy.guard.TargetLock;
-
-public class TargetLockImpl implements TargetLock, Serializable {
-
-    private static final long serialVersionUID = 2335897394577202732L;
-
-    private final UUID lockId;
-    private final TargetType targetType;
-    private final String target;
-    private final UUID requestId;
-    private final transient LockCallback callback;
-
-    /**
-     * Construct an instance.
-     *
-     * @param type the target type
-     * @param target the target
-     * @param requestId the request Id
-     * @param callback the callback
-     */
-    public TargetLockImpl(TargetType type, String target, UUID requestId, LockCallback callback) {
-        this.lockId = UUID.randomUUID();
-        this.targetType = type;
-        this.target = target;
-        this.requestId = requestId;
-        this.callback = callback;
-    }
-
-    @Override
-    public UUID getLockId() {
-        return this.lockId;
-    }
-
-
-    @Override
-    public TargetType getTargetType() {
-        return targetType;
-    }
-
-    @Override
-    public String getTargetInstance() {
-        return target;
-    }
-
-    @Override
-    public UUID getRequestId() {
-        return this.requestId;
-    }
-
-    public LockCallback getCallback() {
-        return this.callback;
-    }
-
-    @Override
-    public String toString() {
-        return "lockId=" + lockId + ", targetType=" + targetType + ", target=" + target + ", requestId="
-                + requestId;
-    }
-}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/VmTargetLock.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/VmTargetLock.java
deleted file mode 100644 (file)
index 2e612a0..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2017-2019 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard.impl;
-
-import java.util.UUID;
-import org.onap.policy.controlloop.policy.TargetType;
-import org.onap.policy.guard.LockCallback;
-
-public class VmTargetLock extends TargetLockImpl {
-
-    private static final long serialVersionUID = 2335897394577202732L;
-
-    /**
-     * Construct an instance.
-     *
-     * @param type the target type
-     * @param target the target
-     * @param requestId the request Id
-     * @param callback the callback
-     */
-    public VmTargetLock(TargetType type, String target, UUID requestId, LockCallback callback) {
-        super(type, target, requestId, callback);
-    }
-
-    @Override
-    public String toString() {
-        return "VmTargetLock [" + super.toString() + "]";
-    }
-}
diff --git a/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/VnfTargetLock.java b/controlloop/common/guard/src/main/java/org/onap/policy/guard/impl/VnfTargetLock.java
deleted file mode 100644 (file)
index 2912c7a..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2017-2019 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard.impl;
-
-import java.util.UUID;
-import org.onap.policy.controlloop.policy.TargetType;
-import org.onap.policy.guard.LockCallback;
-
-public class VnfTargetLock extends TargetLockImpl {
-
-    private static final long serialVersionUID = 2335897394577202732L;
-
-    /**
-     * Construct an instance.
-     *
-     * @param type the target type
-     * @param target the target
-     * @param requestId the request Id
-     * @param callback the callback
-     */
-    public VnfTargetLock(TargetType type, String target, UUID requestId, LockCallback callback) {
-        super(type, target, requestId, callback);
-    }
-
-    @Override
-    public String toString() {
-        return "VnfTargetLock [" + super.toString() + "]";
-    }
-}
diff --git a/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardTest.java b/controlloop/common/guard/src/test/java/org/onap/policy/guard/PolicyGuardTest.java
deleted file mode 100644 (file)
index 5f77d03..0000000
+++ /dev/null
@@ -1,335 +0,0 @@
-/*-
- * ============LICENSE_START=======================================================
- * guard
- * ================================================================================
- * Copyright (C) 2017-2019 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.
- * 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.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END=========================================================
- */
-
-package org.onap.policy.guard;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.UUID;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.onap.policy.controlloop.policy.TargetType;
-import org.onap.policy.drools.core.lock.PolicyResourceLockManager;
-import org.onap.policy.guard.PolicyGuard.Factory;
-import org.onap.policy.guard.PolicyGuard.LockResult;
-import org.onap.policy.guard.impl.PnfTargetLock;
-import org.onap.policy.guard.impl.VmTargetLock;
-import org.onap.policy.guard.impl.VnfTargetLock;
-
-public class PolicyGuardTest {
-    private static final String INSTANCENAME = "targetInstance";
-    private static final int LOCK_SEC = 10;
-
-    private static Factory saveFactory;
-
-    private Factory factory;
-    private PolicyResourceLockManager mgr;
-    private UUID uuid;
-    private DummyLockCallback dlcb;
-
-    private class DummyLockCallback implements LockCallback {
-        @Override
-        public boolean isActive() {
-            return false;
-        }
-
-        @Override
-        public boolean releaseLock() {
-            return false;
-        }
-    }
-
-    private class DummyTargetLock implements TargetLock {
-        private TargetType type;
-        private UUID reqid;
-
-        public DummyTargetLock(TargetType type, UUID reqid) {
-            this.type = type;
-            this.reqid = reqid;
-        }
-
-        @Override
-        public UUID getLockId() {
-            return null;
-        }
-
-        @Override
-        public TargetType getTargetType() {
-            return type;
-        }
-
-        @Override
-        public String getTargetInstance() {
-            return INSTANCENAME;
-        }
-
-        @Override
-        public UUID getRequestId() {
-            return reqid;
-        }
-    }
-
-    @BeforeClass
-    public static void setUpBeforeClass() {
-        saveFactory = PolicyGuard.getFactory();
-    }
-
-    @AfterClass
-    public static void tearDownAfterClass() {
-        PolicyGuard.setFactory(saveFactory);
-    }
-
-    /**
-     * Setup method.
-     */
-    @Before
-    public void setUp() {
-        mgr = spy(new PolicyResourceLockManager() {
-            /*
-             * we want each test to have its own lock manager, but the constructor for the
-             * manager is protected; this gets around that
-             */
-        });
-
-        factory = mock(Factory.class);
-        when(factory.getManager()).thenReturn(mgr);
-
-        uuid = UUID.randomUUID();
-        dlcb = new DummyLockCallback();
-
-        PolicyGuard.setFactory(factory);
-    }
-
-    @Test
-    public void testLockVm() {
-        TargetType type = TargetType.VM;
-
-        // Test isLocked before and after lock added
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-        LockResult<GuardResult, TargetLock> result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        assertTrue(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(VmTargetLock.class, result.getB().getClass());
-
-        VmTargetLock vtl = (VmTargetLock) result.getB();
-        assertNotNull(vtl.getLockId());
-        assertEquals(INSTANCENAME, vtl.getTargetInstance());
-        assertEquals(TargetType.VM, vtl.getTargetType());
-        assertNotNull(vtl.getRequestId());
-        assertEquals(dlcb, vtl.getCallback());
-
-        // Test isLocked after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-    }
-
-    @Test
-    public void testLockPnf() {
-        TargetType type = TargetType.PNF;
-
-        // Test isLocked before and after lock added
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-        LockResult<GuardResult, TargetLock> result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        assertTrue(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(PnfTargetLock.class, result.getB().getClass());
-
-        PnfTargetLock ptl = (PnfTargetLock) result.getB();
-        assertNotNull(ptl.getLockId());
-        assertEquals(INSTANCENAME, ptl.getTargetInstance());
-        assertEquals(TargetType.PNF, ptl.getTargetType());
-        assertNotNull(ptl.getRequestId());
-        assertEquals(dlcb, ptl.getCallback());
-
-        // Test isLocked after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-    }
-
-
-    @Test
-    public void testLockVnf() {
-        TargetType type = TargetType.VNF;
-
-        // Test isLocked before and after lock added
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-        LockResult<GuardResult, TargetLock> result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        assertTrue(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(VnfTargetLock.class, result.getB().getClass());
-
-        VnfTargetLock vtl = (VnfTargetLock) result.getB();
-        assertNotNull(vtl.getLockId());
-        assertEquals(INSTANCENAME, vtl.getTargetInstance());
-        assertEquals(TargetType.VNF, vtl.getTargetType());
-        assertNotNull(vtl.getRequestId());
-        assertEquals(dlcb, vtl.getCallback());
-
-        // Test isLocked after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-    }
-
-    @Test
-    public void testLockVfc() {
-        TargetType type = TargetType.VFC;
-
-        // Test isLocked before and after lock added
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-        LockResult<GuardResult, TargetLock> result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_EXCEPTION, result.getA());
-        assertNull(result.getB());
-
-        // Test isLocked after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-    }
-
-    @Test
-    public void testUnLockNotLocked() {
-        TargetType type = TargetType.VM;
-
-        // Test isLocked before and after lock added
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-        LockResult<GuardResult, TargetLock> result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        assertTrue(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(VmTargetLock.class, result.getB().getClass());
-
-        // Test isLocked after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        // Test unlock after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-    }
-
-    @Test
-    public void testLockAlreadyLocked() {
-        TargetType type = TargetType.VM;
-
-        // Test isLocked before and after lock added
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-        LockResult<GuardResult, TargetLock> result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        assertTrue(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(VmTargetLock.class, result.getB().getClass());
-
-        UUID uuid2 = UUID.randomUUID();
-        result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid2, dlcb, LOCK_SEC);
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid2));
-
-        assertTrue(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-
-        assertEquals(GuardResult.LOCK_DENIED, result.getA());
-        assertNull(result.getB());
-
-        // Test isLocked after lock removed
-        PolicyGuard.unlockTarget(new DummyTargetLock(type, uuid));
-        assertFalse(PolicyGuard.isLocked(type, INSTANCENAME, uuid));
-    }
-
-    @Test
-    public void testInnards() {
-        TargetType type = TargetType.VM;
-
-        assertFalse(dlcb.isActive());
-        assertFalse(dlcb.releaseLock());
-
-        DummyTargetLock dtl = new DummyTargetLock(type, uuid);
-        assertNull(dtl.getLockId());
-        assertEquals(uuid, dtl.getRequestId());
-        assertEquals(INSTANCENAME, dtl.getTargetInstance());
-        assertEquals(type, dtl.getTargetType());
-    }
-
-    @Test
-    public void testLockTargetTargetTypeStringUuidLockCallbackInt() {
-        TargetType type = TargetType.VM;
-
-        LockResult<GuardResult, TargetLock> result;
-
-        // acquired
-        result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        verify(mgr).lock(INSTANCENAME, type + ":" + uuid, LOCK_SEC);
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(VmTargetLock.class, result.getB().getClass());
-
-        // diff owner - denied
-        UUID uuid2 = UUID.randomUUID();
-        result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid2, dlcb, LOCK_SEC + 10);
-        verify(mgr).lock(INSTANCENAME, type + ":" + uuid2, LOCK_SEC + 10);
-        assertEquals(GuardResult.LOCK_DENIED, result.getA());
-        assertNull(result.getB());
-    }
-
-    @Test
-    public void testLockTargetTargetLockInt() {
-        TargetType type = TargetType.VM;
-
-        LockResult<GuardResult, TargetLock> result;
-
-        // acquired
-        result = PolicyGuard.lockTarget(type, INSTANCENAME, uuid, dlcb, LOCK_SEC);
-        verify(mgr).lock(INSTANCENAME, type + ":" + uuid, LOCK_SEC);
-        assertEquals(GuardResult.LOCK_ACQUIRED, result.getA());
-        assertEquals(VmTargetLock.class, result.getB().getClass());
-
-        TargetLock lock = result.getB();
-
-        // refresh - re-acquired
-        assertEquals(GuardResult.LOCK_ACQUIRED, PolicyGuard.lockTarget(lock, LOCK_SEC + 1));
-        verify(mgr).refresh(INSTANCENAME, type + ":" + uuid, LOCK_SEC + 1);
-
-        // unlock
-        PolicyGuard.unlockTarget(lock);
-
-        // refresh - denied, as we no longer own the lock
-        assertEquals(GuardResult.LOCK_DENIED, PolicyGuard.lockTarget(lock, LOCK_SEC + 2));
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testMakeOwner_NullTargetType() {
-        PolicyGuard.isLocked(null, INSTANCENAME, uuid);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testMakeOwner_NullReqId() {
-        PolicyGuard.isLocked(TargetType.PNF, INSTANCENAME, null);
-    }
-}
index 4cbdd49..cfd1877 100644 (file)
@@ -8,9 +8,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.
@@ -34,6 +34,7 @@ import org.onap.policy.controlloop.policy.Policy;
 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager;
 import org.onap.policy.controlloop.eventmanager.ControlLoopEventManager.NewEventStatus;
 import org.onap.policy.controlloop.eventmanager.ControlLoopOperationManager;
+import org.onap.policy.controlloop.eventmanager.LockCallbackWorkingMemory;
 import org.onap.policy.controlloop.actor.so.SoActorServiceProvider;
 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider;
 import org.onap.policy.controlloop.actor.cds.CdsActorServiceProvider.CdsActorServiceManager;
@@ -51,6 +52,7 @@ import org.onap.policy.appclcm.LcmCommonHeader;
 import org.onap.policy.cds.CdsResponse;
 import org.onap.policy.cds.client.CdsProcessorGrpcClient;
 import org.onap.policy.cds.properties.CdsServerProperties;
+import org.onap.policy.drools.utils.Pair;
 import org.onap.policy.sdnr.PciRequestWrapper;
 import org.onap.policy.sdnr.PciResponseWrapper;
 import org.onap.policy.sdnr.PciRequest;
@@ -64,10 +66,7 @@ import org.onap.policy.so.SoResponseWrapper;
 import org.onap.policy.sdnc.SdncRequest;
 import org.onap.policy.sdnc.SdncManager;
 import org.onap.policy.sdnc.SdncResponse;
-import org.onap.policy.guard.PolicyGuard;
-import org.onap.policy.guard.PolicyGuard.LockResult;
-import org.onap.policy.guard.TargetLock;
-import org.onap.policy.guard.GuardResult;
+import org.onap.policy.drools.core.lock.Lock;
 import org.onap.policy.guard.PolicyGuardRequest;
 import org.onap.policy.guard.PolicyGuardResponse;
 import org.onap.policy.guard.PolicyGuardXacmlRequestAttributes;
@@ -144,24 +143,24 @@ end
 rule "${policyName}.SETUP"
     salience 1
     when
-        not( Params( getClosedLoopControlName() == "${closedLoopControlName}", 
+        not( Params( getClosedLoopControlName() == "${closedLoopControlName}",
             getControlLoopYaml() == "${controlLoopYaml}" ) )
     then
-    
+
     Params params = new Params();
     params.setClosedLoopControlName("${closedLoopControlName}");
     params.setControlLoopYaml("${controlLoopYaml}");
     insert(params);
-    
+
     ParamsInitCleaner initCleaner = new ParamsInitCleaner();
     initCleaner.setClosedLoopControlName("${closedLoopControlName}");
     insert(initCleaner);
 
     // Note: globals have bad behavior when persistence is used,
     //       hence explicitly getting the logger vs using a global
-    
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {} : YAML=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(), 
+    logger.info("{}: {} : YAML=[{}]", params.getClosedLoopControlName(), drools.getRule().getName(),
         params.getControlLoopYaml());
 end
 
@@ -175,15 +174,15 @@ rule "${policyName}.EVENT"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
-        not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        not ( ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() ) )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    
+
     try {
-      
+
         //
         // Check the event, because we need it to not be null when
         // we create the ControlLoopEventManager. The ControlLoopEventManager
@@ -197,12 +196,12 @@ rule "${policyName}.EVENT"
             notification.setPolicyName(drools.getRule().getName());
             notification.setPolicyScope("${policyScope}");
             notification.setPolicyVersion("${policyVersion}");
-            
+
             //
             // Let interested parties know
             //
             PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
-            
+
             //
             // Retract it from memory
             //
@@ -213,10 +212,10 @@ rule "${policyName}.EVENT"
             //
             // Create an EventManager
             //
-            ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(), 
+            ControlLoopEventManager manager = new ControlLoopEventManager($params.getClosedLoopControlName(),
                 $event.getRequestId());
             //
-            // Determine if EventManager can actively process the event 
+            // Determine if EventManager can actively process the event
             // (i.e. syntax, is_closed_loop_disabled checks etc.)
             //
             VirtualControlLoopNotification notification = manager.activate($params.getControlLoopYaml(), $event);
@@ -258,7 +257,7 @@ rule "${policyName}.EVENT"
                 //
                 retract($event);
             }
-            
+
             //
             // Now that the manager is inserted into Drools working memory, we'll wait for
             // another rule to fire in order to continue processing. This way we can also
@@ -267,7 +266,7 @@ rule "${policyName}.EVENT"
         }
     } catch (Exception e) {
         logger.warn("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName(), e);
-        
+
         VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
         notification.setNotification(ControlLoopNotificationType.REJECTED);
         notification.setMessage("Exception occurred: " + e.getMessage());
@@ -295,17 +294,17 @@ rule "${policyName}.EVENT.MANAGER"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "ClosedLoop", !expired )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {}: event={} manager={} clTimer={}", 
+    logger.info("{}: {}: event={} manager={} clTimer={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
                 $event, $manager, $clTimer);
-    
+
     try {
         //
         // Check which event this is.
@@ -318,7 +317,7 @@ rule "${policyName}.EVENT.MANAGER"
             //
             // We don't care about subsequent onsets
             //
-            logger.info("{}: {}: subsequent onset", 
+            logger.info("{}: {}: subsequent onset",
                         $params.getClosedLoopControlName(), drools.getRule().getName());
             retract($event);
             return;
@@ -327,7 +326,7 @@ rule "${policyName}.EVENT.MANAGER"
             //
             // Ignore any bad syntax events
             //
-            logger.warn("{}: {}: syntax error", 
+            logger.warn("{}: {}: syntax error",
                         $params.getClosedLoopControlName(), drools.getRule().getName());
             retract($event);
             return;
@@ -338,12 +337,12 @@ rule "${policyName}.EVENT.MANAGER"
         // cleanup and avoid the other rules being fired for this event.
         //
         if (eventStatus != NewEventStatus.FIRST_ONSET) {
-            logger.warn("{}: {}: not first onset", 
+            logger.warn("{}: {}: not first onset",
                         $params.getClosedLoopControlName(), drools.getRule().getName());
             retract($event);
         }
-        
-        logger.debug("{}: {}: target={}", $params.getClosedLoopControlName(), 
+
+        logger.debug("{}: {}: target={}", $params.getClosedLoopControlName(),
                      drools.getRule().getName(), $event.getTarget());
         //
         // Now start seeing if we need to process this event
@@ -353,20 +352,20 @@ rule "${policyName}.EVENT.MANAGER"
         // Check if this is a Final Event
         //
         VirtualControlLoopNotification notification = $manager.isControlLoopFinal();
-    
-    
+
+
         if (notification != null) {
             //
             // Its final, but are we waiting for abatement?
             //
             if ($manager.getNumAbatements() > 0) {
-                logger.info("{}: {}: abatement received for {}.  Closing the control loop", 
-                            $params.getClosedLoopControlName(), drools.getRule().getName(), 
+                logger.info("{}: {}: abatement received for {}.  Closing the control loop",
+                            $params.getClosedLoopControlName(), drools.getRule().getName(),
                             $event.getRequestId());
-                
+
                 /// DB Write---end event processing for this RequestId()
                 $manager.commitAbatement("Event Abated","Closed");
-                
+
                 notification.setFrom("policy");
                 notification.setPolicyName(drools.getRule().getName());
                 notification.setPolicyScope("${policyScope}");
@@ -378,22 +377,22 @@ rule "${policyName}.EVENT.MANAGER"
                 //
                 // Unlock the target
                 //
-                TargetLock lock = $manager.unlockCurrentOperation();
-                if (lock != null) {
-                    logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(), 
-                                 drools.getRule().getName(), lock);
+                Lock lock = $manager.unlockCurrentOperation();
+                if(lock != null) {
+                    logger.debug("{}: {}: retracting lock={}", $params.getClosedLoopControlName(),
+                                drools.getRule().getName(), lock);
                     retract(lock);
                 }
                 //
                 // Retract everything from memory
                 //
-                logger.info("{}: {}: retracting onset, manager, and timer", 
+                logger.info("{}: {}: retracting onset, manager, and timer",
                             $params.getClosedLoopControlName(), drools.getRule().getName());
-                
+
                 retract($manager.getOnsetEvent());
-                
+
                 // don't retract manager, etc. - a clean-up rule will do that
-                
+
                 //
                 // TODO - what if we get subsequent Events for this RequestId?
                 // By default, it will all start over again. May be confusing for Ruby.
@@ -404,18 +403,18 @@ rule "${policyName}.EVENT.MANAGER"
                 // Check whether we need to wait for abatement
                 //
                 if ($manager.getProcessor().getControlLoop().getAbatement() == true && notification.getNotification() == ControlLoopNotificationType.FINAL_SUCCESS) {
-                  logger.info("{}: {}: waiting for abatement ..", 
+                  logger.info("{}: {}: waiting for abatement ..",
                               $params.getClosedLoopControlName(), drools.getRule().getName());
                 } else {
-                  logger.info("{}: {}: no abatement expect for {}.  Closing the control loop", 
-                              $params.getClosedLoopControlName(), drools.getRule().getName(), 
+                  logger.info("{}: {}: no abatement expect for {}.  Closing the control loop",
+                              $params.getClosedLoopControlName(), drools.getRule().getName(),
                               $event.getRequestId());
-                  
+
                   notification.setFrom("policy");
                   notification.setPolicyName(drools.getRule().getName());
                   notification.setPolicyScope("${policyScope}");
                   notification.setPolicyVersion("${policyVersion}");
-                  
+
                   //
                   // In this case, we are done
                   //
@@ -423,20 +422,20 @@ rule "${policyName}.EVENT.MANAGER"
                   //
                   // Unlock the target
                   //
-                  TargetLock lock = $manager.unlockCurrentOperation();
-                  if (lock != null) {
-                      logger.debug("{}: {}: retracting lock=", $params.getClosedLoopControlName(), 
+                  Lock lock = $manager.unlockCurrentOperation();
+                  if(lock != null) {
+                      logger.debug("{}: {}: retracting lock={}", $params.getClosedLoopControlName(),
                                   drools.getRule().getName(), lock);
                       retract(lock);
                   }
                   //
                   // Retract everything from memory
                   //
-                  logger.info("{}: {}: retracting onset, manager, and timer", 
+                  logger.info("{}: {}: retracting onset, manager, and timer",
                               $params.getClosedLoopControlName(), drools.getRule().getName());
-                  
+
                   retract($manager.getOnsetEvent());
-                
+
                 // don't retract manager, etc. - a clean-up rule will do that
                 }
             }
@@ -449,66 +448,49 @@ rule "${policyName}.EVENT.MANAGER"
               //
               // Let's ask for a lock right away
               //
-              LockResult<GuardResult, TargetLock> result = $manager.lockCurrentOperation();
-              logger.info("{}: {}: guard lock acquired={}", 
-                            $params.getClosedLoopControlName(), drools.getRule().getName(), 
-                            result.getB());
-              if (result.getA().equals(GuardResult.LOCK_ACQUIRED)) {
-                  //
-                  // insert the operation into memory
-                  //
-                  insert(operation);
-                  //
-                  // insert operation timeout object
-                  //
-                  ControlLoopTimer opTimer = new ControlLoopTimer();
-                  opTimer.setTimerType("Operation");
-                  opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
-                  opTimer.setRequestId($event.getRequestId().toString());
-                  Integer timeout = operation.getOperationTimeout();
-                  opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
-                  insert(opTimer);
-              
-                  //
-                  // Insert lock into memory
-                  //
-                  insert(result.getB());
-              } else {
-                  logger.debug("The target resource {} is already processing",
-                            $event.getAai().get($event.getTarget()));
-                  notification = new VirtualControlLoopNotification($event);
-                  notification.setNotification(ControlLoopNotificationType.REJECTED);
-                  notification.setMessage("The target " + $event.getAai().get($event.getTarget()) 
-                      + " is already locked");
-                  notification.setFrom("policy");
-                  notification.setPolicyName(drools.getRule().getName());
-                  notification.setPolicyScope("${policyScope}");
-                  notification.setPolicyVersion("${policyVersion}");
-      
-                  PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
+              logger.info("{}: {}: requesting lock for operation={}",
+                            $params.getClosedLoopControlName(), drools.getRule().getName(),
+                            operation);
+
+              Pair<Lock,Lock> oldNew = $manager.lockCurrentOperation(
+                        new LockCallbackWorkingMemory($params.getClosedLoopControlName(), drools.getWorkingMemory()));
+              if(oldNew.first() != null) {
+                  logger.debug("{}: {}: retracting lock={}", $params.getClosedLoopControlName(),
+                              drools.getRule().getName(), oldNew.first());
+                  retract(oldNew.first());
+              }
+              if(oldNew.second() != null) {
+                  logger.debug("{}: {}: inserting lock={}", $params.getClosedLoopControlName(),
+                              drools.getRule().getName(), oldNew.second());
+                  insert(oldNew.second());
+              }
 
-                  retract($event);
-                
-                  // don't retract manager, etc. - a clean-up rule will do that
+              //
+              // insert the operation into memory
+              //
+              insert(operation);
+              //
+              // insert operation timeout object
+              //
+              ControlLoopTimer opTimer = new ControlLoopTimer();
+              opTimer.setTimerType("Operation");
+              opTimer.setClosedLoopControlName($event.getClosedLoopControlName());
+              opTimer.setRequestId($event.getRequestId().toString());
+              Integer timeout = operation.getOperationTimeout();
+              opTimer.setDelay(timeout > 0 ? timeout.toString() + "s" : $clTimer.getDelay());
+              insert(opTimer);
 
-                  if (result.getB() != null) {
-                      retract(result.getB());
-                  }
-              }
-              logger.info("{}: {}: starting operation={}", 
-                          $params.getClosedLoopControlName(), drools.getRule().getName(), 
-                          operation);
             } else {
                 //
                 // Probably waiting for abatement
                 //
-              logger.info("{}: {}: no operation, probably waiting for abatement", 
+              logger.info("{}: {}: no operation, probably waiting for abatement",
                           $params.getClosedLoopControlName(), drools.getRule().getName());
             }
         }
     } catch (Exception e) {
-         logger.warn("{}: {}: unexpected", 
-                  $params.getClosedLoopControlName(), 
+         logger.warn("{}: {}: unexpected",
+                  $params.getClosedLoopControlName(),
                   drools.getRule().getName(), e);
 
          VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
@@ -518,14 +500,53 @@ rule "${policyName}.EVENT.MANAGER"
          notification.setPolicyName(drools.getRule().getName());
          notification.setPolicyScope("${policyScope}");
          notification.setPolicyVersion("${policyVersion}");
-  
+
          PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
 
          retract($event);
-                
+
          // don't retract manager, etc. - a clean-up rule will do that
     }
-        
+
+end
+
+/*
+*
+* Lock denied
+*
+*/
+rule "${policyName}.EVENT.MANAGER.OPERATION.LOCK.DENIED"
+    when
+        $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
+            requestId == $event.getRequestId() )
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
+            onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
+        $lock : Lock (ownerKey == $event.getRequestId().toString(), isUnavailable())
+    then
+
+    Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
+    logger.info("{}: {}: event={} manager={} operation={} lock={}",
+                $params.getClosedLoopControlName(), drools.getRule().getName(),
+                $event, $manager, $operation, $lock);
+
+    logger.debug("The target resource {} is already processing",
+                        $event.getAai().get($event.getTarget()));
+    VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
+    notification.setNotification(ControlLoopNotificationType.REJECTED);
+    notification.setMessage("The target " + $event.getAai().get($event.getTarget())
+                        + " is already locked");
+    notification.setFrom("policy");
+    notification.setPolicyName(drools.getRule().getName());
+    notification.setPolicyScope("${policyScope}");
+    notification.setPolicyVersion("${policyVersion}");
+
+    PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
+
+    retract($event);
+
+    // don't retract manager, etc. - a clean-up rule will do that
 end
 
 /*
@@ -537,28 +558,27 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId(), "Permit".equalsIgnoreCase(getGuardApprovalStatus()) )
-        $lock : TargetLock (requestId == $event.getRequestId())
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {}: event={} manager={} operation={} lock={}", 
+    logger.info("{}: {}: event={} manager={} operation={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
-                $event, $manager, $operation, $lock);    
+                $event, $manager, $operation);
 
     Object request = null;
     boolean caughtException = false;
-    
+
     try {
         request = $operation.startOperation($event);
-        
+
         if (request != null) {
-          logger.debug("{}: {}: starting operation ..", 
+          logger.debug("{}: {}: starting operation ..",
                        $params.getClosedLoopControlName(), drools.getRule().getName());
           //
           // Tell interested parties we are performing this Operation
@@ -585,19 +605,19 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                   }
                   break;
               case "SO":
-                  // at this point the AAI named query request should have already been made, 
+                  // at this point the AAI named query request should have already been made,
                   // the response recieved and used
                   // in the construction of the SO Request which is stored in operationRequest
 
                   if(request instanceof SoRequest) {
-                      // Call SO. The response will be inserted into memory once it's received 
+                      // Call SO. The response will be inserted into memory once it's received
                       class mySoCallback implements SoManager.SoCallback {
                           public void onSoResponseWrapper(SoResponseWrapper wrapper) {
                               drools.getWorkingMemory().insert(wrapper);
                           }
                       }
-                      SoActorServiceProvider.sendRequest($event.getRequestId().toString(), 
-                          new mySoCallback(), 
+                      SoActorServiceProvider.sendRequest($event.getRequestId().toString(),
+                          new mySoCallback(),
                           request,
                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.url"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("so.username"),
@@ -608,7 +628,7 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                   if (request instanceof VfcRequest) {
                       // Start VFC thread
                       class myVfcCallback implements VfcManager.VfcCallback {
-                          
+
                           public void onResponse(VfcResponse responseError) {
                               drools.getWorkingMemory().insert(responseError);
                           }
@@ -620,9 +640,9 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                           PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.username"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("vfc.password")));
                       t.start();
-                  }          
+                  }
                   break;
-                
+
               case "SDNC":
                   if (request instanceof SdncRequest) {
                      // Start SDNC thread
@@ -630,16 +650,16 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                           public void onCallback(SdncResponse response) {
                               drools.getWorkingMemory().insert(response);
                           }
-                      }  
+                      }
                       // Start SDNC thread
-                      Thread t = new Thread(new SdncManager(new mySdncCallback(), 
+                      Thread t = new Thread(new SdncManager(new mySdncCallback(),
                           (SdncRequest)request,
                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.url"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.username"),
                           PolicyEngineConstants.getManager().getEnvironmentProperty("sdnc.password")));
                       t.start();
                   }
-                  break;                       
+                  break;
               case "SDNR":
                   if (request instanceof PciRequestWrapper) {
                       PolicyEngineConstants.getManager().deliver("SDNR-CL", request);
@@ -678,8 +698,8 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
           //
           // What happens if its null?
           //
-            logger.warn("{}: {}: unexpected null operation request", 
-                      $params.getClosedLoopControlName(), 
+            logger.warn("{}: {}: unexpected null operation request",
+                      $params.getClosedLoopControlName(),
                       drools.getRule().getName());
             if ("SO".equals($operation.policy.getActor())) {
                 retract($opTimer);
@@ -697,14 +717,14 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
                 modify($manager) {finishOperation($operation)};
             }
         }
-        
+
     } catch (Exception e) {
         String msg = e.getMessage();
-        logger.warn("{}: {}: operation={}:  AAI failure: {}", 
+        logger.warn("{}: {}: operation={}:  AAI failure: {}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
                     $operation, msg, e);
         $operation.setOperationHasException(msg);
-        
+
         if(request != null) {
             //
             // Create a notification for it ("DB Write - end operation")
@@ -717,15 +737,15 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_PERMITTED"
             notification.setNotification(ControlLoopNotificationType.OPERATION_FAILURE);
             notification.setMessage($operation.getOperationHistory());
             notification.setHistory($operation.getHistory());
-          
+
             PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
         }
-    
+
         retract($opTimer);
         retract($operation);
         caughtException = true;
     }
-    
+
     // Having the modify statement in the catch clause doesn't work for whatever reason
     if (caughtException) {
         modify($manager) {finishOperation($operation)};
@@ -735,7 +755,7 @@ end
 
 /*
 *
-* We were able to acquire a lock so now let's ask Xacml Guard whether 
+* We were able to acquire a lock so now let's ask Xacml Guard whether
 * we are allowed to proceed with the request to the actor.
 *
 */
@@ -743,24 +763,24 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
-            onset.getRequestId() == $event.getRequestId(), getGuardApprovalStatus() == "NONE" )
-        $lock : TargetLock (requestId == $event.getRequestId())
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
+            onset.getRequestId() == $event.getRequestId(), "None".equalsIgnoreCase(getGuardApprovalStatus()) )
+        $lock : Lock (ownerKey == $event.getRequestId().toString(), isActive())
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {}: event={} manager={} operation={} lock={}", 
+    logger.info("{}: {}: event={} manager={} operation={} lock={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
                 $event, $manager, $operation, $lock);
-    
+
     //
     // Sending notification that we are about to query Guard ("DB write - start operation")
     //
     VirtualControlLoopNotification notification = new VirtualControlLoopNotification($event);
     notification.setNotification(ControlLoopNotificationType.OPERATION);
-    notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " " 
+    notification.setMessage("Sending guard query for " + $operation.policy.getActor() + " "
         + $operation.policy.getRecipe());
     notification.setHistory($operation.getHistory());
     notification.setFrom("policy");
@@ -771,11 +791,11 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
     PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
 
     //
-    // Now send Guard Request to XACML Guard. In order to bypass the call to Guard, 
+    // Now send Guard Request to XACML Guard. In order to bypass the call to Guard,
     // just change guardEnabled to false.
     //
-    // In order to use REST XACML, provide a URL instead of "" as a second argument 
-    // to the CallGuardTask() and set the first argument to null 
+    // In order to use REST XACML, provide a URL instead of "" as a second argument
+    // to the CallGuardTask() and set the first argument to null
     // (instead of XacmlPdpEngine).
     //
 
@@ -822,35 +842,34 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.LOCKED.GUARD_NOT_YET_QUERIED"
 end
 
 //
-// This rule will be triggered when a thread talking to the XACML Guard inserts a 
+// This rule will be triggered when a thread talking to the XACML Guard inserts a
 // guardResponse object into the working memory
 //
 rule "${policyName}.GUARD.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
-            requestId == $event.getRequestId() ) 
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
+            requestId == $event.getRequestId() )
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $lock : TargetLock (requestId == $event.getRequestId())
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
         $guardResponse : PolicyGuardResponse(requestId == $event.getRequestId(), $operation.policy.recipe == operation)
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
-    logger.info("{}: {}: event={} manager={} operation={} lock={} opTimer={} guardResponse={}", 
+    logger.info("{}: {}: event={} manager={} operation={} opTimer={} guardResponse={}",
                  $params.getClosedLoopControlName(), drools.getRule().getName(),
-                 $event, $manager, $operation, $lock, $opTimer, $guardResponse);
-        
-        
+                 $event, $manager, $operation, $opTimer, $guardResponse);
+
+
     //we will permit the operation if there was no Guard for it
     if("Indeterminate".equalsIgnoreCase($guardResponse.getResult())){
         $guardResponse.setResult("Permit");
     }
-    
+
     //
     // This notification has Guard result in "message". ("DB write - end operation in case of Guard Deny")
     //
@@ -863,11 +882,11 @@ rule "${policyName}.GUARD.RESPONSE"
     notification.setPolicyName(drools.getRule().getName());
     notification.setPolicyScope("${policyScope}");
     notification.setPolicyVersion("${policyVersion}");
-    
+
     PolicyEngineConstants.getManager().deliver("POLICY-CL-MGT", notification);
-    
+
     if("Permit".equalsIgnoreCase($guardResponse.getResult())){
-    
+
         modify($operation){setGuardApprovalStatus($guardResponse.getResult())};
     }
     else {
@@ -878,9 +897,9 @@ rule "${policyName}.GUARD.RESPONSE"
         retract($operation);
         modify($manager) {finishOperation($operation)};
     }
-    
+
     retract($guardResponse);
-            
+
 end
 
 /*
@@ -897,29 +916,28 @@ end
 rule "${policyName}.APPC.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
-            closedLoopEventStatus == ControlLoopEventStatus.ONSET ) 
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
+            closedLoopEventStatus == ControlLoopEventStatus.ONSET )
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : Response( getCommonHeader().RequestId == $event.getRequestId() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                  $params.getClosedLoopControlName(), drools.getRule().getName(),
-                 $event, $manager, $operation, $lock, $opTimer, $response);
+                 $event, $manager, $operation, $opTimer, $response);
     //
     // Get the result of the operation
     //
     PolicyResult policyResult = $operation.onResponse($response);
     if (policyResult != null) {
-        logger.debug("{}: {}: operation finished - result={}", 
+        logger.debug("{}: {}: operation finished - result={}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
                     policyResult);
         //
@@ -993,14 +1011,14 @@ rule "${policyName}.APPC.RESPONSE.CLEANUP"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $response : Response($id : getCommonHeader().RequestId )
-        not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) 
+        not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: orphan appc response={}", 
+    logger.debug("{}: {}: orphan appc response={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
-        
+
     //
     // Retract it
     //
@@ -1015,33 +1033,32 @@ end
 rule "${policyName}.APPC.LCM.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
-            closedLoopEventStatus == ControlLoopEventStatus.ONSET ) 
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
+            closedLoopEventStatus == ControlLoopEventStatus.ONSET )
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : LcmResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer, $response);
-    
+                $event, $manager, $operation, $operation, $opTimer, $response);
+
     //
     // Get the result of the operation
     //
     PolicyResult policyResult = $operation.onResponse($response);
     if (policyResult != null) {
-      logger.debug("{}: {}: operation finished - result={}", 
+      logger.debug("{}: {}: operation finished - result={}",
                   $params.getClosedLoopControlName(), drools.getRule().getName(),
                   policyResult);
-      
+
       //
       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
       //
@@ -1103,12 +1120,12 @@ rule "${policyName}.APPC.LCM.RESPONSE.CLEANUP"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $response : LcmResponseWrapper($id : getBody().getCommonHeader().getRequestId )
-        not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) 
+        not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
     then
-    
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: orphan appc response={}", 
+    logger.debug("{}: {}: orphan appc response={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
     //
     // Retract it
@@ -1124,33 +1141,32 @@ end
 rule "${policyName}.SDNR.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
-            closedLoopEventStatus == ControlLoopEventStatus.ONSET ) 
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
+            closedLoopEventStatus == ControlLoopEventStatus.ONSET )
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : PciResponseWrapper( getBody().getCommonHeader().getRequestId() == $event.getRequestId() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer, $response);
-    
+                $event, $manager, $operation, $operation, $opTimer, $response);
+
     //
     // Get the result of the operation
     //
     PolicyResult policyResult = $operation.onResponse($response);
     if (policyResult != null) {
-      logger.debug("{}: {}: operation finished - result={}", 
+      logger.debug("{}: {}: operation finished - result={}",
                   $params.getClosedLoopControlName(), drools.getRule().getName(),
                   policyResult);
-      
+
       //
       // This Operation has completed, construct a notification showing our results. (DB write - end operation)
       //
@@ -1212,12 +1228,12 @@ rule "${policyName}.SDNR.RESPONSE.CLEANUP"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $response : PciResponseWrapper($id : getBody().getCommonHeader().getRequestId )
-        not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) ) 
+        not ( VirtualControlLoopEvent( requestId == $id, closedLoopEventStatus == ControlLoopEventStatus.ONSET ) )
     then
-    
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: orphan SDNR response={}", 
+    logger.debug("{}: {}: orphan SDNR response={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(), $id);
     //
     // Retract it
@@ -1233,32 +1249,31 @@ end
 rule "${policyName}.SO.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : SoResponseWrapper(requestId.toString() == $event.getRequestId().toString() )
     then
 
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer, $response);
-        
+                $event, $manager, $operation, $operation, $opTimer, $response);
+
     // Get the result of the operation
     //
     PolicyResult policyResult = $operation.onResponse($response);
     if (policyResult != null) {
-        logger.debug("{}: {}: operation finished - result={}", 
+        logger.debug("{}: {}: operation finished - result={}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
                     policyResult);
-      
+
         //
         // This Operation has completed, construct a notification showing our results
         //
@@ -1321,22 +1336,21 @@ end
 rule "${policyName}.VFC.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
-        $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )    
+        $response : VfcResponse( requestId.toString() == $event.getRequestId().toString() )
     then
         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
         logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-        logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
+        logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
-                    $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                    $event, $manager, $operation, $operation, $opTimer, $response);
 
         // Get the result of the operation
         //
@@ -1398,22 +1412,21 @@ end
 rule "${policyName}.SDNC.RESPONSE"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
-        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(), 
+        $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName(),
             closedLoopEventStatus == ControlLoopEventStatus.ONSET )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
-        $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )    
+        $response : SdncResponse( requestId.toString() == $event.getRequestId().toString() )
     then
         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
         logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-        logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}", 
+        logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
-                    $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                    $event, $manager, $operation, $operation, $opTimer, $response);
 
         // Get the result of the operation
         //
@@ -1481,16 +1494,15 @@ rule "${policyName}.CDS.RESPONSE"
             onset.getRequestId() == $event.getRequestId() )
         $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), timerType == "Operation", !expired )
-        $lock : TargetLock (requestId == $event.getRequestId())
         $response : CdsResponse( requestId == $event.getRequestId().toString() )
 
     then
 
         Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
         logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-        logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={} response={}",
+        logger.debug("{}: {}: event={} manager={} operation={} opTimer={} response={}",
                     $params.getClosedLoopControlName(), drools.getRule().getName(),
-                    $event, $manager, $operation, $lock, $operation, $opTimer, $response);
+                    $event, $manager, $operation, $operation, $opTimer, $response);
 
         // Get the result of the operation
         PolicyResult policyResult = $operation.onResponse($response);
@@ -1571,23 +1583,22 @@ rule "${policyName}.EVENT.MANAGER.OPERATION.TIMEOUT"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(), 
+        $operation : ControlLoopOperationManager( onset.closedLoopControlName == $event.getClosedLoopControlName(),
             onset.getRequestId() == $event.getRequestId() )
-        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $opTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), expired, timerType == "Operation" )
-        $lock : TargetLock (requestId == $event.getRequestId())
     then
-    
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
-    logger.debug("{}: {}: event={} manager={} operation={} lock={} opTimer={}", 
+    logger.debug("{}: {}: event={} manager={} operation={} opTimer={}",
                 $params.getClosedLoopControlName(), drools.getRule().getName(),
-                $event, $manager, $operation, $lock, $operation, $opTimer);
-    
+                $event, $manager, $operation, $operation, $opTimer);
+
     //
-    // Tell it its timed out
+    // Tell it it has timed out
     //
     $operation.setOperationHasTimedOut();
     //
@@ -1638,16 +1649,16 @@ rule "${policyName}.EVENT.MANAGER.TIMEOUT"
     when
         $params : Params( getClosedLoopControlName() == "${closedLoopControlName}" )
         $event : VirtualControlLoopEvent( closedLoopControlName == $params.getClosedLoopControlName() )
-        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $manager : ControlLoopEventManager( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId() )
-        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(), 
+        $clTimer : ControlLoopTimer( closedLoopControlName == $event.getClosedLoopControlName(),
             requestId == $event.getRequestId().toString(), expired, timerType == "ClosedLoop" )
     then
-    
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $params.getClosedLoopControlName(), drools.getRule().getName());
 
-    logger.debug("{}: {}: event={}", 
+    logger.debug("{}: {}: event={}",
               $params.getClosedLoopControlName(), drools.getRule().getName(),
               $event);
     //
@@ -1680,47 +1691,46 @@ rule "${policyName}.EVENT.MANAGER.CLEANUP"
     when
         $manager : ControlLoopEventManager( $clName : getClosedLoopControlName(), $requestId : getRequestId() )
         $operations : LinkedList()
-                        from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName, 
+                        from collect( ControlLoopOperationManager( onset.closedLoopControlName == $clName,
                             onset.getRequestId() == $requestId ) )
         $timers : LinkedList()
-                        from collect( ControlLoopTimer( closedLoopControlName == $clName, 
+                        from collect( ControlLoopTimer( closedLoopControlName == $clName,
                             requestId == $requestId.toString() ) )
-        $locks : LinkedList()
-                        from collect( TargetLock (requestId == $requestId) )
         not( VirtualControlLoopEvent( closedLoopControlName == $clName, requestId == $requestId ) )
     then
-    
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, drools.getRule().getName());
 
-    logger.debug("{}: {}: manager={} timers={} operations={}", 
+    logger.debug("{}: {}: manager={} timers={} operations={}",
               $clName, drools.getRule().getName(),
               $manager, $timers.size(), $operations.size());
-    
+
+    //
+    // Retract lock by invoking unlock()
+    //
+    Lock lock = $manager.unlockCurrentOperation();
+    if(lock != null) {
+        retract(lock);
+    }
+
     //
     // Retract EVERYTHING
     //
+
     retract($manager);
-    
+
     for(Object manager: $operations) {
         retract((ControlLoopOperationManager) manager);
     }
     for(Object timer: $timers) {
         retract((ControlLoopTimer) timer);
     }
-    for(Object lock: $locks) {
-        TargetLock tgt = (TargetLock) lock;
-        //
-        // Ensure we release the lock
-        //
-        PolicyGuard.unlockTarget(tgt);
-        retract(tgt);
-    }
 end
 
 /*
 *
-* This rule will clean up any rogue onsets where there is no 
+* This rule will clean up any rogue onsets where there is no
 * ControlLoopParams object corresponding to the onset event.
 *
 */
@@ -1729,10 +1739,10 @@ rule "${policyName}.EVENT.CLEANUP"
         $event : VirtualControlLoopEvent( $clName: closedLoopControlName )
         not ( Params( getClosedLoopControlName() == $clName) )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $clName, drools.getRule().getName());
-    logger.debug("{}: {}: orphan onset event={}", 
+    logger.debug("{}: {}: orphan onset event={}",
                 $clName, drools.getRule().getName(), $event);
 
     retract($event);
@@ -1748,11 +1758,11 @@ rule "${policyName}.PARAMS.CLEANING"
         $params: Params( )
         ParamsInitCleaner( )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
         $params.getControlLoopYaml());
-        
+
     ParamsCleaner cleaner = new ParamsCleaner();
     cleaner.setClosedLoopControlName($params.getClosedLoopControlName());
     cleaner.setControlLoopYaml($params.getControlLoopYaml());
@@ -1768,10 +1778,10 @@ rule "${policyName}.PARAMS.FINISHED"
     when
         $initCleaner: ParamsInitCleaner( )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {}", $initCleaner.getClosedLoopControlName(), drools.getRule().getName());
-    
+
     retract($initCleaner);
 end
 
@@ -1788,11 +1798,11 @@ rule "${policyName}.PARAMS.ACTIVE"
         $cleaner: ParamsCleaner( getClosedLoopControlName() == "${closedLoopControlName}",
                             getControlLoopYaml() == "${controlLoopYaml}"  )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
         $params.getControlLoopYaml());
-        
+
     retract($cleaner);
 end
 
@@ -1808,11 +1818,11 @@ rule "${policyName}.PARAMS.DELETE"
         $cleaner: ParamsCleaner( getClosedLoopControlName() == $params.getClosedLoopControlName(),
                             getControlLoopYaml() == $params.getControlLoopYaml()  )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {} : YAML=[{}]", $params.getClosedLoopControlName(), drools.getRule().getName(),
         $params.getControlLoopYaml());
-        
+
     retract($params);
 end
 
@@ -1825,10 +1835,10 @@ rule "${policyName}.PARAMS.CLEANED"
     when
         $cleaner: ParamsCleaner( )
     then
+
     Logger logger = LoggerFactory.getLogger(drools.getRule().getPackage());
     logger.info("{}: {} : YAML=[{}]", $cleaner.getClosedLoopControlName(), drools.getRule().getName(),
         $cleaner.getControlLoopYaml());
-        
+
     retract($cleaner);
 end
index 0793b88..db5da1e 100644 (file)
@@ -48,6 +48,8 @@ public class ControlLoopFailureTest extends ControlLoopBase implements TopicList
     private UUID requestId2;
     private UUID requestId3;
     private int eventCount;
+    private int nsuccess = 0;
+    private int nreject = 0;
 
     /**
      * Setup simulator.
@@ -106,19 +108,25 @@ public class ControlLoopFailureTest extends ControlLoopBase implements TopicList
         sendEvent(pair.first, requestId, ControlLoopEventStatus.ONSET, "vnf01");
 
         /*
-         * Send a second event requesting an action for a different target entity
+         * Send a second event for a different target to ensure there are no problems with obtaining
+         * a lock
          */
         sendEvent(pair.first, requestId2, ControlLoopEventStatus.ONSET, "vnf02");
 
         /*
-         * Send a second event for a different target to ensure there are no problems with obtaining
-         * a lock for a different
+         * Send a third event requesting an action for a duplicate target entity
          */
+        sendEvent(pair.first, requestId3, ControlLoopEventStatus.ONSET, "vnf01");
+
         kieSession.fireUntilHalt();
 
         // allow object clean-up
         kieSession.fireAllRules();
 
+        // should be one success and one failure for vnf01
+        assertEquals(1, nsuccess);
+        assertEquals(1, nreject);
+
         /*
          * The only fact in memory should be Params
          */
@@ -136,7 +144,7 @@ public class ControlLoopFailureTest extends ControlLoopBase implements TopicList
      * @see org.onap.policy.drools.PolicyEngineListener#newEventNotification(java.lang.String)
      */
     @Override
-    public void onTopicEvent(CommInfrastructure commType, String topic, String event) {
+    public synchronized void onTopicEvent(CommInfrastructure commType, String topic, String event) {
         /*
          * Pull the object that was sent out to DMAAP and make sure it is a ControlLoopNoticiation
          * of type active
@@ -156,6 +164,17 @@ public class ControlLoopFailureTest extends ControlLoopBase implements TopicList
             if (policyName.endsWith("EVENT")) {
                 logger.debug("Rule Fired: " + notification.getPolicyName());
                 assertTrue(ControlLoopNotificationType.ACTIVE.equals(notification.getNotification()));
+            } else if (policyName.endsWith("DENIED")) {
+                logger.debug("Rule Fired: " + notification.getPolicyName());
+                assertTrue(ControlLoopNotificationType.REJECTED.equals(notification.getNotification()));
+                assertNotNull(notification.getMessage());
+                assertTrue(notification.getMessage().contains("is already locked"));
+                if (requestId.equals(notification.getRequestId()) || requestId3.equals(notification.getRequestId())) {
+                    ++nreject;
+                }
+                if (++eventCount == 3) {
+                    kieSession.halt();
+                }
             } else if (policyName.endsWith("GUARD_NOT_YET_QUERIED")) {
                 logger.debug("Rule Fired: " + notification.getPolicyName());
                 assertTrue(ControlLoopNotificationType.OPERATION.equals(notification.getNotification()));
@@ -181,18 +200,16 @@ public class ControlLoopFailureTest extends ControlLoopBase implements TopicList
                 assertTrue(ControlLoopNotificationType.OPERATION_SUCCESS.equals(notification.getNotification()));
                 assertNotNull(notification.getMessage());
                 assertTrue(notification.getMessage().startsWith("actor=APPC"));
-                if (requestId.equals(notification.getRequestId())) {
-                    sendEvent(pair.first, requestId, ControlLoopEventStatus.ABATED, "vnf01");
+                if (requestId.equals(notification.getRequestId()) || requestId3.equals(notification.getRequestId())) {
+                    sendEvent(pair.first, notification.getRequestId(), ControlLoopEventStatus.ABATED, "vnf01");
                 } else if (requestId2.equals(notification.getRequestId())) {
                     sendEvent(pair.first, requestId2, ControlLoopEventStatus.ABATED, "vnf02");
                 }
             } else if (policyName.endsWith("EVENT.MANAGER")) {
                 logger.debug("Rule Fired: " + notification.getPolicyName());
-                if (requestId3.equals(notification.getRequestId())) {
-                    /*
-                     * The event with the duplicate target should be rejected
-                     */
-                    assertTrue(ControlLoopNotificationType.REJECTED.equals(notification.getNotification()));
+                if (requestId.equals(notification.getRequestId()) || requestId3.equals(notification.getRequestId())) {
+                    assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.getNotification()));
+                    ++nsuccess;
                 } else {
                     assertTrue(ControlLoopNotificationType.FINAL_SUCCESS.equals(notification.getNotification()));
                 }