IdManager RPCs switched to using FutureRpcResults
[genius.git] / idmanager / idmanager-impl / src / main / java / org / opendaylight / genius / idmanager / IdManager.java
index 131d2154e53134e301e935497718afbb53c0c67a..52ae66db36366a1164520e9397d81506fef38793 100644 (file)
@@ -5,7 +5,6 @@
  * 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.genius.idmanager;
 
 import static java.util.Comparator.comparing;
@@ -13,7 +12,7 @@ import static java.util.stream.Collectors.toCollection;
 import static org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType.CONFIGURATION;
 
 import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.Futures;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -47,6 +46,8 @@ 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.FutureRpcResults.LogLevel;
 import org.opendaylight.infrautils.jobcoordinator.JobCoordinator;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdInput;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.AllocateIdOutput;
@@ -72,9 +73,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.idmanager.rev160406.
 import org.opendaylight.yang.gen.v1.urn.opendaylight.genius.lockmanager.rev160413.LockManagerService;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.common.OperationFailedException;
-import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
 import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.ops4j.pax.cdi.api.OsgiService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -187,55 +186,44 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
     @Override
     public Future<RpcResult<Void>> createIdPool(CreateIdPoolInput input) {
         LOG.info("createIdPool called with input {}", input);
-        String poolName = input.getPoolName();
         long low = input.getLow();
         long high = input.getHigh();
         long blockSize = idUtils.computeBlockSize(low, high);
-        Future<RpcResult<Void>> futureResult;
-        try {
-            idUtils.lock(lockManager, poolName);
-            WriteTransaction tx = broker.newWriteOnlyTransaction();
-            poolName = poolName.intern();
-            IdPool idPool;
-            idPool = createGlobalPool(tx, 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);
+        return FutureRpcResults.fromListenableFuture(LOG, "createIdPool", input, () -> {
+            String poolName = input.getPoolName().intern();
+            try {
+                idUtils.lock(lockManager, poolName);
+                WriteTransaction tx = broker.newWriteOnlyTransaction();
+                IdPool idPool;
+                idPool = createGlobalPool(tx, 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);
+                }
+                // TODO just "return tx.submit()" instead.. BUT check that all callers @CheckReturnValue
+                tx.submit().checkedGet();
+                return Futures.immediateFuture((Void) null);
+            } finally {
+                idUtils.unlock(lockManager, poolName);
             }
-            tx.submit().checkedGet();
-            futureResult = RpcResultBuilder.<Void>success().buildFuture();
-        } catch (OperationFailedException | IdManagerException e) {
-            futureResult = buildFailedRpcResultFuture("createIdPool failed: " + input.toString(), e);
-        } finally {
-            idUtils.unlock(lockManager, poolName);
-        }
-        return futureResult;
+        }).build();
     }
 
     @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);
-        long newIdValue = -1;
-        AllocateIdOutputBuilder output = new AllocateIdOutputBuilder();
-        Future<RpcResult<AllocateIdOutput>> futureResult;
-        try {
-            //allocateIdFromLocalPool method returns a list of IDs with one element. This element is obtained by get(0)
-            newIdValue = allocateIdFromLocalPool(poolName, localPoolName, idKey, 1).get(0);
-            output.setIdValue(newIdValue);
-            futureResult = RpcResultBuilder.<AllocateIdOutput>success().withResult(output.build()).buildFuture();
-        } catch (OperationFailedException | IdManagerException e) {
-            completeExceptionallyIfPresent(poolName, idKey, e);
-            futureResult = buildFailedRpcResultFuture("allocateId failed: " + input.toString(), e);
-        }
-        return futureResult;
+        return FutureRpcResults.fromBuilder(LOG, "allocateId", input, () -> {
+            String localPoolName = idUtils.getLocalPoolName(poolName);
+            // allocateIdFromLocalPool method returns a list of IDs with one element. This element is obtained by get(0)
+            long newIdValue = allocateIdFromLocalPool(poolName, localPoolName, idKey, 1).get(0);
+            return new AllocateIdOutputBuilder().setIdValue(newIdValue);
+        }).onFailure(e -> completeExceptionallyIfPresent(poolName, idKey, e)).build();
     }
 
-    private void completeExceptionallyIfPresent(String poolName, String idKey, Exception exception) {
+    private void completeExceptionallyIfPresent(String poolName, String idKey, Throwable exception) {
         CompletableFuture<List<Long>> completableFuture =
                 idUtils.removeAllocatedIds(idUtils.getUniqueKey(poolName, idKey));
         if (completableFuture != null) {
@@ -245,38 +233,24 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
 
     @Override
     public Future<RpcResult<AllocateIdRangeOutput>> allocateIdRange(AllocateIdRangeInput input) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("AllocateIdRange called with input {}", input);
-        }
         String idKey = input.getIdKey();
         String poolName = input.getPoolName();
         long size = input.getSize();
         String localPoolName = idUtils.getLocalPoolName(poolName);
-        List<Long> newIdValuesList = new ArrayList<>();
         AllocateIdRangeOutputBuilder output = new AllocateIdRangeOutputBuilder();
-        Future<RpcResult<AllocateIdRangeOutput>> futureResult;
-        try {
-            newIdValuesList = allocateIdFromLocalPool(poolName, localPoolName, idKey, size);
+        return FutureRpcResults.fromBuilder(LOG, "allocateIdRange", input, () -> {
+            List<Long> newIdValuesList = allocateIdFromLocalPool(poolName, localPoolName, idKey, size);
             Collections.sort(newIdValuesList);
             output.setIdValues(newIdValuesList);
-            futureResult = RpcResultBuilder.<AllocateIdRangeOutput>success().withResult(output.build()).buildFuture();
-        } catch (OperationFailedException | IdManagerException e) {
-            completeExceptionallyIfPresent(poolName, idKey, e);
-            futureResult = buildFailedRpcResultFuture("allocateIdRange failed: " + input.toString(), e);
-        }
-        return futureResult;
+            return output;
+        }).onFailure(e -> completeExceptionallyIfPresent(poolName, idKey, e)).build();
     }
 
     @Override
     public Future<RpcResult<Void>> deleteIdPool(DeleteIdPoolInput input) {
-        if (LOG.isDebugEnabled()) {
-            LOG.debug("DeleteIdPool called with input {}", input);
-        }
-        String poolName = input.getPoolName();
-        Future<RpcResult<Void>> futureResult;
-        try {
+        return FutureRpcResults.fromListenableFuture(LOG, "deleteIdPool", input, () -> {
+            String poolName = input.getPoolName().intern();
             InstanceIdentifier<IdPool> idPoolToBeDeleted = idUtils.getIdPoolInstance(poolName);
-            poolName = poolName.intern();
             synchronized (poolName) {
                 IdPool idPool = singleTxDB.syncRead(CONFIGURATION, idPoolToBeDeleted);
                 List<ChildPools> childPoolList = idPool.getChildPools();
@@ -284,48 +258,32 @@ public class IdManager implements IdManagerService, IdManagerMonitor {
                     childPoolList.stream().forEach(childPool -> deletePool(childPool.getChildPoolName()));
                 }
                 singleTxDB.syncDelete(CONFIGURATION, idPoolToBeDeleted);
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Deleted id pool {}", poolName);
-                }
             }
-            futureResult = RpcResultBuilder.<Void>success().buildFuture();
-        } catch (OperationFailedException e) {
-            futureResult = buildFailedRpcResultFuture("deleteIdPool failed: " + input.toString(), e);
-        }
-        return futureResult;
+            // TODO return the Future from a TBD asyncDelete instead.. BUT check that all callers @CheckReturnValue
+            return Futures.immediateFuture((Void) null);
+        }).build();
     }
 
     @Override
     public Future<RpcResult<Void>> releaseId(ReleaseIdInput input) {
         String poolName = input.getPoolName();
         String idKey = input.getIdKey();
-        LOG.info("Releasing ID {} from pool {}", idKey, poolName);
-        Future<RpcResult<Void>> futureResult;
         String uniqueKey = idUtils.getUniqueKey(poolName, idKey);
-        try {
+        return FutureRpcResults.fromListenableFuture(LOG, "releaseId", input, () -> {
             idUtils.lock(lockManager, uniqueKey);
             releaseIdFromLocalPool(poolName, idUtils.getLocalPoolName(poolName), idKey);
-            futureResult = RpcResultBuilder.<Void>success().buildFuture();
-        } catch (ReadFailedException | IdManagerException e) {
-            futureResult = buildFailedRpcResultFuture("releaseId failed: " + input.toString(), e);
+            // TODO return the Future from releaseIdFromLocalPool() instead.. check all callers @CheckReturnValue
+            return Futures.immediateFuture((Void) null);
+        }).onFailureLogLevel(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);
-        }
-        return futureResult;
-    }
-
-    private <T> ListenableFuture<RpcResult<T>> buildFailedRpcResultFuture(String msg, Exception exception) {
-        if (exception instanceof IdDoesNotExistException) {
-            // Do not log full stack trace in case ID does not exist
-            LOG.error(msg, exception);
-        } else {
-            LOG.error(msg, exception);
-        }
-        RpcResultBuilder<T> failedRpcResultBuilder = RpcResultBuilder.failed();
-        failedRpcResultBuilder.withError(ErrorType.APPLICATION, msg, exception);
-        if (exception instanceof OperationFailedException) {
-            failedRpcResultBuilder.withRpcErrors(((OperationFailedException) exception).getErrorList());
-        }
-        return failedRpcResultBuilder.buildFuture();
+        }).build();
     }
 
     private List<Long> allocateIdFromLocalPool(String parentPoolName, String localPoolName,