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
8 package org.opendaylight.mdsal.dom.broker;
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.util.concurrent.FluentFuture;
14 import com.google.common.util.concurrent.FutureCallback;
15 import com.google.common.util.concurrent.MoreExecutors;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.EnumMap;
20 import java.util.concurrent.atomic.AtomicLong;
21 import org.opendaylight.mdsal.common.api.CommitInfo;
22 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeCursorAwareTransaction;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducer;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducerException;
27 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
28 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadWriteTransaction;
29 import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
30 import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
31 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
32 import org.opendaylight.mdsal.dom.api.DOMTransactionChain;
33 import org.opendaylight.mdsal.dom.api.DOMTransactionChainListener;
34 import org.opendaylight.mdsal.dom.spi.ForwardingDOMDataTreeService;
36 public class ShardedDOMTransactionChainAdapter implements DOMTransactionChain {
38 private final DOMDataTreeService dataTreeService;
39 private final Object txChainIdentifier;
40 private final AtomicLong txNum = new AtomicLong();
41 private final DOMTransactionChainListener txChainListener;
42 private final CachedDataTreeService cachedDataTreeService;
43 private TransactionChainWriteTransaction writeTx;
44 private TransactionChainReadTransaction readTx;
45 private FluentFuture<? extends CommitInfo> writeTxCommitFuture;
46 private boolean finished = false;
48 public ShardedDOMTransactionChainAdapter(final Object txChainIdentifier,
49 final DOMDataTreeService dataTreeService, final DOMTransactionChainListener txChainListener) {
50 this.dataTreeService = requireNonNull(dataTreeService);
51 this.txChainIdentifier = requireNonNull(txChainIdentifier);
52 this.txChainListener = txChainListener;
53 this.cachedDataTreeService = new CachedDataTreeService(dataTreeService);
57 public DOMDataTreeReadTransaction newReadOnlyTransaction() {
61 readTx = new TransactionChainReadTransaction(newTransactionIdentifier(),
62 new ShardedDOMReadTransactionAdapter(newTransactionIdentifier(), dataTreeService),
63 writeTxCommitFuture, this);
69 public DOMDataTreeWriteTransaction newWriteOnlyTransaction() {
73 writeTx = new TransactionChainWriteTransaction(newTransactionIdentifier(),
74 new ShardedDOMWriteTransactionAdapter(newTransactionIdentifier(),
75 cachedDataTreeService), this);
81 public DOMDataTreeReadWriteTransaction newReadWriteTransaction() {
85 ShardedDOMReadWriteTransactionAdapter adapter = new ShardedDOMReadWriteTransactionAdapter(
86 newTransactionIdentifier(), cachedDataTreeService);
87 TransactionChainReadWriteTransaction readWriteTx = new TransactionChainReadWriteTransaction(
88 newTransactionIdentifier(), adapter, adapter.getReadAdapter(), writeTxCommitFuture, this);
90 writeTx = readWriteTx;
97 // already closed, do nothing
102 checkWriteTxClosed();
103 writeTxCommitFuture.addCallback(new FutureCallback<CommitInfo>() {
105 public void onSuccess(final CommitInfo result) {
106 txChainListener.onTransactionChainSuccessful(ShardedDOMTransactionChainAdapter.this);
110 public void onFailure(final Throwable throwable) {
111 // We don't have to do nothing here,
112 // tx should take car of it
114 }, MoreExecutors.directExecutor());
116 cachedDataTreeService.closeProducers();
120 public void closeReadTransaction() {
124 public void closeWriteTransaction(final FluentFuture<? extends CommitInfo> commitFuture) {
125 writeTxCommitFuture = commitFuture;
129 private Object newTransactionIdentifier() {
130 return "DOM-CHAIN-" + txChainIdentifier + "-" + txNum.getAndIncrement();
133 private void checkWriteTxClosed() {
134 checkState(writeTx == null);
137 private void checkReadTxClosed() {
138 checkState(readTx == null);
141 private void checkRunning() {
142 checkState(!finished);
145 public void transactionFailed(final DOMDataTreeTransaction tx, final Throwable cause) {
146 txChainListener.onTransactionChainFailed(this, tx, cause);
147 if (writeTx != null) {
150 if (readTx != null) {
153 cachedDataTreeService.closeProducers();
157 private static final class CachedDataTreeService extends ForwardingDOMDataTreeService {
158 private final Map<LogicalDatastoreType, NoopCloseDataProducer> producersMap =
159 new EnumMap<>(LogicalDatastoreType.class);
160 private final DOMDataTreeService delegate;
162 CachedDataTreeService(final DOMDataTreeService delegate) {
163 this.delegate = requireNonNull(delegate);
167 public DOMDataTreeProducer createProducer(final Collection<DOMDataTreeIdentifier> subtrees) {
168 checkState(subtrees.size() == 1);
169 DOMDataTreeIdentifier treeId = subtrees.iterator().next();
170 NoopCloseDataProducer producer = new NoopCloseDataProducer(delegate.createProducer(
171 Collections.singleton(treeId)));
172 producersMap.putIfAbsent(treeId.getDatastoreType(), producer);
177 protected DOMDataTreeService delegate() {
181 void closeProducers() {
182 producersMap.values().forEach(NoopCloseDataProducer::closeDelegate);
186 private static final class NoopCloseDataProducer implements DOMDataTreeProducer {
187 private final DOMDataTreeProducer delegateTreeProducer;
189 NoopCloseDataProducer(final DOMDataTreeProducer delegateTreeProducer) {
190 this.delegateTreeProducer = delegateTreeProducer;
194 public DOMDataTreeCursorAwareTransaction createTransaction(final boolean isolated) {
195 return delegateTreeProducer.createTransaction(isolated);
199 public DOMDataTreeProducer createProducer(final Collection<DOMDataTreeIdentifier> subtrees) {
200 return delegateTreeProducer.createProducer(subtrees);
204 public void close() {
208 public void closeDelegate() {
210 delegateTreeProducer.close();
211 } catch (final DOMDataTreeProducerException e) {
212 throw new IllegalStateException("Trying to close DOMDataTreeProducer with open transaction", e);