Genius Neon MRI changes
[genius.git] / idmanager / idmanager-impl / src / main / java / org / opendaylight / genius / idmanager / IdManager.java
index ebf66d39640590e07c8cdceabb3e1b6e2cca9e35..172bb94f0e2015c816a711d7ad7083d1980b69d7 100644 (file)
@@ -9,10 +9,13 @@ package org.opendaylight.genius.idmanager;
 
 import static java.util.Comparator.comparing;
 import static java.util.stream.Collectors.toCollection;
-import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
+import static org.opendaylight.controller.md.sal.binding.api.WriteTransaction.CREATE_MISSING_PARENTS;
+import static org.opendaylight.genius.infra.Datastore.CONFIGURATION;
 
 import com.google.common.base.Optional;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -26,17 +29,18 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.PostConstruct;
 import javax.annotation.PreDestroy;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+
+import org.apache.aries.blueprint.annotation.service.Reference;
 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.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.daexim.DataImportBootReady;
+import org.opendaylight.genius.datastoreutils.ExpectedDataObjectNotFoundException;
 import org.opendaylight.genius.datastoreutils.SingleTransactionDataBroker;
 import org.opendaylight.genius.idmanager.ReleasedIdHolder.DelayedIdEntry;
 import org.opendaylight.genius.idmanager.api.IdManagerMonitor;
@@ -45,10 +49,13 @@ import org.opendaylight.genius.idmanager.jobs.IdHolderSyncJob;
 import org.opendaylight.genius.idmanager.jobs.LocalPoolCreateJob;
 import org.opendaylight.genius.idmanager.jobs.LocalPoolDeleteJob;
 import org.opendaylight.genius.idmanager.jobs.UpdateIdEntryJob;
-import org.opendaylight.genius.infra.FutureRpcResults;
+import org.opendaylight.genius.infra.Datastore.Configuration;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunner;
 import org.opendaylight.genius.infra.ManagedNewTransactionRunnerImpl;
+import org.opendaylight.genius.infra.TypedReadWriteTransaction;
+import org.opendaylight.genius.infra.TypedWriteTransaction;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
+import org.opendaylight.serviceutils.tools.mdsal.rpc.FutureRpcResults;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutputBuilder;
@@ -56,10 +63,14 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdRangeOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdRangeOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.CreateIdPoolOutputBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.DeleteIdPoolOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdManagerService;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.IdPools;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.ReleaseIdOutput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPool;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.id.pools.IdPoolKey;
@@ -74,7 +85,6 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev16041
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.OperationFailedException;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.ops4j.pax.cdi.api.OsgiService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -96,7 +106,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
 
     @Inject
     public IdManager(DataBroker db, LockManagerService lockManager, IdUtils idUtils,
-            @OsgiService DataImportBootReady dataImportBootReady, JobCoordinator jobCoordinator)
+                     @Reference DataImportBootReady dataImportBootReady, JobCoordinator jobCoordinator)
                     throws ReadFailedException {
         this.broker = db;
         this.txRunner = new ManagedNewTransactionRunnerImpl(db);
@@ -139,7 +149,8 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     private void populateCache() throws ReadFailedException {
         // If IP changes during reboot, then there will be orphaned child pools.
         InstanceIdentifier<IdPools> idPoolsInstance = idUtils.getIdPools();
-        Optional<IdPools> idPoolsOptional = singleTxDB.syncReadOptional(CONFIGURATION, idPoolsInstance);
+        Optional<IdPools> idPoolsOptional =
+                singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, idPoolsInstance);
         if (!idPoolsOptional.isPresent()) {
             return;
         }
@@ -185,7 +196,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     @Override
-    public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input) {
+    public ListenableFuture<RpcResult<CreateIdPoolOutput>> createIdPool(CreateIdPoolInput input) {
         LOG.info("createIdPool called with input {}", input);
         long low = input.getLow();
         long high = input.getHigh();
@@ -194,15 +205,15 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
             String poolName = input.getPoolName().intern();
             try {
                 idUtils.lock(lockManager, poolName);
-                return txRunner.callWithNewWriteOnlyTransactionAndSubmit(tx -> {
-                    IdPool idPool = createGlobalPool(tx, poolName, low, high, blockSize);
+                return Futures.transform(txRunner.callWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
+                    IdPool idPool = createGlobalPool(confTx, poolName, low, high, blockSize);
                     String localPoolName = idUtils.getLocalPoolName(poolName);
                     IdLocalPool idLocalPool = localPool.get(poolName);
                     if (idLocalPool == null) {
-                        createLocalPool(tx, localPoolName, idPool);
-                        idUtils.updateChildPool(tx, idPool.getPoolName(), localPoolName);
+                        createLocalPool(confTx, localPoolName, idPool);
+                        idUtils.updateChildPool(confTx, idPool.getPoolName(), localPoolName);
                     }
-                });
+                }), unused -> new CreateIdPoolOutputBuilder().build(), MoreExecutors.directExecutor());
             } finally {
                 idUtils.unlock(lockManager, poolName);
             }
@@ -210,7 +221,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     @Override
-    public Future<RpcResult<AllocateIdOutput>> allocateId(AllocateIdInput input) {
+    public ListenableFuture<RpcResult<AllocateIdOutput>> allocateId(AllocateIdInput input) {
         String idKey = input.getIdKey();
         String poolName = input.getPoolName();
         return FutureRpcResults.fromBuilder(LOG, "allocateId", input, () -> {
@@ -230,7 +241,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     @Override
-    public Future<RpcResult<AllocateIdRangeOutput>> allocateIdRange(AllocateIdRangeInput input) {
+    public ListenableFuture<RpcResult<AllocateIdRangeOutput>> allocateIdRange(AllocateIdRangeInput input) {
         String idKey = input.getIdKey();
         String poolName = input.getPoolName();
         long size = input.getSize();
@@ -245,25 +256,25 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     @Override
-    public Future<RpcResult<Void>> deleteIdPool(DeleteIdPoolInput input) {
+    public ListenableFuture<RpcResult<DeleteIdPoolOutput>> deleteIdPool(DeleteIdPoolInput input) {
         return FutureRpcResults.fromListenableFuture(LOG, "deleteIdPool", input, () -> {
             String poolName = input.getPoolName().intern();
             InstanceIdentifier<IdPool> idPoolToBeDeleted = idUtils.getIdPoolInstance(poolName);
             synchronized (poolName) {
-                IdPool idPool = singleTxDB.syncRead(CONFIGURATION, idPoolToBeDeleted);
+                IdPool idPool = singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
                 List<ChildPools> childPoolList = idPool.getChildPools();
                 if (childPoolList != null) {
                     childPoolList.forEach(childPool -> deletePool(childPool.getChildPoolName()));
                 }
-                singleTxDB.syncDelete(CONFIGURATION, idPoolToBeDeleted);
+                singleTxDB.syncDelete(LogicalDatastoreType.CONFIGURATION, idPoolToBeDeleted);
             }
             // TODO return the Future from a TBD asyncDelete instead.. BUT check that all callers @CheckReturnValue
-            return Futures.immediateFuture((Void) null);
+            return Futures.immediateFuture((DeleteIdPoolOutput) null);
         }).build();
     }
 
     @Override
-    public Future<RpcResult<Void>> releaseId(ReleaseIdInput input) {
+    public ListenableFuture<RpcResult<ReleaseIdOutput>> releaseId(ReleaseIdInput input) {
         String poolName = input.getPoolName();
         String idKey = input.getIdKey();
         String uniqueKey = idUtils.getUniqueKey(poolName, idKey);
@@ -271,17 +282,18 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
             idUtils.lock(lockManager, uniqueKey);
             releaseIdFromLocalPool(poolName, idUtils.getLocalPoolName(poolName), idKey);
             // TODO return the Future from releaseIdFromLocalPool() instead.. check all callers @CheckReturnValue
-            return Futures.immediateFuture((Void) null);
-        }).onFailureLogLevel(org.opendaylight.genius.tools.mdsal.rpc.FutureRpcResults.LogLevel.NONE).onFailure(e -> {
-            if (e instanceof IdDoesNotExistException) {
-                // Do not log full stack trace in case ID does not exist
-                LOG.error("RPC releaseId() failed due to IdDoesNotExistException; input = {}", input);
-            } else {
-                // But for all other cases do:
-                LOG.error("RPC releaseId() failed; input = {}", input, e);
-            }
-            idUtils.unlock(lockManager, uniqueKey);
-        }).build();
+            return Futures.immediateFuture((ReleaseIdOutput) null);
+        }).onFailureLogLevel(org.opendaylight.serviceutils.tools.mdsal.rpc.FutureRpcResults.LogLevel.NONE)
+                .onFailure(e -> {
+                    if (e instanceof IdDoesNotExistException) {
+                        // Do not log full stack trace in case ID does not exist
+                        LOG.error("RPC releaseId() failed due to IdDoesNotExistException; input = {}", input);
+                    } else {
+                        // But for all other cases do:
+                        LOG.error("RPC releaseId() failed; input = {}", input, e);
+                    }
+                    idUtils.unlock(lockManager, uniqueKey);
+                }).build();
     }
 
     private List<Long> allocateIdFromLocalPool(String parentPoolName, String localPoolName,
@@ -331,7 +343,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     private Long getIdFromLocalPoolCache(IdLocalPool localIdPool, String parentPoolName)
-            throws OperationFailedException, IdManagerException {
+            throws IdManagerException {
         while (true) {
             IdHolder availableIds = localIdPool.getAvailableIds();
             if (availableIds != null) {
@@ -367,14 +379,13 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
      * Changes made to availableIds and releasedIds will not be persisted to the datastore.
      */
     private long getIdBlockFromParentPool(String parentPoolName, IdLocalPool localIdPool)
-            throws OperationFailedException, IdManagerException {
+            throws IdManagerException {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Allocating block of id from parent pool {}", parentPoolName);
         }
         InstanceIdentifier<IdPool> idPoolInstanceIdentifier = idUtils.getIdPoolInstance(parentPoolName);
         parentPoolName = parentPoolName.intern();
         idUtils.lock(lockManager, parentPoolName);
-        long idCount = 0;
         try {
             // Check if the childpool already got id block.
             long availableIdCount =
@@ -383,28 +394,34 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
             if (availableIdCount > 0) {
                 return availableIdCount;
             }
-            WriteTransaction tx = broker.newWriteOnlyTransaction();
-            IdPool parentIdPool = singleTxDB.syncRead(CONFIGURATION, idPoolInstanceIdentifier);
-            idCount = allocateIdBlockFromParentPool(localIdPool, parentIdPool, tx);
-            tx.submit().checkedGet();
-        } catch (IdManagerException | NullPointerException e) {
-            LOG.error("Error getting id block from parent pool", e);
+            return txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
+                Optional<IdPool> parentIdPool = confTx.read(idPoolInstanceIdentifier).get();
+                if (parentIdPool.isPresent()) {
+                    return allocateIdBlockFromParentPool(localIdPool, parentIdPool.get(), confTx);
+                } else {
+                    throw new ExpectedDataObjectNotFoundException(LogicalDatastoreType.CONFIGURATION,
+                            idPoolInstanceIdentifier);
+                }
+            }).get();
+        } catch (InterruptedException | ExecutionException e) {
+            throw new IdManagerException("Error getting id block from parent pool", e);
         } finally {
             idUtils.unlock(lockManager, parentPoolName);
         }
-        return idCount;
     }
 
-    private long allocateIdBlockFromParentPool(IdLocalPool localPoolCache, IdPool parentIdPool, WriteTransaction tx)
+    private long allocateIdBlockFromParentPool(IdLocalPool localPoolCache, IdPool parentIdPool,
+            TypedWriteTransaction<Configuration> confTx)
             throws OperationFailedException, IdManagerException {
-        long idCount = -1;
-        ReleasedIdsHolderBuilder releasedIdsBuilderParent = idUtils.getReleaseIdsHolderBuilder(parentIdPool);
+        long idCount;
+        ReleasedIdsHolderBuilder releasedIdsBuilderParent = IdUtils.getReleaseIdsHolderBuilder(parentIdPool);
         while (true) {
-            idCount = allocateIdBlockFromAvailableIdsHolder(localPoolCache, parentIdPool, tx);
+            idCount = allocateIdBlockFromAvailableIdsHolder(localPoolCache, parentIdPool, confTx);
             if (idCount > 0) {
                 return idCount;
             }
-            idCount = allocateIdBlockFromReleasedIdsHolder(localPoolCache, releasedIdsBuilderParent, parentIdPool, tx);
+            idCount = allocateIdBlockFromReleasedIdsHolder(localPoolCache, releasedIdsBuilderParent, parentIdPool,
+                    confTx);
             if (idCount > 0) {
                 return idCount;
             }
@@ -432,8 +449,9 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
             if (!childPools.getChildPoolName().equals(idUtils.getLocalPoolName(parentIdPool.getPoolName()))) {
                 InstanceIdentifier<IdPool> idPoolInstanceIdentifier = idUtils
                         .getIdPoolInstance(childPools.getChildPoolName());
-                IdPool otherChildPool = singleTxDB.syncRead(CONFIGURATION, idPoolInstanceIdentifier);
-                ReleasedIdsHolderBuilder releasedIds = idUtils.getReleaseIdsHolderBuilder(otherChildPool);
+                IdPool otherChildPool =
+                        singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier);
+                ReleasedIdsHolderBuilder releasedIds = IdUtils.getReleaseIdsHolderBuilder(otherChildPool);
 
                 List<DelayedIdEntries> delayedIdEntriesChild = releasedIds.getDelayedIdEntries();
                 List<DelayedIdEntries> delayedIdEntriesParent = releasedIdsBuilderParent.getDelayedIdEntries();
@@ -454,8 +472,8 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
                         + idUtils.getAvailableIdsCount(availableIds);
                 long count = releasedIdsBuilderParent.getAvailableIdCount() + totalAvailableIdCount;
                 releasedIdsBuilderParent.setDelayedIdEntries(delayedIdEntriesParent).setAvailableIdCount(count);
-                singleTxDB.syncUpdate(CONFIGURATION, idPoolInstanceIdentifier,
-                        new IdPoolBuilder().setKey(new IdPoolKey(otherChildPool.getPoolName()))
+                singleTxDB.syncUpdate(LogicalDatastoreType.CONFIGURATION, idPoolInstanceIdentifier,
+                        new IdPoolBuilder().withKey(new IdPoolKey(otherChildPool.getPoolName()))
                                 .setAvailableIdsHolder(availableIds.build()).setReleasedIdsHolder(releasedIds.build())
                                 .build());
                 return totalAvailableIdCount;
@@ -465,7 +483,8 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     private long allocateIdBlockFromReleasedIdsHolder(IdLocalPool localIdPool,
-            ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool, WriteTransaction tx) {
+            ReleasedIdsHolderBuilder releasedIdsBuilderParent, IdPool parentIdPool,
+            TypedWriteTransaction<Configuration> confTx) {
         if (releasedIdsBuilderParent.getAvailableIdCount() == 0) {
             LOG.debug("Ids unavailable in releasedIds of parent pool {}", parentIdPool);
             return 0;
@@ -492,13 +511,12 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
                         new IdPoolKey(parentIdPool.getPoolName())).child(ReleasedIdsHolder.class).build();
         releasedIdsBuilderParent.setAvailableIdCount(releasedIdsBuilderParent.getAvailableIdCount() - idCount);
         LOG.debug("Allocated {} ids from releasedIds of parent pool {}", idCount, parentIdPool);
-        tx.merge(CONFIGURATION, releasedIdsHolderInstanceIdentifier,
-                releasedIdsBuilderParent.build(), true);
+        confTx.merge(releasedIdsHolderInstanceIdentifier, releasedIdsBuilderParent.build(), CREATE_MISSING_PARENTS);
         return idCount;
     }
 
     private long allocateIdBlockFromAvailableIdsHolder(IdLocalPool localIdPool, IdPool parentIdPool,
-            WriteTransaction tx) {
+            TypedWriteTransaction<Configuration> confTx) {
         long idCount = 0;
         AvailableIdsHolderBuilder availableIdsBuilderParent = idUtils.getAvailableIdsHolderBuilder(parentIdPool);
         long end = availableIdsBuilderParent.getEnd();
@@ -521,8 +539,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
         if (LOG.isDebugEnabled()) {
             LOG.debug("Allocated {} ids from availableIds of global pool {}", idCount, parentIdPool);
         }
-        tx.merge(CONFIGURATION, availableIdsHolderInstanceIdentifier,
-                availableIdsBuilderParent.build(), true);
+        confTx.merge(availableIdsHolderInstanceIdentifier, availableIdsBuilderParent.build(), CREATE_MISSING_PARENTS);
         return idCount;
     }
 
@@ -544,14 +561,14 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
         }
         localPoolName = localPoolName.intern();
         InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = idUtils.getIdPoolInstance(parentPoolName);
-        IdPool parentIdPool = singleTxDB.syncRead(CONFIGURATION, parentIdPoolInstanceIdentifier);
+        IdPool parentIdPool = singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION, parentIdPoolInstanceIdentifier);
         List<IdEntries> idEntries = parentIdPool.getIdEntries();
-        List<IdEntries> newIdEntries = idEntries;
         if (idEntries == null) {
             throw new IdDoesNotExistException(parentPoolName, idKey);
         }
         InstanceIdentifier<IdEntries> existingId = idUtils.getIdEntry(parentIdPoolInstanceIdentifier, idKey);
-        Optional<IdEntries> existingIdEntryObject = singleTxDB.syncReadOptional(CONFIGURATION, existingId);
+        Optional<IdEntries> existingIdEntryObject =
+                singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, existingId);
         if (!existingIdEntryObject.isPresent()) {
             LOG.info("Specified Id key {} does not exist in id pool {}", idKey, parentPoolName);
             idUtils.unlock(lockManager, idLatchKey);
@@ -560,7 +577,7 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
         IdEntries existingIdEntry = existingIdEntryObject.get();
         List<Long> idValuesList = existingIdEntry.getIdValue();
         IdLocalPool localIdPoolCache = localPool.get(parentPoolName);
-        boolean isRemoved = newIdEntries.remove(existingIdEntry);
+        boolean isRemoved = idEntries.remove(existingIdEntry);
         LOG.debug("The entry {} is removed {}", existingIdEntry, isRemoved);
         updateDelayedEntriesInLocalCache(idValuesList, parentPoolName, localIdPoolCache);
         IdHolderSyncJob poolSyncJob = new IdHolderSyncJob(localPoolName, localIdPoolCache.getReleasedIds(), txRunner,
@@ -588,31 +605,36 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
         cleanJobTimer.schedule(scheduledTask, IdUtils.DEFAULT_DELAY_TIME * 1000);
     }
 
-    private IdPool createGlobalPool(WriteTransaction tx, String poolName, long low, long high, long blockSize)
-            throws ReadFailedException {
+    private IdPool createGlobalPool(TypedReadWriteTransaction<Configuration> confTx, String poolName, long low,
+            long high, long blockSize) throws IdManagerException {
         IdPool idPool;
         InstanceIdentifier<IdPool> idPoolInstanceIdentifier = idUtils.getIdPoolInstance(poolName);
-        Optional<IdPool> existingIdPool = singleTxDB.syncReadOptional(CONFIGURATION, idPoolInstanceIdentifier);
-        if (!existingIdPool.isPresent()) {
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Creating new global pool {}", poolName);
-            }
-            idPool = idUtils.createGlobalPool(poolName, low, high, blockSize);
-            tx.put(CONFIGURATION, idPoolInstanceIdentifier, idPool, true);
-        } else {
-            idPool = existingIdPool.get();
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("GlobalPool exists {}", idPool);
+        try {
+            Optional<IdPool> existingIdPool = confTx.read(idPoolInstanceIdentifier).get();
+            if (!existingIdPool.isPresent()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Creating new global pool {}", poolName);
+                }
+                idPool = idUtils.createGlobalPool(poolName, low, high, blockSize);
+                confTx.put(idPoolInstanceIdentifier, idPool, CREATE_MISSING_PARENTS);
+            } else {
+                idPool = existingIdPool.get();
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("GlobalPool exists {}", idPool);
+                }
             }
+            return idPool;
+        } catch (ExecutionException | InterruptedException e) {
+            throw new IdManagerException("Error retrieving the existing id pool for " + poolName, e);
         }
-        return idPool;
     }
 
-    private IdLocalPool createLocalPool(WriteTransaction tx, String localPoolName, IdPool idPool)
+    private IdLocalPool createLocalPool(TypedWriteTransaction<Configuration> confTx, String localPoolName,
+            IdPool idPool)
             throws OperationFailedException, IdManagerException {
         localPoolName = localPoolName.intern();
         IdLocalPool idLocalPool = new IdLocalPool(idUtils, localPoolName);
-        allocateIdBlockFromParentPool(idLocalPool, idPool, tx);
+        allocateIdBlockFromParentPool(idLocalPool, idPool, confTx);
         String parentPool = idPool.getPoolName();
         localPool.put(parentPool, idLocalPool);
         LocalPoolCreateJob job = new LocalPoolCreateJob(idLocalPool, txRunner, idPool.getPoolName(),
@@ -643,10 +665,6 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
         localPool.put(parentPoolName, localPoolCache);
     }
 
-    public java.util.Optional<IdLocalPool> getIdLocalPool(String parentPoolName) {
-        return java.util.Optional.ofNullable(localPool.get(parentPoolName)).map(IdLocalPool::deepCopyOf);
-    }
-
     private List<Long> checkForIdInIdEntries(String parentPoolName, String idKey, String uniqueIdKey,
             CompletableFuture<List<Long>> futureIdValues, boolean hasExistingFutureIdValues)
             throws IdManagerException, ReadFailedException {
@@ -654,7 +672,8 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
         InstanceIdentifier<IdEntries> existingId = idUtils.getIdEntry(parentIdPoolInstanceIdentifier, idKey);
         idUtils.lock(lockManager, uniqueIdKey);
         List<Long> newIdValuesList = new ArrayList<>();
-        Optional<IdEntries> existingIdEntry = singleTxDB.syncReadOptional(CONFIGURATION, existingId);
+        Optional<IdEntries> existingIdEntry =
+                singleTxDB.syncReadOptional(LogicalDatastoreType.CONFIGURATION, existingId);
         if (existingIdEntry.isPresent()) {
             newIdValuesList = existingIdEntry.get().getIdValue();
             LOG.debug("Existing ids {} for the key {} ", newIdValuesList, idKey);
@@ -672,21 +691,37 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     }
 
     private IdLocalPool getOrCreateLocalIdPool(String parentPoolName, String localPoolName)
-            throws IdManagerException, ReadFailedException, OperationFailedException, TransactionCommitFailedException {
+        throws IdManagerException, ReadFailedException {
         IdLocalPool localIdPool = localPool.get(parentPoolName);
         if (localIdPool == null) {
             idUtils.lock(lockManager, parentPoolName);
             try {
                 // Check if a previous thread that got the cluster-wide lock
                 // first, has created the localPool
+                InstanceIdentifier<IdPool> childIdPoolInstanceIdentifier = idUtils
+                        .getIdPoolInstance(localPoolName);
+                IdPool childIdPool = singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION,
+                    childIdPoolInstanceIdentifier);
+                if (childIdPool != null) {
+                    updateLocalIdPoolCache(childIdPool, parentPoolName);
+                }
                 if (localPool.get(parentPoolName) == null) {
-                    WriteTransaction tx = broker.newWriteOnlyTransaction();
-                    InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = idUtils
-                            .getIdPoolInstance(parentPoolName);
-                    IdPool parentIdPool = singleTxDB.syncRead(CONFIGURATION, parentIdPoolInstanceIdentifier);
-                    // Return localIdPool
-                    localIdPool = createLocalPool(tx, localPoolName, parentIdPool);
-                    tx.submit().checkedGet();
+                    try {
+                        return txRunner.applyWithNewReadWriteTransactionAndSubmit(CONFIGURATION, confTx -> {
+                            InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier = idUtils
+                                    .getIdPoolInstance(parentPoolName);
+                            Optional<IdPool> parentIdPool = confTx.read(parentIdPoolInstanceIdentifier).get();
+                            if (parentIdPool.isPresent()) {
+                                // Return localIdPool
+                                return createLocalPool(confTx, localPoolName, parentIdPool.get());
+                            } else {
+                                throw new ExpectedDataObjectNotFoundException(LogicalDatastoreType.CONFIGURATION,
+                                        parentIdPoolInstanceIdentifier);
+                            }
+                        }).get();
+                    } catch (InterruptedException | ExecutionException e) {
+                        throw new IdManagerException("Error creating a local id pool", e);
+                    }
                 } else {
                     localIdPool = localPool.get(parentPoolName);
                 }
@@ -700,18 +735,18 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     private void getRangeOfIds(String parentPoolName, String localPoolName, long size, List<Long> newIdValuesList,
             IdLocalPool localIdPool, long newIdValue) throws ReadFailedException, IdManagerException {
         InstanceIdentifier<IdPool> parentIdPoolInstanceIdentifier1 = idUtils.getIdPoolInstance(parentPoolName);
-        IdPool parentIdPool = singleTxDB.syncRead(CONFIGURATION, parentIdPoolInstanceIdentifier1);
+        IdPool parentIdPool = singleTxDB.syncRead(LogicalDatastoreType.CONFIGURATION, parentIdPoolInstanceIdentifier1);
         long totalAvailableIdCount = localIdPool.getAvailableIds().getAvailableIdCount()
                 + localIdPool.getReleasedIds().getAvailableIdCount();
         AvailableIdsHolderBuilder availableParentIds = idUtils.getAvailableIdsHolderBuilder(parentIdPool);
-        ReleasedIdsHolderBuilder releasedParentIds = idUtils.getReleaseIdsHolderBuilder(parentIdPool);
+        ReleasedIdsHolderBuilder releasedParentIds = IdUtils.getReleaseIdsHolderBuilder(parentIdPool);
         totalAvailableIdCount = totalAvailableIdCount + releasedParentIds.getAvailableIdCount()
                 + idUtils.getAvailableIdsCount(availableParentIds);
         if (totalAvailableIdCount > size) {
             while (size > 0) {
                 try {
                     newIdValue = getIdFromLocalPoolCache(localIdPool, parentPoolName);
-                } catch (OperationFailedException e) {
+                } catch (IdManagerException e) {
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Releasing IDs to pool {}", localPoolName);
                     }