Bug 4105: Implement candidate registration close 92/26792/1
authorTom Pantelis <tpanteli@brocade.com>
Sat, 8 Aug 2015 10:57:03 +0000 (06:57 -0400)
committerTom Pantelis <tpanteli@brocade.com>
Thu, 10 Sep 2015 18:50:35 +0000 (14:50 -0400)
Added an UnregisterCandidateLocal message which is sent when
a DistributedEntityOwnershipCandidateRegistration is closed.

Change-Id: I6336e1b83a7764bfb4abc2fc37e196175c008dc3
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/DistributedEntityOwnershipCandidateRegistration.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/DistributedEntityOwnershipService.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipShard.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/messages/UnregisterCandidateLocal.java [new file with mode: 0644]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/DistributedEntityOwnershipServiceTest.java

index 1089ec28039f8ff0be20fb558999115e86b358a0..70c454e3afbbc79c90b67669b5025f45a1e3009a 100644 (file)
@@ -17,13 +17,16 @@ import org.opendaylight.controller.md.sal.common.impl.clustering.AbstractEntityO
  * @author Thomas Pantelis
  */
 class DistributedEntityOwnershipCandidateRegistration extends AbstractEntityOwnershipCandidateRegistration {
+    private final DistributedEntityOwnershipService service;
 
-    DistributedEntityOwnershipCandidateRegistration(EntityOwnershipCandidate candidate, Entity entity) {
+    DistributedEntityOwnershipCandidateRegistration(EntityOwnershipCandidate candidate, Entity entity,
+            DistributedEntityOwnershipService service) {
         super(candidate, entity);
+        this.service = service;
     }
 
     @Override
     public void close() {
-        // TODO - need to send unregister message.
+        service.unregisterCandidate(getEntity());
     }
 }
index 90720eead6f180b4037356e2723a4f58910723a5..13ecfffefec1f980b7cc676738010a9e4cad2714 100644 (file)
@@ -15,6 +15,7 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.TimeUnit;
 import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
 import org.opendaylight.controller.cluster.datastore.entityownership.messages.RegisterCandidateLocal;
+import org.opendaylight.controller.cluster.datastore.entityownership.messages.UnregisterCandidateLocal;
 import org.opendaylight.controller.cluster.datastore.messages.CreateShard;
 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
@@ -106,17 +107,24 @@ public class DistributedEntityOwnershipService implements EntityOwnershipService
     public EntityOwnershipCandidateRegistration registerCandidate(Entity entity, EntityOwnershipCandidate candidate)
             throws CandidateAlreadyRegisteredException {
 
-        EntityOwnershipCandidate currentCandidate = registeredEntities.putIfAbsent(entity,candidate);
+        EntityOwnershipCandidate currentCandidate = registeredEntities.putIfAbsent(entity, candidate);
         if(currentCandidate != null) {
             throw new CandidateAlreadyRegisteredException(entity, currentCandidate);
         }
 
         RegisterCandidateLocal registerCandidate = new RegisterCandidateLocal(candidate, entity);
 
-        LOG.debug("Registering candidate with message: " + registerCandidate);
+        LOG.debug("Registering candidate with message: {}", registerCandidate);
 
         executeLocalEntityOwnershipShardOperation(registerCandidate);
-        return new DistributedEntityOwnershipCandidateRegistration(candidate, entity);
+        return new DistributedEntityOwnershipCandidateRegistration(candidate, entity, this);
+    }
+
+    void unregisterCandidate(Entity entity) {
+        LOG.debug("Unregistering candidate for {}", entity);
+
+        executeLocalEntityOwnershipShardOperation(new UnregisterCandidateLocal(entity));
+        registeredEntities.remove(entity);
     }
 
     @Override
index 230b597f2d42ffde56f5f0aa8b91c9da62470dbe..52f85f481e150ea41fcd201d9b556c387b5e7123 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Map;
 import org.opendaylight.controller.cluster.datastore.DatastoreContext;
 import org.opendaylight.controller.cluster.datastore.Shard;
 import org.opendaylight.controller.cluster.datastore.entityownership.messages.RegisterCandidateLocal;
+import org.opendaylight.controller.cluster.datastore.entityownership.messages.UnregisterCandidateLocal;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.messages.SuccessReply;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@@ -41,12 +42,20 @@ public class EntityOwnershipShard extends Shard {
     public void onReceiveCommand(final Object message) throws Exception {
         if(message instanceof RegisterCandidateLocal) {
             onRegisterCandidateLocal((RegisterCandidateLocal)message);
+        } else if(message instanceof UnregisterCandidateLocal) {
+            onUnregisterCandidateLocal((UnregisterCandidateLocal)message);
         } else {
             super.onReceiveCommand(message);
         }
     }
 
     private void onRegisterCandidateLocal(RegisterCandidateLocal registerCandidate) {
+        // TODO - implement
+        getSender().tell(SuccessReply.INSTANCE, getSelf());
+    }
+
+    private void onUnregisterCandidateLocal(UnregisterCandidateLocal unregisterCandidate) {
+        // TODO - implement
         getSender().tell(SuccessReply.INSTANCE, getSelf());
     }
 
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/messages/UnregisterCandidateLocal.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/messages/UnregisterCandidateLocal.java
new file mode 100644 (file)
index 0000000..d99ec7b
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2015 Brocade Communications Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.cluster.datastore.entityownership.messages;
+
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+
+/**
+ * Message sent to the local EntityOwnershipShard to unregister a candidate.
+ *
+ * @author Thomas Pantelis
+ */
+public class UnregisterCandidateLocal {
+    private final Entity entity;
+
+    public UnregisterCandidateLocal(Entity entity) {
+        this.entity = entity;
+    }
+
+    public Entity getEntity() {
+        return entity;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("UnregisterCandidateLocal [entity=").append(entity).append("]");
+        return builder.toString();
+    }
+}
index ee5b1c5a2d3d1f5a896e05e56c20b18ad2a010ba..860d3dc80914edb0f5ab028d1adb227fbf9b61c8 100644 (file)
@@ -10,9 +10,11 @@ package org.opendaylight.controller.cluster.datastore.entityownership;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 import akka.actor.ActorRef;
+import akka.actor.PoisonPill;
 import akka.actor.Props;
 import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.Collections;
@@ -21,12 +23,14 @@ import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
 import org.opendaylight.controller.cluster.datastore.DatastoreContext;
 import org.opendaylight.controller.cluster.datastore.DistributedDataStore;
 import org.opendaylight.controller.cluster.datastore.entityownership.messages.RegisterCandidateLocal;
+import org.opendaylight.controller.cluster.datastore.entityownership.messages.UnregisterCandidateLocal;
 import org.opendaylight.controller.cluster.datastore.identifiers.ShardIdentifier;
 import org.opendaylight.controller.cluster.datastore.utils.MockClusterWrapper;
 import org.opendaylight.controller.cluster.datastore.utils.MockConfiguration;
@@ -57,7 +61,7 @@ public class DistributedEntityOwnershipServiceTest extends AbstractActorTest {
     private DistributedDataStore dataStore;
 
     @Before
-    public void setUp() throws Exception {
+    public void setUp() {
         DatastoreContext datastoreContext = DatastoreContext.newBuilder().dataStoreType(dataStoreType).
                 shardInitializationTimeout(10, TimeUnit.SECONDS).build();
         dataStore = new DistributedDataStore(getSystem(), new MockClusterWrapper(),
@@ -66,6 +70,11 @@ public class DistributedEntityOwnershipServiceTest extends AbstractActorTest {
         dataStore.onGlobalContextUpdated(TestModel.createTestContext());
     }
 
+    @After
+    public void tearDown() {
+        dataStore.getActorContext().getShardManager().tell(PoisonPill.getInstance(), ActorRef.noSender());
+    }
+
     @Test
     public void testEntityOwnershipShardCreated() throws Exception {
         DistributedEntityOwnershipService service = new DistributedEntityOwnershipService(dataStore);
@@ -101,7 +110,7 @@ public class DistributedEntityOwnershipServiceTest extends AbstractActorTest {
         verifyEntityOwnershipCandidateRegistration(entity, reg);
         verifyRegisterCandidateLocal(shardPropsCreator, entity, candidate);
 
-        // Test same entity - should throw exception
+        // Register the same entity - should throw exception
 
         EntityOwnershipCandidate candidate2 = mock(EntityOwnershipCandidate.class);
         try {
@@ -113,7 +122,7 @@ public class DistributedEntityOwnershipServiceTest extends AbstractActorTest {
             assertEquals("getEntity", entity, e.getEntity());
         }
 
-        // Test different entity
+        // Register a different entity - should succeed
 
         Entity entity2 = new Entity(ENTITY_TYPE2, YangInstanceIdentifier.of(QNAME));
         shardPropsCreator.expectShardMessage(RegisterCandidateLocal.class);
@@ -126,6 +135,46 @@ public class DistributedEntityOwnershipServiceTest extends AbstractActorTest {
         service.close();
     }
 
+    @Test
+    public void testCloseCandidateRegistration() throws Exception {
+        final TestShardPropsCreator shardPropsCreator = new TestShardPropsCreator();
+        DistributedEntityOwnershipService service = new DistributedEntityOwnershipService(dataStore) {
+            @Override
+            protected EntityOwnershipShardPropsCreator newShardPropsCreator() {
+                return shardPropsCreator;
+            }
+        };
+
+        service.start();
+
+        shardPropsCreator.expectShardMessage(RegisterCandidateLocal.class);
+
+        Entity entity = new Entity(ENTITY_TYPE, YangInstanceIdentifier.of(QNAME));
+        EntityOwnershipCandidate candidate = mock(EntityOwnershipCandidate.class);
+
+        EntityOwnershipCandidateRegistration reg = service.registerCandidate(entity, candidate);
+
+        verifyEntityOwnershipCandidateRegistration(entity, reg);
+        verifyRegisterCandidateLocal(shardPropsCreator, entity, candidate);
+
+        shardPropsCreator.expectShardMessage(UnregisterCandidateLocal.class);
+
+        reg.close();
+
+        UnregisterCandidateLocal unregCandidate = shardPropsCreator.waitForShardMessage();
+        assertEquals("getEntity", entity, unregCandidate.getEntity());
+
+        // Re-register - should succeed.
+
+        shardPropsCreator.expectShardMessage(RegisterCandidateLocal.class);
+
+        service.registerCandidate(entity, candidate);
+
+        verifyRegisterCandidateLocal(shardPropsCreator, entity, candidate);
+
+        service.close();
+    }
+
     @Test
     public void testRegisterListener() {
     }
@@ -156,8 +205,8 @@ public class DistributedEntityOwnershipServiceTest extends AbstractActorTest {
 
         @SuppressWarnings("unchecked")
         <T> T waitForShardMessage() {
-            assertEquals("Message received", true, Uninterruptibles.awaitUninterruptibly(
-                    messageReceived.get(), 5, TimeUnit.SECONDS));
+            assertTrue("Message " + messageClass.get().getSimpleName() + " was not received",
+                    Uninterruptibles.awaitUninterruptibly(messageReceived.get(), 5, TimeUnit.SECONDS));
             assertEquals("Message type", messageClass.get(), receivedMessage.get().getClass());
             return (T) receivedMessage.get();
         }