2 * Copyright © 2017 Orange, Inc. and others. All rights reserved.
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
9 package org.opendaylight.transportpce.common.device;
11 import com.google.common.base.Optional;
12 import com.google.common.util.concurrent.CheckedFuture;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
17 import java.util.concurrent.CountDownLatch;
18 import java.util.concurrent.Executors;
19 import java.util.concurrent.ScheduledExecutorService;
20 import java.util.concurrent.TimeUnit;
21 import java.util.concurrent.atomic.AtomicBoolean;
22 import javax.annotation.Nullable;
24 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
25 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
26 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
27 import org.opendaylight.yangtools.yang.binding.DataObject;
28 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * Represents read-write transaction on netconf device.
34 * This transaction can be obtained by {@link DeviceTransactionManager}.
37 * WARNING: Only one transaction can be opened at the same time on device!
38 * It's important to close (cancel/submit) transaction when work is done with it
39 * (so others can access the device).
42 public class DeviceTransaction {
44 private static final Logger LOG = LoggerFactory.getLogger(DeviceTransaction.class);
46 private final ReadWriteTransaction rwTx;
47 private final CountDownLatch deviceLock;
48 private final ScheduledExecutorService scheduledExecutorService;
49 private final AtomicBoolean wasSubmittedOrCancelled = new AtomicBoolean(false);
51 DeviceTransaction(ReadWriteTransaction rwTx, CountDownLatch deviceLock) {
53 this.deviceLock = deviceLock;
54 this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
55 LOG.debug("Device transaction created. Lock: {}", deviceLock);
58 public <T extends DataObject> CheckedFuture<Optional<T>, ReadFailedException> read(LogicalDatastoreType store,
59 InstanceIdentifier<T> path) {
60 return rwTx.read(store, path);
63 public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
64 rwTx.put(store, path, data);
67 public <T extends DataObject> void put(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
68 boolean createMissingParents) {
69 rwTx.put(store, path, data, createMissingParents);
72 public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data) {
73 rwTx.merge(store, path, data);
76 public <T extends DataObject> void merge(LogicalDatastoreType store, InstanceIdentifier<T> path, T data,
77 boolean createMissingParents) {
78 rwTx.merge(store, path, data, createMissingParents);
81 public void delete(LogicalDatastoreType store, InstanceIdentifier<?> path) {
82 rwTx.delete(store, path);
86 * Cancels transaction and unlocks it.
87 * @return true if cancel was successful.
89 public boolean cancel() {
90 if (wasSubmittedOrCancelled.get()) {
91 LOG.warn("Transaction was already submitted or canceled!");
95 LOG.debug("Transaction cancelled. Lock: {}", deviceLock);
96 wasSubmittedOrCancelled.set(true);
102 * Submits data changed in transaction to device with defined timeout to submit. If time from timeout runs out then
103 * submit will be interrupted and device will be unlocked.
105 * @param timeout a timeout
106 * @param timeUnit a time unit
107 * @return ListenableFuture which indicates when is submit completed.
109 public ListenableFuture<Void> submit(long timeout, TimeUnit timeUnit) {
110 if (wasSubmittedOrCancelled.get()) {
111 String msg = "Transaction was already submitted or canceled!";
113 return Futures.immediateFailedFuture(new IllegalStateException(msg));
116 LOG.debug("Transaction submitted. Lock: {}", deviceLock);
117 wasSubmittedOrCancelled.set(true);
118 ListenableFuture<Void> future =
119 Futures.withTimeout(rwTx.submit(), timeout, timeUnit, scheduledExecutorService);
121 Futures.addCallback(future, new FutureCallback<Void>() {
123 public void onSuccess(@Nullable Void result) {
124 LOG.debug("Transaction with lock {} successfully submitted.", deviceLock);
129 public void onFailure(Throwable throwable) {
130 LOG.error("Device transaction submit failed or submit took longer than {} {}!"
131 + " Unlocking device.", timeout, timeUnit, throwable);
134 }, scheduledExecutorService);
139 * Returns state of transaction.
140 * @return true if transaction was closed; otherwise false
142 public AtomicBoolean wasSubmittedOrCancelled() {
143 return wasSubmittedOrCancelled;
146 private void afterClose() {
147 scheduledExecutorService.shutdown();
148 deviceLock.countDown();