fix CheckedFutures deprecated warnings
[transportpce.git] / common / src / main / java / org / opendaylight / transportpce / common / device / DeviceTransaction.java
1 /*
2  * Copyright © 2017 Orange, 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
9 package org.opendaylight.transportpce.common.device;
10
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.FutureCallback;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15
16 import java.util.concurrent.CountDownLatch;
17 import java.util.concurrent.Executors;
18 import java.util.concurrent.ScheduledExecutorService;
19 import java.util.concurrent.TimeUnit;
20 import java.util.concurrent.atomic.AtomicBoolean;
21 import javax.annotation.Nullable;
22
23 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
24 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
25 import org.opendaylight.yangtools.yang.binding.DataObject;
26 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29
30 /**
31  * Represents read-write transaction on netconf device.
32  * This transaction can be obtained by {@link DeviceTransactionManager}.
33  *
34  * <p>
35  * WARNING: Only one transaction can be opened at the same time on device!
36  * It's important to close (cancel/submit) transaction when work is done with it
37  * (so others can access the device).
38  * </p>
39  */
40 public class DeviceTransaction {
41
42     private static final Logger LOG = LoggerFactory.getLogger(DeviceTransaction.class);
43
44     private final ReadWriteTransaction rwTx;
45     private final CountDownLatch deviceLock;
46     private final ScheduledExecutorService scheduledExecutorService;
47     private final AtomicBoolean wasSubmittedOrCancelled = new AtomicBoolean(false);
48
49     DeviceTransaction(ReadWriteTransaction rwTx, CountDownLatch deviceLock) {
50         this.rwTx = rwTx;
51         this.deviceLock = deviceLock;
52         this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
53         LOG.debug("Device transaction created. Lock: {}", deviceLock);
54     }
55
56     public <T extends DataObject> ListenableFuture<Optional<T>> read(LogicalDatastoreType store,
57             InstanceIdentifier<T> path) {
58         return rwTx.read(store, path);
59     }
60
61     public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
62         rwTx.put(store, path, data);
63     }
64
65     public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
66             boolean createMissingParents) {
67         rwTx.put(store, path, data, createMissingParents);
68     }
69
70     public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
71         rwTx.merge(store, path, data);
72     }
73
74     public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
75             boolean createMissingParents) {
76         rwTx.merge(store, path, data, createMissingParents);
77     }
78
79     public void delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
80         rwTx.delete(store, path);
81     }
82
83     /**
84      * Cancels transaction and unlocks it.
85      * @return true if cancel was successful.
86      */
87     public boolean cancel() {
88         if (wasSubmittedOrCancelled.get()) {
89             LOG.warn("Transaction was already submitted or canceled!");
90             return false;
91         }
92
93         LOG.debug("Transaction cancelled. Lock: {}", deviceLock);
94         wasSubmittedOrCancelled.set(true);
95         afterClose();
96         return rwTx.cancel();
97     }
98
99     /**
100      * Submits data changed in transaction to device with defined timeout to submit. If time from timeout runs out then
101      * submit will be interrupted and device will be unlocked.
102      *
103      * @param timeout a timeout
104      * @param timeUnit a time unit
105      * @return ListenableFuture which indicates when is submit completed.
106      */
107     public ListenableFuture<Void> submit(long timeout, TimeUnit timeUnit) {
108         if (wasSubmittedOrCancelled.get()) {
109             String msg = "Transaction was already submitted or canceled!";
110             LOG.error(msg);
111             return Futures.immediateFailedFuture(new IllegalStateException(msg));
112         }
113
114         LOG.debug("Transaction submitted. Lock: {}", deviceLock);
115         wasSubmittedOrCancelled.set(true);
116         ListenableFuture<Void> future =
117                 Futures.withTimeout(rwTx.submit(), timeout, timeUnit, scheduledExecutorService);
118
119         Futures.addCallback(future, new FutureCallback<Void>() {
120             @Override
121             public void onSuccess(@Nullable Void result) {
122                 LOG.debug("Transaction with lock {} successfully submitted.", deviceLock);
123                 afterClose();
124             }
125
126             @Override
127             public void onFailure(Throwable throwable) {
128                 LOG.error("Device transaction submit failed or submit took longer than {} {}!"
129                         + " Unlocking device.", timeout, timeUnit, throwable);
130                 afterClose();
131             }
132         }, scheduledExecutorService);
133         return future;
134     }
135
136     /**
137      * Returns state of transaction.
138      * @return true if transaction was closed; otherwise false
139      */
140     public AtomicBoolean wasSubmittedOrCancelled() {
141         return wasSubmittedOrCancelled;
142     }
143
144     private void afterClose() {
145         scheduledExecutorService.shutdown();
146         deviceLock.countDown();
147     }
148 }