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");
110 final CheckedFuture<Void, TransactionCommitFailedException> submitFuture = wTx.submit();
111 Futures.addCallback(submitFuture, new FutureCallback<Void>() {
113 public void onSuccess(Void result) {
118 public void onFailure(Throwable t) {
119 if (t instanceof TransactionCommitFailedException) {
120 LOG.error("Transaction commit failed. {}", t);
122 LOG.error("Exception during transaction submitting. {}", t);
131 <T extends DataObject> void addDeleteOperationTotTxChain(final LogicalDatastoreType store,
132 final InstanceIdentifier<T> path) {
133 final WriteTransaction writeTx = getTransactionSafely();
134 writeTx.delete(store, path);
137 <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
138 final InstanceIdentifier<T> path, final T data) {
139 final WriteTransaction writeTx = getTransactionSafely();
140 writeTx.put(store, path, data);
144 public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
145 final AsyncTransaction<?, ?> transaction, final Throwable cause) {
146 LOG.warn("txChain failed -> recreating", cause);
151 public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
152 // NOOP - only yet, here is probably place for notification to get new WriteTransaction
155 private void recreateTxChain() {
156 txChainFactory.close();
157 createTxChain(dataBroker);
158 synchronized (txLock) {
163 private WriteTransaction getTransactionSafely() {
164 if (wTx == null && !TransactionChainManagerStatus.SHUTTING_DOWN.equals(transactionChainManagerStatus)) {
165 synchronized (txLock) {
167 wTx = txChainFactory.newWriteOnlyTransaction();
175 void enableSubmit() {
176 submitIsEnabled = true;
180 public void close() {
181 LOG.debug("Removing node {} from operational DS.", nodeII);
182 synchronized (txLock) {
183 final WriteTransaction writeTx = getTransactionSafely();
184 this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
185 writeTx.delete(LogicalDatastoreType.OPERATIONAL, nodeII);
186 LOG.debug("Delete node {} from operational DS put to write transaction.", nodeII);
187 CheckedFuture<Void, TransactionCommitFailedException> submitsFuture = writeTx.submit();
188 LOG.debug("Delete node {} from operational DS write transaction submitted.", nodeII);
189 Futures.addCallback(submitsFuture, new FutureCallback<Void>() {
191 public void onSuccess(final Void aVoid) {
192 LOG.debug("Removing node {} from operational DS successful .", nodeII);
193 notifyReadyForNewTransactionChainAndCloseFactory();
197 public void onFailure(final Throwable throwable) {
198 LOG.info("Attempt to close transaction chain factory failed.", throwable);
199 notifyReadyForNewTransactionChainAndCloseFactory();
206 private void notifyReadyForNewTransactionChainAndCloseFactory() {
207 synchronized (this) {
209 LOG.debug("Closing registration in manager.");
210 managerRegistration.close();
211 } catch (Exception e) {
212 LOG.warn("Failed to close transaction chain manager's registration.", e);
214 managerRegistration = null;
215 if (null != readyForNewTransactionChainHandler) {
216 readyForNewTransactionChainHandler.onReadyForNewTransactionChain();
219 txChainFactory.close();
220 LOG.debug("Transaction chain factory closed.");
223 public enum TransactionChainManagerStatus {
224 WORKING, SHUTTING_DOWN;