Leader elector distributed primitive interfaces

Change-Id: Ieebf5ddfcf8c5c6a55e4d6d328829cc8dbeef38a
diff --git a/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java b/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java
index fd38d24..08c2dbb 100644
--- a/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java
+++ b/core/api/src/main/java/org/onosproject/store/primitives/DistributedPrimitiveCreator.java
@@ -19,6 +19,7 @@
 import org.onosproject.store.service.AsyncAtomicValue;
 import org.onosproject.store.service.AsyncConsistentMap;
 import org.onosproject.store.service.AsyncDistributedSet;
+import org.onosproject.store.service.AsyncLeaderElector;
 import org.onosproject.store.service.DistributedQueue;
 import org.onosproject.store.service.Serializer;
 
@@ -75,4 +76,12 @@
      * @return set
      */
     <E> AsyncDistributedSet<E> newAsyncDistributedSet(String name, Serializer serializer);
+
+    /**
+     * Creates a new {@code AsyncLeaderElector}.
+     *
+     * @param name leader elector name
+     * @return leader elector
+     */
+    AsyncLeaderElector newAsyncLeaderElector(String name);
 }
\ No newline at end of file
diff --git a/core/api/src/main/java/org/onosproject/store/service/AsyncLeaderElector.java b/core/api/src/main/java/org/onosproject/store/service/AsyncLeaderElector.java
new file mode 100644
index 0000000..000d10f
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/AsyncLeaderElector.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.function.Consumer;
+
+import org.onosproject.cluster.Leadership;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.event.Change;
+
+/**
+ * Distributed mutual exclusion primitive.
+ * <p>
+ * {@code AsyncLeaderElector} facilitates mutually exclusive access to a shared resource by various cluster members.
+ * Each resource is identified by a unique topic name and members register their desire to access the resource by
+ * calling the {@link AsyncLeaderElector#run run} method. Access is grated on a FIFO basis. An instance can
+ * unregister itself from the leadership election by calling {@link AsyncLeaderElector#withdraw withdraw} method.
+ * If an instance currently holding the resource dies then the next instance waiting to be leader (in FIFO order)
+ * will be automatically granted access to the resource.
+ * <p>
+ * One can register listeners to be notified when a leadership change occurs. The Listeners are notified via a
+ * {@link Leadership} {@link Change change} subject.
+ * <p>
+ * Additionally, {@code AsyncLeaderElector} provides methods to query the current state of leadership for topics.
+ * <p>
+ * All methods of this interface return a {@link CompletableFuture future} immediately after a successful invocation.
+ * The operation itself is executed asynchronous and the returned future will be
+ * {@link CompletableFuture#complete completed} when the operation finishes.
+ */
+public interface AsyncLeaderElector extends DistributedPrimitive {
+
+    @Override
+    default DistributedPrimitive.Type type() {
+        return DistributedPrimitive.Type.LEADER_ELECTOR;
+    }
+
+    /**
+     * Attempts to become leader for a topic.
+     * @param topic leadership topic
+     * @param nodeId instance identifier of the node
+     * @return CompletableFuture that is completed with the current Leadership state of the topic
+     */
+    CompletableFuture<Leadership> run(String topic, NodeId nodeId);
+
+    /**
+     * Withdraws from leadership race for a topic.
+     * @param topic leadership topic
+     * @return CompletableFuture that is completed when the withdraw is done
+     */
+    CompletableFuture<Void> withdraw(String topic);
+
+    /**
+     * Attempts to promote a node to leadership displacing the current leader.
+     * @param topic leadership topic
+     * @param nodeId instance identifier of the new leader
+     * @return CompletableFuture that is completed with a boolean when the operation is done. Boolean is true if
+     * leadership transfer was successfully executed; false if it failed. This operation can fail (i.e. return false)
+     * if the node to be made new leader is not registering to run for election for the topic.
+     */
+    CompletableFuture<Boolean> anoint(String topic, NodeId nodeId);
+
+    /**
+     * Returns the {@link Leadership} for the specified topic.
+     * @param topic leadership topic
+     * @return CompletableFuture that is completed with the current Leadership state of the topic
+     */
+    CompletableFuture<Leadership> getLeadership(String topic);
+
+    /**
+     * Returns the current {@link Leadership}s for all topics.
+     * @return CompletableFuture that is completed with the topic to Leadership mapping
+     */
+    CompletableFuture<Map<String, Leadership>> getLeaderships();
+
+    /**
+     * Registers a listener to be notified of Leadership changes for all topics.
+     * @param consumer listener to notify
+     * @return CompletableFuture that is completed when the operation completes
+     */
+    CompletableFuture<Void> addChangeListener(Consumer<Change<Leadership>> consumer);
+
+    /**
+     * Unregisters a previously registered change notification listener.
+     * <p>
+     * If the specified listener was not previously registered, this operation will be a noop.
+     * @param consumer listener to remove
+     * @return CompletableFuture that is completed when the operation completes
+     */
+    CompletableFuture<Void> removeChangeListener(Consumer<Change<Leadership>> consumer);
+}
diff --git a/core/api/src/main/java/org/onosproject/store/service/LeaderElector.java b/core/api/src/main/java/org/onosproject/store/service/LeaderElector.java
new file mode 100644
index 0000000..b5d1c66
--- /dev/null
+++ b/core/api/src/main/java/org/onosproject/store/service/LeaderElector.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2016 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.store.service;
+
+import java.util.Map;
+import java.util.function.Consumer;
+
+import org.onosproject.cluster.Leadership;
+import org.onosproject.cluster.NodeId;
+import org.onosproject.event.Change;
+
+/**
+ * {@code LeaderElector} provides the same functionality as {@link AsyncLeaderElector} with
+ * the only difference that all its methods block until the corresponding operation completes.
+ */
+public interface LeaderElector extends DistributedPrimitive {
+
+    @Override
+    default DistributedPrimitive.Type type() {
+        return DistributedPrimitive.Type.LEADER_ELECTOR;
+    }
+
+    /**
+     * Attempts to become leader for a topic.
+     * @param topic leadership topic
+     * @param nodeId instance identifier of the node
+     * @return current Leadership state of the topic
+     */
+    Leadership run(String topic, NodeId nodeId);
+
+    /**
+     * Withdraws from leadership race for a topic.
+     * @param topic leadership topic
+     */
+    void withdraw(String topic);
+
+    /**
+     * Attempts to promote a node to leadership displacing the current leader.
+     * @param topic leadership topic
+     * @param nodeId instance identifier of the new leader
+     * @return {@code true} if leadership transfer was successfully executed; {@code false} if it failed.
+     * This operation can return {@code false} if the node to be made new leader is not registered to
+     * run for election for the topic.
+     */
+    boolean anoint(String topic, NodeId nodeId);
+
+    /**
+     * Returns the {@link Leadership} for the specified topic.
+     * @param topic leadership topic
+     * @return current Leadership state of the topic
+     */
+    Leadership getLeadership(String topic);
+
+    /**
+     * Returns the current {@link Leadership}s for all topics.
+     * @return topic name to Leadership mapping
+     */
+    Map<String, Leadership> getLeaderships();
+
+    /**
+     * Registers a listener to be notified of Leadership changes for all topics.
+     * @param consumer listener to add
+     */
+    void addChangeListener(Consumer<Change<Leadership>> consumer);
+
+    /**
+     * Unregisters a previously registered change notification listener.
+     * <p>
+     * If the specified listener was not previously registered, this operation will be a noop.
+     * @param consumer listener to remove
+     */
+    void removeChangeListener(Consumer<Change<Leadership>> consumer);
+}