2 * Copyright (c) 2015 Cisco Systems, 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.openflowplugin.impl.device;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.CheckedFuture;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.Futures;
16 import javax.annotation.Nonnull;
17 import org.opendaylight.controller.md.sal.binding.api.BindingTransactionChain;
18 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
19 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
20 import org.opendaylight.controller.md.sal.common.api.data.AsyncTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.TransactionChain;
23 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainListener;
24 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
25 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
26 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
27 import org.opendaylight.yangtools.concepts.Registration;
28 import org.opendaylight.yangtools.yang.binding.DataObject;
29 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
30 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
36 * org.opendaylight.openflowplugin.impl.device
38 * Package protected class for controlling {@link WriteTransaction} life cycle. It is
39 * a {@link TransactionChainListener} and provide package protected methods for writeToTransaction
40 * method (wrapped {@link WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject)})
41 * and submitTransaction method (wrapped {@link WriteTransaction#submit()})
43 * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
45 * Created: Apr 2, 2015
47 class TransactionChainManager implements TransactionChainListener, AutoCloseable {
49 private static final Logger LOG = LoggerFactory.getLogger(TransactionChainManager.class);
51 private final Object txLock = new Object();
53 private final DataBroker dataBroker;
54 private WriteTransaction wTx;
55 private BindingTransactionChain txChainFactory;
56 private boolean submitIsEnabled;
58 public TransactionChainManagerStatus getTransactionChainManagerStatus() {
59 return transactionChainManagerStatus;
62 private TransactionChainManagerStatus transactionChainManagerStatus;
63 private ReadyForNewTransactionChainHandler readyForNewTransactionChainHandler;
64 private final KeyedInstanceIdentifier<Node, NodeKey> nodeII;
65 private Registration managerRegistration;
67 TransactionChainManager(@Nonnull final DataBroker dataBroker,
68 @Nonnull final KeyedInstanceIdentifier<Node, NodeKey> nodeII,
69 @Nonnull final Registration managerRegistration) {
70 this.dataBroker = Preconditions.checkNotNull(dataBroker);
71 this.nodeII = Preconditions.checkNotNull(nodeII);
72 this.managerRegistration = Preconditions.checkNotNull(managerRegistration);
73 this.transactionChainManagerStatus = TransactionChainManagerStatus.WORKING;
74 createTxChain(dataBroker);
75 LOG.debug("created txChainManager");
78 private void createTxChain(final DataBroker dataBroker) {
79 txChainFactory = dataBroker.createTransactionChain(TransactionChainManager.this);
82 void initialSubmitWriteTransaction() {
84 submitWriteTransaction();
87 public synchronized boolean attemptToRegisterHandler(final ReadyForNewTransactionChainHandler readyForNewTransactionChainHandler) {
88 if (TransactionChainManagerStatus.SHUTTING_DOWN.equals(this.transactionChainManagerStatus)
89 && null == this.readyForNewTransactionChainHandler) {
90 this.readyForNewTransactionChainHandler = readyForNewTransactionChainHandler;
91 if (managerRegistration == null) {
92 this.readyForNewTransactionChainHandler.onReadyForNewTransactionChain();
100 boolean submitWriteTransaction() {
101 if (!submitIsEnabled) {
102 LOG.trace("transaction not committed - submit block issued");
105 synchronized (txLock) {
107 LOG.trace("nothing to commit - submit returns true");
116 <T extends DataObject> void addDeleteOperationTotTxChain(final LogicalDatastoreType store,
117 final InstanceIdentifier<T> path) {
118 final WriteTransaction writeTx = getTransactionSafely();
119 writeTx.delete(store, path);
122 <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
123 final InstanceIdentifier<T> path, final T data) {
124 final WriteTransaction writeTx = getTransactionSafely();
125 writeTx.put(store, path, data);
129 public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
130 final AsyncTransaction<?, ?> transaction, final Throwable cause) {
131 LOG.warn("txChain failed -> recreating", cause);
136 public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
137 // NOOP - only yet, here is probably place for notification to get new WriteTransaction
140 private void recreateTxChain() {
141 txChainFactory.close();
142 createTxChain(dataBroker);
143 synchronized (txLock) {
148 private WriteTransaction getTransactionSafely() {
149 if (wTx == null && !TransactionChainManagerStatus.SHUTTING_DOWN.equals(transactionChainManagerStatus)) {
150 synchronized (txLock) {
152 wTx = txChainFactory.newWriteOnlyTransaction();
160 void enableSubmit() {
161 submitIsEnabled = true;
165 public void close() {
166 LOG.debug("Removing node {} from operational DS.", nodeII);
167 synchronized (txLock) {
168 final WriteTransaction writeTx = getTransactionSafely();
169 this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
170 writeTx.delete(LogicalDatastoreType.OPERATIONAL, nodeII);
171 LOG.debug("Delete node {} from operational DS put to write transaction.", nodeII);
172 CheckedFuture<Void, TransactionCommitFailedException> submitsFuture = writeTx.submit();
173 LOG.debug("Delete node {} from operational DS write transaction submitted.", nodeII);
174 Futures.addCallback(submitsFuture, new FutureCallback<Void>() {
176 public void onSuccess(final Void aVoid) {
177 LOG.debug("Removing node {} from operational DS successful .", nodeII);
178 notifyReadyForNewTransactionChainAndCloseFactory();
182 public void onFailure(final Throwable throwable) {
183 LOG.info("Attempt to close transaction chain factory failed.", throwable);
184 notifyReadyForNewTransactionChainAndCloseFactory();
191 private void notifyReadyForNewTransactionChainAndCloseFactory() {
192 synchronized (this) {
194 LOG.debug("Closing registration in manager.");
195 managerRegistration.close();
196 } catch (Exception e) {
197 LOG.warn("Failed to close transaction chain manager's registration.", e);
199 managerRegistration = null;
200 if (null != readyForNewTransactionChainHandler) {
201 readyForNewTransactionChainHandler.onReadyForNewTransactionChain();
204 txChainFactory.close();
205 LOG.debug("Transaction chain factory closed.");
208 public enum TransactionChainManagerStatus {
209 WORKING, SHUTTING_DOWN;