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.CheckedFuture;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.ListenableFuture;
15 import java.util.Collections;
16 import java.util.EnumMap;
17 import java.util.List;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
21 import org.opendaylight.mdsal.dom.api.DOMDataTreeCursorAwareTransaction;
22 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducer;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducerException;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteCursor;
27 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
28 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
29 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
30 import org.slf4j.Logger;
31 import org.slf4j.LoggerFactory;
33 public class ShardedDOMWriteTransactionAdapter implements DOMDataTreeWriteTransaction {
34 private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMWriteTransactionAdapter.class);
36 private final Map<LogicalDatastoreType, DOMDataTreeProducer> producerMap;
37 private final Map<LogicalDatastoreType, DOMDataTreeCursorAwareTransaction> transactionMap;
38 private final Map<LogicalDatastoreType, DOMDataTreeWriteCursor> cursorMap;
40 private final DOMDataTreeService treeService;
41 private final Object txIdentifier;
42 private boolean finished = false;
43 private boolean initialized = false;
45 ShardedDOMWriteTransactionAdapter(final Object identifier, final DOMDataTreeService transactionDelegator) {
46 this.treeService = Preconditions.checkNotNull(transactionDelegator);
47 this.txIdentifier = Preconditions.checkNotNull(identifier);
48 this.producerMap = new EnumMap<>(LogicalDatastoreType.class);
49 this.transactionMap = new EnumMap<>(LogicalDatastoreType.class);
50 this.cursorMap = new EnumMap<>(LogicalDatastoreType.class);
54 public boolean cancel() {
55 LOG.debug("{}: Cancelling transaction");
56 if (finished == true) {
60 // We close cursor, cancel transactions and close producers and
61 // mark transaction as finished
62 cursorMap.values().forEach(DOMDataTreeWriteCursor::close);
63 transactionMap.values().forEach(domDataTreeCursorAwareTransaction ->
64 Preconditions.checkState(domDataTreeCursorAwareTransaction.cancel()));
71 public CheckedFuture<Void, TransactionCommitFailedException> submit() {
73 LOG.debug("{}: Submitting transaction", txIdentifier);
74 if (initialized == false) {
75 // If underlying producers, transactions and cursors are
76 // not even initialized just seal this transaction and
77 // return immediate future
79 return Futures.immediateCheckedFuture(null);
81 // First we need to close cursors
82 cursorMap.values().forEach(DOMDataTreeWriteCursor::close);
83 final ListenableFuture<List<Void>> aggregatedSubmit = Futures.allAsList(
84 transactionMap.get(LogicalDatastoreType.CONFIGURATION).submit(),
85 transactionMap.get(LogicalDatastoreType.OPERATIONAL).submit());
87 // Now we can close producers and mark transaction as finished
91 return Futures.makeChecked(
92 Futures.transform(aggregatedSubmit, (List<Void> input) -> input.get(0)),
93 TransactionCommitFailedExceptionMapper.COMMIT_ERROR_MAPPER);
97 public Object getIdentifier() {
102 public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path,
103 final NormalizedNode<?, ?> data) {
105 LOG.debug("{}: Invoking put operation at {}:{} with payload {}", txIdentifier, store, path);
106 if (initialized == false) {
107 initializeDataTreeProducerLayer(path.getParent());
110 final DOMDataTreeWriteCursor cursor = cursorMap.get(store);
111 cursor.write(path.getLastPathArgument(), data);
115 public void merge(final LogicalDatastoreType store, final YangInstanceIdentifier path,
116 final NormalizedNode<?, ?> data) {
118 LOG.debug("{}: Invoking merge operation at {}:{} with payload {}", txIdentifier, store, path);
119 if (initialized == false) {
120 initializeDataTreeProducerLayer(path.getParent());
123 final DOMDataTreeWriteCursor cursor = cursorMap.get(store);
124 cursor.merge(path.getLastPathArgument(), data);
128 public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
130 LOG.debug("{}: Invoking delete operation at {}:{}", txIdentifier, store, path);
131 if (initialized == false) {
132 initializeDataTreeProducerLayer(path.getParent());
135 final DOMDataTreeWriteCursor cursor = cursorMap.get(store);
136 cursor.delete(path.getLastPathArgument());
139 // TODO initialize producer, transaction and cursor for only
140 // for necessary data store at one time
141 private void initializeDataTreeProducerLayer(final YangInstanceIdentifier path) {
142 Preconditions.checkState(producerMap.isEmpty(), "Producers already initialized");
143 Preconditions.checkState(transactionMap.isEmpty(), "Transactions already initialized");
144 Preconditions.checkState(cursorMap.isEmpty(), "Cursors already initialized");
146 LOG.debug("{}: Creating data tree producers on path {}", txIdentifier, path);
147 producerMap.put(LogicalDatastoreType.CONFIGURATION,
148 treeService.createProducer(
149 Collections.singleton(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, path))));
150 producerMap.put(LogicalDatastoreType.OPERATIONAL,
151 treeService.createProducer(
152 Collections.singleton(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, path))));
154 LOG.debug("{}: Creating DOMDataTreeCursorAwareTransactions delegates", txIdentifier, path);
155 transactionMap.put(LogicalDatastoreType.CONFIGURATION,
156 producerMap.get(LogicalDatastoreType.CONFIGURATION).createTransaction(true));
157 transactionMap.put(LogicalDatastoreType.OPERATIONAL,
158 producerMap.get(LogicalDatastoreType.OPERATIONAL).createTransaction(true));
160 LOG.debug("{}: Creating DOMDataTreeWriteCursors delegates");
161 cursorMap.put(LogicalDatastoreType.CONFIGURATION,
162 transactionMap.get(LogicalDatastoreType.CONFIGURATION)
163 .createCursor(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, path)));
164 cursorMap.put(LogicalDatastoreType.OPERATIONAL,
165 transactionMap.get(LogicalDatastoreType.OPERATIONAL)
166 .createCursor(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, path)));
171 private void checkRunning() {
172 Preconditions.checkState(finished == false, "{}: Transaction already finished");
175 private void closeProducers() {
176 producerMap.values().forEach(domDataTreeProducer -> {
178 domDataTreeProducer.close();
179 } catch (final DOMDataTreeProducerException e) {
180 throw new IllegalStateException("Trying to close DOMDataTreeProducer with open transaction", e);