b2a03c298772caba9509e3122598dd8f1bc06aee
[controller.git] / opendaylight / md-sal / sal-common-impl / src / main / java / org / opendaylight / controller / md / sal / common / impl / service / AbstractDataTransaction.java
1 /**
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.md.sal.common.impl.service;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.util.concurrent.AsyncFunction;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.util.concurrent.Future;
16 import java.util.concurrent.TimeUnit;
17 import org.opendaylight.controller.md.sal.common.api.TransactionStatus;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
19 import org.opendaylight.controller.md.sal.common.impl.AbstractDataModification;
20 import org.opendaylight.yangtools.concepts.Path;
21 import org.opendaylight.yangtools.yang.common.RpcResult;
22 import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
23 import org.slf4j.Logger;
24 import org.slf4j.LoggerFactory;
25
26 public abstract class AbstractDataTransaction<P extends Path<P>, D extends Object> extends
27         AbstractDataModification<P, D> {
28     private static final Logger LOG = LoggerFactory.getLogger(AbstractDataTransaction.class);
29     private static final ListenableFuture<RpcResult<TransactionStatus>> SUCCESS_FUTURE =
30             Futures.immediateFuture(RpcResultBuilder.success(TransactionStatus.COMMITED).build());
31
32     private final Object identifier;
33     private final long allocationTime;
34     private long readyTime = 0;
35     private long completeTime = 0;
36
37     private TransactionStatus status = TransactionStatus.NEW;
38
39     private final AbstractDataBroker<P, D, ? extends Object> broker;
40
41     protected AbstractDataTransaction(final Object identifier,
42             final AbstractDataBroker<P, D, ? extends Object> dataBroker) {
43         super(dataBroker);
44         this.identifier = Preconditions.checkNotNull(identifier);
45         this.broker = Preconditions.checkNotNull(dataBroker);
46         this.allocationTime = System.nanoTime();
47         LOG.debug("Transaction {} Allocated.", identifier);
48     }
49
50     @Override
51     public Object getIdentifier() {
52         return this.identifier;
53     }
54
55     @Override
56     public Future<RpcResult<TransactionStatus>> commit() {
57         readyTime = System.nanoTime();
58         if (LOG.isDebugEnabled()) {
59             LOG.debug("Transaction {} Ready after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(readyTime - allocationTime));
60         }
61         changeStatus(TransactionStatus.SUBMITED);
62         return this.broker.commit(this);
63     }
64
65     @Override
66     public D readConfigurationData(final P path) {
67         final D local = getUpdatedConfigurationData().get(path);
68         if (local != null) {
69             return local;
70         }
71         return this.broker.readConfigurationData(path);
72     }
73
74     @Override
75     public D readOperationalData(final P path) {
76         final D local = this.getUpdatedOperationalData().get(path);
77         if (local != null) {
78             return local;
79         }
80         return this.broker.readOperationalData(path);
81     }
82
83     @Override
84     public int hashCode() {
85         final int prime = 31;
86         int result = 1;
87         result = prime * result + ((identifier == null) ? 0 : identifier.hashCode());
88         return result;
89     }
90
91     @Override
92     public boolean equals(final Object obj) {
93         if (this == obj) {
94             return true;
95         }
96         if (obj == null) {
97             return false;
98         }
99         if (getClass() != obj.getClass()) {
100             return false;
101         }
102         AbstractDataTransaction<?, ?> other = (AbstractDataTransaction<?, ?>) obj;
103         if (identifier == null) {
104             if (other.identifier != null) {
105                 return false;
106             }
107         } else if (!identifier.equals(other.identifier)) {
108             return false;
109         }
110         return true;
111     }
112
113     @Override
114     public TransactionStatus getStatus() {
115         return this.status;
116     }
117
118     protected abstract void onStatusChange(final TransactionStatus status);
119
120     public void succeeded() {
121         this.completeTime = System.nanoTime();
122         if (LOG.isDebugEnabled()) {
123             LOG.debug("Transaction {} Committed after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(completeTime - readyTime));
124         }
125         changeStatus(TransactionStatus.COMMITED);
126     }
127
128     public void failed() {
129         this.completeTime = System.nanoTime();
130
131         if (LOG.isDebugEnabled()) {
132             LOG.debug("Transaction {} Failed after {}ms.", identifier, TimeUnit.NANOSECONDS.toMillis(completeTime - readyTime));
133         }
134         changeStatus(TransactionStatus.FAILED);
135     }
136
137     private void changeStatus(final TransactionStatus status) {
138         LOG.debug("Transaction {} transitioned from {} to {}", getIdentifier(), this.status, status);
139         this.status = status;
140         this.onStatusChange(status);
141     }
142
143     public static ListenableFuture<RpcResult<TransactionStatus>> convertToLegacyCommitFuture(final CheckedFuture<Void,TransactionCommitFailedException> from) {
144         return Futures.transform(from, new AsyncFunction<Void, RpcResult<TransactionStatus>>() {
145             @Override
146             public ListenableFuture<RpcResult<TransactionStatus>> apply(final Void input) {
147                 return SUCCESS_FUTURE;
148             }
149         });
150     }
151 }