Adding IdManager/LockManager and related Changes 93/30693/3
authorManohar SL <manohar.sl@ericsson.com>
Thu, 3 Dec 2015 09:53:03 +0000 (15:23 +0530)
committerGauravBhagwani <gaurav.bhagwani@ericsson.com>
Fri, 4 Dec 2015 11:51:29 +0000 (17:21 +0530)
Change-Id: I5910c4537a5825667c04a6ca71312c83775e2a99
Signed-off-by: Gaurav Bhagwani <gaurav.bhagwani@ericsson.com>
33 files changed:
features/pom.xml
features/src/main/features/features.xml
idmanager/idmanager-api/src/main/yang/id-manager.yang
idmanager/idmanager-impl/pom.xml
idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManager.java
idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdManagerServiceProvider.java
idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java [new file with mode: 0644]
idmanager/idmanager-impl/src/test/java/org/opendaylight/idmanager/test/IdManagerTest.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmConstants.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/IfmUtil.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/InterfacemgrProvider.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/commons/InterfaceManagerCommonUtils.java
interfacemgr/interfacemgr-impl/src/main/java/org/opendaylight/vpnservice/interfacemgr/renderer/ovs/confighelpers/OvsVlanMemberConfigAddHelper.java
interfacemgr/interfacemgr-impl/src/test/java/org/opendaylight/vpnservice/interfacemgr/test/InterfaceManagerTestUtil.java
lockmanager/lockmanager-api/pom.xml [new file with mode: 0644]
lockmanager/lockmanager-api/src/main/yang/lock-manager.yang [new file with mode: 0644]
lockmanager/lockmanager-impl/pom.xml [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/config/default-config.xml [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java [new file with mode: 0644]
lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang [new file with mode: 0644]
lockmanager/pom.xml [new file with mode: 0644]
mdsalutil/mdsalutil-api/src/main/java/org/opendaylight/vpnservice/mdsalutil/MDSALUtil.java
nexthopmgr/nexthopmgr-impl/src/main/java/org/opendaylight/vpnservice/nexthopmgr/NexthopManager.java
nexthopmgr/nexthopmgr-impl/src/test/java/org/opendaylight/vpnservice/nexthopmgr/test/NexthopManagerTest.java
pom.xml
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnInterfaceManager.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnManager.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnUtil.java
vpnmanager/vpnmanager-impl/src/main/java/org/opendaylight/vpnservice/VpnserviceProvider.java

index 298fc80..8433fba 100644 (file)
@@ -33,6 +33,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <interfacemgr.version>${vpnservices.version}</interfacemgr.version>
     <nexthopmgr.version>${vpnservices.version}</nexthopmgr.version>
     <fibmanager.version>${vpnservices.version}</fibmanager.version>
+    <lockmanager.version>${vpnservices.version}</lockmanager.version>
     <idmanager.version>${vpnservices.version}</idmanager.version>
   </properties>
   <dependencyManagement>
@@ -209,6 +210,23 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
       <artifactId>fibmanager-api</artifactId>
       <version>${fibmanager.version}</version>
     </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>lockmanager-impl</artifactId>
+      <version>${lockmanager.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>lockmanager-impl</artifactId>
+      <version>${lockmanager.version}</version>
+      <classifier>config</classifier>
+      <type>xml</type>
+    </dependency>
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>lockmanager-api</artifactId>
+      <version>${lockmanager.version}</version>
+    </dependency>
     <dependency>
       <groupId>${project.groupId}</groupId>
       <artifactId>idmanager-impl</artifactId>
index e03ef33..b4a6735 100644 (file)
@@ -21,6 +21,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version='${mdsal.model.version}'>odl-mdsal-models</feature>
     <feature version='${openflowplugin.version}'>odl-openflowplugin-nsf-model</feature>
     <bundle>mvn:org.opendaylight.vpnservice/model-bgp/{{VERSION}}</bundle>
+    <bundle>mvn:org.opendaylight.vpnservice/lockmanager-api/${lockmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/idmanager-api/${idmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/vpnmanager-api/${vpnmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/nexthopmgr-api/${nexthopmgr.version}</bundle>
@@ -33,6 +34,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <feature version='${project.version}'>odl-vpnservice-api</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-southbound</feature>
     <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
+    <bundle>mvn:org.opendaylight.vpnservice/lockmanager-impl/${lockmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/bgpmanager-api/${vpnservices.version}</bundle>
     <bundle>mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version}</bundle>
@@ -47,6 +49,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <!--<bundle>mvn:org.opendaylight.vpnservice.third-party/org.apache.thriftlib/1.0.1-SNAPSHOT</bundle>-->
     <bundle>wrap:mvn:org.apache.thrift/libthrift/0.9.1$overwrite=merge&amp;Bundle-Version=0.9.1&amp;Export-Package=*;-noimport:=true;version="0.9.1"</bundle>
     <!--<bundle>wrap:mvn:javax.servlet/servlet-api/2.5</bundle>-->
+    <configfile finalname="lockmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/lockmanager-impl/${lockmanager.version}/xml/config</configfile>
        <configfile finalname="idmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/idmanager-impl/${idmanager.version}/xml/config</configfile>
     <configfile finalname="bgpmanager-impl-default-config.xml">mvn:org.opendaylight.vpnservice/bgpmanager-impl/${vpnservices.version}/xml/config</configfile>
     <configfile finalname="mdsalutil-impl-default-config.xml">mvn:org.opendaylight.vpnservice/mdsalutil-impl/${interfacemgr.version}/xml/config</configfile>
index 79bd2ff..7e4a41f 100644 (file)
@@ -3,41 +3,133 @@ module id-manager {
     prefix idmgr;
 
     revision "2015-04-03" {
-        description "ID generator and manager Service module";
+        description "YANG model describes methods for allocating or releasing Ids as well as to create/delete Id Pools. The child pools
+                      are created inside the IdManager. This helps to improve ID Pool scalability/performance";
     }
 
-    container pools {
-      description
-        "id pool instances";
-      config false;
+    container id-pools {
+      description "Parent Id Pool is responsible allocating block (or) set of Ids to child Id Pools. The number of child pools are determined using some algorthimic approach inside IdManager. For example,  spawning child pools based on Id allocation request rate for the given Pool, one child pool per blade in the cluster etc";
+      config true;
       list id-pool {
         key "pool-name";
-        leaf id-start { type uint32;}
-        leaf pool-size { type uint64;}
-        leaf pool-name { type string;}
-        list generated-ids {
-          key "id-key";
-          leaf id-key { type string;}
-          leaf id-value { type uint32;}
+        leaf pool-name {
+            type string;
+            mandatory true;
+        }
+        leaf block-size {
+            type uint16;
+            mandatory true;
+        }
+        leaf parent-pool-name {
+            type string;
+        }
+        list child-pools {
+            key "child-pool-name";
+            leaf child-pool-name {
+                type string;
+                mandatory true;
+            }
+            leaf last-access-time {
+                type uint32;
+            }
+        }
+        list id-entries {
+            description "Id entry for the given Id Pool, where id-key is used to identify the id entry";
+            key "id-key";
+            leaf id-key { type string;}
+            leaf id-value { type uint32;}
+        }
+        container available-ids-holder {
+            uses available-ids;
+        }
+        container released-ids-holder {
+            uses released-ids;
         }
       }
     }
 
+    grouping available-ids {
+        leaf start {
+            type uint32;
+        }
+        leaf end {
+            type uint32;
+        }
+        leaf cursor {
+            type int64;
+        }
+    }
+
+    grouping released-ids {
+        leaf available-id-count {
+            type uint32;
+        }
+        leaf delayed-time-sec {
+            type uint32;
+            mandatory true;
+        }
+        list delayed-id-entries {
+            uses delayed-id-entry;
+        }
+    }
+
+    grouping delayed-id-entry {
+        leaf id {
+            type uint32;
+            mandatory true;
+        }
+        leaf ready-time-sec {
+            type uint32;
+            mandatory true;
+        }
+    }
+
     rpc createIdPool {
-      input {
-        leaf pool-name { type string; }
-        leaf id-start { type uint32; }
-        leaf pool-size { type uint64; }
-      }
+        input {
+            leaf pool-name {
+                type string;
+            }
+            leaf low {
+                type uint32;
+            }
+            leaf high {
+                type uint32;
+            }
+        }
     }
 
-    rpc getUniqueId {
-      input {
-        leaf pool-name { type string; }
-        leaf id-key {type string; }
-      }
-      output {
-        leaf id-value { type uint32; }
-      }
+    rpc deleteIdPool {
+        input {
+            leaf pool-name {
+                type string;
+            }
+        }
+    }
+
+    rpc allocateId {
+        input {
+             leaf pool-name {
+                type string;
+             }
+             leaf id-key {
+                type string;
+             }
+        }
+        output {
+            leaf id-value {
+                type uint32;
+            }
+        }
+    }
+
+    rpc releaseId {
+        input {
+             leaf pool-name {
+                type string;
+             }
+             leaf id-key {
+                type string;
+             }
+        }
     }
 }
index 4e135b9..e1ea21c 100644 (file)
@@ -26,6 +26,16 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
       <artifactId>idmanager-api</artifactId>
       <version>${vpnservices.version}</version>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.vpnservice</groupId>
+      <artifactId>lockmanager-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+    <dependency>
+       <groupId>org.opendaylight.vpnservice</groupId>
+       <artifactId>mdsalutil-api</artifactId>
+       <version>${vpnservices.version}</version>
+    </dependency>
   </dependencies>
 
 </project>
index a57086a..07f0e3c 100644 (file)
@@ -8,37 +8,61 @@
 
 package org.opendaylight.idmanager;
 
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.DataChangeListener;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.vpnservice.mdsalutil.MDSALUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
 import org.opendaylight.yangtools.concepts.ListenerRegistration;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.*;
-
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Future;
 
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
 
 public class IdManager implements IdManagerService, AutoCloseable{
     private static final Logger LOG = LoggerFactory.getLogger(IdManager.class);
-    private ListenerRegistration<DataChangeListener> listenerRegistration;
-    private final DataBroker broker;
 
+       private static final long DEFAULT_IDLE_TIME = 24 * 60 * 60;
 
+    private ListenerRegistration<DataChangeListener> listenerRegistration;
+    private final DataBroker broker;
+    private LockManagerService lockManager;
 
     @Override
     public void close() throws Exception {
@@ -57,146 +81,423 @@ public class IdManager implements IdManagerService, AutoCloseable{
         broker = db;
     }
 
-    private <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
-                                                    InstanceIdentifier<T> path) {
-
-        ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+    public void setLockManager(LockManagerService lockManager) {
+        this.lockManager = lockManager;
+    }
 
-        Optional<T> result = Optional.absent();
+    @Override
+    public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input) {
+        LOG.debug("createIdPool called with input {}", input);
+        String poolName = input.getPoolName();
+        long low = input.getLow();
+        long high = input.getHigh();
+        long blockSize = IdUtils.computeBlockSize(low, high);
+        RpcResultBuilder<Void> createIdPoolRpcBuilder;
+        IdUtils.lockPool(lockManager, poolName);
         try {
-            result = tx.read(datastoreType, path).get();
-        } catch (Exception e) {
-            throw new RuntimeException(e);
+            InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName);
+            poolName = poolName.intern();
+            IdPool idPool;
+            idPool = createGlobalPool(poolName, low, high, blockSize, idPoolInstanceIdentifier);
+            String localPoolName = IdUtils.getLocalPoolName(poolName);
+            if (createLocalPool(localPoolName, idPool)) {
+                LOG.debug("Updating global id pool {} with childPool {}", poolName, localPoolName);
+                updateChildPool(poolName, localPoolName);
+            }
+            createIdPoolRpcBuilder = RpcResultBuilder.success();
+        } catch (Exception ex) {
+            LOG.error("Creation of Id Pool {} failed due to {}", poolName, ex);
+            createIdPoolRpcBuilder = RpcResultBuilder.failed();
+            createIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+        } finally {
+            IdUtils.unlockPool(lockManager, poolName);
         }
-
-        return result;
-    }
-
-    protected  <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
-                                                   InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
-        WriteTransaction tx = broker.newWriteOnlyTransaction();
-        tx.put(datastoreType, path, data, true);
-        Futures.addCallback(tx.submit(), callback);
+        return Futures.immediateFuture(createIdPoolRpcBuilder.build());
     }
 
-    protected  <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
-                                                    InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
-        WriteTransaction tx = broker.newWriteOnlyTransaction();
-        tx.merge(datastoreType, path, data, true);
-        Futures.addCallback(tx.submit(), callback);
+    @Override
+    public Future<RpcResult<AllocateIdOutput>> allocateId(AllocateIdInput input) {
+        LOG.debug("AllocateId called with input {}", input);
+        String idKey = input.getIdKey();
+        String poolName = input.getPoolName();
+        String localPoolName = IdUtils.getLocalPoolName(poolName);
+        RpcResultBuilder<AllocateIdOutput> allocateIdRpcBuilder;
+        long newIdValue = -1;
+        AllocateIdOutputBuilder output = new AllocateIdOutputBuilder();
+        try {
+            newIdValue = allocateIdFromLocalPool(localPoolName, idKey);
+            output.setIdValue(newIdValue);
+            allocateIdRpcBuilder = RpcResultBuilder.success();
+            allocateIdRpcBuilder.withResult(output.build());
+        } catch (Exception ex) {
+            LOG.error("Allocate id in pool {} failed due to {}", poolName, ex);
+            allocateIdRpcBuilder = RpcResultBuilder.failed();
+            allocateIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+        }
+        return Futures.immediateFuture(allocateIdRpcBuilder.build());
     }
 
     @Override
-    public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input)
-    {
-
+    public Future<RpcResult<Void>> deleteIdPool(DeleteIdPoolInput input) {
+        LOG.debug("DeleteIdPool called with input {}", input);
         String poolName = input.getPoolName();
-        long startIndx = input.getIdStart();
-        long poolSize = input.getPoolSize().longValue();
-        RpcResultBuilder<Void> rpcResultBuilder;
-
-        LOG.debug("poolName: {}, startIndx: {} , poolSize: {} ", poolName, startIndx,  poolSize);
-
+        RpcResultBuilder<Void> deleteIdPoolRpcBuilder;
         try {
-            InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
-                    InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
-            InstanceIdentifier<IdPool> id = idBuilder.build();
-            Optional<IdPool> pool = read(LogicalDatastoreType.OPERATIONAL, id);
-            if (!pool.isPresent()) {
-                LOG.debug("Creating a new global pool: {} ", poolName);
-                IdPool newPool = getPoolInterface(poolName, startIndx, poolSize);
-                LOG.debug("NewPool: {}", newPool);
-                asyncWrite(LogicalDatastoreType.OPERATIONAL, id, newPool, DEFAULT_CALLBACK);
-
+            InstanceIdentifier<IdPool> idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName);
+            poolName = poolName.intern();
+            synchronized(poolName) {
+                IdPool idPool = getIdPool(idPoolToBeDeleted);
+                List<ChildPools> childPoolList = idPool.getChildPools();
+                if (childPoolList != null) {
+                    for (ChildPools childPoolName : childPoolList) {
+                        deletePool(childPoolName.getChildPoolName());
+                    }
+                }
+                MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
+                LOG.debug("Deleted id pool {}", poolName);
             }
-
-            rpcResultBuilder = RpcResultBuilder.success();
+            deleteIdPoolRpcBuilder = RpcResultBuilder.success();
         }
-        catch(Exception e){
-            LOG.error("Creation of global pool {} failed due to {}" ,poolName, e);
-            rpcResultBuilder = RpcResultBuilder.failed();
+        catch (Exception ex) {
+            LOG.error("Delete id in pool {} failed due to {}", poolName, ex);
+            deleteIdPoolRpcBuilder = RpcResultBuilder.failed();
+            deleteIdPoolRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
         }
-
-        return Futures.immediateFuture(rpcResultBuilder.build());
+        return Futures.immediateFuture(deleteIdPoolRpcBuilder.build());
     }
 
-
     @Override
-    public Future<RpcResult<GetUniqueIdOutput>> getUniqueId(GetUniqueIdInput input){
-
+    public Future<RpcResult<Void>> releaseId(ReleaseIdInput input) {
         String poolName = input.getPoolName();
         String idKey = input.getIdKey();
+        RpcResultBuilder<Void> releaseIdRpcBuilder;
+        try {
+            releaseIdFromLocalPool(IdUtils.getLocalPoolName(poolName), idKey);
+            releaseIdRpcBuilder = RpcResultBuilder.success();
+        } catch (Exception ex) {
+            LOG.error("Release id {} from pool {} failed due to {}", idKey, poolName, ex);
+            releaseIdRpcBuilder = RpcResultBuilder.failed();
+            releaseIdRpcBuilder.withError(ErrorType.APPLICATION, ex.getMessage());
+        }
+        return Futures.immediateFuture(releaseIdRpcBuilder.build());
+    }
 
-        LOG.debug("poolName: {} ,idKey: {}", poolName, idKey);
-        RpcResultBuilder<GetUniqueIdOutput> rpcResultBuilder;
+    private long allocateIdFromLocalPool(String localPoolName, String idKey) {
+        long newIdValue = -1;
+        InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName);
+        localPoolName = localPoolName.intern();
+        synchronized (localPoolName) {
+            IdEntries newIdEntry;
+            IdPool pool = getIdPool(idPoolInstanceIdentifier);
+            List<IdEntries> idEntries = pool.getIdEntries();
+
+            AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(pool);
+            ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(pool);
+            //Calling cleanupExcessIds since there could be excessive ids.
+            cleanupExcessIds(availableIds, releasedIds, pool.getParentPoolName(), pool.getBlockSize());
+            if (idEntries == null) {
+                idEntries = new LinkedList<IdEntries>();
+            } else {
+                InstanceIdentifier<IdEntries> existingId = IdUtils.getIdEntry(idPoolInstanceIdentifier, idKey);
+                Optional<IdEntries> existingIdEntry = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId);
+                if (existingIdEntry.isPresent()) {
+                    newIdValue = existingIdEntry.get().getIdValue();
+                    LOG.debug("Existing id {} for the key {} ", idKey, newIdValue);
+                    InstanceIdentifier<ReleasedIdsHolder> releasedIdsHolderInstanceIdentifier = InstanceIdentifier
+                                .builder(IdPools.class).child(IdPool.class, new IdPoolKey(localPoolName)).child(ReleasedIdsHolder.class).build();
+                        MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIds.build());
+                    return newIdValue;
+                }
+            }
+            newIdValue = getIdFromPool(pool, availableIds, releasedIds);
+            newIdEntry = IdUtils.createIdEntries(idKey, newIdValue);
+            idEntries.add(newIdEntry);
+            pool = new IdPoolBuilder(pool).setIdEntries(idEntries)
+                   .setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build()).build();
+            MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, pool);
+            updateChildPool(pool.getParentPoolName(), localPoolName);
+        }
+        return newIdValue;
+    }
 
+    private long getIdFromPool(IdPool pool, AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds) {
+        long newIdValue = -1;
+        while (true) {
+            newIdValue = IdUtils.getIdFromReleaseIdsIfAvailable(releasedIds);
+            if (newIdValue != -1) {
+                LOG.debug("Retrieved id value {} from released id holder", newIdValue);
+                return newIdValue;
+            }
+            newIdValue = IdUtils.getIdFromAvailableIds(availableIds);
+            if (newIdValue != -1) {
+                LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, pool.getPoolName());
+                return newIdValue;
+            }
+            long idCount = allocateIdBlockFromParentPool(pool.getParentPoolName(), availableIds, releasedIds);
+            if (idCount <= 0) {
+                LOG.debug("Unable to allocate Id block from global pool");
+                throw new RuntimeException(String.format("Ids exhausted for pool : %s", pool.getPoolName()));
+            }
+        }
+    }
+
+    /**
+     * Changes made to releaseIds and AvailableIds are not persisted.
+     * @param availableIds
+     * @param releasedIds
+     * @param parentPoolName
+     * @param blockSize
+     */
+    private void cleanupExcessIds(AvailableIdsHolderBuilder availableIds, ReleasedIdsHolderBuilder releasedIds, String parentPoolName, int blockSize) {
+        IdUtils.processDelayList(releasedIds);
+        long totalAvailableIdCount = releasedIds.getAvailableIdCount() + IdUtils.getAvailableIdsCount(availableIds);
+        if (totalAvailableIdCount > blockSize * 2) {
+            parentPoolName = parentPoolName.intern();
+            InstanceIdentifier<ReleasedIdsHolder> releasedIdInstanceIdentifier = IdUtils.getReleasedIdsHolderInstance(parentPoolName);
+            IdUtils.lockPool(lockManager, parentPoolName);
+            try {
+                Optional<ReleasedIdsHolder> releasedIdsHolder = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier);
+                ReleasedIdsHolderBuilder releasedIdsParent;
+                if (!releasedIdsHolder.isPresent()) {
+                    LOG.error("ReleasedIds not present in parent pool. Unable to cleanup excess ids");
+                    return;
+                }
+                releasedIdsParent = new ReleasedIdsHolderBuilder(releasedIdsHolder.get());
+                LOG.debug("Releasing excesss Ids from local pool");
+                IdUtils.freeExcessAvailableIds(releasedIds, releasedIdsParent, blockSize);
+                MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, releasedIdInstanceIdentifier, releasedIdsParent.build());
+            } finally {
+                IdUtils.unlockPool(lockManager, parentPoolName);
+            }
+        }
+    }
+
+    /**
+     * Changes made to availableIds and releasedIds will not be persisted to the datastore
+     * @param parentPoolName
+     * @param availableIdsBuilder
+     * @param releasedIdsBuilder
+     * @return
+     */
+    private long allocateIdBlockFromParentPool(String parentPoolName,
+            AvailableIdsHolderBuilder availableIdsBuilder, ReleasedIdsHolderBuilder releasedIdsBuilder) {
+        LOG.debug("Allocating block of id from parent pool {}", parentPoolName);
+        InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(parentPoolName);
+        parentPoolName = parentPoolName.intern();
+        long idCount = -1;
+        IdUtils.lockPool(lockManager, parentPoolName);
         try {
-            InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
-                    InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
-            InstanceIdentifier<IdPool> id = idBuilder.build();
-            Optional<IdPool> globalPool = read(LogicalDatastoreType.OPERATIONAL, id);
-            GetUniqueIdOutputBuilder output = new GetUniqueIdOutputBuilder();
-            Long newIdValue = null;
-            GeneratedIds newGenId = null;
-            if (globalPool.isPresent()) {
-                IdPool pool = globalPool.get();
-                List<GeneratedIds> generatedIds = pool.getGeneratedIds();
-
-                if (generatedIds == null) {
-                    generatedIds = new ArrayList<GeneratedIds>();
+            IdPool parentIdPool = getIdPool(idPoolInstanceIdentifier);
+            ReleasedIdsHolderBuilder releasedIdsBuilderParent = IdUtils.getReleaseIdsHolderBuilder(parentIdPool);
+            while (true) {
+                idCount = allocateIdBlockFromReleasedIdsHolder(releasedIdsBuilder, releasedIdsBuilderParent, parentIdPool);
+                if (idCount > 0) {
+                    return idCount;
+                }
+                idCount = allocateIdBlockFromAvailableIdsHolder(availableIdsBuilder, parentIdPool);
+                if (idCount > 0) {
+                    return idCount;
                 }
-                if (!generatedIds.isEmpty()) {
-                    for (GeneratedIds genId : generatedIds) {
-                        if (genId.getIdKey().equals(idKey)) {
-                            newIdValue = genId.getIdValue();
-                            LOG.debug("Existing id {} for the key {} ", idKey, newIdValue);
-                        }
+                idCount = getIdsFromOtherChildPools(releasedIdsBuilderParent, parentIdPool);
+                if (idCount <= 0) {
+                    LOG.debug("Unable to allocate Id block from global pool");
+                    throw new RuntimeException(String.format("Ids exhausted for pool : %s", parentPoolName));
+                }
+            }
+        }
+        finally {
+            IdUtils.unlockPool(lockManager, parentPoolName);
+        }
+    }
 
-                    }
+    private long getIdsFromOtherChildPools(ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) {
+        List<ChildPools> childPoolsList = parentIdPool.getChildPools();
+        // Sorting the child pools on last accessed time so that the pool that was not accessed for a long time comes first.
+        Collections.sort(childPoolsList, new Comparator<ChildPools>() {
+            @Override
+            public int compare(ChildPools childPool1, ChildPools childPool2) {
+                return childPool1.getLastAccessTime().compareTo(childPool2.getLastAccessTime());
+            }
+        });
+        long currentTime = System.currentTimeMillis() / 1000;
+        for (ChildPools childPools : childPoolsList) {
+            if (childPools.getLastAccessTime() + DEFAULT_IDLE_TIME < currentTime) {
+                break;
+            }
+            if (!childPools.getChildPoolName().equals(IdUtils.getLocalPoolName(parentIdPool.getPoolName()))) {
+                InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(childPools.getChildPoolName());
+                IdPool otherChildPool = getIdPool(idPoolInstanceIdentifier);
+                ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(otherChildPool);
+                AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(otherChildPool);
+                long totalAvailableIdCount = releasedIds.getDelayedIdEntries().size() + IdUtils.getAvailableIdsCount(availableIds);
+                List<DelayedIdEntries> delayedIdEntriesChild = releasedIds.getDelayedIdEntries();
+                List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
+                if (delayedIdEntriesParent == null) {
+                    delayedIdEntriesParent = new LinkedList<>();
                 }
-                synchronized (this) {
-                    if (newIdValue == null) {
-                        newIdValue = (long) generatedIds.size() + 1;
-                        LOG.debug("Creating a new id {} for the pool: {} ", newIdValue, poolName);
-                        newGenId = getIdsInterface(idKey, newIdValue);
-                        generatedIds.add(newGenId);
-                        pool = new IdPoolBuilder(pool).setGeneratedIds(generatedIds).build();
-                        asyncUpdate(LogicalDatastoreType.OPERATIONAL, id, pool, DEFAULT_CALLBACK);
-                    }
+                delayedIdEntriesParent.addAll(delayedIdEntriesChild);
+                delayedIdEntriesChild.removeAll(delayedIdEntriesChild);
+                while (IdUtils.isIdAvailable(availableIds)) {
+                    long cursor = availableIds.getCursor() + 1;
+                    delayedIdEntriesParent.add(new DelayedIdEntriesBuilder().setId(cursor).setReadyTimeSec(System.currentTimeMillis()).build());
+                    availableIds.setCursor(cursor);
                 }
-                output.setIdValue(newIdValue);
+                long count = releasedIdsBuilderParent.getAvailableIdCount() + totalAvailableIdCount;
+                releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent).setAvailableIdCount(count);
+                MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier,
+                        new IdPoolBuilder(otherChildPool).setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build()).build());
+                return totalAvailableIdCount;
             }
+        }
+        return 0;
+    }
 
-            rpcResultBuilder = RpcResultBuilder.success();
-            rpcResultBuilder.withResult(output.build());
+       private long allocateIdBlockFromReleasedIdsHolder(ReleasedIdsHolderBuilder releasedIdsBuilderChild, ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool) {
+        if (releasedIdsBuilderParent.getAvailableIdCount() == 0) {
+            LOG.debug("Ids unavailable in releasedIds of parent pool {}", parentIdPool);
+            return 0;
         }
-        catch(Exception e){
-            LOG.error("Creation of id for the key {} , global pool {} failed due to {}" ,idKey, poolName, e);
-            rpcResultBuilder = RpcResultBuilder.failed();
+        List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
+        List<DelayedIdEntries> delayedIdEntriesChild = releasedIdsBuilderChild.getDelayedIdEntries();
+        if (delayedIdEntriesChild == null) {
+            delayedIdEntriesChild = new LinkedList<DelayedIdEntries>();
         }
-        return Futures.immediateFuture(rpcResultBuilder.build());
+        int idCount = Math.min(delayedIdEntriesParent.size(), parentIdPool.getBlockSize());
+        List<DelayedIdEntries> idEntriesToBeRemoved = delayedIdEntriesParent.subList(0, idCount);
+        delayedIdEntriesChild.addAll(0, idEntriesToBeRemoved);
+        delayedIdEntriesParent.removeAll(idEntriesToBeRemoved);
+        releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent);
+        releasedIdsBuilderChild.setDelayedIdEntries(delayedIdEntriesChild);
+        releasedIdsBuilderChild.setAvailableIdCount(releasedIdsBuilderChild.getAvailableIdCount() + idCount);
+        InstanceIdentifier<ReleasedIdsHolder> releasedIdsHolderInstanceIdentifier = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(parentIdPool.getPoolName())).child(ReleasedIdsHolder.class).build();
+        releasedIdsBuilderParent.setAvailableIdCount(releasedIdsBuilderParent.getAvailableIdCount() - idCount);
+        LOG.debug("Allocated {} ids from releasedIds of parent pool {}", idCount, parentIdPool);
+        MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, releasedIdsHolderInstanceIdentifier, releasedIdsBuilderParent.build());
+        return idCount;
     }
 
+    private long allocateIdBlockFromAvailableIdsHolder(AvailableIdsHolderBuilder availableIdsBuilder, IdPool parentIdPool) {
+        long idCount = 0;
+        AvailableIdsHolderBuilder availableIdsBuilderParent = IdUtils.getAvailableIdsHolderBuilder(parentIdPool);
+        long end = availableIdsBuilderParent.getEnd();
+        long cur = availableIdsBuilderParent.getCursor();
+        if (!IdUtils.isIdAvailable(availableIdsBuilderParent)) {
+            LOG.debug("Ids exhausted in parent pool {}", parentIdPool);
+            return idCount;
+        }
+        // Update availableIdsHolder of Local Pool
+        availableIdsBuilder.setStart(cur + 1);
+        idCount = Math.min(end - cur, parentIdPool.getBlockSize());
+        availableIdsBuilder.setEnd(cur + idCount);
+        availableIdsBuilder.setCursor(cur);
+        // Update availableIdsHolder of Global Pool
+        InstanceIdentifier<AvailableIdsHolder> availableIdsHolderInstanceIdentifier = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(parentIdPool.getPoolName())).child(AvailableIdsHolder.class).build();
+        availableIdsBuilderParent.setCursor(cur + idCount);
+        LOG.debug("Allocated {} ids from availableIds of global pool {}", idCount, parentIdPool);
+        MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, availableIdsHolderInstanceIdentifier, availableIdsBuilderParent.build());
+        return idCount;
+    }
 
-    private IdPool getPoolInterface(String poolName, long startIndx, long poolSize) {
-        BigInteger size = BigInteger.valueOf(poolSize);
-        return new IdPoolBuilder().setKey(new IdPoolKey(poolName)).setPoolName(poolName).setIdStart(startIndx)
-                .setPoolSize(size).build();
+    private void releaseIdFromLocalPool(String poolName, String idKey) {
+        InstanceIdentifier<IdPool> idPoolInstanceIdentifier = IdUtils.getIdPoolInstance(poolName);
+        poolName = poolName.intern();
+        synchronized (poolName) {
+            IdPool pool = getIdPool(idPoolInstanceIdentifier);
+            List<IdEntries> idEntries = pool.getIdEntries();
+            List<IdEntries> newIdEntries = idEntries;
+            if (idEntries == null) {
+                throw new RuntimeException("Id Entries does not exist");
+            }
+            InstanceIdentifier<IdEntries> existingId = IdUtils.getIdEntry(idPoolInstanceIdentifier, idKey);
+            Optional<IdEntries> existingIdEntryObject = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, existingId);
+            if (!existingIdEntryObject.isPresent()) {
+                throw new RuntimeException(String.format("Specified Id key %s does not exist in id pool %s", idKey, poolName));
+            }
+            IdEntries existingIdEntry = existingIdEntryObject.get();
+            long idValue = existingIdEntry.getIdValue();
+            newIdEntries.remove(existingIdEntry);
+            ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(pool);
+            AvailableIdsHolderBuilder availableIds = IdUtils.getAvailableIdsHolderBuilder(pool);
+            long delayTime = System.currentTimeMillis() / 1000 + releasedIds.getDelayedTimeSec();
+            DelayedIdEntries delayedIdEntry = IdUtils.createDelayedIdEntry(idValue, delayTime);
+            List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
+            if (delayedIdEntries == null) {
+                delayedIdEntries = new LinkedList<DelayedIdEntries>();
+            }
+            delayedIdEntries.add(delayedIdEntry);
+            long availableIdCount = releasedIds
+                    .getAvailableIdCount() == null ? 0
+                            : releasedIds.getAvailableIdCount();
+            releasedIds.setDelayedIdEntries(delayedIdEntries);
+            releasedIds.setAvailableIdCount(availableIdCount);
+            //Calling cleanupExcessIds since there could be excessive ids.
+            cleanupExcessIds(availableIds, releasedIds, pool.getParentPoolName(), pool.getBlockSize());
+            pool = new IdPoolBuilder(pool).setIdEntries(newIdEntries)
+                    .setAvailableIdsHolder(availableIds.build())
+                    .setReleasedIdsHolder(releasedIds.build()).build();
+            MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, pool);
+            LOG.debug("Released id ({}, {}) from pool {}", idKey, idValue, poolName);
+        }
     }
 
-    private GeneratedIds getIdsInterface(String idKey, long newIdVal) {
-        return new GeneratedIdsBuilder().setKey(new GeneratedIdsKey(idKey)).setIdKey(idKey)
-                .setIdValue(newIdVal).build();
+    private IdPool createGlobalPool(String poolName, long low, long high,
+            long blockSize, InstanceIdentifier<IdPool> idPoolInstanceIdentifier) {
+        IdPool idPool;
+        Optional<IdPool> existingIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
+        if (!existingIdPool.isPresent()) {
+            LOG.debug("Creating new global pool {}", poolName);
+            idPool = IdUtils.createGlobalPool(poolName, low, high, blockSize);
+            MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier, idPool);
+        }
+        else {
+            idPool = existingIdPool.get();
+            LOG.debug("GlobalPool exists {}", idPool);
+        }
+        return idPool;
     }
 
-    private static final FutureCallback<Void> DEFAULT_CALLBACK =
-        new FutureCallback<Void>() {
-            public void onSuccess(Void result) {
-                LOG.debug("Success in Datastore write operation");
+    private boolean createLocalPool(String localPoolName, IdPool idPool) {
+        localPoolName = localPoolName.intern();
+        synchronized (localPoolName) {
+            InstanceIdentifier<IdPool> localIdPoolInstanceIdentifier = IdUtils.getIdPoolInstance(localPoolName);
+            Optional<IdPool> localIdPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier);
+            if (!localIdPool.isPresent()) {
+                LOG.debug("Creating new local pool");
+                IdPool newLocalIdPool = IdUtils.createLocalIdPool(localPoolName, idPool);
+                MDSALUtil.syncWrite(broker, LogicalDatastoreType.CONFIGURATION, localIdPoolInstanceIdentifier, newLocalIdPool);
+                LOG.debug("Local pool created {}", newLocalIdPool);
+                return true;
             }
+        }
+        return false;
+    }
 
-            public void onFailure(Throwable error) {
-                LOG.error("Error in Datastore write operation", error);
+    private void deletePool(String poolName) {
+        InstanceIdentifier<IdPool> idPoolToBeDeleted = IdUtils.getIdPoolInstance(poolName);
+        synchronized (poolName) {
+            Optional<IdPool> idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
+            if (idPool.isPresent()) {
+                MDSALUtil.syncDelete(broker, LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
+                LOG.debug("Deleted local pool {}", poolName);
             }
-        };
+        }
+    }
+
+    private IdPool getIdPool(InstanceIdentifier<IdPool> idPoolInstanceIdentifier) {
+        Optional<IdPool> idPool = MDSALUtil.read(broker, LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
+        if (!idPool.isPresent()) {
+            throw new RuntimeException(String.format("Specified pool %s does not exist" , idPool));
+        }
+        return idPool.get();
+    }
+
+    private void updateChildPool(String poolName, String localPoolName) {
+        ChildPools childPool = IdUtils.createChildPool(localPoolName);
+        InstanceIdentifier<ChildPools> childPoolInstanceIdentifier = IdUtils.getChildPoolsInstanceIdentifier(poolName, localPoolName);
+        MDSALUtil.syncUpdate(broker, LogicalDatastoreType.CONFIGURATION, childPoolInstanceIdentifier, childPool);
+    }
 }
index ab016b1..b027da1 100644 (file)
@@ -15,6 +15,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
 
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -22,9 +23,10 @@ import org.slf4j.LoggerFactory;
 public class IdManagerServiceProvider implements BindingAwareProvider,
             AutoCloseable {
 
-        private static final Logger LOG = LoggerFactory.getLogger(IdManagerServiceProvider.class);
-        private IdManager idManager;
-        private RpcProviderRegistry rpcProviderRegistry;
+    private static final Logger LOG = LoggerFactory.getLogger(IdManagerServiceProvider.class);
+    private IdManager idManager;
+    private RpcProviderRegistry rpcProviderRegistry;
+    private LockManagerService lockManager;
 
     public RpcProviderRegistry getRpcProviderRegistry() {
         return rpcProviderRegistry;
@@ -34,12 +36,17 @@ public class IdManagerServiceProvider implements BindingAwareProvider,
         this.rpcProviderRegistry = rpcProviderRegistry;
     }
 
-        @Override
+    public void setLockManager(LockManagerService lockManager) {
+        this.lockManager = lockManager;
+    }
+
+    @Override
     public void onSessionInitiated(ProviderContext session){
         LOG.info("IDManagerserviceProvider Session Initiated");
         try {
             final  DataBroker dataBroker = session.getSALService(DataBroker.class);
             idManager = new IdManager(dataBroker);
+            idManager.setLockManager(lockManager);
             final BindingAwareBroker.RpcRegistration<IdManagerService> rpcRegistration = getRpcProviderRegistry().addRpcImplementation(IdManagerService.class, idManager);
         } catch (Exception e) {
             LOG.error("Error initializing services", e);
diff --git a/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java b/idmanager/idmanager-impl/src/main/java/org/opendaylight/idmanager/IdUtils.java
new file mode 100644 (file)
index 0000000..507dad2
--- /dev/null
@@ -0,0 +1,307 @@
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.idmanager;
+
+import java.net.InetAddress;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DelayedIdEntry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInputBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.net.InetAddresses;
+
+class IdUtils {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(IdUtils.class);
+    private static final long DEFAULT_DELAY_TIME = 30;
+    private static final long DEFAULT_AVAILABLE_ID_COUNT = 0;
+    private static final int DEFAULT_BLOCK_SIZE_DIFF = 50;
+
+    private static int BLADE_ID;
+    static {
+        String hostName;
+        try {
+            hostName = InetAddress.getLocalHost().getHostName();
+            BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost());
+            if (hostName.indexOf("-") > 0) {
+                BLADE_ID = new Integer(hostName.split("-")[1].toString()).intValue();
+            } else {
+                LOGGER.error("Host name {} is not matching with the condition!! PL-X is expected", hostName);
+            }
+        } catch (Exception e) {
+            LOGGER.error("IdManager - Exception - {}", e.getMessage());
+        }
+    }
+
+    protected static InstanceIdentifier<IdEntries> getIdEntry(InstanceIdentifier<IdPool> poolName, String idKey) {
+        InstanceIdentifier.InstanceIdentifierBuilder<IdEntries> idEntriesBuilder = poolName
+                .builder().child(IdEntries.class, new IdEntriesKey(idKey));
+        InstanceIdentifier<IdEntries> idEntry = idEntriesBuilder.build();
+        return idEntry;
+    }
+
+    protected static IdEntries createIdEntries(String idKey, long newIdVal) {
+        return new IdEntriesBuilder().setKey(new IdEntriesKey(idKey))
+                .setIdKey(idKey).setIdValue(newIdVal).build();
+    }
+
+    protected static DelayedIdEntries createDelayedIdEntry(long idValue, long delayTime) {
+        return new DelayedIdEntriesBuilder()
+                .setId(idValue)
+                .setReadyTimeSec(delayTime).build();
+    }
+
+    protected static IdPool createGlobalPool(String poolName, long low, long high, long blockSize) {
+        AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(low, high, low - 1);
+        ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, 0);
+        int size = (int) blockSize;
+        return new IdPoolBuilder().setKey(new IdPoolKey(poolName))
+                .setBlockSize(size).setPoolName(poolName)
+                .setAvailableIdsHolder(availableIdsHolder)
+                .setReleasedIdsHolder(releasedIdsHolder).build();
+    }
+
+    protected static AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) {
+        AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder()
+                .setStart(low).setEnd(high).setCursor(cursor).build();
+        return availableIdsHolder;
+    }
+
+    protected static ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, long delayTime) {
+        ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder()
+                .setAvailableIdCount(availableIdCount)
+                .setDelayedTimeSec(delayTime).build();
+        return releasedIdsHolder;
+    }
+
+    protected static InstanceIdentifier<IdPool> getIdPoolInstance(String poolName) {
+        InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idPoolBuilder = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(poolName));
+        InstanceIdentifier<IdPool> id = idPoolBuilder.build();
+        return id;
+    }
+
+    protected static InstanceIdentifier<ReleasedIdsHolder> getReleasedIdsHolderInstance(String poolName) {
+        InstanceIdentifier.InstanceIdentifierBuilder<ReleasedIdsHolder> releasedIdsHolder = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(poolName)).child(ReleasedIdsHolder.class);
+        InstanceIdentifier<ReleasedIdsHolder> releasedIds = releasedIdsHolder.build();
+        return releasedIds;
+    }
+
+    /**
+     * Changes made to releasedIds are not persisted in the datastore.
+     * @param releasedIds
+     * @return
+     */
+    protected static long getIdFromReleaseIdsIfAvailable(ReleasedIdsHolderBuilder releasedIds) {
+        List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
+        long newIdValue = -1;
+        if (delayedIdEntries != null && !delayedIdEntries.isEmpty()) {
+            processDelayList(releasedIds);
+            if (releasedIds.getAvailableIdCount() > 0) {
+                DelayedIdEntries delayedIdEntry= delayedIdEntries.get(0);
+                newIdValue = delayedIdEntry.getId();
+                delayedIdEntries.remove(delayedIdEntry);
+                releasedIds.setDelayedIdEntries(delayedIdEntries);
+                releasedIds.setAvailableIdCount(releasedIds.getAvailableIdCount() - 1);
+            }
+        }
+        return newIdValue;
+    }
+
+    /**
+     * Changes made to availableIds are not persisted to datastore.
+     * @param availableIds
+     * @return
+     */
+    protected static long getIdFromAvailableIds(AvailableIdsHolderBuilder availableIds) {
+        long newIdValue = -1;
+        if (availableIds != null && isIdAvailable(availableIds)) {
+            newIdValue = availableIds.getCursor() + 1;
+            availableIds.setCursor(newIdValue);
+        }
+        return newIdValue;
+    }
+
+    protected static boolean isIdAvailable(AvailableIdsHolderBuilder availableIds) {
+        if (availableIds.getCursor() != null && availableIds.getEnd() != null)
+            return availableIds.getCursor() < availableIds.getEnd();
+        return false;
+    }
+
+    protected static String getLocalPoolName(String poolName) {
+        return (poolName + "." + BLADE_ID);
+    }
+
+    protected static IdPool createLocalIdPool(String localPoolName, IdPool parentIdPool) {
+        ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(DEFAULT_AVAILABLE_ID_COUNT, DEFAULT_DELAY_TIME);
+        return new IdPoolBuilder().setKey(new IdPoolKey(localPoolName))
+                .setPoolName(localPoolName)
+                .setParentPoolName(parentIdPool.getPoolName())
+                .setBlockSize(parentIdPool.getBlockSize())
+                .setReleasedIdsHolder(releasedIdsHolder).build();
+    }
+
+    protected static ChildPools createChildPool(String childPoolName) {
+        return new ChildPoolsBuilder().setKey(new ChildPoolsKey(childPoolName)).setChildPoolName(childPoolName).setLastAccessTime(System.currentTimeMillis() / 1000).build();
+    }
+
+    protected static AvailableIdsHolderBuilder getAvailableIdsHolderBuilder(IdPool pool) {
+        AvailableIdsHolder availableIds = pool.getAvailableIdsHolder();
+        if (availableIds != null )
+            return new AvailableIdsHolderBuilder(availableIds);
+        return new AvailableIdsHolderBuilder();
+    }
+
+    protected static ReleasedIdsHolderBuilder getReleaseIdsHolderBuilder(IdPool pool) {
+        ReleasedIdsHolder releasedIds = pool.getReleasedIdsHolder();
+        if (releasedIds != null)
+            return new ReleasedIdsHolderBuilder(releasedIds);
+        return new ReleasedIdsHolderBuilder();
+    }
+
+    /**
+     * Changes made to releaseIds are not persisted to the Datastore. Method invoking should ensure that releaseIds gets persisted.
+     * @param releasedIds
+     */
+    protected static void processDelayList(ReleasedIdsHolderBuilder releasedIds) {
+        List<DelayedIdEntries> delayedIdEntries = releasedIds.getDelayedIdEntries();
+        if (delayedIdEntries ==  null)
+            return;
+        long availableIdCount = releasedIds.getAvailableIdCount() == null ? 0 : releasedIds.getAvailableIdCount();
+        int index = (int) availableIdCount;
+        long currentTimeSec = System.currentTimeMillis() / 1000;
+        DelayedIdEntry delayedIdEntry;
+        while (index < delayedIdEntries.size()) {
+            delayedIdEntry = delayedIdEntries.get(index);
+            if (delayedIdEntry.getReadyTimeSec() > currentTimeSec) {
+                break;
+            }
+            availableIdCount++;
+            index++;
+        }
+        releasedIds.setAvailableIdCount(availableIdCount);
+    }
+
+    /**
+     * Changes made to the parameters passed are not persisted to the Datastore. Method invoking should ensure that these gets persisted.
+     * @param releasedIdsChild
+     * @param releasedIdsParent
+     * @param idCountToBeFreed
+     */
+    protected static void freeExcessAvailableIds(ReleasedIdsHolderBuilder releasedIdsChild, ReleasedIdsHolderBuilder releasedIdsParent, int idCountToBeFreed) {
+        List<DelayedIdEntries> existingDelayedIdEntriesInParent = releasedIdsParent.getDelayedIdEntries();
+        List<DelayedIdEntries> delayedIdEntriesChild = releasedIdsChild.getDelayedIdEntries();
+        long availableIdCountParent = releasedIdsParent.getAvailableIdCount();
+        long availableIdCountChild = releasedIdsChild.getAvailableIdCount();
+        if (existingDelayedIdEntriesInParent == null) {
+            existingDelayedIdEntriesInParent = new LinkedList<>();
+        }
+        idCountToBeFreed = Math.min(idCountToBeFreed, delayedIdEntriesChild.size());
+        for (int index = 0; index < idCountToBeFreed; index++) {
+            existingDelayedIdEntriesInParent.add(delayedIdEntriesChild.get(0));
+            delayedIdEntriesChild.remove(0);
+        }
+        releasedIdsChild.setDelayedIdEntries(delayedIdEntriesChild).setAvailableIdCount(availableIdCountChild - idCountToBeFreed);
+        releasedIdsParent.setDelayedIdEntries(existingDelayedIdEntriesInParent).setAvailableIdCount(availableIdCountParent + idCountToBeFreed);
+    }
+
+    protected static InstanceIdentifier<IdEntries> getIdEntriesInstanceIdentifier(String poolName, String idKey) {
+        InstanceIdentifier<IdEntries> idEntries = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(poolName)).child(IdEntries.class, new IdEntriesKey(idKey)).build();
+        return idEntries;
+    }
+
+    protected static InstanceIdentifier<ChildPools> getChildPoolsInstanceIdentifier(String poolName, String localPoolName) {
+        InstanceIdentifier<ChildPools> childPools = InstanceIdentifier
+                .builder(IdPools.class)
+                .child(IdPool.class, new IdPoolKey(poolName))
+                .child(ChildPools.class, new ChildPoolsKey(localPoolName)).build();
+        return childPools;
+    }
+
+    protected static long computeBlockSize(long low, long high) {
+        long blockSize;
+
+        long diff = high - low;
+        if (diff > DEFAULT_BLOCK_SIZE_DIFF) {
+            blockSize = diff / DEFAULT_BLOCK_SIZE_DIFF;
+        } else {
+            blockSize = 1;
+        }
+        return blockSize;
+    }
+
+    public static long getAvailableIdsCount(AvailableIdsHolderBuilder availableIds) {
+        if(availableIds != null && isIdAvailable(availableIds)) {
+            return availableIds.getEnd() - availableIds.getCursor();
+        }
+        return 0;
+    }
+
+    public static void lockPool(LockManagerService lockManager, String poolName) {
+         LockInput input = new LockInputBuilder().setLockName(poolName).build();
+         Future<RpcResult<Void>> result = lockManager.lock(input);
+         try {
+             if ((result != null) && (result.get().isSuccessful())) {
+                 LOGGER.debug("Acquired lock {}", poolName);
+             } else {
+                 throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName));
+             }
+         } catch (InterruptedException | ExecutionException e) {
+             LOGGER.error("Unable to getLock for pool {}", poolName);
+             throw new RuntimeException(String.format("Unable to getLock for pool %s", poolName), e.getCause());
+         }
+    }
+
+    public static void unlockPool(LockManagerService lockManager, String poolName) {
+        UnlockInput input = new UnlockInputBuilder().setLockName(poolName).build();
+        Future<RpcResult<Void>> result = lockManager.unlock(input);
+        try {
+            if ((result != null) && (result.get().isSuccessful())) {
+                LOGGER.debug("Unlocked {}", poolName);
+            } else {
+                LOGGER.debug("Unable to unlock pool {}", poolName);
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOGGER.error("Unable to unlock for pool {}", poolName);
+            throw new RuntimeException(String.format("Unable to unlock pool %s", poolName), e.getCause());
+        }
+   }
+}
\ No newline at end of file
index 7002c7b..181cc49 100644 (file)
 package org.opendaylight.idmanager.test;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Future;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.idmanager.IdManager;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.*;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.id.pool.GeneratedIds;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.DeleteIdPoolInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.AvailableIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ChildPoolsKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.IdEntriesKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.id.pool.ReleasedIdsHolderBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntries;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.released.ids.DelayedIdEntriesBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import java.math.BigInteger;
-import java.util.*;
-import java.util.concurrent.Future;
+
+import com.google.common.base.Optional;
+import com.google.common.net.InetAddresses;
+import com.google.common.util.concurrent.Futures;
 
 
 @RunWith(MockitoJUnitRunner.class)
 public class IdManagerTest {
     private static final Logger LOG = LoggerFactory.getLogger(IdManagerTest.class);
-    Map<InstanceIdentifier<?>,DataObject> written = new HashMap<>();
-    Map<InstanceIdentifier<?>,DataObject> updated = new HashMap<>();
+    private static int BLADE_ID;
+    static {
+        String hostName;
+        try {
+            hostName = InetAddress.getLocalHost().getHostName();
+            BLADE_ID = InetAddresses.coerceToInteger(InetAddress.getLocalHost());
+            if (hostName.indexOf("-") > 0) {
+                BLADE_ID = new Integer(hostName.split("-")[1].toString()).intValue();
+            } else {
+                LOG.error("Host name {} is not matching with the condition!! PL-X is expected", hostName);
+            }
+        } catch (Exception e) {
+            LOG.error("IdManager - Exception - {}", e.getMessage());
+        }
+    }
+
+    Map<InstanceIdentifier<?>,DataObject> configDataStore = new HashMap<>();
     @Mock DataBroker dataBroker;
     @Mock ReadOnlyTransaction mockReadTx;
     @Mock WriteTransaction mockWriteTx;
-    CreateIdPoolInput createPoolTest;
-    GetUniqueIdInput  getIdInputTest;
+    @Mock LockManagerService lockManager;
+    Future<RpcResult<Void>> rpcResult;
     IdManager idManager;
-    IdPool idPoolTest;
+    IdPool globalIdPool;
     InstanceIdentifier<IdPool> identifier;
+    InstanceIdentifier<IdPool> childIdentifier;
+    InstanceIdentifier<ChildPools> childPoolIdentifier;
+    String globalPoolName = "test-pool";
+    String localPoolName = new StringBuilder(globalPoolName).append(".").append(BLADE_ID).toString();
+    String idKey = "test-key1";
+    int idStart = 100;
+    int idEnd = 200;
+    int blockSize = 2;
+    String idKey2 = "test-key2";
+    int idValue = 25;
 
     @Before
     public void setUp() throws Exception {
 
-        idManager = new IdManager(dataBroker) {
-            protected  <T extends DataObject> void asyncWrite(LogicalDatastoreType datastoreType,
-                                                             InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
-                written.put(path, data);
-            }
-            protected  <T extends DataObject> void asyncUpdate(LogicalDatastoreType datastoreType,
-                                                              InstanceIdentifier<T> path, T data, FutureCallback<Void> callback) {
-                updated.put(path, data);
-            }
-
-        };
+        idManager = new IdManager(dataBroker);
+        idManager.setLockManager(lockManager);
         setupMocks();
     }
 
     private void setupMocks() {
-        createPoolTest = buildCreateIdPool("vpn", 100, 100);
-        getIdInputTest = buildUniqueId("vpn", "vpn1");
-        idPoolTest = buildIdPool("vpn", 100, 100);
-        identifier = buildInstanceIdentifier("vpn");
+        globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).build();
+        identifier = buildInstanceIdentifier(globalPoolName);
+        childIdentifier = buildInstanceIdentifier(localPoolName);
+        childPoolIdentifier = buildChildPoolInstanceIdentifier(globalPoolName, localPoolName);
         when(dataBroker.newReadOnlyTransaction()).thenReturn(mockReadTx);
         when(dataBroker.newWriteOnlyTransaction()).thenReturn(mockWriteTx);
+        when(lockManager.lock(any(LockInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+        when(lockManager.unlock(any(UnlockInput.class))).thenReturn(Futures.immediateFuture(RpcResultBuilder.<Void>success().build()));
+        doReturn(Futures.immediateCheckedFuture(null)).when(mockWriteTx).submit();
+        doReturn(Futures.immediateCheckedFuture(null)).when(mockReadTx).read(eq(LogicalDatastoreType.OPERATIONAL), any(InstanceIdentifier.class));
     }
 
     @Test
-    public void testCreateIdPool()
+    public void testCreateIdPool() throws Exception
     {
+        CreateIdPoolInput createPoolTest = buildCreateIdPool(globalPoolName, idStart, idEnd);
         doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
-                LogicalDatastoreType.OPERATIONAL, identifier);
-
+                LogicalDatastoreType.CONFIGURATION, identifier);
+        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, childIdentifier);
         Future<RpcResult<Void>> result = idManager.createIdPool(createPoolTest);
-        Collection<DataObject> idPoolVal  = new ArrayList< >();
-        idPoolVal = written.values();
-        assertEquals(1,written.size());
-            for (DataObject poolData: idPoolVal) {
-                IdPool pool = null;
-                if (poolData instanceof IdPool) {
-                    pool = (IdPool) poolData;
-                    assertEquals(createPoolTest.getPoolName(), pool.getPoolName());
-                    assertEquals(createPoolTest.getIdStart(), pool.getIdStart());
-                    assertEquals(createPoolTest.getPoolSize(), pool.getPoolSize());
-                }
-            }
+        DataObject dataObject;
+        IdPool pool;
+        assertTrue(result.get().isSuccessful());
+        assertEquals(0,configDataStore.size());
+        dataObject = configDataStore.get(childIdentifier);
+        if (dataObject instanceof IdPool) {
+            pool = (IdPool) dataObject;
+            assertEquals(localPoolName, pool.getPoolName());
+            assertEquals(createPoolTest.getPoolName(), pool.getParentPoolName());
+            assertEquals(null, pool.getAvailableIdsHolder());
+            assertEquals(30, pool.getReleasedIdsHolder().getDelayedTimeSec().longValue());
+            assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().longValue());
+            assertEquals(blockSize, pool.getBlockSize().longValue());
+        }
+        dataObject = configDataStore.get(identifier);
+        if (dataObject instanceof IdPool) {
+            pool = (IdPool) dataObject;
+            assertEquals(createPoolTest.getPoolName(), pool.getPoolName());
+            assertEquals(0, pool.getReleasedIdsHolder().getDelayedTimeSec().longValue());
+            assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().longValue());
+            assertEquals(createPoolTest.getLow(), pool.getAvailableIdsHolder().getStart());
+            assertEquals(createPoolTest.getHigh(), pool.getAvailableIdsHolder().getEnd());
+            assertEquals(createPoolTest.getLow() - 1, pool.getAvailableIdsHolder().getCursor().intValue());
+            assertEquals(blockSize, pool.getBlockSize().longValue());
+        }
+        dataObject = configDataStore.get(childPoolIdentifier);
+        if (dataObject instanceof ChildPools) {
+            ChildPools childPool = (ChildPools) dataObject;
+            assertEquals(localPoolName, childPool.getChildPoolName());
+        }
     }
 
     @Test
-    public void testUniqueId()
+    public void testAllocateId() throws Exception
     {
-        Optional<IdPool> expected = Optional.of(idPoolTest);
+        AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, idKey);
+        Optional<IdPool> expected = Optional.of(globalIdPool);
+        List<IdEntries> idEntries = new ArrayList<IdEntries>();
+        idEntries.add(buildIdEntry(idKey2, idValue));
+        Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).setIdEntries(idEntries).build());
         doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
-                LogicalDatastoreType.OPERATIONAL, identifier);
-
-        idManager.getUniqueId(getIdInputTest);
-        Collection<DataObject> idPoolVal  = new ArrayList< >();
-        idPoolVal = updated.values();
-        assertEquals(1,updated.size());
-            for (DataObject poolData: idPoolVal) {
-                IdPool pool = null;
-                if (poolData instanceof IdPool) {
-                    pool = (IdPool) poolData;
-                    assertEquals(getIdInputTest.getPoolName(), pool.getPoolName());
-                    List <GeneratedIds> genIds = pool.getGeneratedIds();
-                    assertEquals(1,genIds.size());
-                }
-            }
+                LogicalDatastoreType.CONFIGURATION, identifier);
+        doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, childIdentifier);
+        InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(idKey);
+        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier);
+        InstanceIdentifier<AvailableIdsHolder> availableIdsIdentifier = buildAvailbaleIdsIdentifier(globalPoolName);
+
+        Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(allocateIdInput);
+        assertTrue(result.get().isSuccessful());
+        assertEquals(0,configDataStore.size());
+        DataObject dataObject = configDataStore.get(childIdentifier);
+        if (dataObject instanceof IdPool) {
+            IdPool pool = (IdPool) dataObject;
+            assertEquals(localPoolName, pool.getPoolName());
+            assertEquals(idStart, pool.getAvailableIdsHolder().getStart().intValue());
+            assertEquals(idStart + blockSize - 1 , pool.getAvailableIdsHolder().getEnd().intValue());
+            assertEquals(idStart, pool.getAvailableIdsHolder().getCursor().intValue());
+            assertEquals(2, pool.getIdEntries().size());
+        }
+        dataObject = configDataStore.get(availableIdsIdentifier);
+        if (dataObject instanceof AvailableIdsHolder) {
+            AvailableIdsHolder availableIds = (AvailableIdsHolder) dataObject;
+            assertEquals(idEnd, availableIds.getEnd().intValue());
+            assertEquals(idStart, availableIds.getStart().intValue());
+            assertEquals(idStart + blockSize - 1, availableIds.getCursor().intValue());
+        }
+    }
+
+    @Test
+    public void testReleaseId() throws Exception {
+        ReleaseIdInput releaseIdInput = createReleaseIdInput(globalPoolName, idKey);
+        List<IdEntries> idEntries = new ArrayList<IdEntries>();
+        idEntries.add(buildIdEntry(idKey, idValue));
+        Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).setIdEntries(idEntries).build());
+        doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, childIdentifier);
+        InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(idKey);
+        Optional<IdEntries> expectedIdEntry = Optional.of(buildIdEntry(idKey, idValue));
+        doReturn(Futures.immediateCheckedFuture(expectedIdEntry)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier);
+        Future<RpcResult<Void>> result = idManager.releaseId(releaseIdInput);
+        assertTrue(result.get().isSuccessful());
+        assertEquals(0, configDataStore.size());
+        DataObject idPoolVal = configDataStore.get(childIdentifier);
+        if (idPoolVal instanceof IdPool) {
+            IdPool pool = (IdPool) idPoolVal;
+            assertEquals(0, pool.getIdEntries().size());
+            assertEquals(0, pool.getReleasedIdsHolder().getAvailableIdCount().intValue());
+            assertEquals(idValue, pool.getReleasedIdsHolder().getDelayedIdEntries().get(0).getId().intValue());
+        }
+    }
+
+    @Test
+    public void testCleanupReleasedIds() throws Exception {
+        AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, idKey2);
+        Optional<ReleasedIdsHolder> expected = Optional.of(createReleasedIdsHolder(0, null, 0));
+        long[] excessIds = new long[] { 1, 2, 3, 4, 5 };
+        List<IdEntries> idEntries = new ArrayList<IdEntries>();
+        idEntries.add(buildIdEntry(idKey2, idValue));
+        ReleasedIdsHolder excessReleasedIds = createReleasedIdsHolder(0, buildDelayedIdEntries(excessIds), (long) 30);
+        Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName)
+                .setIdEntries(idEntries).setReleasedIdsHolder(excessReleasedIds)
+                .build());
+        InstanceIdentifier<ReleasedIdsHolder> releaseIdsIdentifier = buildReleaseIdsIdentifier(globalPoolName);
+        doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx)
+                .read(LogicalDatastoreType.CONFIGURATION, releaseIdsIdentifier);
+        doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(
+                mockReadTx).read(LogicalDatastoreType.CONFIGURATION,
+                childIdentifier);
+        InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(idKey2);
+        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(
+                mockReadTx).read(LogicalDatastoreType.CONFIGURATION,
+                idEntriesIdentifier);
+
+        Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(allocateIdInput);
+        assertTrue(result.get().isSuccessful());
+        assertEquals(0, configDataStore.size());
+        DataObject dataObject = configDataStore.get(childIdentifier);
+        if (dataObject instanceof IdPool) {
+            IdPool pool = (IdPool) dataObject;
+            assertEquals(localPoolName, pool.getPoolName());
+            assertEquals(excessIds.length - 3, pool.getReleasedIdsHolder().getAvailableIdCount().intValue());
+            assertEquals(2, pool.getIdEntries().size());
+        }
+        dataObject = configDataStore.get(releaseIdsIdentifier);
+        if (dataObject instanceof ReleasedIdsHolder) {
+            ReleasedIdsHolder releasedIds = (ReleasedIdsHolder) dataObject;
+            assertEquals(2, releasedIds.getAvailableIdCount().intValue());
+            assertEquals(2, releasedIds.getDelayedIdEntries().size());
+        }
+    }
+
+    @Test
+    public void testAllocateIdBlockFromReleasedIds() throws Exception {
+        AllocateIdInput allocateIdInput = buildAllocateId(globalPoolName, globalPoolName);
+        List<DelayedIdEntries> delayedIdEntries = buildDelayedIdEntries(new long[] {1, 2, 3});
+        ReleasedIdsHolder expectedReleasedIds = createReleasedIdsHolder(3, delayedIdEntries , 0);
+        IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).setReleasedIdsHolder(expectedReleasedIds).build();
+        Optional<IdPool> expected = Optional.of(globalIdPool);
+        Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build());
+        doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, identifier);
+        doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, childIdentifier);
+        InstanceIdentifier<IdEntries> idEntriesIdentifier = buildIdEntriesIdentifier(globalPoolName);
+        doReturn(Futures.immediateCheckedFuture(Optional.absent())).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, idEntriesIdentifier);
+        InstanceIdentifier<ReleasedIdsHolder> releaseIdsIdentifier = buildReleaseIdsIdentifier(globalPoolName);
+
+        Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(allocateIdInput);
+        assertTrue(result.get().isSuccessful());
+        assertEquals(0,configDataStore.size());
+        DataObject dataObject = configDataStore.get(childIdentifier);
+        if (dataObject instanceof IdPool) {
+            IdPool pool = (IdPool) dataObject;
+            assertEquals(localPoolName, pool.getPoolName());
+            assertEquals(1, pool.getReleasedIdsHolder().getDelayedIdEntries().size());
+            assertEquals(1, pool.getIdEntries().size());
+            assertEquals(1, pool.getReleasedIdsHolder().getAvailableIdCount().intValue());
+        }
+        dataObject = configDataStore.get(releaseIdsIdentifier);
+        if (dataObject instanceof ReleasedIdsHolder) {
+            ReleasedIdsHolder releasedIds = (ReleasedIdsHolder) dataObject;
+            assertEquals(1, releasedIds.getAvailableIdCount().intValue());
+            assertEquals(1, releasedIds.getDelayedIdEntries().size());
+        }
+    }
+
+    @Test
+    public void testDeletePool() throws Exception {
+        IdPool globalIdPool = buildGlobalIdPool(globalPoolName, idStart, idEnd, blockSize, buildChildPool(localPoolName)).build();
+        Optional<IdPool> expected = Optional.of(globalIdPool);
+        Optional<IdPool> expectedLocalPool = Optional.of(buildLocalIdPool(blockSize, localPoolName, globalPoolName).build());
+        doReturn(Futures.immediateCheckedFuture(expected)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, identifier);
+        doReturn(Futures.immediateCheckedFuture(expectedLocalPool)).when(mockReadTx).read(
+                LogicalDatastoreType.CONFIGURATION, childIdentifier);
+        DeleteIdPoolInput deleteIdPoolInput = createDeleteIdPoolInput(globalPoolName);
+        configDataStore.put(childIdentifier, null);
+        configDataStore.put(identifier, null);
+        Future<RpcResult<Void>> result = idManager.deleteIdPool(deleteIdPoolInput);
+        assertTrue(result.get().isSuccessful());
+        assertEquals(2, configDataStore.size());
+    }
+
+    private InstanceIdentifier<ReleasedIdsHolder> buildReleaseIdsIdentifier(
+            String poolName) {
+        InstanceIdentifier<ReleasedIdsHolder> releasedIds = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(poolName)).child(ReleasedIdsHolder.class).build();
+        return releasedIds;
+    }
+
+    private InstanceIdentifier<AvailableIdsHolder> buildAvailbaleIdsIdentifier(
+            String poolName) {
+        InstanceIdentifier<AvailableIdsHolder> availableIds = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(poolName)).child(AvailableIdsHolder.class).build();
+        return availableIds;
+    }
+
+    private InstanceIdentifier<ChildPools> buildChildPoolInstanceIdentifier(String poolName, String childPoolName) {
+        InstanceIdentifier<ChildPools> childPool = InstanceIdentifier
+                .builder(IdPools.class).child(IdPool.class,
+                        new IdPoolKey(poolName)).child(ChildPools.class, new ChildPoolsKey(childPoolName)).build();
+        return childPool;
+    }
+
+    private ReleaseIdInput createReleaseIdInput(String poolName, String idKey) {
+        return new ReleaseIdInputBuilder().setIdKey(idKey).setPoolName(poolName).build();
     }
 
-    private CreateIdPoolInput buildCreateIdPool(String poolName, long idStart, long poolSize) {
+    private IdEntries buildIdEntry(String idKey, long idValue) {
+        return new IdEntriesBuilder().setIdKey(idKey).setIdValue(idValue).build();
+    }
+
+    private InstanceIdentifier<IdEntries> buildIdEntriesIdentifier(String idKey) {
+        InstanceIdentifier.InstanceIdentifierBuilder<IdEntries> idEntriesBuilder = childIdentifier
+                .builder().child(IdEntries.class, new IdEntriesKey(idKey));
+        InstanceIdentifier<IdEntries> idEntry = idEntriesBuilder.build();
+        return idEntry;
+    }
+
+    private CreateIdPoolInput buildCreateIdPool(String poolName, long low, long high) {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder().setPoolName(poolName)
-                .setIdStart(idStart)
-                .setPoolSize(BigInteger.valueOf(poolSize))
+                .setLow(low)
+                .setHigh(high)
                 .build();
         return createPool;
     }
 
-    private IdPool buildIdPool(String poolName, long idStart, long poolSize) {
-        IdPool idPool = new IdPoolBuilder().setPoolName(poolName)
-                .setIdStart(idStart)
-                .setPoolSize(BigInteger.valueOf(poolSize))
-                .build();
-        return idPool;
+    private IdPoolBuilder buildGlobalIdPool(String poolName, long idStart, long poolSize, int blockSize, List<ChildPools> childPools) {
+        AvailableIdsHolder availableIdsHolder = createAvailableIdsHolder(idStart, poolSize, idStart - 1);
+        ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(0, null, 0);
+        return new IdPoolBuilder().setKey(new IdPoolKey(poolName))
+                .setPoolName(poolName)
+                .setBlockSize(blockSize)
+                .setChildPools(childPools)
+                .setAvailableIdsHolder(availableIdsHolder)
+                .setReleasedIdsHolder(releasedIdsHolder);
     }
 
-    private GetUniqueIdInput buildUniqueId(String poolName, String idKey) {
-        GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder().setPoolName(poolName)
+    private IdPoolBuilder buildLocalIdPool(int blockSize, String localPoolName, String parentPoolName) {
+        ReleasedIdsHolder releasedIdsHolder = createReleasedIdsHolder(0, null, (long) 30);
+        return new IdPoolBuilder().setBlockSize(blockSize)
+                .setKey(new IdPoolKey(localPoolName))
+                .setParentPoolName(parentPoolName)
+                .setReleasedIdsHolder(releasedIdsHolder);
+    }
+
+    private AllocateIdInput buildAllocateId(String poolName, String idKey) {
+        AllocateIdInput getIdInput = new AllocateIdInputBuilder().setPoolName(poolName)
                 .setIdKey(idKey).build();
         return getIdInput;
     }
 
-    private InstanceIdentifier<IdPool> buildInstanceIdentifier(String poolName){
+    private InstanceIdentifier<IdPool> buildInstanceIdentifier(String poolName) {
         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
-                InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
+                InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
         InstanceIdentifier<IdPool> id = idBuilder.build();
         return id;
     }
-}
 
+    private AvailableIdsHolder createAvailableIdsHolder(long low, long high, long cursor) {
+        AvailableIdsHolder availableIdsHolder = new AvailableIdsHolderBuilder()
+                .setStart(low).setEnd(high).setCursor(cursor).build();
+        return availableIdsHolder;
+    }
+
+    private ReleasedIdsHolder createReleasedIdsHolder(long availableIdCount, List<DelayedIdEntries> delayedIdEntries, long delayTime) {
+        ReleasedIdsHolder releasedIdsHolder = new ReleasedIdsHolderBuilder()
+                .setAvailableIdCount(availableIdCount)
+                .setDelayedIdEntries(delayedIdEntries)
+                .setDelayedTimeSec(delayTime).build();
+        return releasedIdsHolder;
+    }
+
+    private DeleteIdPoolInput createDeleteIdPoolInput(String poolName) {
+        return new DeleteIdPoolInputBuilder().setPoolName(poolName).build();
+    }
+
+    private List<DelayedIdEntries> buildDelayedIdEntries(long[] idValues) {
+        List<DelayedIdEntries> delayedIdEntriesList = new ArrayList<DelayedIdEntries>();
+        for (long idValue : idValues) {
+            DelayedIdEntries delayedIdEntries = new DelayedIdEntriesBuilder().setId(idValue).setReadyTimeSec(0L).build();
+            delayedIdEntriesList.add(delayedIdEntries);
+        }
+        return delayedIdEntriesList;
+    }
+
+    private List<ChildPools> buildChildPool(String childPoolName) {
+        ChildPools childPools = new ChildPoolsBuilder().setChildPoolName(childPoolName).build();
+        List<ChildPools> childPoolsList = new ArrayList<ChildPools>();
+        childPoolsList.add(childPools);
+        return childPoolsList;
+    }
+}
\ No newline at end of file
index bcaf8ef..351a37a 100644 (file)
@@ -10,7 +10,8 @@ package org.opendaylight.vpnservice.interfacemgr;
 
 public class IfmConstants {
     public static final String IFM_IDPOOL_NAME = "interfaces";
-    public static final long IFM_IDPOOL_START = 1L;
+    public static final long IFM_ID_POOL_START = 1L;
+    public static final long IFM_ID_POOL_END = 65535;
     public static final String IFM_IDPOOL_SIZE = "65535";
     public static final String OF_URI_PREFIX = "openflow:";
     public static final String OF_URI_SEPARATOR = ":";
index 400ebd2..ebfed47 100644 (file)
@@ -26,10 +26,15 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instru
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.types.rev131026.instruction.list.Instruction;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
@@ -80,7 +85,7 @@ public class IfmUtil {
 
     public static InstanceIdentifier<IdPool> getPoolId(String poolName){
         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
-                        InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
+                        InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
         InstanceIdentifier<IdPool> id = idBuilder.build();
         return id;
     }
index b2003ff..e886115 100644 (file)
@@ -98,8 +98,8 @@ public class InterfacemgrProvider implements BindingAwareProvider, AutoCloseable
     private void createIdPool() {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
             .setPoolName(IfmConstants.IFM_IDPOOL_NAME)
-            .setIdStart(IfmConstants.IFM_IDPOOL_START)
-            .setPoolSize(new BigInteger(IfmConstants.IFM_IDPOOL_SIZE))
+                .setLow(IfmConstants.IFM_ID_POOL_START)
+                .setHigh(IfmConstants.IFM_ID_POOL_END)
             .build();
         //TODO: Error handling
         Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
index 6b10cb0..3456bf3 100644 (file)
@@ -24,9 +24,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.No
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
@@ -119,26 +116,6 @@ public class InterfaceManagerCommonUtils {
         return ifStateOptional.get();
     }
 
-    public static Integer getUniqueId(IdManager idManager, String idKey) {
-        GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder()
-                .setPoolName(IfmConstants.IFM_LPORT_TAG_IDPOOL_NAME)
-                .setIdKey(idKey).build();
-
-        try {
-            Future<RpcResult<GetUniqueIdOutput>> result = idManager.
-                    getUniqueId(getIdInput);
-            RpcResult<GetUniqueIdOutput> rpcResult = result.get();
-            if(rpcResult.isSuccessful()) {
-                return rpcResult.getResult().getIdValue().intValue();
-            } else {
-                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
-            }
-        } catch (NullPointerException | InterruptedException | ExecutionException e) {
-            LOG.warn("Exception when getting Unique Id",e);
-        }
-        return 0;
-    }
-
     public static String getJobKey(String dpId, String portName) {
         String jobKey = "";
         if (dpId != null && !"".equals(dpId)) {
index e90a8f9..78f87f3 100644 (file)
@@ -12,6 +12,8 @@ import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.idmanager.IdManager;
+import org.opendaylight.vpnservice.VpnUtil;
+import org.opendaylight.vpnservice.interfacemgr.IfmConstants;
 import org.opendaylight.vpnservice.interfacemgr.IfmUtil;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceManagerCommonUtils;
 import org.opendaylight.vpnservice.interfacemgr.commons.InterfaceMetaUtils;
@@ -137,13 +139,16 @@ public class OvsVlanMemberConfigAddHelper {
 
     private static long createInterfaceChildEntry(DataBroker dataBroker, IdManager idManager, WriteTransaction t,
                                                 InterfaceParentEntryKey interfaceParentEntryKey, String childInterface){
-        long lportTag = InterfaceManagerCommonUtils.getUniqueId(idManager, childInterface);
-        InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
-        InstanceIdentifier<InterfaceChildEntry> intfId =
-                InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
-        InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
-                .setChildInterface(childInterface);
-        t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(),true);
-        return lportTag;
+
+            //TODO FIXME
+//        long lportTag = InterfaceManagerCommonUtils.getUniqueId(idManager, childInterface);
+//        InterfaceChildEntryKey interfaceChildEntryKey = new InterfaceChildEntryKey(childInterface);
+//        InstanceIdentifier<InterfaceChildEntry> intfId =
+//                InterfaceMetaUtils.getInterfaceChildEntryIdentifier(interfaceParentEntryKey, interfaceChildEntryKey);
+//        InterfaceChildEntryBuilder entryBuilder = new InterfaceChildEntryBuilder().setKey(interfaceChildEntryKey)
+//                .setChildInterface(childInterface);
+//        t.put(LogicalDatastoreType.CONFIGURATION, intfId, entryBuilder.build(),true);
+//        return lportTag;
+        return 0L;
     }
 }
index 1bcba00..e8e7e6f 100644 (file)
@@ -44,9 +44,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.re
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.Options;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.ovsdb.rev150105.ovsdb.port._interface.attributes.OptionsKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntry;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.interfacemgr.meta.rev151007.bridge._interface.info.BridgeEntryKey;
diff --git a/lockmanager/lockmanager-api/pom.xml b/lockmanager/lockmanager-api/pom.xml
new file mode 100644 (file)
index 0000000..4b9fe8c
--- /dev/null
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <parent>
+    <groupId>org.opendaylight.vpnservice</groupId>
+    <artifactId>binding-parent</artifactId>
+    <version>0.2.0-SNAPSHOT</version>
+    <relativePath>../../commons/binding-parent</relativePath>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vpnservice</groupId>
+  <artifactId>lockmanager-api</artifactId>
+  <version>${vpnservices.version}</version>
+  <packaging>bundle</packaging>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-binding</artifactId>
+      <version>${yangtools.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-common</artifactId>
+      <version>${yangtools.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+      <pluginManagement>
+          <plugins>
+              <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+              <plugin>
+                  <groupId>org.eclipse.m2e</groupId>
+                  <artifactId>lifecycle-mapping</artifactId>
+                  <version>1.0.0</version>
+                  <configuration>
+                      <lifecycleMappingMetadata>
+                          <pluginExecutions>
+                              <pluginExecution>
+                                  <pluginExecutionFilter>
+                                      <groupId>
+                                          org.opendaylight.yangtools
+                                      </groupId>
+                                      <artifactId>
+                                          yang-maven-plugin
+                                      </artifactId>
+                                      <versionRange>
+                                          [0.7.1-SNAPSHOT,)
+                                      </versionRange>
+                                      <goals>
+                                          <goal>generate-sources</goal>
+                                      </goals>
+                                  </pluginExecutionFilter>
+                                  <action>
+                                      <ignore></ignore>
+                                  </action>
+                              </pluginExecution>
+                          </pluginExecutions>
+                      </lifecycleMappingMetadata>
+                  </configuration>
+              </plugin>
+          </plugins>
+      </pluginManagement>
+  </build>
+</project>
diff --git a/lockmanager/lockmanager-api/src/main/yang/lock-manager.yang b/lockmanager/lockmanager-api/src/main/yang/lock-manager.yang
new file mode 100644 (file)
index 0000000..4ac3049
--- /dev/null
@@ -0,0 +1,71 @@
+module lock-manager {
+    namespace "urn:opendaylight:vpnservice:lockmanager";
+    prefix lockmgr;
+
+    revision "2015-08-19" {
+        description "YANG model describes methods that ensure locking while accessing the datastore";
+    }
+
+    typedef time-units {
+      type enumeration {
+        enum days;
+        enum hours;
+        enum microseconds;
+        enum milliseconds;
+        enum minutes;
+        enum nanoseconds;
+        enum seconds;
+      }
+    }
+
+    container locks {
+      description "Holds the list of lock name and lock owner";
+      list lock {
+        key "lock-name";
+        leaf lock-name {
+            type string;
+            mandatory true;
+        }
+        leaf lock-owner {
+            type string;
+            mandatory true;
+        }
+      }
+    }
+
+    rpc lock {
+        description "Method that checks if its locked already. If not adds the lock to the list of locks. Else tries until it acquires the lock";
+        input {
+             leaf lock-name {
+                type string;
+                mandatory true;
+             }
+        }
+    }
+
+    rpc try-lock {
+        description "Method that checks if its locked already. If not adds the lock to the list of locks. Else tries for the specified time";
+        input {
+             leaf lock-name {
+                type string;
+                mandatory true;
+             }
+             leaf time {
+                type uint32;
+             }
+             leaf time-unit {
+                type time-units;
+             }
+        }
+    }
+
+    rpc unlock {
+        description "Method that removes the lock from the list of locks";
+        input {
+             leaf lock-name {
+                type string;
+                mandatory true;
+             }
+        }
+    }
+}
\ No newline at end of file
diff --git a/lockmanager/lockmanager-impl/pom.xml b/lockmanager/lockmanager-impl/pom.xml
new file mode 100644 (file)
index 0000000..915f691
--- /dev/null
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: --><!--
+Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <parent>
+    <groupId>org.opendaylight.vpnservice</groupId>
+    <artifactId>config-parent</artifactId>
+    <version>0.2.0-SNAPSHOT</version>
+    <relativePath>../../commons/config-parent</relativePath>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.opendaylight.vpnservice</groupId>
+  <artifactId>lockmanager-impl</artifactId>
+  <version>${vpnservices.version}</version>
+  <packaging>bundle</packaging>
+  <dependencies>
+    <dependency>
+      <groupId>org.opendaylight.vpnservice</groupId>
+      <artifactId>lockmanager-api</artifactId>
+      <version>${vpnservices.version}</version>
+    </dependency>
+  </dependencies>
+  <build>
+      <pluginManagement>
+          <plugins>
+              <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+              <plugin>
+                  <groupId>org.eclipse.m2e</groupId>
+                  <artifactId>lifecycle-mapping</artifactId>
+                  <version>1.0.0</version>
+                  <configuration>
+                      <lifecycleMappingMetadata>
+                          <pluginExecutions>
+                              <pluginExecution>
+                                  <pluginExecutionFilter>
+                                      <groupId>
+                                          org.opendaylight.yangtools
+                                      </groupId>
+                                      <artifactId>
+                                          yang-maven-plugin
+                                      </artifactId>
+                                      <versionRange>
+                                          [0.7.1-SNAPSHOT,)
+                                      </versionRange>
+                                      <goals>
+                                          <goal>generate-sources</goal>
+                                      </goals>
+                                  </pluginExecutionFilter>
+                                  <action>
+                                      <ignore></ignore>
+                                  </action>
+                              </pluginExecution>
+                              <pluginExecution>
+                                  <pluginExecutionFilter>
+                                      <groupId>org.jacoco</groupId>
+                                      <artifactId>
+                                          jacoco-maven-plugin
+                                      </artifactId>
+                                      <versionRange>
+                                          [0.7.2.201409121644,)
+                                      </versionRange>
+                                      <goals>
+                                          <goal>prepare-agent</goal>
+                                      </goals>
+                                  </pluginExecutionFilter>
+                                  <action>
+                                      <ignore></ignore>
+                                  </action>
+                              </pluginExecution>
+                          </pluginExecutions>
+                      </lifecycleMappingMetadata>
+                  </configuration>
+              </plugin>
+          </plugins>
+      </pluginManagement>
+  </build>
+</project>
\ No newline at end of file
diff --git a/lockmanager/lockmanager-impl/src/main/config/default-config.xml b/lockmanager/lockmanager-impl/src/main/config/default-config.xml
new file mode 100644 (file)
index 0000000..fbf1b5b
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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
+-->
+<snapshot>
+  <required-capabilities>
+      <capability>urn:opendaylight:params:xml:ns:yang:lockmanager:impl?module=lockmanager-impl&amp;revision=2015-08-19</capability>
+      <capability>urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding?module=opendaylight-md-sal-binding&amp;revision=2013-10-28</capability>
+  </required-capabilities>
+  <configuration>
+
+    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+        <module>
+          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:lockmanager:impl">prefix:lockmanager-impl</type>
+          <name>lockmanager-default</name>
+          <broker>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
+            <name>binding-osgi-broker</name>
+          </broker>
+          <rpc-registry>
+            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-rpc-registry</type>
+            <name>binding-rpc-broker</name>
+          </rpc-registry>
+        </module>
+      </modules>
+    </data>
+  </configuration>
+</snapshot>
diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManager.java
new file mode 100644 (file)
index 0000000..28e548f
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.lockmanager;
+
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TryLockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.UnlockInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.Lock;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Optional;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+
+public class LockManager implements LockManagerService {
+    private static final Logger LOG = LoggerFactory.getLogger(LockManager.class);
+
+    private static final int DEFAULT_RETRY_COUNT = 3;
+    private static final int DEFAULT_WAIT_TIME_IN_MILLIS = 1000;
+
+    private final DataBroker broker;
+
+    public LockManager(final DataBroker db) {
+        broker = db;
+    }
+
+    @Override
+    public Future<RpcResult<Void>> lock(LockInput input) {
+        String lockName = input.getLockName();
+        LOG.info("Locking {}" , lockName);
+        InstanceIdentifier<Lock> lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName);
+        Lock lockData = LockManagerUtils.buildLockData(lockName);
+        try {
+            getLock(lockInstanceIdentifier, lockData);
+            RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.success();
+            LOG.info("Acquired lock {}" , lockName);
+            return Futures.immediateFuture(lockRpcBuilder.build());
+        } catch (InterruptedException e) {
+            RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.failed();
+            LOG.info("Failed to get lock {}" , lockName);
+            return Futures.immediateFuture(lockRpcBuilder.build());
+        }
+    }
+
+    @Override
+    public Future<RpcResult<Void>> tryLock(TryLockInput input) {
+        String lockName = input.getLockName();
+        LOG.info("Locking {}" , lockName);
+        long waitTime = input.getTime() == null ? DEFAULT_WAIT_TIME_IN_MILLIS * DEFAULT_RETRY_COUNT : input.getTime();
+        TimeUnit timeUnit = (TimeUnit) (input.getTimeUnit() == null ? TimeUnit.MILLISECONDS: LockManagerUtils.convertToTimeUnit(input.getTimeUnit()));
+        waitTime = LockManagerUtils.convertToMillis(waitTime, timeUnit);
+        long retryCount = waitTime / DEFAULT_WAIT_TIME_IN_MILLIS;
+        InstanceIdentifier<Lock> lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName);
+        Lock lockData = LockManagerUtils.buildLockData(lockName);
+        try {
+            if (getLock(lockInstanceIdentifier, lockData, retryCount)) {
+                RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.success();
+                LOG.info("Acquired lock {}" , lockName);
+                return Futures.immediateFuture(lockRpcBuilder.build());
+            }
+            RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.failed();
+            LOG.info("Failed to get lock {}" , lockName);
+            return Futures.immediateFuture(lockRpcBuilder.build());
+        } catch (Exception e) {
+            RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.failed();
+            LOG.info("Failed to get lock {}" , lockName);
+            return Futures.immediateFuture(lockRpcBuilder.build());
+        }
+    }
+
+    @Override
+    public Future<RpcResult<Void>> unlock(UnlockInput input) {
+        String lockName = input.getLockName();
+        LOG.info("Unlocking {}" , lockName);
+        InstanceIdentifier<Lock> lockInstanceIdentifier = LockManagerUtils.getLockInstanceIdentifier(lockName);
+        unlock(lockName, lockInstanceIdentifier);
+        RpcResultBuilder<Void> lockRpcBuilder = RpcResultBuilder.success();
+        return Futures.immediateFuture(lockRpcBuilder.build());
+    }
+
+    /**
+     * Try to acquire lock indefinitely until it is successful.
+     * @param lockInstanceIdentifier
+     * @param lockData
+     */
+    private void getLock(final InstanceIdentifier<Lock> lockInstanceIdentifier, final Lock lockData) throws InterruptedException {
+        try {
+            if (!readWriteLock(lockInstanceIdentifier, lockData)) {
+                LOG.debug("Already locked trying after {}", DEFAULT_WAIT_TIME_IN_MILLIS);
+                LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+                getLock(lockInstanceIdentifier, lockData);
+            }
+        } catch (ExecutionException e) {
+            LOG.error("In getLock unable to get lock due to {}, trying again", e.getMessage());
+            LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+            getLock(lockInstanceIdentifier, lockData);
+        }
+    }
+
+    /**
+     * Try to acquire lock for mentioned retryCount. Returns true if successfully acquired lock.
+     * @param lockInstanceIdentifier
+     * @param lockData
+     * @param retryCount
+     * @return
+     * @throws InterruptedException
+     */
+    private boolean getLock(InstanceIdentifier<Lock> lockInstanceIdentifier,
+            Lock lockData, long retryCount) throws InterruptedException {
+        if (retryCount < 0) {
+            return false;
+        }
+        try {
+            if (!readWriteLock(lockInstanceIdentifier, lockData)) {
+                LOG.debug("Already locked trying after {}, retry value {}", DEFAULT_WAIT_TIME_IN_MILLIS, retryCount);
+                LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+                return getLock(lockInstanceIdentifier, lockData, retryCount - 1);
+            }
+        } catch (ExecutionException e) {
+            LOG.error("In getLock unable to get lock due to {}, trying again, retry value {}", e.getMessage(), retryCount);
+            LockManagerUtils.sleep(DEFAULT_WAIT_TIME_IN_MILLIS);
+            return getLock(lockInstanceIdentifier, lockData, retryCount - 1);
+        }
+        return true;
+    }
+
+    /**
+     * Read and write the lock immediately if available. Returns true if successfully locked.
+     * @param lockInstanceIdentifier
+     * @param lockData
+     * @return
+     * @throws InterruptedException
+     * @throws ExecutionException
+     */
+    private boolean readWriteLock (final InstanceIdentifier<Lock> lockInstanceIdentifier, final Lock lockData) throws InterruptedException, ExecutionException {
+        ReadWriteTransaction tx = broker.newReadWriteTransaction();
+        Optional<Lock> result = Optional.absent();
+        result = tx.read(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier).get();
+        if (!result.isPresent()) {
+            tx.put(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier, lockData, true);
+            CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+            futures.get();
+            return true;
+        }
+        if (result.get().getLockOwner() == Thread.currentThread().getName()) {
+            return true;
+        }
+        return false;
+    }
+
+    private void unlock(final String lockName, final InstanceIdentifier<Lock> lockInstanceIdentifier) {
+        ReadWriteTransaction tx = broker.newReadWriteTransaction();
+        Optional<Lock> result = Optional.absent();
+        try {
+            result = tx.read(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier).get();
+            if (!result.isPresent()) {
+                LOG.info("{} is already unlocked", lockName);
+                return;
+            }
+            tx.delete(LogicalDatastoreType.OPERATIONAL, lockInstanceIdentifier);
+            CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+            futures.get();
+        } catch (Exception e) {
+            LOG.error("In unlock unable to unlock due to {}", e.getMessage());
+        }
+    }
+
+
+}
diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerServiceProvider.java
new file mode 100644 (file)
index 0000000..c90ba23
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.lockmanager;
+
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
+import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
+
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.LockManagerService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class LockManagerServiceProvider implements BindingAwareProvider,
+            AutoCloseable {
+
+        private static final Logger LOG = LoggerFactory.getLogger(LockManagerServiceProvider.class);
+        private LockManager lockManager;
+        private RpcProviderRegistry rpcProviderRegistry;
+
+    public RpcProviderRegistry getRpcProviderRegistry() {
+        return rpcProviderRegistry;
+    }
+
+    public void setRpcProviderRegistry(RpcProviderRegistry rpcProviderRegistry) {
+        this.rpcProviderRegistry = rpcProviderRegistry;
+    }
+
+        @Override
+    public void onSessionInitiated(ProviderContext session){
+        LOG.info("LockManagerServiceProvider Session Initiated");
+        try {
+            final  DataBroker dataBroker = session.getSALService(DataBroker.class);
+            lockManager = new LockManager(dataBroker);
+            final BindingAwareBroker.RpcRegistration<LockManagerService> rpcRegistration = getRpcProviderRegistry().addRpcImplementation(LockManagerService.class, lockManager);
+        } catch (Exception e) {
+            LOG.error("Error initializing services", e);
+        }
+    }
+
+    public LockManagerServiceProvider(RpcProviderRegistry rpcRegistry) {
+        this.rpcProviderRegistry = rpcRegistry;
+    }
+
+    @Override
+    public void close() throws Exception {
+        }
+    }
\ No newline at end of file
diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/lockmanager/LockManagerUtils.java
new file mode 100644 (file)
index 0000000..e4b8a96
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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.lockmanager;
+
+import java.util.concurrent.TimeUnit;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.Locks;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.TimeUnits;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.Lock;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.LockBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.lockmanager.rev150819.locks.LockKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class LockManagerUtils {
+
+    public static long convertToMillis(long waitTime, TimeUnit timeUnit) {
+        return timeUnit.toMillis(waitTime);
+    }
+
+    public static void sleep(long waitTime) {
+        try {
+            Thread.sleep(waitTime);
+        } catch (InterruptedException exception) {
+        }
+    }
+
+    public static TimeUnit convertToTimeUnit(TimeUnits timeUnit) {
+        switch (timeUnit) {
+        case Days:
+            return TimeUnit.DAYS;
+        case Microseconds:
+            return TimeUnit.MICROSECONDS;
+        case Hours:
+            return TimeUnit.HOURS;
+        case Minutes:
+            return TimeUnit.MINUTES;
+        case Nanoseconds:
+            return TimeUnit.NANOSECONDS;
+        case Seconds:
+            return TimeUnit.SECONDS;
+        case Milliseconds:
+        default:
+            return TimeUnit.MILLISECONDS;
+        }
+    }
+
+    public static InstanceIdentifier<Lock> getLockInstanceIdentifier(String lockName) {
+        return InstanceIdentifier
+                .builder(Locks.class).child(Lock.class,
+                        new LockKey(lockName)).build();
+    }
+
+    public static Lock buildLockData(String lockName) {
+        return new LockBuilder().setKey(new LockKey(lockName)).setLockName(lockName).setLockOwner(Thread.currentThread().getName()).build();
+    }
+}
\ No newline at end of file
diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModule.java
new file mode 100644 (file)
index 0000000..8df2fca
--- /dev/null
@@ -0,0 +1,26 @@
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819;
+
+import org.opendaylight.lockmanager.LockManagerServiceProvider;
+
+public class LockManagerImplModule extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.AbstractLockManagerImplModule {
+    public LockManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+        super(identifier, dependencyResolver);
+    }
+
+    public LockManagerImplModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver, org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.LockManagerImplModule oldModule, java.lang.AutoCloseable oldInstance) {
+        super(identifier, dependencyResolver, oldModule, oldInstance);
+    }
+
+    @Override
+    public void customValidation() {
+        // add custom validation form module attributes here.
+    }
+
+    @Override
+    public java.lang.AutoCloseable createInstance() {
+        LockManagerServiceProvider provider = new LockManagerServiceProvider(getRpcRegistryDependency());
+        getBrokerDependency().registerProvider(provider);
+        return provider;
+    }
+
+}
diff --git a/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java b/lockmanager/lockmanager-impl/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/lockmanager/impl/rev150819/LockManagerImplModuleFactory.java
new file mode 100644 (file)
index 0000000..12b3b60
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+* Generated file
+*
+* Generated from: yang module name: lockmanager-impl yang module local name: lockmanager-impl
+* Generated by: org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
+* Generated at: Thu Aug 27 12:50:22 IST 2015
+*
+* Do not modify this file unless it is present under src/main directory
+*/
+package org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819;
+public class LockManagerImplModuleFactory extends org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.lockmanager.impl.rev150819.AbstractLockManagerImplModuleFactory {
+
+}
diff --git a/lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang b/lockmanager/lockmanager-impl/src/main/yang/lockmanager-impl.yang
new file mode 100644 (file)
index 0000000..3178ba8
--- /dev/null
@@ -0,0 +1,44 @@
+module lockmanager-impl {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:lockmanager:impl";
+    prefix "lockmanager-impl";
+
+    import config { prefix config; revision-date 2013-04-05; }
+    import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
+
+    description
+        "Service definition for lockmanager project";
+
+    revision "2015-08-19" {
+        description
+            "Initial revision";
+    }
+
+    identity lockmanager-impl {
+        base config:module-type;
+        config:java-name-prefix LockManagerImpl;
+    }
+
+    augment "/config:modules/config:module/config:configuration" {
+        case lockmanager-impl {
+            when "/config:modules/config:module/config:type = 'lockmanager-impl'";
+            container broker {
+                uses config:service-ref {
+                    refine type {
+                        mandatory true;
+                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
+                    }
+                }
+            }
+            container rpc-registry {
+                 uses config:service-ref {
+                      refine type {
+                         mandatory true;
+                         config:required-identity md-sal-binding:binding-rpc-registry;
+                      }
+                 }
+            }
+
+        }
+    }
+}
diff --git a/lockmanager/pom.xml b/lockmanager/pom.xml
new file mode 100644 (file)
index 0000000..9bc8422
--- /dev/null
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (c) 2015 Ericsson India Global Services Pvt Ltd. 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 INTERNAL
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+  <parent>
+    <groupId>org.opendaylight.odlparent</groupId>
+    <artifactId>odlparent</artifactId>
+    <version>1.6.0-SNAPSHOT</version>
+    <relativePath/>
+  </parent>
+
+  <groupId>org.opendaylight.vpnservice</groupId>
+  <artifactId>lockmanager-aggregator</artifactId>
+  <version>0.2.0-SNAPSHOT</version>
+  <name>lockmanager</name>
+  <packaging>pom</packaging>
+  <modelVersion>4.0.0</modelVersion>
+  <prerequisites>
+    <maven>3.1.1</maven>
+  </prerequisites>
+  <modules>
+    <module>lockmanager-api</module>
+    <module>lockmanager-impl</module>
+  </modules>
+  <!-- DO NOT install or deploy the repo root pom as it's only needed to initiate a build -->
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-deploy-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-install-plugin</artifactId>
+        <configuration>
+          <skip>true</skip>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+</project>
\ No newline at end of file
index 23b7b61..5ccaa57 100644 (file)
@@ -14,6 +14,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
 import java.util.concurrent.LinkedBlockingQueue;
 
 import org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.action.PopVlanActionCaseBuilder;
@@ -63,10 +64,20 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.Tr
 import org.opendaylight.yang.gen.v1.urn.opendaylight.packet.service.rev130709.TransmitPacketInputBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.InstanceIdentifierBuilder;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
 import com.google.common.primitives.Bytes;
 import com.google.common.primitives.Ints;
+import com.google.common.util.concurrent.CheckedFuture;
 
 public class MDSALUtil {
 
@@ -76,6 +87,7 @@ public class MDSALUtil {
     private static final Instructions EMPTY_Instructions = new InstructionsBuilder().setInstruction(
             new ArrayList<Instruction>()).build();
     private static final Match EMPTY_Matches = new MatchBuilder().build();
+    private static final Logger logger = LoggerFactory.getLogger(MDSALUtil.class);
 
     public static FlowEntity buildFlowEntity(BigInteger dpnId, short tableId, String flowId, int priority, String flowName,
             int idleTimeOut, int hardTimeOut, BigInteger cookie, List<MatchInfo> listMatchInfo,
@@ -336,4 +348,74 @@ public class MDSALUtil {
                                 new WriteMetadataBuilder().setMetadata(metadata).setMetadataMask(mask).build())
                                 .build()).setKey(new InstructionKey(instructionKey)).build();
     }
+
+    public static <T extends DataObject> Optional<T> read(LogicalDatastoreType datastoreType,
+                                                          InstanceIdentifier<T> path, DataBroker broker) {
+
+        ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+        Optional<T> result = Optional.absent();
+        try {
+            result = tx.read(datastoreType, path).get();
+        } catch (Exception e) {
+            logger.error("An error occured while reading data from the path {} with the exception {}", path, e);
+        }
+        return result;
+    }
+
+    public static <T extends DataObject> Optional<T> read(DataBroker broker,
+                                                          LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
+
+        ReadOnlyTransaction tx = broker.newReadOnlyTransaction();
+
+        Optional<T> result = Optional.absent();
+        try {
+            result = tx.read(datastoreType, path).get();
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        return result;
+    }
+
+    public static <T extends DataObject> void syncWrite(DataBroker broker,
+                                                        LogicalDatastoreType datastoreType, InstanceIdentifier<T> path,
+                                                        T data) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.put(datastoreType, path, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            logger.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    public static <T extends DataObject> void syncUpdate(DataBroker broker,
+                                                         LogicalDatastoreType datastoreType, InstanceIdentifier<T> path,
+                                                         T data) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.merge(datastoreType, path, data, true);
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            logger.error("Error writing to datastore (path, data) : ({}, {})", path, data);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    public static <T extends DataObject> void syncDelete(DataBroker broker,
+                                                         LogicalDatastoreType datastoreType, InstanceIdentifier<T> obj) {
+        WriteTransaction tx = broker.newWriteOnlyTransaction();
+        tx.delete(datastoreType, obj);
+        CheckedFuture<Void, TransactionCommitFailedException> futures = tx.submit();
+        try {
+            futures.get();
+        } catch (InterruptedException | ExecutionException e) {
+            logger.error("Error deleting from datastore (path) : ({})", obj);
+            throw new RuntimeException(e.getMessage());
+        }
+    }
 }
index c0a9983..f44e841 100644 (file)
@@ -35,11 +35,14 @@ import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev14081
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.vpn.instances.VpnInstanceKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.GroupTypes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.CreateIdPoolInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.*;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.l3nexthop.rev150409.l3nexthop.tunnelnexthops.*;
@@ -106,20 +109,13 @@ public class NexthopManager implements L3nexthopService, AutoCloseable {
 
     protected void createNexthopPointerPool() {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
-            .setPoolName("nextHopPointerPool")
-            .setIdStart(1L)
-            .setPoolSize(new BigInteger("65535"))
-            .build();
+                .setPoolName("nextHopPointerPool")
+                .setLow(150000L)
+                .setHigh(175000L)
+                .build();
         //TODO: Error handling
         Future<RpcResult<Void>> result = idManager.createIdPool(createPool);
         LOG.trace("NextHopPointerPool result : {}", result);
-//            try {
-//                LOG.info("Result2: {}",result.get());
-//            } catch (InterruptedException | ExecutionException e) {
-//                // TODO Auto-generated catch block
-//                LOG.error("Error in result.get");
-//            }
-
     }
 
 
@@ -146,15 +142,15 @@ public class NexthopManager implements L3nexthopService, AutoCloseable {
         return dpn;
     }
 
-    protected int createNextHopPointer(String nexthopKey) {
-        GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder()
-            .setPoolName("nextHopPointerPool").setIdKey(nexthopKey)
-            .build();
+    protected long createNextHopPointer(String nexthopKey) {
+        AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+                .setPoolName("nextHopPointerPool").setIdKey(nexthopKey)
+                .build();
         //TODO: Proper error handling once IdManager code is complete
         try {
-            Future<RpcResult<GetUniqueIdOutput>> result = idManager.getUniqueId(getIdInput);
-            RpcResult<GetUniqueIdOutput> rpcResult = result.get();
-            return rpcResult.getResult().getIdValue().intValue();
+            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+            RpcResult<AllocateIdOutput> rpcResult = result.get();
+            return rpcResult.getResult().getIdValue();
         } catch (NullPointerException | InterruptedException | ExecutionException e) {
             LOG.trace("",e);
         }
@@ -163,7 +159,7 @@ public class NexthopManager implements L3nexthopService, AutoCloseable {
 
     public void createLocalNextHop(String ifName, String vpnName, String ipAddress, String macAddress) {
         String nhKey = new String("nexthop." + vpnName + ipAddress);
-        int groupId = createNextHopPointer(nhKey);
+        long groupId = createNextHopPointer(nhKey);
 
         long vpnId = getVpnId(vpnName);
         BigInteger dpnId = interfaceManager.getDpnForInterface(ifName);
@@ -197,7 +193,7 @@ public class NexthopManager implements L3nexthopService, AutoCloseable {
 
     public void createRemoteNextHop(String ifName, String ipAddress) {
         String nhKey = new String("nexthop." + ifName + ipAddress);
-        int groupId = createNextHopPointer(nhKey);
+        long groupId = createNextHopPointer(nhKey);
 
         BigInteger dpnId = interfaceManager.getDpnForInterface(ifName);
         TunnelNexthop nexthop = getTunnelNexthop(dpnId, ipAddress);
index fdcb511..bef3a27 100644 (file)
@@ -158,7 +158,7 @@ public class NexthopManagerTest {
     dataChangeEvent = new MockDataChangedEvent();
     vpnNexthop = new VpnNexthopBuilder().setEgressPointer(10L).setIpAddress(ipAddress).build();
     nhmgr = new NexthopManager(dataBroker) {
-      protected int createNextHopPointer(String nexthopKey) {
+      protected long createNextHopPointer(String nexthopKey) {
         return groupId;
       }
 
diff --git a/pom.xml b/pom.xml
index b7fbb63..f090c56 100644 (file)
--- a/pom.xml
+++ b/pom.xml
@@ -20,10 +20,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html INTERNAL
     <module>commons/config-parent</module>
     <module>model-bgp</module>
     <module>mdsalutil</module>
+    <module>lockmanager</module>
+    <module>idmanager</module>
     <module>vpnmanager</module>
     <module>interfacemgr</module>
     <module>nexthopmgr</module>
-    <module>idmanager</module>
     <module>fibmanager</module>
     <module>bgpmanager</module>
     <module>distribution/karaf</module>
index b56c1d0..0fc976e 100644 (file)
@@ -55,10 +55,10 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacencyLi
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.AdjacencyBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.VpnInstance1;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnInterfaces;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.huawei.params.xml.ns.yang.l3vpn.rev140815.VpnAfConfig;
@@ -202,7 +202,11 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             LOG.trace("NextHops are {}", nextHops);
             for (Adjacency nextHop : nextHops) {
                 String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-                long label = getUniqueId(key);
+                String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
+//                long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
+//                        .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
+                long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                        VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
                 value.add(new AdjacencyBuilder(nextHop).setLabel(label).build());
             }
 
@@ -212,31 +216,16 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
             syncWrite(LogicalDatastoreType.OPERATIONAL, interfaceId, opInterface, DEFAULT_CALLBACK);
             for (Adjacency nextHop : nextHops) {
                 String key = rd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-                long label = getUniqueId(key);
+                String prefix = VpnUtil.getIpPrefix(nextHop.getIpAddress());
+//                long label = getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, VpnUtil
+//                        .getNextHopLabelKey((rd == null) ? intf.getVpnInstanceName() : rd, prefix));
+                long label = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME,
+                        VpnUtil.getNextHopLabelKey(rd, nextHop.getIpAddress()));
                 updatePrefixToBGP(rd, nextHop, nextHopIp, label);
             }
         }
     }
 
-    private Integer getUniqueId(String idKey) {
-        GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder()
-                                           .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
-                                           .setIdKey(idKey).build();
-
-        try {
-            Future<RpcResult<GetUniqueIdOutput>> result = idManager.getUniqueId(getIdInput);
-            RpcResult<GetUniqueIdOutput> rpcResult = result.get();
-            if(rpcResult.isSuccessful()) {
-                return rpcResult.getResult().getIdValue().intValue();
-            } else {
-                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
-            }
-        } catch (NullPointerException | InterruptedException | ExecutionException e) {
-            LOG.warn("Exception when getting Unique Id",e);
-        }
-        return 0;
-    }
-
     private long getVpnId(String vpnName) {
         //TODO: This should be a Util function
         InstanceIdentifier<VpnInstance1> id = InstanceIdentifier.builder(VpnInstances.class)
@@ -495,7 +484,7 @@ public class VpnInterfaceManager extends AbstractDataChangeListener<VpnInterface
                     if(label == VpnConstants.INVALID_ID) {
                         //Generate label using ID Manager
                         String key = newRd + VpnConstants.SEPARATOR + nextHop.getIpAddress();
-                        label = getUniqueId(key);
+//                        label = getUniqueId(key);
                     }
                     removePrefixFromBGP(rd, nextHop);
                     //updatePrefixToBGP(newRd, nextHop, nextHopIp, label);
index 8e44ce2..b387c29 100644 (file)
@@ -37,9 +37,9 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev15
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTables;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.fibentries.VrfTablesKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.fibmanager.rev150330.vrfentries.VrfEntry;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.GetUniqueIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -143,7 +143,7 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
             VpnInstance value) {
         LOG.trace("key: {}, value: {}", identifier, value);
 
-        long vpnId = getUniqueId(value.getVpnInstanceName());
+        long vpnId = VpnUtil.getUniqueId(idManager, VpnConstants.VPN_IDPOOL_NAME, value.getVpnInstanceName());
 
         VpnInstance opValue = new VpnInstanceBuilder(value).
                  addAugmentation(VpnInstance1.class, new VpnInstance1Builder().setVpnId(vpnId).build()).build();
@@ -228,24 +228,24 @@ public class VpnManager extends AbstractDataChangeListener<VpnInstance> implemen
         return null;
     }
 
-    private Integer getUniqueId(String idKey) {
-        GetUniqueIdInput getIdInput = new GetUniqueIdInputBuilder()
-                                           .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
-                                           .setIdKey(idKey).build();
-
-        try {
-            Future<RpcResult<GetUniqueIdOutput>> result = idManager.getUniqueId(getIdInput);
-            RpcResult<GetUniqueIdOutput> rpcResult = result.get();
-            if(rpcResult.isSuccessful()) {
-                return rpcResult.getResult().getIdValue().intValue();
-            } else {
-                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
-            }
-        } catch (InterruptedException | ExecutionException e) {
-            LOG.warn("Exception when getting Unique Id",e);
-        }
-        return 0;
-    }
+//    private Integer getUniqueId(IdManagerService idManager, String poolName,String idKey) {
+//        AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+//                .setPoolName(poolName)
+//                .setIdKey(idKey).build();
+//
+//        try {
+//            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+//            RpcResult<AllocateIdOutput> rpcResult = result.get();
+//            if(rpcResult.isSuccessful()) {
+//                return rpcResult.getResult().getIdValue().intValue();
+//            } else {
+//                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+//            }
+//        } catch (InterruptedException | ExecutionException e) {
+//            LOG.warn("Exception when getting Unique Id",e);
+//        }
+//        return 0;
+//    }
 
     private <T extends DataObject> void delete(LogicalDatastoreType datastoreType, InstanceIdentifier<T> path) {
         WriteTransaction tx = broker.newWriteOnlyTransaction();
index 3d4be78..75b55e2 100644 (file)
@@ -25,13 +25,26 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.adjacency.list.Adjacency;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.Adjacencies;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.l3vpn.rev130911.AdjacenciesBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.Pools;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPool;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdPools;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPool;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.id.pools.IdPoolKey;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.AllocateIdOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.ReleaseIdInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.vpnservice.idmanager.rev150403.IdManagerService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class VpnUtil {
+
+    private static final Logger LOG = LoggerFactory.getLogger(VpnUtil.class);
+    private static final int DEFAULT_PREFIX_LENGTH = 32;
+    private static final String PREFIX_SEPARATOR = "/";
+
     static InstanceIdentifier<VpnInterface> getVpnInterfaceIdentifier(String vpnInterfaceName) {
         return InstanceIdentifier.builder(VpnInterfaces.class)
                 .child(VpnInterface.class, new VpnInterfaceKey(vpnInterfaceName)).build();
@@ -53,7 +66,7 @@ public class VpnUtil {
 
     public static InstanceIdentifier<IdPool> getPoolId(String poolName){
         InstanceIdentifier.InstanceIdentifierBuilder<IdPool> idBuilder =
-                        InstanceIdentifier.builder(Pools.class).child(IdPool.class, new IdPoolKey(poolName));
+                        InstanceIdentifier.builder(IdPools.class).child(IdPool.class, new IdPoolKey(poolName));
         InstanceIdentifier<IdPool> id = idBuilder.build();
         return id;
     }
@@ -66,4 +79,36 @@ public class VpnUtil {
         return InstanceIdentifier.builder(Interfaces.class)
                 .child(Interface.class, new InterfaceKey(interfaceName)).build();
     }
+
+    public static String getNextHopLabelKey(String rd, String prefix){
+        String key = rd + VpnConstants.SEPARATOR + prefix;
+        return key;
+    }
+
+    static String getIpPrefix(String prefix) {
+        String prefixValues[] = prefix.split("/");
+        if (prefixValues.length == 1) {
+            prefix = prefix + PREFIX_SEPARATOR + DEFAULT_PREFIX_LENGTH ;
+        }
+        return prefix;
+    }
+
+    public static int getUniqueId(IdManagerService idManager, String poolName,String idKey) {
+        AllocateIdInput getIdInput = new AllocateIdInputBuilder()
+                .setPoolName(poolName)
+                .setIdKey(idKey).build();
+
+        try {
+            Future<RpcResult<AllocateIdOutput>> result = idManager.allocateId(getIdInput);
+            RpcResult<AllocateIdOutput> rpcResult = result.get();
+            if(rpcResult.isSuccessful()) {
+                return rpcResult.getResult().getIdValue().intValue();
+            } else {
+                LOG.warn("RPC Call to Get Unique Id returned with Errors {}", rpcResult.getErrors());
+            }
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Exception when getting Unique Id",e);
+        }
+        return 0;
+    }
 }
index 0548c36..eb8b3d1 100644 (file)
@@ -85,8 +85,8 @@ public class VpnserviceProvider implements BindingAwareProvider, IVpnManager,
     private void createIdPool() {
         CreateIdPoolInput createPool = new CreateIdPoolInputBuilder()
             .setPoolName(VpnConstants.VPN_IDPOOL_NAME)
-            .setIdStart(VpnConstants.VPN_IDPOOL_START)
-            .setPoolSize(new BigInteger(VpnConstants.VPN_IDPOOL_SIZE))
+            .setLow(VpnConstants.VPN_IDPOOL_START)
+            .setHigh(new BigInteger(VpnConstants.VPN_IDPOOL_SIZE).longValue())
             .build();
         try {
            Future<RpcResult<Void>> result = idManager.createIdPool(createPool);