Bug 4105: Add hasOwner param to EntityOwnershipListener#ownershipChanged 98/26898/2
authorTom Pantelis <tpanteli@brocade.com>
Fri, 11 Sep 2015 04:13:51 +0000 (00:13 -0400)
committerGerrit Code Review <gerrit@opendaylight.org>
Mon, 14 Sep 2015 12:01:28 +0000 (12:01 +0000)
OF clustering needs to know when the last candidate is removed for an
entity so it can clean up inventory. We decided to add a new param,
hasOwner, passed to EntityOwnershipListener#ownershipChanged to indicate if
there is at least one remaining candidate and current owner when a
controller node loses ownership. So if
wasOwner=true && isOwner=false && hasOwner=false, the OF code can
remove the device node from inventory.

To simplify the EntityOwnershipListener#ownershipChanged interface and
to allow for possible future parameters w/o breaking the interface, the
parameters are now encapsulated in an EntityOwnershipChanged DTO. There
already was the same EntityOwnershipChanged class in
sal-distributed-datastore - this class was removed.

Change-Id: I07375f154ac55d34062380ad6d0b30d970bd28e7
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
(cherry picked from commit 061d4edabfb421ec79d1dc7afe4163aa52828450)

14 files changed:
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipChange.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListener.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnerChangeListener.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipListenerActor.java
opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipListenerSupport.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/EntityOwnershipChanged.java [deleted file]
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/AbstractEntityOwnershipTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/DistributedEntityOwnershipIntegrationTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnerChangeListenerTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipListenerActorTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipListenerSupportTest.java
opendaylight/md-sal/sal-distributed-datastore/src/test/java/org/opendaylight/controller/cluster/datastore/entityownership/EntityOwnershipShardTest.java
opendaylight/md-sal/samples/clustering-test-app/provider/src/main/java/org/opendaylight/controller/clustering/it/provider/CarProvider.java

diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipChange.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipChange.java
new file mode 100644 (file)
index 0000000..b9d67f1
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * 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.md.sal.common.api.clustering;
+
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+
+/**
+ * A DTO that encapsulates an ownership change for an entity.
+ *
+ * @author Thomas Pantelis
+ */
+public class EntityOwnershipChange {
+    private final Entity entity;
+    private final boolean wasOwner;
+    private final boolean isOwner;
+    private final boolean hasOwner;
+
+    public EntityOwnershipChange(@Nonnull Entity entity, boolean wasOwner, boolean isOwner, boolean hasOwner) {
+        this.entity = Preconditions.checkNotNull(entity, "entity can't be null");
+        this.wasOwner = wasOwner;
+        this.isOwner = isOwner;
+        this.hasOwner = hasOwner;
+    }
+
+    /**
+     * Returns the entity whose ownership status changed.
+     * @return the entity
+     */
+    @Nonnull public Entity getEntity() {
+        return entity;
+    }
+
+    /**
+     * Returns the previous ownership status of the entity for this process instance.
+     * @return true if this process was the owner of the entity at the time this notification was generated
+     */
+    public boolean wasOwner() {
+        return wasOwner;
+    }
+
+    /**
+     * Returns the current ownership status of the entity for this process instance.
+     * @return true if this process is now the owner of the entity
+     */
+    public boolean isOwner() {
+        return isOwner;
+    }
+
+    /**
+     * Returns the current ownership status of the entity across all process instances.
+     * @return true if the entity has an owner which may or may not be this process. If false, then
+     *         the entity has no candidates and thus no owner.
+     */
+    public boolean hasOwner() {
+        return hasOwner;
+    }
+
+    @Override
+    public String toString() {
+        return "EntityOwnershipChanged [entity=" + entity + ", wasOwner=" + wasOwner + ", isOwner=" + isOwner
+                + ", hasOwner=" + hasOwner + "]";
+    }
+}
index 96b9ec2e5f3ab7f6153db6d8dfaf0454362ec25c..b4eb44569b0d46116519bbcbd36c1ca257d32fef 100644 (file)
@@ -14,12 +14,22 @@ package org.opendaylight.controller.md.sal.common.api.clustering;
 public interface EntityOwnershipListener {
 
     /**
 public interface EntityOwnershipListener {
 
     /**
-     * A notification that is generated when the ownership status for a given entity changes in the current process.
+     * A notification that is generated when the ownership status of an entity changes.
      *
      *
-     * @param entity the entity whose ownership status has changed
-     * @param wasOwner true if this process was the owner of the given entity right before this notification
-     *                 was generated
-     * @param isOwner true if this process now owns the given entity
+     * The following outlines valid combinations of the ownership status flags in the EntityOwnershipChange
+     * parameter and their meanings:
+     * <ul>
+     * <li><b>wasOwner = false, isOwner = true, hasOwner = true</b> - this process has been granted ownership</li>
+     * <li><b>wasOwner = true, isOwner = false, hasOwner = true</b> - this process was the owner but ownership
+     *     transitioned to another process</li>
+     * <li><b>wasOwner = false, isOwner = false, hasOwner = true</b> - ownership transitioned to another process
+     *     and this process was not the previous owner</li>
+     * <li><b>wasOwner = false, isOwner = false, hasOwner = false</b> - the entity no longer has any candidates and
+     *     thus no owner and this process was not the previous owner</li>
+     * <li><b>wasOwner = true, isOwner = false, hasOwner = false</b> - the entity no longer has any candidates and
+     *     thus no owner and this process was the previous owner</li>
+     * </ul>
+     * @param ownershipChange contains the entity and its ownership status flags
      */
      */
-    void ownershipChanged(Entity entity, boolean wasOwner, boolean isOwner);
+    void ownershipChanged(EntityOwnershipChange ownershipChange);
 }
 }
index cf9df1821a93bab26787e10941c42e870888b17f..cc0b8a318ddc29778cf17b82da2a78adb0237887 100644 (file)
@@ -67,14 +67,14 @@ class EntityOwnerChangeListener implements DOMDataTreeChangeListener {
             if(!Objects.equal(origOwner, newOwner)) {
                 boolean isOwner = Objects.equal(localMemberName, newOwner);
                 boolean wasOwner = Objects.equal(localMemberName, origOwner);
             if(!Objects.equal(origOwner, newOwner)) {
                 boolean isOwner = Objects.equal(localMemberName, newOwner);
                 boolean wasOwner = Objects.equal(localMemberName, origOwner);
-                if(isOwner || wasOwner) {
-                    Entity entity = createEntity(change.getRootPath());
+                boolean hasOwner = newOwner != null && !newOwner.toString().isEmpty();
 
 
-                    LOG.debug("{}: Calling notifyEntityOwnershipListeners: entity: {}, wasOwner: {}, isOwner: {}",
-                            logId(), entity, wasOwner, isOwner);
+                Entity entity = createEntity(change.getRootPath());
 
 
-                    listenerSupport.notifyEntityOwnershipListeners(entity, wasOwner, isOwner);
-                }
+                LOG.debug("{}: Calling notifyEntityOwnershipListeners: entity: {}, wasOwner: {}, isOwner: {}, hasOwner: {}",
+                        logId(), entity, wasOwner, isOwner, hasOwner);
+
+                listenerSupport.notifyEntityOwnershipListeners(entity, wasOwner, isOwner, hasOwner);
             }
         }
     }
             }
         }
     }
index f62f7492f612b464fef2cc67b887ca3421c51173..8c6b04cbf3c1eeeaccf181dfc0f9a612685a8123 100644 (file)
@@ -11,7 +11,7 @@ import akka.actor.Props;
 import akka.japi.Creator;
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
 import akka.japi.Creator;
 import com.google.common.base.Preconditions;
 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActor;
-import org.opendaylight.controller.cluster.datastore.entityownership.messages.EntityOwnershipChanged;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,16 +32,16 @@ class EntityOwnershipListenerActor extends AbstractUntypedActor {
 
     @Override
     protected void handleReceive(Object message) {
 
     @Override
     protected void handleReceive(Object message) {
-        if(message instanceof EntityOwnershipChanged) {
-            onEntityOwnershipChanged((EntityOwnershipChanged)message);
+        if(message instanceof EntityOwnershipChange) {
+            onEntityOwnershipChanged((EntityOwnershipChange)message);
         }
     }
 
         }
     }
 
-    private void onEntityOwnershipChanged(EntityOwnershipChanged change) {
+    private void onEntityOwnershipChanged(EntityOwnershipChange change) {
         LOG.debug("Notifying EntityOwnershipListener {}: {}", listener, change);
 
         try {
         LOG.debug("Notifying EntityOwnershipListener {}: {}", listener, change);
 
         try {
-            listener.ownershipChanged(change.getEntity(), change.wasOwner(), change.isOwner());
+            listener.ownershipChanged(change);
         } catch (Exception e) {
             LOG.error("Error notifying listener {}", listener, e);
         }
         } catch (Exception e) {
             LOG.error("Error notifying listener {}", listener, e);
         }
index ed4a004ed046b72fd83ef17a23dfc0552f8d1512..a09d224954aedcbde762045d9d9e51c61a5bf7f6 100644 (file)
@@ -16,9 +16,9 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.IdentityHashMap;
 import java.util.Map;
 import java.util.Collection;
 import java.util.IdentityHashMap;
 import java.util.Map;
-import org.opendaylight.controller.cluster.datastore.entityownership.messages.EntityOwnershipChanged;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidate;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidate;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -80,27 +80,27 @@ class EntityOwnershipListenerSupport {
         removeListener(listener, entityType, entityTypeListenerMap);
     }
 
         removeListener(listener, entityType, entityTypeListenerMap);
     }
 
-    void notifyEntityOwnershipListeners(Entity entity, boolean wasOwner, boolean isOwner) {
-        notifyListeners(entity, entity, wasOwner, isOwner, entityListenerMap);
-        notifyListeners(entity, entity.getType(), wasOwner, isOwner, entityTypeListenerMap);
+    void notifyEntityOwnershipListeners(Entity entity, boolean wasOwner, boolean isOwner, boolean hasOwner) {
+        notifyListeners(entity, entity, wasOwner, isOwner, hasOwner, entityListenerMap);
+        notifyListeners(entity, entity.getType(), wasOwner, isOwner, hasOwner, entityTypeListenerMap);
     }
 
     }
 
-    void notifyEntityOwnershipListener(Entity entity, boolean wasOwner, boolean isOwner,
+    void notifyEntityOwnershipListener(Entity entity, boolean wasOwner, boolean isOwner, boolean hasOwner,
             EntityOwnershipListener listener) {
             EntityOwnershipListener listener) {
-        notifyListeners(entity, wasOwner, isOwner, Arrays.asList(listener));
+        notifyListeners(entity, wasOwner, isOwner, hasOwner, Arrays.asList(listener));
     }
 
     }
 
-    private <T> void notifyListeners(Entity entity, T mapKey, boolean wasOwner, boolean isOwner,
+    private <T> void notifyListeners(Entity entity, T mapKey, boolean wasOwner, boolean isOwner, boolean hasOwner,
             Multimap<T, EntityOwnershipListener> listenerMap) {
         Collection<EntityOwnershipListener> listeners = listenerMap.get(mapKey);
         if(!listeners.isEmpty()) {
             Multimap<T, EntityOwnershipListener> listenerMap) {
         Collection<EntityOwnershipListener> listeners = listenerMap.get(mapKey);
         if(!listeners.isEmpty()) {
-            notifyListeners(entity, wasOwner, isOwner, listeners);
+            notifyListeners(entity, wasOwner, isOwner, hasOwner, listeners);
         }
     }
 
         }
     }
 
-    private void notifyListeners(Entity entity, boolean wasOwner, boolean isOwner,
+    private void notifyListeners(Entity entity, boolean wasOwner, boolean isOwner, boolean hasOwner,
             Collection<EntityOwnershipListener> listeners) {
             Collection<EntityOwnershipListener> listeners) {
-        EntityOwnershipChanged changed = new EntityOwnershipChanged(entity, wasOwner, isOwner);
+        EntityOwnershipChange changed = new EntityOwnershipChange(entity, wasOwner, isOwner, hasOwner);
         for(EntityOwnershipListener listener: listeners) {
             ActorRef listenerActor = listenerActorFor(listener);
 
         for(EntityOwnershipListener listener: listeners) {
             ActorRef listenerActor = listenerActorFor(listener);
 
index 58a7a036759dc6fa9de884a22449563f53c14888..d8b1b5324487d10508829b8469fec6ffc9beb97c 100644 (file)
@@ -169,7 +169,7 @@ class EntityOwnershipShard extends Shard {
                 if(registerListener.getEntityType().equals(entityType)) {
                     Entity entity = new Entity(entityType,
                             (YangInstanceIdentifier) entityNode.getChild(ENTITY_ID_NODE_ID).get().getValue());
                 if(registerListener.getEntityType().equals(entityType)) {
                     Entity entity = new Entity(entityType,
                             (YangInstanceIdentifier) entityNode.getChild(ENTITY_ID_NODE_ID).get().getValue());
-                    listenerSupport.notifyEntityOwnershipListener(entity, false, true, registerListener.getListener());
+                    listenerSupport.notifyEntityOwnershipListener(entity, false, true, true, registerListener.getListener());
                 }
             }
         });
                 }
             }
         });
diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/messages/EntityOwnershipChanged.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/entityownership/messages/EntityOwnershipChanged.java
deleted file mode 100644 (file)
index 86fd9f7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * 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 com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
-
-/**
- * Message encapsulating an entity ownership change.
- *
- * @author Thomas Pantelis
- */
-public class EntityOwnershipChanged {
-    private final Entity entity;
-    private final boolean wasOwner;
-    private final boolean isOwner;
-
-    public EntityOwnershipChanged(Entity entity, boolean wasOwner, boolean isOwner) {
-        this.entity = Preconditions.checkNotNull(entity, "entity can't be null");
-        this.wasOwner = wasOwner;
-        this.isOwner = isOwner;
-    }
-
-    public Entity getEntity() {
-        return entity;
-    }
-
-    public boolean wasOwner() {
-        return wasOwner;
-    }
-
-    public boolean isOwner() {
-        return isOwner;
-    }
-
-    @Override
-    public String toString() {
-        return "EntityOwnershipChanged [entity=" + entity + ", wasOwner=" + wasOwner + ", isOwner=" + isOwner + "]";
-    }
-}
index 3134a6eedd4a540721cc8c03b88d93411585b092..ea7648efb9df918bd034f858f6d26eebd5a48afd 100644 (file)
@@ -23,9 +23,14 @@ import com.google.common.base.Optional;
 import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.concurrent.TimeUnit;
 import com.google.common.base.Stopwatch;
 import com.google.common.util.concurrent.Uninterruptibles;
 import java.util.concurrent.TimeUnit;
+import org.hamcrest.Description;
 import org.junit.Assert;
 import org.junit.Assert;
+import org.mockito.ArgumentMatcher;
+import org.mockito.Matchers;
 import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
 import org.opendaylight.controller.cluster.datastore.ShardDataTree;
 import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
 import org.opendaylight.controller.cluster.datastore.ShardDataTree;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.clustering.entity.owners.rev150804.EntityOwners;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.clustering.entity.owners.rev150804.entity.owners.EntityType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.clustering.entity.owners.rev150804.entity.owners.entity.type.entity.Candidate;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.clustering.entity.owners.rev150804.EntityOwners;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.clustering.entity.owners.rev150804.entity.owners.EntityType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.clustering.entity.owners.rev150804.entity.owners.entity.type.entity.Candidate;
@@ -172,4 +177,36 @@ public class AbstractEntityOwnershipTest extends AbstractActorTest {
         shardDataTree.getDataTree().commit(candidate);
         shardDataTree.notifyListeners(candidate);
     }
         shardDataTree.getDataTree().commit(candidate);
         shardDataTree.notifyListeners(candidate);
     }
+
+    static EntityOwnershipChange ownershipChange(final Entity expEntity, final boolean expWasOwner,
+            final boolean expIsOwner, final boolean expHasOwner) {
+        return Matchers.argThat(new ArgumentMatcher<EntityOwnershipChange>() {
+            @Override
+            public boolean matches(Object argument) {
+                EntityOwnershipChange change = (EntityOwnershipChange) argument;
+                return expEntity.equals(change.getEntity()) && expWasOwner == change.wasOwner() &&
+                        expIsOwner == change.isOwner() && expHasOwner == change.hasOwner();
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendValue(new EntityOwnershipChange(expEntity, expWasOwner, expIsOwner, expHasOwner));
+            }
+        });
+    }
+
+    static EntityOwnershipChange ownershipChange(final Entity expEntity) {
+        return Matchers.argThat(new ArgumentMatcher<EntityOwnershipChange>() {
+            @Override
+            public boolean matches(Object argument) {
+                EntityOwnershipChange change = (EntityOwnershipChange) argument;
+                return expEntity.equals(change.getEntity());
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendValue(new EntityOwnershipChange(expEntity, false, false, false));
+            }
+        });
+    }
 }
 }
index fc978f8687f7e3241a416873b57455c273e60b53..ed7ca2d33e3ce5a0f79f4b4894a183ceaf722b6d 100644 (file)
@@ -8,12 +8,10 @@
 package org.opendaylight.controller.cluster.datastore.entityownership;
 
 import static org.junit.Assert.assertEquals;
 package org.opendaylight.controller.cluster.datastore.entityownership;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
+import static org.opendaylight.controller.cluster.datastore.entityownership.AbstractEntityOwnershipTest.ownershipChange;
 import static org.opendaylight.controller.cluster.datastore.entityownership.EntityOwnersModel.CANDIDATE_NAME_NODE_ID;
 import static org.opendaylight.controller.cluster.datastore.entityownership.EntityOwnersModel.entityPath;
 import akka.actor.ActorSystem;
 import static org.opendaylight.controller.cluster.datastore.entityownership.EntityOwnersModel.CANDIDATE_NAME_NODE_ID;
 import static org.opendaylight.controller.cluster.datastore.entityownership.EntityOwnersModel.entityPath;
 import akka.actor.ActorSystem;
@@ -94,6 +92,18 @@ public class DistributedEntityOwnershipIntegrationTest {
     @Mock
     private EntityOwnershipCandidate follower2MockCandidate;
 
     @Mock
     private EntityOwnershipCandidate follower2MockCandidate;
 
+    @Mock
+    private EntityOwnershipCandidate leaderMockListener;
+
+    @Mock
+    private EntityOwnershipCandidate leaderMockListener2;
+
+    @Mock
+    private EntityOwnershipCandidate follower1MockListener;
+
+    @Mock
+    private EntityOwnershipCandidate follower2MockListener;
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
@@ -149,54 +159,71 @@ public class DistributedEntityOwnershipIntegrationTest {
     public void test() throws Exception {
         initDatastores("test");
 
     public void test() throws Exception {
         initDatastores("test");
 
+        leaderEntityOwnershipService.registerListener(ENTITY_TYPE1, leaderMockListener);
+        leaderEntityOwnershipService.registerListener(ENTITY_TYPE2, leaderMockListener2);
+        follower1EntityOwnershipService.registerListener(ENTITY_TYPE1, follower1MockListener);
+
         // Register leader candidate for entity1 and verify it becomes owner
 
         leaderEntityOwnershipService.registerCandidate(ENTITY1, leaderMockCandidate);
         // Register leader candidate for entity1 and verify it becomes owner
 
         leaderEntityOwnershipService.registerCandidate(ENTITY1, leaderMockCandidate);
-        verify(leaderMockCandidate, timeout(5000)).ownershipChanged(ENTITY1, false, true);
-        reset(leaderMockCandidate);
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY1, false, true, true));
+        verify(follower1MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY1, false, false, true));
+        reset(leaderMockListener, follower1MockListener);
 
         // Register leader candidate for entity1_2 (same id, different type) and verify it becomes owner
 
         leaderEntityOwnershipService.registerCandidate(ENTITY1_2, leaderMockCandidate);
 
         // Register leader candidate for entity1_2 (same id, different type) and verify it becomes owner
 
         leaderEntityOwnershipService.registerCandidate(ENTITY1_2, leaderMockCandidate);
-        verify(leaderMockCandidate, timeout(5000)).ownershipChanged(ENTITY1_2, false, true);
-        reset(leaderMockCandidate);
+        verify(leaderMockListener2, timeout(5000)).ownershipChanged(ownershipChange(ENTITY1_2, false, true, true));
+        verify(leaderMockListener, timeout(300).never()).ownershipChanged(ownershipChange(ENTITY1_2));
+        reset(leaderMockListener2);
 
         // Register follower1 candidate for entity1 and verify it gets added but doesn't become owner
 
         follower1EntityOwnershipService.registerCandidate(ENTITY1, follower1MockCandidate);
         verifyCandidates(leaderDistributedDataStore, ENTITY1, "member-1", "member-2");
         verifyOwner(leaderDistributedDataStore, ENTITY1, "member-1");
 
         // Register follower1 candidate for entity1 and verify it gets added but doesn't become owner
 
         follower1EntityOwnershipService.registerCandidate(ENTITY1, follower1MockCandidate);
         verifyCandidates(leaderDistributedDataStore, ENTITY1, "member-1", "member-2");
         verifyOwner(leaderDistributedDataStore, ENTITY1, "member-1");
-        verify(follower1MockCandidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(leaderMockListener, timeout(300).never()).ownershipChanged(ownershipChange(ENTITY1));
+        verify(follower1MockListener, timeout(300).never()).ownershipChanged(ownershipChange(ENTITY1));
 
         // Register follower1 candidate for entity2 and verify it becomes owner
 
         follower1EntityOwnershipService.registerCandidate(ENTITY2, follower1MockCandidate);
 
         // Register follower1 candidate for entity2 and verify it becomes owner
 
         follower1EntityOwnershipService.registerCandidate(ENTITY2, follower1MockCandidate);
-        verify(follower1MockCandidate, timeout(5000)).ownershipChanged(ENTITY2, false, true);
-        reset(follower1MockCandidate);
+        verify(follower1MockCandidate, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, false, true, true));
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, false, false, true));
+        reset(leaderMockListener, follower1MockListener);
 
         // Register follower2 candidate for entity2 and verify it gets added but doesn't become owner
 
 
         // Register follower2 candidate for entity2 and verify it gets added but doesn't become owner
 
+        follower2EntityOwnershipService.registerListener(ENTITY_TYPE1, follower2MockListener);
         follower2EntityOwnershipService.registerCandidate(ENTITY2, follower2MockCandidate);
         verifyCandidates(leaderDistributedDataStore, ENTITY2, "member-2", "member-3");
         verifyOwner(leaderDistributedDataStore, ENTITY2, "member-2");
         follower2EntityOwnershipService.registerCandidate(ENTITY2, follower2MockCandidate);
         verifyCandidates(leaderDistributedDataStore, ENTITY2, "member-2", "member-3");
         verifyOwner(leaderDistributedDataStore, ENTITY2, "member-2");
-        verify(follower2MockCandidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
 
         // Unregister follower1 candidate for entity2 and verify follower2 becomes owner
 
         follower1EntityOwnershipService.unregisterCandidate(ENTITY2, follower1MockCandidate);
 
         // Unregister follower1 candidate for entity2 and verify follower2 becomes owner
 
         follower1EntityOwnershipService.unregisterCandidate(ENTITY2, follower1MockCandidate);
-        verify(follower2MockCandidate, timeout(5000)).ownershipChanged(ENTITY2, false, true);
+        verifyOwner(leaderDistributedDataStore, ENTITY2, "member-3");
+        verify(follower2MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, false, true, true));
+        verify(follower1MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, true, false, true));
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, false, false, true));
+        verifyCandidates(leaderDistributedDataStore, ENTITY2, "member-3");
 
         // Register follower1 candidate for entity3 and verify it becomes owner
 
         follower1EntityOwnershipService.registerCandidate(ENTITY3, follower1MockCandidate);
 
         // Register follower1 candidate for entity3 and verify it becomes owner
 
         follower1EntityOwnershipService.registerCandidate(ENTITY3, follower1MockCandidate);
-        verify(follower1MockCandidate, timeout(5000)).ownershipChanged(ENTITY3, false, true);
         verifyOwner(leaderDistributedDataStore, ENTITY3, "member-2");
         verifyOwner(leaderDistributedDataStore, ENTITY3, "member-2");
+        verify(follower1MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY3, false, true, true));
+        verify(follower2MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY3, false, false, true));
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY3, false, false, true));
 
         // Register follower2 candidate for entity4 and verify it becomes owner
 
         follower2EntityOwnershipService.registerCandidate(ENTITY4, follower2MockCandidate);
 
         // Register follower2 candidate for entity4 and verify it becomes owner
 
         follower2EntityOwnershipService.registerCandidate(ENTITY4, follower2MockCandidate);
-        verify(follower2MockCandidate, timeout(5000)).ownershipChanged(ENTITY4, false, true);
-        reset(follower2MockCandidate);
+        verifyOwner(leaderDistributedDataStore, ENTITY4, "member-3");
+        verify(follower2MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY4, false, true, true));
+        verify(follower1MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY4, false, false, true));
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY4, false, false, true));
+        reset(follower2MockListener);
 
         // Register follower1 candidate for entity4 and verify it gets added but doesn't become owner
 
 
         // Register follower1 candidate for entity4 and verify it gets added but doesn't become owner
 
@@ -204,26 +231,29 @@ public class DistributedEntityOwnershipIntegrationTest {
         follower1EntityOwnershipService.registerCandidate(ENTITY4, follower1MockCandidate);
         verifyCandidates(leaderDistributedDataStore, ENTITY4, "member-3", "member-2");
         verifyOwner(leaderDistributedDataStore, ENTITY4, "member-3");
         follower1EntityOwnershipService.registerCandidate(ENTITY4, follower1MockCandidate);
         verifyCandidates(leaderDistributedDataStore, ENTITY4, "member-3", "member-2");
         verifyOwner(leaderDistributedDataStore, ENTITY4, "member-3");
-        verify(follower1MockCandidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
 
         // Shutdown follower2 and verify it's owned entities (entity 2 & 4) get re-assigned
 
 
         // Shutdown follower2 and verify it's owned entities (entity 2 & 4) get re-assigned
 
-        reset(follower1MockCandidate);
+        reset(leaderMockListener, follower1MockListener);
         JavaTestKit.shutdownActorSystem(follower2System);
 
         JavaTestKit.shutdownActorSystem(follower2System);
 
-        verify(follower1MockCandidate, timeout(15000)).ownershipChanged(ENTITY4, false, true);
+        verify(follower1MockListener, timeout(15000)).ownershipChanged(ownershipChange(ENTITY4, false, true, true));
+        verify(leaderMockListener, timeout(15000)).ownershipChanged(ownershipChange(ENTITY4, false, false, true));
+        verify(leaderMockListener, timeout(15000)).ownershipChanged(ownershipChange(ENTITY2, false, false, false));
         verifyOwner(leaderDistributedDataStore, ENTITY2, ""); // no other candidate
 
         // Register leader candidate for entity2 and verify it becomes owner
 
         leaderEntityOwnershipService.registerCandidate(ENTITY2, leaderMockCandidate);
         verifyOwner(leaderDistributedDataStore, ENTITY2, ""); // no other candidate
 
         // Register leader candidate for entity2 and verify it becomes owner
 
         leaderEntityOwnershipService.registerCandidate(ENTITY2, leaderMockCandidate);
-        verify(leaderMockCandidate, timeout(5000)).ownershipChanged(ENTITY2, false, true);
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, false, true, true));
         verifyOwner(leaderDistributedDataStore, ENTITY2, "member-1");
 
         // Unregister leader candidate for entity2 and verify the owner is cleared
 
         leaderEntityOwnershipService.unregisterCandidate(ENTITY2, leaderMockCandidate);
         verifyOwner(leaderDistributedDataStore, ENTITY2, "");
         verifyOwner(leaderDistributedDataStore, ENTITY2, "member-1");
 
         // Unregister leader candidate for entity2 and verify the owner is cleared
 
         leaderEntityOwnershipService.unregisterCandidate(ENTITY2, leaderMockCandidate);
         verifyOwner(leaderDistributedDataStore, ENTITY2, "");
+        verify(leaderMockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, true, false, false));
+        verify(follower1MockListener, timeout(5000)).ownershipChanged(ownershipChange(ENTITY2, false, false, false));
     }
 
     private void verifyCandidates(DistributedDataStore dataStore, Entity entity, String... expCandidates) throws Exception {
     }
 
     private void verifyCandidates(DistributedDataStore dataStore, Entity entity, String... expCandidates) throws Exception {
index 8b80d6b9e76ecceaec30993d7e42496466aae578..e13f45640cc73287338b52a3e46007c3f17510e4 100644 (file)
@@ -59,48 +59,78 @@ public class EntityOwnerChangeListenerTest {
     public void testOnDataTreeChanged() throws Exception {
         writeNode(ENTITY_OWNERS_PATH, entityOwnersWithCandidate(ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME));
         writeNode(ENTITY_OWNERS_PATH, entityOwnersWithCandidate(ENTITY_TYPE, ENTITY_ID2, LOCAL_MEMBER_NAME));
     public void testOnDataTreeChanged() throws Exception {
         writeNode(ENTITY_OWNERS_PATH, entityOwnersWithCandidate(ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME));
         writeNode(ENTITY_OWNERS_PATH, entityOwnersWithCandidate(ENTITY_TYPE, ENTITY_ID2, LOCAL_MEMBER_NAME));
-        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(),
+                anyBoolean(), anyBoolean());
+
+        // Write local member as owner for entity 1
 
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, LOCAL_MEMBER_NAME));
 
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, LOCAL_MEMBER_NAME));
-        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, false, true);
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, false, true, true);
+
+        // Add remote member 1 as candidate for entity 1 - listener support should not get notified
 
         reset(mockListenerSupport);
         writeNode(ENTITY_OWNERS_PATH, entityOwnersWithCandidate(ENTITY_TYPE, ENTITY_ID1, REMOTE_MEMBER_NAME1));
 
         reset(mockListenerSupport);
         writeNode(ENTITY_OWNERS_PATH, entityOwnersWithCandidate(ENTITY_TYPE, ENTITY_ID1, REMOTE_MEMBER_NAME1));
-        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(),
+                anyBoolean(), anyBoolean());
+
+        // Change owner to remote member 1 for entity 1
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, REMOTE_MEMBER_NAME1));
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, REMOTE_MEMBER_NAME1));
-        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, true, false);
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, true, false, true);
+
+        // Change owner to remote member 2 for entity 1
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, REMOTE_MEMBER_NAME2));
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, REMOTE_MEMBER_NAME2));
-        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, false, false, true);
+
+        // Clear the owner for entity 1
+
+        reset(mockListenerSupport);
+        writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, ""));
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, false, false, false);
+
+        // Change owner to the local member for entity 1
 
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, LOCAL_MEMBER_NAME));
 
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID1), entityEntryWithOwner(ENTITY_ID1, LOCAL_MEMBER_NAME));
-        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, false, true);
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY1, false, true, true);
+
+        // Change owner to remote member 2 for entity 2
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, REMOTE_MEMBER_NAME1));
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, REMOTE_MEMBER_NAME1));
-        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY2, false, false, true);
+
+        // Change owner to the local member for entity 2
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, LOCAL_MEMBER_NAME));
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, LOCAL_MEMBER_NAME));
-        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY2, false, true);
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY2, false, true, true);
+
+        // Write local member owner for entity 2 again - expect no change
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, LOCAL_MEMBER_NAME));
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, LOCAL_MEMBER_NAME));
-        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(),
+                anyBoolean(), anyBoolean());
+
+        // Clear the owner for entity 2
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, null));
 
         reset(mockListenerSupport);
         writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, null));
-        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY2, true, false);
+        verify(mockListenerSupport).notifyEntityOwnershipListeners(ENTITY2, true, false, false);
+
+        // Clear the owner for entity 2 again - expect no change
+
+        reset(mockListenerSupport);
+        writeNode(entityPath(ENTITY_TYPE, ENTITY_ID2), entityEntryWithOwner(ENTITY_ID2, null));
+        verify(mockListenerSupport, never()).notifyEntityOwnershipListeners(any(Entity.class), anyBoolean(),
+                anyBoolean(), anyBoolean());
     }
 
     private void writeNode(YangInstanceIdentifier path, NormalizedNode<?, ?> node) throws DataValidationFailedException {
         AbstractEntityOwnershipTest.writeNode(path, node, shardDataTree);
     }
     }
 
     private void writeNode(YangInstanceIdentifier path, NormalizedNode<?, ?> node) throws DataValidationFailedException {
         AbstractEntityOwnershipTest.writeNode(path, node, shardDataTree);
     }
-
-    private void deleteNode(YangInstanceIdentifier path) throws DataValidationFailedException {
-        AbstractEntityOwnershipTest.deleteNode(path, shardDataTree);
-    }
 }
 }
index 50ed12f21bb23487715b269811439b02572b2f1e..ef8e951b1879f1a10bd2ce8626d172abd1aa154d 100644 (file)
@@ -16,10 +16,9 @@ import akka.actor.ActorRef;
 import akka.testkit.TestActorRef;
 import org.junit.After;
 import org.junit.Test;
 import akka.testkit.TestActorRef;
 import org.junit.After;
 import org.junit.Test;
-import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
-import org.opendaylight.controller.cluster.datastore.entityownership.messages.EntityOwnershipChanged;
 import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -29,7 +28,7 @@ import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
  *
  * @author Thomas Pantelis
  */
  *
  * @author Thomas Pantelis
  */
-public class EntityOwnershipListenerActorTest extends AbstractActorTest {
+public class EntityOwnershipListenerActorTest extends AbstractEntityOwnershipTest {
     private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
 
     @After
     private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
 
     @After
@@ -47,9 +46,10 @@ public class EntityOwnershipListenerActorTest extends AbstractActorTest {
         Entity entity = new Entity("test", YangInstanceIdentifier.of(QName.create("test", "id1")));
         boolean wasOwner = false;
         boolean isOwner = true;
         Entity entity = new Entity("test", YangInstanceIdentifier.of(QName.create("test", "id1")));
         boolean wasOwner = false;
         boolean isOwner = true;
-        listenerActor.tell(new EntityOwnershipChanged(entity, wasOwner, isOwner), ActorRef.noSender());
+        boolean hasOwner = true;
+        listenerActor.tell(new EntityOwnershipChange(entity, wasOwner, isOwner, hasOwner), ActorRef.noSender());
 
 
-        verify(mockListener, timeout(5000)).ownershipChanged(entity, wasOwner, isOwner);
+        verify(mockListener, timeout(5000)).ownershipChanged(ownershipChange(entity, wasOwner, isOwner, hasOwner));
     }
 
     @Test
     }
 
     @Test
@@ -57,16 +57,16 @@ public class EntityOwnershipListenerActorTest extends AbstractActorTest {
         EntityOwnershipListener mockListener = mock(EntityOwnershipListener.class);
 
         Entity entity1 = new Entity("test", YangInstanceIdentifier.of(QName.create("test", "id1")));
         EntityOwnershipListener mockListener = mock(EntityOwnershipListener.class);
 
         Entity entity1 = new Entity("test", YangInstanceIdentifier.of(QName.create("test", "id1")));
-        doThrow(new RuntimeException("mock")).when(mockListener).ownershipChanged(entity1, false, true);
+        doThrow(new RuntimeException("mock")).when(mockListener).ownershipChanged(ownershipChange(entity1, false, true, true));
         Entity entity2 = new Entity("test", YangInstanceIdentifier.of(QName.create("test", "id2")));
         Entity entity2 = new Entity("test", YangInstanceIdentifier.of(QName.create("test", "id2")));
-        doNothing().when(mockListener).ownershipChanged(entity2, true, false);
+        doNothing().when(mockListener).ownershipChanged(ownershipChange(entity2, true, false, false));
 
         TestActorRef<EntityOwnershipListenerActor> listenerActor = actorFactory.createTestActor(
                 EntityOwnershipListenerActor.props(mockListener), actorFactory.generateActorId("listener"));
 
 
         TestActorRef<EntityOwnershipListenerActor> listenerActor = actorFactory.createTestActor(
                 EntityOwnershipListenerActor.props(mockListener), actorFactory.generateActorId("listener"));
 
-        listenerActor.tell(new EntityOwnershipChanged(entity1, false, true), ActorRef.noSender());
-        listenerActor.tell(new EntityOwnershipChanged(entity2, true, false), ActorRef.noSender());
+        listenerActor.tell(new EntityOwnershipChange(entity1, false, true, true), ActorRef.noSender());
+        listenerActor.tell(new EntityOwnershipChange(entity2, true, false, false), ActorRef.noSender());
 
 
-        verify(mockListener, timeout(5000)).ownershipChanged(entity2, true, false);
+        verify(mockListener, timeout(5000)).ownershipChanged(ownershipChange(entity2, true, false, false));
     }
 }
     }
 }
index 00448751da91155514e424375612d3b11029251b..2394ee0bb15b5a6e35e92f2607198ad7cda827b4 100644 (file)
@@ -8,8 +8,6 @@
 package org.opendaylight.controller.cluster.datastore.entityownership;
 
 import static org.junit.Assert.assertEquals;
 package org.opendaylight.controller.cluster.datastore.entityownership;
 
 import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -27,7 +25,6 @@ import java.util.concurrent.TimeUnit;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.controller.cluster.datastore.AbstractActorTest;
 import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.cluster.raft.TestActorFactory;
 import org.opendaylight.controller.cluster.raft.utils.DoNothingActor;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
@@ -43,7 +40,7 @@ import scala.collection.immutable.Iterable;
  *
  * @author Thomas Pantelis
  */
  *
  * @author Thomas Pantelis
  */
-public class EntityOwnershipListenerSupportTest extends AbstractActorTest {
+public class EntityOwnershipListenerSupportTest extends AbstractEntityOwnershipTest {
     private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
     private ActorContext actorContext;
 
     private final TestActorFactory actorFactory = new TestActorFactory(getSystem());
     private ActorContext actorContext;
 
@@ -83,73 +80,73 @@ public class EntityOwnershipListenerSupportTest extends AbstractActorTest {
 
         // Notify entity1 changed and verify listeners are notified.
 
 
         // Notify entity1 changed and verify listeners are notified.
 
-        support.notifyEntityOwnershipListeners(entity1, false, true);
+        support.notifyEntityOwnershipListeners(entity1, false, true, true);
 
 
-        verify(mockListener1, timeout(5000)).ownershipChanged(entity1, false, true);
-        verify(mockListener2, timeout(5000)).ownershipChanged(entity1, false, true);
-        verify(mockListener3, timeout(5000)).ownershipChanged(entity1, false, true);
+        verify(mockListener1, timeout(5000)).ownershipChanged(ownershipChange(entity1, false, true, true));
+        verify(mockListener2, timeout(5000)).ownershipChanged(ownershipChange(entity1, false, true, true));
+        verify(mockListener3, timeout(5000)).ownershipChanged(ownershipChange(entity1, false, true, true));
         assertEquals("# of listener actors", 3, actorContext.children().size());
 
         // Notify entity2 changed and verify only mockListener1 and mockListener3 are notified.
 
         assertEquals("# of listener actors", 3, actorContext.children().size());
 
         // Notify entity2 changed and verify only mockListener1 and mockListener3 are notified.
 
-        support.notifyEntityOwnershipListeners(entity2, false, true);
+        support.notifyEntityOwnershipListeners(entity2, false, false, false);
 
 
-        verify(mockListener1, timeout(5000)).ownershipChanged(entity2, false, true);
-        verify(mockListener3, timeout(5000)).ownershipChanged(entity2, false, true);
+        verify(mockListener1, timeout(5000)).ownershipChanged(ownershipChange(entity2, false, false, false));
+        verify(mockListener3, timeout(5000)).ownershipChanged(ownershipChange(entity2, false, false, false));
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(mockListener2, never()).ownershipChanged(eq(entity2), anyBoolean(), anyBoolean());
+        verify(mockListener2, never()).ownershipChanged(ownershipChange(entity2));
         assertEquals("# of listener actors", 3, actorContext.children().size());
 
         // Notify entity3 changed and verify only mockListener3 is notified.
 
         assertEquals("# of listener actors", 3, actorContext.children().size());
 
         // Notify entity3 changed and verify only mockListener3 is notified.
 
-        support.notifyEntityOwnershipListeners(entity3, false, true);
+        support.notifyEntityOwnershipListeners(entity3, false, true, true);
 
 
-        verify(mockListener3, timeout(5000)).ownershipChanged(entity3, false, true);
+        verify(mockListener3, timeout(5000)).ownershipChanged(ownershipChange(entity3, false, true, true));
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(mockListener1, never()).ownershipChanged(eq(entity3), anyBoolean(), anyBoolean());
-        verify(mockListener2, never()).ownershipChanged(eq(entity3), anyBoolean(), anyBoolean());
+        verify(mockListener1, never()).ownershipChanged(ownershipChange(entity3));
+        verify(mockListener2, never()).ownershipChanged(ownershipChange(entity3));
 
         // Notify entity4 changed and verify no listeners are notified.
 
 
         // Notify entity4 changed and verify no listeners are notified.
 
-        support.notifyEntityOwnershipListeners(entity4, false, true);
+        support.notifyEntityOwnershipListeners(entity4, true, false, true);
 
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
 
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(mockListener1, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
-        verify(mockListener2, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
-        verify(mockListener3, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
+        verify(mockListener1, never()).ownershipChanged(ownershipChange(entity4));
+        verify(mockListener2, never()).ownershipChanged(ownershipChange(entity4));
+        verify(mockListener3, never()).ownershipChanged(ownershipChange(entity4));
 
         // Notify entity5 changed and verify no listener is notified.
 
 
         // Notify entity5 changed and verify no listener is notified.
 
-        support.notifyEntityOwnershipListeners(entity5, false, true);
+        support.notifyEntityOwnershipListeners(entity5, true, false, true);
 
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
 
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(mockListener1, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
-        verify(mockListener2, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
-        verify(mockListener3, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
+        verify(mockListener1, never()).ownershipChanged(ownershipChange(entity4));
+        verify(mockListener2, never()).ownershipChanged(ownershipChange(entity4));
+        verify(mockListener3, never()).ownershipChanged(ownershipChange(entity4));
 
         reset(mockListener1, mockListener2, mockListener3);
 
         // Unregister mockListener1 for entity1, issue a change and verify only mockListeners 2 & 3 are notified.
 
         support.removeEntityOwnershipListener(entity1, mockListener1);
 
         reset(mockListener1, mockListener2, mockListener3);
 
         // Unregister mockListener1 for entity1, issue a change and verify only mockListeners 2 & 3 are notified.
 
         support.removeEntityOwnershipListener(entity1, mockListener1);
-        support.notifyEntityOwnershipListeners(entity1, false, true);
+        support.notifyEntityOwnershipListeners(entity1, true, false, true);
 
 
-        verify(mockListener2, timeout(5000)).ownershipChanged(entity1, false, true);
-        verify(mockListener3, timeout(5000)).ownershipChanged(entity1, false, true);
+        verify(mockListener2, timeout(5000)).ownershipChanged(ownershipChange(entity1, true, false, true));
+        verify(mockListener3, timeout(5000)).ownershipChanged(ownershipChange(entity1, true, false, true));
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(mockListener1, never()).ownershipChanged(eq(entity1), anyBoolean(), anyBoolean());
+        verify(mockListener1, never()).ownershipChanged(ownershipChange(entity1));
 
         // Unregister mockListener3, issue a change for entity1 and verify only mockListeners2 is notified.
 
         reset(mockListener1, mockListener2, mockListener3);
 
         support.removeEntityOwnershipListener(entity1.getType(), mockListener3);
 
         // Unregister mockListener3, issue a change for entity1 and verify only mockListeners2 is notified.
 
         reset(mockListener1, mockListener2, mockListener3);
 
         support.removeEntityOwnershipListener(entity1.getType(), mockListener3);
-        support.notifyEntityOwnershipListeners(entity1, false, true);
+        support.notifyEntityOwnershipListeners(entity1, false, false, false);
 
 
-        verify(mockListener2, timeout(5000)).ownershipChanged(entity1, false, true);
+        verify(mockListener2, timeout(5000)).ownershipChanged(ownershipChange(entity1, false, false, false));
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(mockListener1, never()).ownershipChanged(eq(entity1), anyBoolean(), anyBoolean());
-        verify(mockListener3, never()).ownershipChanged(eq(entity1), anyBoolean(), anyBoolean());
+        verify(mockListener1, never()).ownershipChanged(ownershipChange(entity1));
+        verify(mockListener3, never()).ownershipChanged(ownershipChange(entity1));
 
         // Completely unregister all listeners and verify their listener actors are destroyed.
 
 
         // Completely unregister all listeners and verify their listener actors are destroyed.
 
@@ -180,11 +177,11 @@ public class EntityOwnershipListenerSupportTest extends AbstractActorTest {
 
         support.addEntityOwnershipListener(entity1, mockListener1);
 
 
         support.addEntityOwnershipListener(entity1, mockListener1);
 
-        support.notifyEntityOwnershipListeners(entity1, false, true);
+        support.notifyEntityOwnershipListeners(entity1, false, false, true);
 
 
-        verify(mockListener1, timeout(5000)).ownershipChanged(entity1, false, true);
-        verify(mockListener2, never()).ownershipChanged(eq(entity1), anyBoolean(), anyBoolean());
-        verify(mockListener3, never()).ownershipChanged(eq(entity1), anyBoolean(), anyBoolean());
+        verify(mockListener1, timeout(5000)).ownershipChanged(ownershipChange(entity1, false, false, true));
+        verify(mockListener2, never()).ownershipChanged(ownershipChange(entity1));
+        verify(mockListener3, never()).ownershipChanged(ownershipChange(entity1));
 
         // Quickly register and unregister mockListener2 - expecting no exceptions.
 
 
         // Quickly register and unregister mockListener2 - expecting no exceptions.
 
index 2dc754472ee9aa2ce490e618b35aab261d8d1f05..c2fbfea98fa3cbf4c70068a89df78b8b1c2028aa 100644 (file)
@@ -7,13 +7,9 @@
  */
 package org.opendaylight.controller.cluster.datastore.entityownership;
 
  */
 package org.opendaylight.controller.cluster.datastore.entityownership;
 
-import static org.hamcrest.CoreMatchers.either;
-import static org.hamcrest.CoreMatchers.equalTo;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertEquals;
+import static org.mockito.AdditionalMatchers.or;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyBoolean;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -40,7 +36,6 @@ import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
-import org.hamcrest.Matcher;
 import org.junit.After;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.AbstractShardTest;
 import org.junit.After;
 import org.junit.Test;
 import org.opendaylight.controller.cluster.datastore.AbstractShardTest;
@@ -72,6 +67,7 @@ import org.opendaylight.controller.cluster.raft.messages.RequestVoteReply;
 import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidate;
 import org.opendaylight.controller.md.cluster.datastore.model.SchemaContextHelper;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidate;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -124,7 +120,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
     }
 
     @Test
     }
 
     @Test
@@ -155,7 +151,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
 
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
     }
 
     @Test
     }
 
     @Test
@@ -198,7 +194,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
 
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
     }
 
     @Test
     }
 
     @Test
@@ -237,7 +233,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
 
         verifyOwner(shard, ENTITY_TYPE, entityId, LOCAL_MEMBER_NAME);
 
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
     }
 
     @Test
     }
 
     @Test
@@ -328,7 +324,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
 
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
 
         // Unregister
 
 
         // Unregister
 
@@ -338,7 +334,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         kit.expectMsgClass(SuccessReply.class);
 
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, "");
         kit.expectMsgClass(SuccessReply.class);
 
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, "");
-        verify(candidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        //verify(candidate).ownershipChanged(entity, true, false, false);
 
         // Register again
 
 
         // Register again
 
@@ -347,7 +343,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
 
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
     }
 
     @Test
     }
 
     @Test
@@ -375,7 +371,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
-        verify(candidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(candidate, never()).ownershipChanged(any(EntityOwnershipChange.class));
 
         // Add another remote candidate and verify ownership doesn't change
 
 
         // Add another remote candidate and verify ownership doesn't change
 
@@ -386,7 +382,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName2);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName2);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
-        verify(candidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(candidate, never()).ownershipChanged(any(EntityOwnershipChange.class));
 
         // Remove the second remote candidate and verify ownership doesn't change
 
 
         // Remove the second remote candidate and verify ownership doesn't change
 
@@ -396,7 +392,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         verifyEntityCandidateRemoved(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName2);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyEntityCandidateRemoved(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName2);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
-        verify(candidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(candidate, never()).ownershipChanged(any(EntityOwnershipChange.class));
 
         // Remove the first remote candidate and verify the local candidate becomes owner
 
 
         // Remove the first remote candidate and verify the local candidate becomes owner
 
@@ -405,7 +401,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyEntityCandidateRemoved(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
 
         verifyEntityCandidateRemoved(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName1);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
 
         // Add the second remote candidate back and verify ownership doesn't change
 
 
         // Add the second remote candidate back and verify ownership doesn't change
 
@@ -415,7 +411,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName2);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
         verifyCommittedEntityCandidate(shard, ENTITY_TYPE, ENTITY_ID1, remoteMemberName2);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         verifyOwner(shard, ENTITY_TYPE, ENTITY_ID1, LOCAL_MEMBER_NAME);
-        verify(candidate, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(candidate, never()).ownershipChanged(any(EntityOwnershipChange.class));
 
         // Unregister the local candidate and verify the second remote candidate becomes owner
 
 
         // Unregister the local candidate and verify the second remote candidate becomes owner
 
@@ -641,7 +637,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         shard.tell(new RegisterCandidateLocal(candidate, entity), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
         verifyCommittedEntityCandidate(shard, entity.getType(), entity.getId(), LOCAL_MEMBER_NAME);
         shard.tell(new RegisterCandidateLocal(candidate, entity), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
         verifyCommittedEntityCandidate(shard, entity.getType(), entity.getId(), LOCAL_MEMBER_NAME);
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
         reset(candidate);
 
         // Simulate a replicated commit from the leader to remove the local candidate that would occur after a
         reset(candidate);
 
         // Simulate a replicated commit from the leader to remove the local candidate that would occur after a
@@ -649,12 +645,12 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         leader.tell(new PeerDown(LOCAL_MEMBER_NAME, localId.toString()), ActorRef.noSender());
 
 
         leader.tell(new PeerDown(LOCAL_MEMBER_NAME, localId.toString()), ActorRef.noSender());
 
-        verify(candidate, timeout(5000)).ownershipChanged(entity, true, false);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, true, false, false));
 
         // Since the the shard has a local candidate registered, it should re-add its candidate to the entity.
 
         verifyCommittedEntityCandidate(shard, entity.getType(), entity.getId(), LOCAL_MEMBER_NAME);
 
         // Since the the shard has a local candidate registered, it should re-add its candidate to the entity.
 
         verifyCommittedEntityCandidate(shard, entity.getType(), entity.getId(), LOCAL_MEMBER_NAME);
-        verify(candidate, timeout(5000)).ownershipChanged(entity, false, true);
+        verify(candidate, timeout(5000)).ownershipChanged(ownershipChange(entity, false, true, true));
 
         // Unregister the local candidate and verify it's removed and no re-added.
 
 
         // Unregister the local candidate and verify it's removed and no re-added.
 
@@ -691,12 +687,12 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         shard.tell(new RegisterCandidateLocal(candidate, entity1), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
         shard.tell(new RegisterCandidateLocal(candidate, entity1), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
-        verify(listener, timeout(5000)).ownershipChanged(entity1, false, true);
+        verify(listener, timeout(5000)).ownershipChanged(ownershipChange(entity1, false, true, true));
 
         shard.tell(new RegisterCandidateLocal(candidate, entity2), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
 
         shard.tell(new RegisterCandidateLocal(candidate, entity2), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
-        verify(listener, timeout(5000)).ownershipChanged(entity2, false, true);
+        verify(listener, timeout(5000)).ownershipChanged(ownershipChange(entity2, false, true, true));
         reset(listener);
 
         // Register another candidate for another entity type and verify listener is not notified.
         reset(listener);
 
         // Register another candidate for another entity type and verify listener is not notified.
@@ -705,7 +701,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         kit.expectMsgClass(SuccessReply.class);
 
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
         kit.expectMsgClass(SuccessReply.class);
 
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
-        verify(listener, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
+        verify(listener, never()).ownershipChanged(ownershipChange(entity4));
 
         // Register remote candidate for entity1
 
 
         // Register remote candidate for entity1
 
@@ -719,7 +715,7 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
         shard.tell(new UnregisterCandidateLocal(candidate, entity1), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
         shard.tell(new UnregisterCandidateLocal(candidate, entity1), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
-        verify(listener, timeout(5000)).ownershipChanged(entity1, true, false);
+        verify(listener, timeout(5000)).ownershipChanged(ownershipChange(entity1, true, false, true));
         reset(listener);
 
         // Unregister the listener, add a candidate for entity3 and verify listener isn't notified
         reset(listener);
 
         // Unregister the listener, add a candidate for entity3 and verify listener isn't notified
@@ -732,22 +728,22 @@ public class EntityOwnershipShardTest extends AbstractEntityOwnershipTest {
 
         verifyOwner(shard, ENTITY_TYPE, entity3.getId(), LOCAL_MEMBER_NAME);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
 
         verifyOwner(shard, ENTITY_TYPE, entity3.getId(), LOCAL_MEMBER_NAME);
         Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
-        verify(listener, never()).ownershipChanged(any(Entity.class), anyBoolean(), anyBoolean());
+        verify(listener, never()).ownershipChanged(any(EntityOwnershipChange.class));
 
 
-        // Re-register the listener and verify it gets notified of current locally owned entities
+        // Re-register the listener and verify it gets notified of currently owned entities
 
         reset(listener, candidate);
 
         shard.tell(new RegisterListenerLocal(listener, ENTITY_TYPE), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
 
         reset(listener, candidate);
 
         shard.tell(new RegisterListenerLocal(listener, ENTITY_TYPE), kit.getRef());
         kit.expectMsgClass(SuccessReply.class);
 
-        Matcher<Entity> entityMatcher = either(equalTo(entity2)).or(equalTo(entity3));
-        verify(listener, timeout(5000).times(2)).ownershipChanged(argThat(entityMatcher), eq(false), eq(true));
+        verify(listener, timeout(5000).times(2)).ownershipChanged(or(ownershipChange(entity2, false, true, true),
+                ownershipChange(entity3, false, true, true)));
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
         Uninterruptibles.sleepUninterruptibly(300, TimeUnit.MILLISECONDS);
-        verify(listener, never()).ownershipChanged(eq(entity4), anyBoolean(), anyBoolean());
-        verify(listener, never()).ownershipChanged(eq(entity1), anyBoolean(), anyBoolean());
-        verify(candidate, never()).ownershipChanged(eq(entity2), anyBoolean(), anyBoolean());
-        verify(candidate, never()).ownershipChanged(eq(entity3), anyBoolean(), anyBoolean());
+        verify(listener, never()).ownershipChanged(ownershipChange(entity4));
+        verify(listener, never()).ownershipChanged(ownershipChange(entity1));
+        verify(candidate, never()).ownershipChanged(ownershipChange(entity2));
+        verify(candidate, never()).ownershipChanged(ownershipChange(entity3));
     }
 
     private void commitModification(TestActorRef<EntityOwnershipShard> shard, NormalizedNode<?, ?> node,
     }
 
     private void commitModification(TestActorRef<EntityOwnershipShard> shard, NormalizedNode<?, ?> node,
index 87aa45c8082cafb0dd8ed75823f0725eae7a38d1..d0b47aebdca04478124b068b265e852206062fde 100644 (file)
@@ -18,6 +18,7 @@ import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidate;
 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidate;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
@@ -173,8 +174,8 @@ public class CarProvider implements CarService {
 
     private static class CarEntityOwnershipCandidate implements EntityOwnershipCandidate {
         @Override
 
     private static class CarEntityOwnershipCandidate implements EntityOwnershipCandidate {
         @Override
-        public void ownershipChanged(Entity entity, boolean wasOwner, boolean isOwner) {
-            LOG.info("ownershipChanged: entity: {}, wasOwner: {}, isOwner: ()", entity, wasOwner, isOwner);
+        public void ownershipChanged(EntityOwnershipChange ownershipChange) {
+            LOG.info("ownershipChanged: {}", ownershipChange);
         }
     }
 }
         }
     }
 }