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.openflowplugin.api.openflow.connection.ConnectionContext;
26 import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
29 import org.opendaylight.yangtools.concepts.Registration;
30 import org.opendaylight.yangtools.yang.binding.DataObject;
31 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
32 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
38 * org.opendaylight.openflowplugin.impl.device
40 * Package protected class for controlling {@link WriteTransaction} life cycle. It is
41 * a {@link TransactionChainListener} and provide package protected methods for writeToTransaction
42 * method (wrapped {@link WriteTransaction#put(LogicalDatastoreType, InstanceIdentifier, DataObject)})
43 * and submitTransaction method (wrapped {@link WriteTransaction#submit()})
45 * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
47 * Created: Apr 2, 2015
49 class TransactionChainManager implements TransactionChainListener, AutoCloseable {
51 private static final Logger LOG = LoggerFactory.getLogger(TransactionChainManager.class);
53 private final Object txLock = new Object();
55 private final DataBroker dataBroker;
56 private WriteTransaction wTx;
57 private BindingTransactionChain txChainFactory;
58 private boolean submitIsEnabled;
60 public TransactionChainManagerStatus getTransactionChainManagerStatus() {
61 return transactionChainManagerStatus;
64 private TransactionChainManagerStatus transactionChainManagerStatus;
65 private ReadyForNewTransactionChainHandler readyForNewTransactionChainHandler;
66 private final KeyedInstanceIdentifier<Node, NodeKey> nodeII;
67 private final ConnectionContext connectionContext;
68 private Registration managerRegistration;
70 TransactionChainManager(@Nonnull final DataBroker dataBroker,
71 @Nonnull final ConnectionContext connectionContext,
72 @Nonnull final Registration managerRegistration) {
73 this.dataBroker = Preconditions.checkNotNull(dataBroker);
74 this.nodeII = Preconditions.checkNotNull(DeviceStateUtil.createNodeInstanceIdentifier(connectionContext.getNodeId()));
75 this.connectionContext = Preconditions.checkNotNull(connectionContext);
76 this.managerRegistration = Preconditions.checkNotNull(managerRegistration);
77 createTxChain(dataBroker);
78 LOG.debug("created txChainManager");
81 private void createTxChain(final DataBroker dataBroker) {
82 txChainFactory = dataBroker.createTransactionChain(TransactionChainManager.this);
83 this.transactionChainManagerStatus = TransactionChainManagerStatus.WORKING;
86 void initialSubmitWriteTransaction() {
88 submitWriteTransaction();
91 public boolean attemptToRegisterHandler(final ReadyForNewTransactionChainHandler readyForNewTransactionChainHandler) {
92 if (null == this.readyForNewTransactionChainHandler) {
94 Preconditions.checkState(null != this.managerRegistration);
95 this.readyForNewTransactionChainHandler = readyForNewTransactionChainHandler;
103 boolean submitWriteTransaction() {
104 if (!submitIsEnabled) {
105 LOG.trace("transaction not committed - submit block issued");
110 LOG.trace("nothing to commit - submit returns true");
113 synchronized (txLock) {
115 LOG.trace("nothing to commit - submit returns true");
124 <T extends DataObject> void addDeleteOperationTotTxChain(final LogicalDatastoreType store,
125 final InstanceIdentifier<T> path) {
126 final WriteTransaction writeTx = getTransactionSafely();
127 writeTx.delete(store, path);
130 <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
131 final InstanceIdentifier<T> path, final T data) {
132 final WriteTransaction writeTx = getTransactionSafely();
133 writeTx.put(store, path, data);
137 public void onTransactionChainFailed(final TransactionChain<?, ?> chain,
138 final AsyncTransaction<?, ?> transaction, final Throwable cause) {
139 LOG.warn("txChain failed -> recreating", cause);
144 public void onTransactionChainSuccessful(final TransactionChain<?, ?> chain) {
145 // NOOP - only yet, here is probably place for notification to get new WriteTransaction
148 private void recreateTxChain() {
149 txChainFactory.close();
150 createTxChain(dataBroker);
151 synchronized (txLock) {
156 private WriteTransaction getTransactionSafely() {
157 if (wTx == null && !TransactionChainManagerStatus.SHUTTING_DOWN.equals(transactionChainManagerStatus)) {
158 synchronized (txLock) {
160 wTx = txChainFactory.newWriteOnlyTransaction();
168 void enableSubmit() {
169 submitIsEnabled = true;
173 public void close() {
174 LOG.debug("Removing node {} from operational DS.", nodeII);
175 synchronized (txLock) {
176 final WriteTransaction writeTx = getTransactionSafely();
177 this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
178 writeTx.delete(LogicalDatastoreType.OPERATIONAL, nodeII);
179 LOG.debug("Delete node {} from operational DS put to write transaction.", nodeII);
180 CheckedFuture<Void, TransactionCommitFailedException> submitsFuture = writeTx.submit();
181 LOG.debug("Delete node {} from operational DS write transaction submitted.", nodeII);
182 Futures.addCallback(submitsFuture, new FutureCallback<Void>() {
184 public void onSuccess(final Void aVoid) {
185 LOG.debug("Removing node {} from operational DS successful .", nodeII);
186 notifyReadyForNewTransactionChainAndCloseFactory();
190 public void onFailure(final Throwable throwable) {
191 LOG.info("Attempt to close transaction chain factory failed.", throwable);
192 notifyReadyForNewTransactionChainAndCloseFactory();
199 private void notifyReadyForNewTransactionChainAndCloseFactory() {
200 synchronized (this) {
201 if (null != readyForNewTransactionChainHandler) {
202 readyForNewTransactionChainHandler.onReadyForNewTransactionChain(connectionContext);
205 LOG.debug("Closing registration in manager.");
206 managerRegistration.close();
207 } catch (Exception e) {
208 LOG.warn("Failed to close transaction chain manager's registration.", e);
210 managerRegistration = null;
212 txChainFactory.close();
213 LOG.debug("Transaction chain factory closed.");
216 public enum TransactionChainManagerStatus {
217 WORKING, SHUTTING_DOWN;