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.FluentFuture;
13 import com.google.common.util.concurrent.Futures;
14 import com.google.common.util.concurrent.MoreExecutors;
15 import java.util.Collections;
16 import java.util.EnumMap;
17 import java.util.List;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.mdsal.common.api.CommitInfo;
21 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
22 import org.opendaylight.mdsal.dom.api.DOMDataTreeCursorAwareTransaction;
23 import org.opendaylight.mdsal.dom.api.DOMDataTreeIdentifier;
24 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducer;
25 import org.opendaylight.mdsal.dom.api.DOMDataTreeProducerException;
26 import org.opendaylight.mdsal.dom.api.DOMDataTreeService;
27 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteCursor;
28 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
29 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
30 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 public class ShardedDOMWriteTransactionAdapter implements DOMDataTreeWriteTransaction {
35 private static final Logger LOG = LoggerFactory.getLogger(ShardedDOMWriteTransactionAdapter.class);
37 private final Map<LogicalDatastoreType, DOMDataTreeProducer> producerMap;
38 private final Map<LogicalDatastoreType, DOMDataTreeCursorAwareTransaction> transactionMap;
39 private final Map<LogicalDatastoreType, DOMDataTreeWriteCursor> cursorMap;
41 private final DOMDataTreeService treeService;
42 private final Object txIdentifier;
43 private boolean finished = false;
44 private boolean initialized = false;
46 ShardedDOMWriteTransactionAdapter(final Object identifier, final DOMDataTreeService transactionDelegator) {
47 this.treeService = Preconditions.checkNotNull(transactionDelegator);
48 this.txIdentifier = Preconditions.checkNotNull(identifier);
49 this.producerMap = new EnumMap<>(LogicalDatastoreType.class);
50 this.transactionMap = new EnumMap<>(LogicalDatastoreType.class);
51 this.cursorMap = new EnumMap<>(LogicalDatastoreType.class);
55 public boolean cancel() {
56 LOG.debug("{}: Cancelling transaction");
61 // We close cursor, cancel transactions and close producers and
62 // mark transaction as finished
63 cursorMap.values().forEach(DOMDataTreeWriteCursor::close);
64 transactionMap.values().forEach(domDataTreeCursorAwareTransaction ->
65 Preconditions.checkState(domDataTreeCursorAwareTransaction.cancel()));
72 public @NonNull FluentFuture<? extends @NonNull CommitInfo> commit() {
74 LOG.debug("{}: Submitting transaction", txIdentifier);
76 // If underlying producers, transactions and cursors are
77 // not even initialized just seal this transaction and
78 // return immediate future
80 return CommitInfo.emptyFluentFuture();
82 // First we need to close cursors
83 cursorMap.values().forEach(DOMDataTreeWriteCursor::close);
84 final FluentFuture<List<CommitInfo>> aggregatedSubmit = FluentFuture.from(Futures.allAsList(
85 transactionMap.get(LogicalDatastoreType.CONFIGURATION).commit(),
86 transactionMap.get(LogicalDatastoreType.OPERATIONAL).commit()));
88 // Now we can close producers and mark transaction as finished
92 return aggregatedSubmit.transform(unused -> CommitInfo.empty(), MoreExecutors.directExecutor());
96 public Object getIdentifier() {
101 public void put(final LogicalDatastoreType store, final YangInstanceIdentifier path,
102 final NormalizedNode<?, ?> data) {
104 LOG.debug("{}: Invoking put operation at {}:{}", txIdentifier, store, path);
105 LOG.trace("{}: payload is {}", txIdentifier, data);
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 {}:{}", txIdentifier, store, path);
119 LOG.trace("{}: payload is {}", txIdentifier, data);
121 initializeDataTreeProducerLayer(path.getParent());
124 final DOMDataTreeWriteCursor cursor = cursorMap.get(store);
125 cursor.merge(path.getLastPathArgument(), data);
129 public void delete(final LogicalDatastoreType store, final YangInstanceIdentifier path) {
131 LOG.debug("{}: Invoking delete operation at {}:{}", txIdentifier, store, path);
133 initializeDataTreeProducerLayer(path.getParent());
136 final DOMDataTreeWriteCursor cursor = cursorMap.get(store);
137 cursor.delete(path.getLastPathArgument());
140 // TODO initialize producer, transaction and cursor for only
141 // for necessary data store at one time
142 private void initializeDataTreeProducerLayer(final YangInstanceIdentifier path) {
143 Preconditions.checkState(producerMap.isEmpty(), "Producers already initialized");
144 Preconditions.checkState(transactionMap.isEmpty(), "Transactions already initialized");
145 Preconditions.checkState(cursorMap.isEmpty(), "Cursors already initialized");
147 LOG.debug("{}: Creating data tree producers on path {}", txIdentifier, path);
148 producerMap.put(LogicalDatastoreType.CONFIGURATION,
149 treeService.createProducer(
150 Collections.singleton(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, path))));
151 producerMap.put(LogicalDatastoreType.OPERATIONAL,
152 treeService.createProducer(
153 Collections.singleton(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, path))));
155 LOG.debug("{}: Creating DOMDataTreeCursorAwareTransactions delegates on {}", txIdentifier, path);
156 transactionMap.put(LogicalDatastoreType.CONFIGURATION,
157 producerMap.get(LogicalDatastoreType.CONFIGURATION).createTransaction(true));
158 transactionMap.put(LogicalDatastoreType.OPERATIONAL,
159 producerMap.get(LogicalDatastoreType.OPERATIONAL).createTransaction(true));
161 LOG.debug("{}: Creating DOMDataTreeWriteCursors delegates");
162 cursorMap.put(LogicalDatastoreType.CONFIGURATION,
163 transactionMap.get(LogicalDatastoreType.CONFIGURATION)
164 .createCursor(new DOMDataTreeIdentifier(LogicalDatastoreType.CONFIGURATION, path)));
165 cursorMap.put(LogicalDatastoreType.OPERATIONAL,
166 transactionMap.get(LogicalDatastoreType.OPERATIONAL)
167 .createCursor(new DOMDataTreeIdentifier(LogicalDatastoreType.OPERATIONAL, path)));
172 private void checkRunning() {
173 Preconditions.checkState(!finished, "{}: Transaction already finished");
176 private void closeProducers() {
177 producerMap.values().forEach(domDataTreeProducer -> {
179 domDataTreeProducer.close();
180 } catch (final DOMDataTreeProducerException e) {
181 throw new IllegalStateException("Trying to close DOMDataTreeProducer with open transaction", e);