Bug 4105: Add public EntityOwnershipService interface 85/26785/2
authorMoiz Raja <moraja@cisco.com>
Fri, 31 Jul 2015 22:40:17 +0000 (15:40 -0700)
committerGerrit Code Review <gerrit@opendaylight.org>
Thu, 10 Sep 2015 19:47:59 +0000 (19:47 +0000)
Change-Id: If65f6ef8116b0a8481a3af1aee88e444771d9e3f
Signed-off-by: Moiz Raja <moraja@cisco.com>
opendaylight/md-sal/sal-common-api/pom.xml
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/CandidateAlreadyRegisteredException.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/Entity.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidate.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidateRegistration.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 [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListenerRegistration.java [new file with mode: 0644]
opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipService.java [new file with mode: 0644]

index fe44128079aee6463a35e58ec4ccca0a23f9bf24..b502dac6a99392ab4d6a95e9f0af152244fef2e3 100644 (file)
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-common</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-api</artifactId>
+    </dependency>
   </dependencies>
 
   <scm>
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/CandidateAlreadyRegisteredException.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/CandidateAlreadyRegisteredException.java
new file mode 100644 (file)
index 0000000..f509b40
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2015 Cisco 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;
+
+/**
+ * Thrown when a Candidate has already been registered for a given Entity. This could be due to a component doing a
+ * duplicate registration or two different components within the same process trying to register a Candidate.
+ */
+public class CandidateAlreadyRegisteredException extends Exception {
+    private final Entity entity;
+    private final EntityOwnershipCandidate registeredCandidate;
+
+    public CandidateAlreadyRegisteredException(@Nonnull Entity entity,
+                                               @Nonnull EntityOwnershipCandidate registeredCandidate,
+                                               String message) {
+        super(message);
+        this.entity = Preconditions.checkNotNull(entity, "entity should not be null");
+        this.registeredCandidate = Preconditions.checkNotNull(registeredCandidate,
+                "registeredCandidate should not be null");
+    }
+
+    public CandidateAlreadyRegisteredException(@Nonnull Entity entity,
+                                               @Nonnull EntityOwnershipCandidate registeredCandidate,
+                                               String message, Throwable throwable) {
+        super(message, throwable);
+        this.entity = Preconditions.checkNotNull(entity, "entity should not be null");
+        this.registeredCandidate = Preconditions.checkNotNull(registeredCandidate,
+                "registeredCandidate should not be null");
+    }
+
+    /**
+     *
+     * @return the entity for which a Candidate has already been registered in the current process
+     */
+    @Nonnull
+    public Entity getEntity() {
+        return entity;
+    }
+
+    /**
+     *
+     * @return the currently registered candidate
+     */
+    @Nonnull
+    public EntityOwnershipCandidate getRegisteredCandidate() {
+        return registeredCandidate;
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/Entity.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/Entity.java
new file mode 100644 (file)
index 0000000..3b9f8a4
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2015 Cisco 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;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+
+/**
+ * <p></p>
+ * A clustered Entity is something which is shared by multiple applications across a cluster. An Entity has a type
+ * and an identifier.
+ * </p>
+ * <p>
+ * The type describes the type of the Entity where examples of a type maybe "openflow" or "netconf"
+ * etc. An Entity type could be tied to how exactly an application shares and "owns" an entity. For example we may want
+ * an application which deals with the openflow entity to be assigned ownership of that entity based on a first come
+ * first served basis. On the other hand for netconf entity types we may want applications to gain ownership based on
+ * a load balancing approach. While this mechanism of assigning a ownership acquisition strategy is not finalized the
+ * intention is that the entity type will play a role in determining the strategy and thus should be put in place.
+ * </p>
+ * <p>
+ * The identifier is a YangInstanceIdentifier. The reason for the choice of YangInstanceIdentifier is because it
+ * can easily be used to represent a data node. For example an inventory node represents a shared entity and it is best
+ * referenced by the YangInstanceIdentifier if the inventory node stored in the data store.
+ * </p>
+ */
+public final class Entity {
+
+    private final String type;
+    private final YangInstanceIdentifier id;
+
+    /**
+     * Construct a new Entity
+     *
+     * @param type the type of the entity
+     * @param id the identifier of the entity
+     */
+    public Entity(@Nonnull String type, @Nonnull YangInstanceIdentifier id) {
+        this.type = Preconditions.checkNotNull(type, "type should not be null");
+        this.id = Preconditions.checkNotNull(id, "id should not be null");
+    }
+
+    /**
+     *
+     * @return id of entity
+     */
+    @Nonnull
+    public YangInstanceIdentifier getId(){
+        return id;
+    }
+
+    /**
+     *
+     * @return type of entity
+     */
+    @Nonnull
+    public String getType(){
+        return type;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        Entity entity = (Entity) o;
+
+        if (!id.equals(entity.id)) {
+            return false;
+        }
+
+        if (!type.equals(entity.type)) {
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = type != null ? type.hashCode() : 0;
+        result = 31 * result + (id != null ? id.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("Entity{");
+        sb.append("type='").append(type).append('\'');
+        sb.append(", id=").append(id);
+        sb.append('}');
+        return sb.toString();
+    }
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidate.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidate.java
new file mode 100644 (file)
index 0000000..085b4fb
--- /dev/null
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015 Cisco 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;
+
+/**
+ * <p>
+ * An EntityOwnershipCandidate represents a component which would like to own a given Entity.
+ * The EntityOwnershipCandidate will be notified of changes in ownership as it is also an EntityOwnershipListener.
+ * </p>
+ */
+public interface EntityOwnershipCandidate extends EntityOwnershipListener {
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidateRegistration.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidateRegistration.java
new file mode 100644 (file)
index 0000000..43bf779
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015 Cisco 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;
+
+/**
+ * An EntityOwnershipCandidateRegistration records a request to register a Candidate for a given Entity. Calling
+ * close on the EntityOwnershipCandidateRegistration will remove the Candidate from any future ownership considerations
+ * for that Entity and will also remove it as a Listener for ownership status changes.
+ */
+public interface EntityOwnershipCandidateRegistration extends EntityOwnershipListenerRegistration {
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListener.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListener.java
new file mode 100644 (file)
index 0000000..96b9ec2
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 Cisco 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;
+
+/**
+ * An EntityOwnershipListener is a component that represents a listener for entity ownership changes
+ */
+public interface EntityOwnershipListener {
+
+    /**
+     * A notification that is generated when the ownership status for a given entity changes in the current process.
+     *
+     * @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
+     */
+    void ownershipChanged(Entity entity, boolean wasOwner, boolean isOwner);
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListenerRegistration.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListenerRegistration.java
new file mode 100644 (file)
index 0000000..ff9c851
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2015 Cisco 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 org.opendaylight.yangtools.concepts.ObjectRegistration;
+
+/**
+ * An EntityOwnershipListenerRegistration records a request to register a ownership status change listener for a
+ * given Entity. Calling close on the registration will unregister listeners and future ownership changes will not
+ * be delivered to the listener.
+ */
+public interface EntityOwnershipListenerRegistration extends ObjectRegistration<EntityOwnershipListener> {
+
+    /**
+     *
+     * @return the entity that the listener was registered for
+     */
+    Entity getEntity();
+
+    /**
+     * Unregister the listener
+     */
+    void close();
+}
diff --git a/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipService.java b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipService.java
new file mode 100644 (file)
index 0000000..fc15dac
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2015 Cisco 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;
+
+/**
+ * <p>
+ * The EntityOwnershipService provides the means for a component/application to request ownership for a given
+ * Entity on the current cluster member. Entity ownership is always tied to a process and two components on the same
+ * process cannot register a candidate for a given Entity.
+ * </p>
+ * <p>
+ * A component/application may also register interest in the ownership status of an Entity. The listener would be
+ * notified whenever the ownership status changes.
+ * </p>
+ */
+public interface EntityOwnershipService {
+
+    /**
+     * Registers as a Candidate that wants to own the given Entity. Only one such request can be made per process.
+     * If multiple requests for registering a Candidate for a given Entity are received in the current process a
+     * CandidateAlreadyRegisteredException will be thrown
+     *
+     * @param entity the entity which the Candidate wants to own
+     * @param candidate the Candidate that wants to own the entity
+     * @return a registration object that can be used to unregister the Candidate
+     * @throws org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException
+     */
+    EntityOwnershipCandidateRegistration registerCandidate(Entity entity, EntityOwnershipCandidate candidate)
+            throws CandidateAlreadyRegisteredException;
+
+    /**
+     * Registers a Listener that is interested in the ownership status of the given Entity. On registration the Listener
+     * will be notified of the ownership status of the given Entity at the time of registration.
+     *
+     * @param entity the Entity whose ownership status the Listener is interested in
+     * @param listener the Listener that is interested in the entity
+     * @return a registration object that can be used to unregister the Listener
+     */
+    EntityOwnershipListenerRegistration registerListener(Entity entity, EntityOwnershipListener listener);
+
+}