From a48538374b8cd6617b6c8ce3adcdc9f30354a732 Mon Sep 17 00:00:00 2001 From: Moiz Raja Date: Fri, 31 Jul 2015 15:40:17 -0700 Subject: [PATCH] Bug 4105: Add public EntityOwnershipService interface Change-Id: If65f6ef8116b0a8481a3af1aee88e444771d9e3f Signed-off-by: Moiz Raja --- opendaylight/md-sal/sal-common-api/pom.xml | 4 + .../CandidateAlreadyRegisteredException.java | 57 ++++++++++ .../md/sal/common/api/clustering/Entity.java | 106 ++++++++++++++++++ .../clustering/EntityOwnershipCandidate.java | 18 +++ .../EntityOwnershipCandidateRegistration.java | 17 +++ .../clustering/EntityOwnershipListener.java | 25 +++++ .../EntityOwnershipListenerRegistration.java | 30 +++++ .../clustering/EntityOwnershipService.java | 47 ++++++++ 8 files changed, 304 insertions(+) create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/CandidateAlreadyRegisteredException.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/Entity.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidate.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidateRegistration.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListener.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListenerRegistration.java create mode 100644 opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipService.java diff --git a/opendaylight/md-sal/sal-common-api/pom.xml b/opendaylight/md-sal/sal-common-api/pom.xml index fe44128079..b502dac6a9 100644 --- a/opendaylight/md-sal/sal-common-api/pom.xml +++ b/opendaylight/md-sal/sal-common-api/pom.xml @@ -27,6 +27,10 @@ org.opendaylight.yangtools yang-common + + org.opendaylight.yangtools + yang-data-api + 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 index 0000000000..f509b4002b --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/CandidateAlreadyRegisteredException.java @@ -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 index 0000000000..3b9f8a425e --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/Entity.java @@ -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; + +/** + *

+ * A clustered Entity is something which is shared by multiple applications across a cluster. An Entity has a type + * and an identifier. + *

+ *

+ * 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. + *

+ *

+ * 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. + *

+ */ +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 index 0000000000..085b4fbaf6 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidate.java @@ -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; + +/** + *

+ * 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. + *

+ */ +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 index 0000000000..43bf779b89 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipCandidateRegistration.java @@ -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 index 0000000000..96b9ec2e5f --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListener.java @@ -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 index 0000000000..ff9c851b14 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipListenerRegistration.java @@ -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 { + + /** + * + * @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 index 0000000000..fc15dac9d3 --- /dev/null +++ b/opendaylight/md-sal/sal-common-api/src/main/java/org/opendaylight/controller/md/sal/common/api/clustering/EntityOwnershipService.java @@ -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; + +/** + *

+ * 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. + *

+ *

+ * A component/application may also register interest in the ownership status of an Entity. The listener would be + * notified whenever the ownership status changes. + *

+ */ +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); + +} -- 2.36.6