Changing Intent Ids to use explicit id assignment

Change-Id: I5a4bff87842c37a869e7691b353529eaefc929db
diff --git a/core/net/src/main/java/org/onlab/onos/core/impl/BlockAllocatorBasedIdGenerator.java b/core/net/src/main/java/org/onlab/onos/core/impl/BlockAllocatorBasedIdGenerator.java
new file mode 100644
index 0000000..e231394
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/core/impl/BlockAllocatorBasedIdGenerator.java
@@ -0,0 +1,36 @@
+package org.onlab.onos.core.impl;
+
+import org.onlab.onos.core.IdBlock;
+import org.onlab.onos.core.IdGenerator;
+import org.onlab.onos.core.UnavailableIdException;
+
+/**
+ * Base class of {@link IdGenerator} implementations which use {@link IdBlockAllocator} as
+ * backend.
+ */
+public class BlockAllocatorBasedIdGenerator implements IdGenerator {
+    protected final IdBlockAllocator allocator;
+    protected IdBlock idBlock;
+
+    /**
+     * Constructs an ID generator which use {@link IdBlockAllocator} as backend.
+     *
+     * @param allocator
+     */
+    protected BlockAllocatorBasedIdGenerator(IdBlockAllocator allocator) {
+        this.allocator = allocator;
+        this.idBlock = allocator.allocateUniqueIdBlock();
+    }
+
+    @Override
+    public long getNewId() {
+        try {
+            return idBlock.getNextId();
+        } catch (UnavailableIdException e) {
+            synchronized (allocator) {
+                idBlock = allocator.allocateUniqueIdBlock();
+                return idBlock.getNextId();
+            }
+        }
+    }
+}
diff --git a/core/net/src/main/java/org/onlab/onos/core/impl/CoreManager.java b/core/net/src/main/java/org/onlab/onos/core/impl/CoreManager.java
index ebc4ed6..a2611ed 100644
--- a/core/net/src/main/java/org/onlab/onos/core/impl/CoreManager.java
+++ b/core/net/src/main/java/org/onlab/onos/core/impl/CoreManager.java
@@ -23,6 +23,8 @@
 import org.onlab.onos.core.ApplicationId;
 import org.onlab.onos.core.ApplicationIdStore;
 import org.onlab.onos.core.CoreService;
+import org.onlab.onos.core.IdBlockStore;
+import org.onlab.onos.core.IdGenerator;
 import org.onlab.onos.core.Version;
 import org.onlab.util.Tools;
 
@@ -35,7 +37,7 @@
 /**
  * Core service implementation.
  */
-@Component
+@Component(immediate = true)
 @Service
 public class CoreManager implements CoreService {
 
@@ -45,6 +47,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected ApplicationIdStore applicationIdStore;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected IdBlockStore idBlockStore;
+
     @Activate
     public void activate() {
         List<String> versionLines = Tools.slurp(VERSION_FILE);
@@ -74,4 +79,11 @@
         return applicationIdStore.registerApplication(name);
     }
 
+    @Override
+    public IdGenerator getIdGenerator(String topic) {
+        // FIXME this should be created lazily (once per topic)
+        IdBlockAllocator allocator = new StoreBasedIdBlockAllocator(topic, idBlockStore);
+        return new BlockAllocatorBasedIdGenerator(allocator);
+    }
+
 }
diff --git a/core/net/src/main/java/org/onlab/onos/core/impl/IdBlockAllocator.java b/core/net/src/main/java/org/onlab/onos/core/impl/IdBlockAllocator.java
new file mode 100644
index 0000000..4e59862
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/core/impl/IdBlockAllocator.java
@@ -0,0 +1,23 @@
+package org.onlab.onos.core.impl;
+
+import org.onlab.onos.core.IdBlock;
+
+/**
+ * An interface that gives unique ID spaces.
+ */
+public interface IdBlockAllocator {
+    /**
+     * Allocates a unique Id Block.
+     *
+     * @return Id Block.
+     */
+    IdBlock allocateUniqueIdBlock();
+
+    /**
+     * Allocates next unique id and retrieve a new range of ids if needed.
+     *
+     * @param range range to use for the identifier
+     * @return Id Block.
+     */
+    IdBlock allocateUniqueIdBlock(long range);
+}
diff --git a/core/net/src/main/java/org/onlab/onos/core/impl/StoreBasedIdBlockAllocator.java b/core/net/src/main/java/org/onlab/onos/core/impl/StoreBasedIdBlockAllocator.java
new file mode 100644
index 0000000..ff55d56
--- /dev/null
+++ b/core/net/src/main/java/org/onlab/onos/core/impl/StoreBasedIdBlockAllocator.java
@@ -0,0 +1,34 @@
+package org.onlab.onos.core.impl;
+
+import org.onlab.onos.core.IdBlock;
+import org.onlab.onos.core.IdBlockStore;
+
+public class StoreBasedIdBlockAllocator implements IdBlockAllocator {
+    private long blockTop;
+    private static final long BLOCK_SIZE = 0x1000000L;
+
+    private final IdBlockStore store;
+    private final String topic;
+
+    public StoreBasedIdBlockAllocator(String topic, IdBlockStore store) {
+        this.topic = topic;
+        this.store = store;
+    }
+
+    /**
+     * Returns a block of IDs which are unique and unused.
+     * Range of IDs is fixed size and is assigned incrementally as this method
+     * called.
+     *
+     * @return an IdBlock containing a set of unique IDs
+     */
+    @Override
+    public synchronized IdBlock allocateUniqueIdBlock() {
+        return store.getIdBlock(topic);
+    }
+
+    @Override
+    public IdBlock allocateUniqueIdBlock(long range) {
+        throw new UnsupportedOperationException("Not supported yet");
+    }
+}
diff --git a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
index 361c2ea..2f8875a 100644
--- a/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
+++ b/core/net/src/main/java/org/onlab/onos/net/intent/impl/IntentManager.java
@@ -25,6 +25,8 @@
 import org.apache.felix.scr.annotations.Reference;
 import org.apache.felix.scr.annotations.ReferenceCardinality;
 import org.apache.felix.scr.annotations.Service;
+import org.onlab.onos.core.CoreService;
+import org.onlab.onos.core.IdGenerator;
 import org.onlab.onos.event.AbstractListenerRegistry;
 import org.onlab.onos.event.EventDeliveryService;
 import org.onlab.onos.net.flow.CompletedBatchOperation;
@@ -88,12 +90,8 @@
     private final AbstractListenerRegistry<IntentEvent, IntentListener>
             listenerRegistry = new AbstractListenerRegistry<>();
 
-    private ExecutorService executor;
-    private ExecutorService monitorExecutor;
-
-    private final IntentStoreDelegate delegate = new InternalStoreDelegate();
-    private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
-    private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
+    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+    protected CoreService coreService;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected IntentStore store;
@@ -110,6 +108,15 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
     protected FlowRuleService flowRuleService;
 
+
+    private ExecutorService executor;
+    private ExecutorService monitorExecutor;
+
+    private final IntentStoreDelegate delegate = new InternalStoreDelegate();
+    private final TopologyChangeDelegate topoDelegate = new InternalTopoChangeDelegate();
+    private final IntentBatchDelegate batchDelegate = new InternalBatchDelegate();
+    private IdGenerator idGenerator;
+
     @Activate
     public void activate() {
         store.setDelegate(delegate);
@@ -118,6 +125,8 @@
         eventDispatcher.addSink(IntentEvent.class, listenerRegistry);
         executor = newSingleThreadExecutor(namedThreads("onos-intents"));
         monitorExecutor = newSingleThreadExecutor(namedThreads("onos-intent-monitor"));
+        idGenerator = coreService.getIdGenerator("intent-ids");
+        Intent.bindIdGenerator(idGenerator);
         log.info("Started");
     }
 
@@ -129,6 +138,7 @@
         eventDispatcher.removeSink(IntentEvent.class);
         executor.shutdown();
         monitorExecutor.shutdown();
+        Intent.unbindIdGenerator(idGenerator);
         log.info("Stopped");
     }