2 * Copyright (c) 2016 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.mdsal.dom.broker;
11 import com.google.common.base.Preconditions;
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 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.EnumMap;
19 import java.util.concurrent.atomic.AtomicLong;
20 import javax.annotation.Nonnull;
21 import javax.annotation.Nullable;
22 import org.opendaylight.mdsal.common.api.AsyncTransaction;
23 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
24 import org.opendaylight.mdsal.common.api.TransactionChainListener;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeCursorAwareTransaction;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
27 import org.opendaylight.mdsal.dom.api.DOMDataTreeListener;
28 import org.opendaylight.mdsal.dom.api.DOMDataTreeLoopException;
29 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducer;
30 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducerException;
31 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
32 import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
33 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
34 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
35 import org.opendaylight.yangtools.concepts.ListenerRegistration;
37 public class ShardedDOMTransactionChainAdapter implements DOMTransactionChain {
39 private final DOMDataTreeService dataTreeService;
40 private final Object txChainIdentifier;
41 private final AtomicLong txNum = new AtomicLong();
42 private final TransactionChainListener txChainListener;
43 private final CachedDataTreeService cachedDataTreeService;
44 private TransactionChainWriteTransaction writeTx;
45 private TransactionChainReadTransaction readTx;
46 private ListenableFuture<Void> writeTxSubmitFuture;
47 private boolean finished = false;
49 public ShardedDOMTransactionChainAdapter(final Object txChainIdentifier,
50 final DOMDataTreeService dataTreeService,
51 final TransactionChainListener txChainListener) {
52 Preconditions.checkNotNull(dataTreeService);
53 Preconditions.checkNotNull(txChainIdentifier);
54 this.dataTreeService = dataTreeService;
55 this.txChainIdentifier = txChainIdentifier;
56 this.txChainListener = txChainListener;
57 this.cachedDataTreeService = new CachedDataTreeService(dataTreeService);
61 public DOMDataTreeReadTransaction newReadOnlyTransaction() {
65 readTx = new TransactionChainReadTransaction(newTransactionIdentifier(),
66 new ShardedDOMReadTransactionAdapter(newTransactionIdentifier(), dataTreeService),
67 writeTxSubmitFuture, this);
73 public DOMDataTreeWriteTransaction newWriteOnlyTransaction() {
77 writeTx = new TransactionChainWriteTransaction(newTransactionIdentifier(),
78 new ShardedDOMWriteTransactionAdapter(newTransactionIdentifier(),
79 cachedDataTreeService), this);
86 if (finished = true) {
87 // already closed, do nothing
93 Futures.addCallback(writeTxSubmitFuture, new FutureCallback<Void>() {
95 public void onSuccess(@Nullable final Void result) {
96 txChainListener.onTransactionChainSuccessful(ShardedDOMTransactionChainAdapter.this);
100 public void onFailure(final Throwable throwable) {
101 // We don't have to do nothing here,
102 // tx should take car of it
106 cachedDataTreeService.closeProducers();
110 public void closeReadTransaction() {
114 public void closeWriteTransaction(final ListenableFuture<Void> submitFuture) {
115 writeTxSubmitFuture = submitFuture;
119 private Object newTransactionIdentifier() {
120 return "DOM-CHAIN-" + txChainIdentifier + "-" + txNum.getAndIncrement();
123 private void checkWriteTxClosed() {
124 Preconditions.checkState(writeTx == null);
127 private void checkReadTxClosed() {
128 Preconditions.checkState(readTx == null);
131 private void checkRunning() {
132 Preconditions.checkState(finished == false);
135 public void transactionFailed(final AsyncTransaction<?, ?> tx, final Throwable cause) {
136 txChainListener.onTransactionChainFailed(this, tx, cause);
137 if (writeTx != null) {
140 if (readTx != null) {
143 cachedDataTreeService.closeProducers();
147 static class CachedDataTreeService implements DOMDataTreeService {
149 private final DOMDataTreeService delegateTreeService;
150 private final Map<LogicalDatastoreType, NoopCloseDataProducer> producersMap =
151 new EnumMap<>(LogicalDatastoreType.class);
153 CachedDataTreeService(final DOMDataTreeService delegateTreeService) {
154 this.delegateTreeService = delegateTreeService;
157 void closeProducers() {
158 producersMap.values().forEach(NoopCloseDataProducer::closeDelegate);
163 public <T extends DOMDataTreeListener> ListenerRegistration<T> registerListener(
164 @Nonnull final T listener, @Nonnull final Collection<DOMDataTreeIdentifier> subtrees,
165 final boolean allowRxMerges, @Nonnull final Collection<DOMDataTreeProducer> producers)
166 throws DOMDataTreeLoopException {
167 return delegateTreeService.registerListener(listener, subtrees, allowRxMerges, producers);
171 public DOMDataTreeProducer createProducer(@Nonnull final Collection<DOMDataTreeIdentifier> subtrees) {
172 Preconditions.checkState(subtrees.size() == 1);
173 NoopCloseDataProducer producer = null;
174 for (final DOMDataTreeIdentifier treeId : subtrees) {
176 new NoopCloseDataProducer(delegateTreeService.createProducer(Collections.singleton(treeId)));
177 producersMap.putIfAbsent(treeId.getDatastoreType(),
183 static class NoopCloseDataProducer implements DOMDataTreeProducer {
185 private final DOMDataTreeProducer delegateTreeProducer;
187 NoopCloseDataProducer(final DOMDataTreeProducer delegateTreeProducer) {
188 this.delegateTreeProducer = delegateTreeProducer;
193 public DOMDataTreeCursorAwareTransaction createTransaction(final boolean isolated) {
194 return delegateTreeProducer.createTransaction(isolated);
199 public DOMDataTreeProducer createProducer(@Nonnull final Collection<DOMDataTreeIdentifier> subtrees) {
200 return delegateTreeProducer.createProducer(subtrees);
204 public void close() throws DOMDataTreeProducerException {
208 public void closeDelegate() {
210 delegateTreeProducer.close();
211 } catch (final DOMDataTreeProducerException e) {
212 throw new IllegalStateException("Trying to close DOMDataTreeProducer with open transaction", e);