[ONOS-7117] Support configuring LeaderElector primitive session timeouts for faster leader elections

Change-Id: I81aa71cbb08ee31c145addbf00a6446ff4a5f9ed
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 6b2a54c..5fad35a 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
@@ -16,6 +16,7 @@
 package org.onosproject.store.primitives;
 
 import java.util.Set;
+import java.util.concurrent.TimeUnit;
 
 import org.onosproject.store.service.AsyncAtomicCounter;
 import org.onosproject.store.service.AsyncAtomicCounterMap;
@@ -31,6 +32,8 @@
 import org.onosproject.store.service.Serializer;
 import org.onosproject.store.service.WorkQueue;
 
+import static org.onosproject.store.service.DistributedPrimitive.DEFAULT_OPERATION_TIMEOUT_MILLIS;
+
 /**
  * Interface for entity that can create instances of different distributed primitives.
  */
@@ -120,7 +123,19 @@
      * @param name leader elector name
      * @return leader elector
      */
-    AsyncLeaderElector newAsyncLeaderElector(String name);
+    default AsyncLeaderElector newAsyncLeaderElector(String name) {
+        return newAsyncLeaderElector(name, DEFAULT_OPERATION_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
+    }
+
+    /**
+     * Creates a new {@code AsyncLeaderElector}.
+     *
+     * @param name leader elector name
+     * @param electionTimeout leader election timeout
+     * @param timeUnit leader election timeout time unit
+     * @return leader elector
+     */
+    AsyncLeaderElector newAsyncLeaderElector(String name, long electionTimeout, TimeUnit timeUnit);
 
     /**
      * Creates a new {@code WorkQueue}.
diff --git a/core/api/src/main/java/org/onosproject/store/service/LeaderElectorBuilder.java b/core/api/src/main/java/org/onosproject/store/service/LeaderElectorBuilder.java
index d395cc5..d3d6951 100644
--- a/core/api/src/main/java/org/onosproject/store/service/LeaderElectorBuilder.java
+++ b/core/api/src/main/java/org/onosproject/store/service/LeaderElectorBuilder.java
@@ -15,6 +15,8 @@
  */
 package org.onosproject.store.service;
 
+import java.util.concurrent.TimeUnit;
+
 import org.onosproject.store.primitives.DistributedPrimitiveBuilder;
 
 /**
@@ -22,7 +24,41 @@
  */
 public abstract class LeaderElectorBuilder
     extends DistributedPrimitiveBuilder<LeaderElectorBuilder, AsyncLeaderElector> {
+
+    private long electionTimeoutMillis = DistributedPrimitive.DEFAULT_OPERATION_TIMEOUT_MILLIS;
+
     public LeaderElectorBuilder() {
         super(DistributedPrimitive.Type.LEADER_ELECTOR);
     }
+
+    /**
+     * Sets the election timeout in milliseconds.
+     *
+     * @param electionTimeoutMillis the election timeout in milliseconds
+     * @return leader elector builder
+     */
+    public LeaderElectorBuilder withElectionTimeout(long electionTimeoutMillis) {
+        this.electionTimeoutMillis = electionTimeoutMillis;
+        return this;
+    }
+
+    /**
+     * Sets the election timeout.
+     *
+     * @param electionTimeout the election timeout
+     * @param timeUnit the timeout time unit
+     * @return leader elector builder
+     */
+    public LeaderElectorBuilder withElectionTimeout(long electionTimeout, TimeUnit timeUnit) {
+        return withElectionTimeout(timeUnit.toMillis(electionTimeout));
+    }
+
+    /**
+     * Returns the election timeout in milliseconds.
+     *
+     * @return the election timeout in milliseconds
+     */
+    public final long electionTimeoutMillis() {
+        return electionTimeoutMillis;
+    }
 }
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultLeaderElectorBuilder.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultLeaderElectorBuilder.java
index 24f3f9b..9cef490 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultLeaderElectorBuilder.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/DefaultLeaderElectorBuilder.java
@@ -15,6 +15,8 @@
  */
 package org.onosproject.store.primitives.impl;
 
+import java.util.concurrent.TimeUnit;
+
 import org.onosproject.store.primitives.DistributedPrimitiveCreator;
 import org.onosproject.store.service.AsyncLeaderElector;
 import org.onosproject.store.service.LeaderElectorBuilder;
@@ -32,6 +34,6 @@
 
     @Override
     public AsyncLeaderElector build() {
-        return primitiveCreator.newAsyncLeaderElector(name());
+        return primitiveCreator.newAsyncLeaderElector(name(), electionTimeoutMillis(), TimeUnit.MILLISECONDS);
     }
 }
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java
index 85999ab..2478600 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/FederatedDistributedPrimitiveCreator.java
@@ -19,6 +19,7 @@
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 
 import com.google.common.base.Charsets;
@@ -123,11 +124,11 @@
     }
 
     @Override
-    public AsyncLeaderElector newAsyncLeaderElector(String name) {
+    public AsyncLeaderElector newAsyncLeaderElector(String name, long leaderTimeout, TimeUnit timeUnit) {
         checkNotNull(name);
         Map<PartitionId, AsyncLeaderElector> leaderElectors =
                 Maps.transformValues(members,
-                                     partition -> partition.newAsyncLeaderElector(name));
+                                     partition -> partition.newAsyncLeaderElector(name, leaderTimeout, timeUnit));
         Hasher<String> hasher = topic -> {
             int hashCode = Hashing.sha256().hashString(topic, Charsets.UTF_8).asInt();
             return sortedMemberPartitionIds.get(Math.abs(hashCode) % members.size());
diff --git a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
index 96e5140..53a7dd1 100644
--- a/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
+++ b/core/store/primitives/src/main/java/org/onosproject/store/primitives/impl/StoragePartitionClient.java
@@ -18,6 +18,7 @@
 import java.time.Duration;
 import java.util.Set;
 import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
 import com.google.common.base.Suppliers;
@@ -257,13 +258,13 @@
     }
 
     @Override
-    public AsyncLeaderElector newAsyncLeaderElector(String name) {
+    public AsyncLeaderElector newAsyncLeaderElector(String name, long leaderTimeout, TimeUnit timeUnit) {
         AtomixLeaderElector leaderElector = new AtomixLeaderElector(client.newProxyBuilder()
                 .withName(name)
                 .withServiceType(DistributedPrimitive.Type.LEADER_ELECTOR.name())
                 .withReadConsistency(ReadConsistency.LINEARIZABLE)
                 .withCommunicationStrategy(CommunicationStrategy.LEADER)
-                .withTimeout(Duration.ofSeconds(5))
+                .withTimeout(Duration.ofMillis(timeUnit.toMillis(leaderTimeout)))
                 .withMaxRetries(5)
                 .build()
                 .open()