Merge "API Usability: Introduced type capture for Transaction Factory"
[controller.git] / opendaylight / md-sal / sal-common-impl / src / main / java / org / opendaylight / controller / md / sal / common / impl / service / AbstractDataTransaction.java
index c73a62779921d74837d96eb9c06a3f274f06cf1b..d544c4b3710b06a12dac1bba3b11b5e13ced4f89 100644 (file)
@@ -8,41 +8,56 @@
 package org.opendaylight.controller.md.sal.common.impl.service;
 
 import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
 
 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
 import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
 import org.opendaylight.yangtools.concepts.Path;
 import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-@SuppressWarnings("all")
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.AsyncFunction;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
 public abstract class AbstractDataTransaction<P extends Path<P>, D extends Object> extends
         AbstractDataModification<P, D> {
     private final static Logger LOG = LoggerFactory.getLogger(AbstractDataTransaction.class);
 
     private final Object identifier;
+    private final long allocationTime;
+    private long readyTime = 0;
+    private long completeTime = 0;
 
-    @Override
-    public Object getIdentifier() {
-        return this.identifier;
-    }
-
-    private TransactionStatus status;
+    private TransactionStatus status = TransactionStatus.NEW;
 
     private final AbstractDataBroker<P, D, ? extends Object> broker;
 
     protected AbstractDataTransaction(final Object identifier,
             final AbstractDataBroker<P, D, ? extends Object> dataBroker) {
         super(dataBroker);
-        this.identifier = identifier;
-        this.broker = dataBroker;
-        this.status = TransactionStatus.NEW;
-        AbstractDataTransaction.LOG.debug("Transaction {} Allocated.", identifier);
+        this.identifier = Preconditions.checkNotNull(identifier);
+        this.broker = Preconditions.checkNotNull(dataBroker);
+        this.allocationTime = System.nanoTime();
+        LOG.debug("Transaction {} Allocated.", identifier);
+    }
+
+    @Override
+    public Object getIdentifier() {
+        return this.identifier;
     }
 
     @Override
     public Future<RpcResult<TransactionStatus>> commit() {
+        readyTime = System.nanoTime();
+        LOG.debug("Transaction {} Ready after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(readyTime - allocationTime));
+        changeStatus(TransactionStatus.SUBMITED);
+
         return this.broker.commit(this);
     }
 
@@ -64,8 +79,6 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D extends Objec
         return this.broker.readOperationalData(path);
     }
 
-
-
     @Override
     public int hashCode() {
         final int prime = 31;
@@ -76,18 +89,23 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D extends Objec
 
     @Override
     public boolean equals(Object obj) {
-        if (this == obj)
+        if (this == obj) {
             return true;
-        if (obj == null)
+        }
+        if (obj == null) {
             return false;
-        if (getClass() != obj.getClass())
+        }
+        if (getClass() != obj.getClass()) {
             return false;
-        AbstractDataTransaction other = (AbstractDataTransaction) obj;
+        }
+        AbstractDataTransaction<?, ?> other = (AbstractDataTransaction<?, ?>) obj;
         if (identifier == null) {
-            if (other.identifier != null)
+            if (other.identifier != null) {
                 return false;
-        } else if (!identifier.equals(other.identifier))
+            }
+        } else if (!identifier.equals(other.identifier)) {
             return false;
+        }
         return true;
     }
 
@@ -98,11 +116,32 @@ public abstract class AbstractDataTransaction<P extends Path<P>, D extends Objec
 
     protected abstract void onStatusChange(final TransactionStatus status);
 
-    public void changeStatus(final TransactionStatus status) {
-        Object _identifier = this.getIdentifier();
-        AbstractDataTransaction.LOG
-                .debug("Transaction {} transitioned from {} to {}", _identifier, this.status, status);
+    public void succeeded() {
+        this.completeTime = System.nanoTime();
+        LOG.debug("Transaction {} Committed after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(completeTime - readyTime));
+        changeStatus(TransactionStatus.COMMITED);
+    }
+
+    public void failed() {
+        this.completeTime = System.nanoTime();
+        LOG.debug("Transaction {} Failed after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(completeTime - readyTime));
+        changeStatus(TransactionStatus.FAILED);
+    }
+
+    private void changeStatus(final TransactionStatus status) {
+        LOG.debug("Transaction {} transitioned from {} to {}", getIdentifier(), this.status, status);
         this.status = status;
         this.onStatusChange(status);
     }
+
+    public static ListenableFuture<RpcResult<TransactionStatus>> convertToLegacyCommitFuture(
+                                        CheckedFuture<Void,TransactionCommitFailedException> from ) {
+        return Futures.transform(from, new AsyncFunction<Void, RpcResult<TransactionStatus>>() {
+            @Override
+            public ListenableFuture<RpcResult<TransactionStatus>> apply(Void input) throws Exception {
+                return Futures.immediateFuture(RpcResultBuilder.<TransactionStatus>
+                                                              success(TransactionStatus.COMMITED).build());
+            }
+        } );
+    }
 }