2 * Copyright (c) 2014 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 java.util.Objects.requireNonNull;
12 import java.lang.invoke.MethodHandles;
13 import java.lang.invoke.VarHandle;
15 import java.util.Map.Entry;
16 import java.util.function.Function;
17 import org.eclipse.jdt.annotation.NonNull;
18 import org.eclipse.jdt.annotation.Nullable;
19 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
20 import org.opendaylight.mdsal.common.api.TransactionDatastoreMismatchException;
21 import org.opendaylight.mdsal.dom.api.DOMDataTreeTransaction;
22 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransaction;
25 * Composite DOM Transaction backed by {@link DOMStoreTransaction}.
28 * Abstract base for composite transaction, which provides access only to common
29 * functionality as retrieval of subtransaction, close method and retrieval of
32 * @param <T> Subtransaction type
34 abstract class AbstractDOMForwardedTransaction<T extends DOMStoreTransaction>
35 implements DOMDataTreeTransaction {
36 private static final VarHandle BACKING_TX;
40 BACKING_TX = MethodHandles.lookup().findVarHandle(AbstractDOMForwardedTransaction.class,
41 "backingTx", Entry.class);
42 } catch (NoSuchFieldException | IllegalAccessException e) {
43 throw new ExceptionInInitializerError(e);
47 private final @NonNull Object identifier;
48 private final Function<LogicalDatastoreType, T> backingTxFactory;
50 private volatile Entry<LogicalDatastoreType, T> backingTx;
53 * Creates new composite Transactions.
56 * Identifier of transaction.
57 * @param backingTxFactory
58 * Function which supplies transaction depending on store type
60 protected AbstractDOMForwardedTransaction(final Object identifier,
61 final Function<LogicalDatastoreType, T> backingTxFactory) {
62 this.identifier = requireNonNull(identifier, "Identifier should not be null");
63 this.backingTxFactory = requireNonNull(backingTxFactory, "Backing transaction factory should not be null");
67 * Returns subtransaction associated with supplied datastore type.
70 * The method allows usage of single datastore type per transaction instance;
71 * eligible datastore type is defined by first method access.
73 * @param datastoreType is used to identify subtransaction object
74 * @return the subtransaction object
75 * @throws NullPointerException if datastoreType is {@code null}
76 * @throws IllegalArgumentException if datastoreType is not supported
77 * @throws TransactionDatastoreMismatchException if datastoreType mismatches the one used at first access
79 protected final @NonNull T getSubtransaction(final LogicalDatastoreType datastoreType) {
80 final var ds = requireNonNull(datastoreType, "datastoreType must not be null.");
82 var entry = backingTx;
84 final var tx = backingTxFactory.apply(datastoreType);
85 final var newEntry = Map.entry(ds, tx);
86 final var witness = (Entry<LogicalDatastoreType, T>) BACKING_TX.compareAndExchange(this, null, newEntry);
87 if (witness != null) {
95 final var encountered = entry.getKey();
96 if (encountered != ds) {
97 throw new TransactionDatastoreMismatchException(encountered, ds);
99 return entry.getValue();
103 * Returns immutable Iterable of all subtransactions.
105 protected @Nullable T getSubtransaction() {
106 final Entry<LogicalDatastoreType, T> entry;
107 return (entry = backingTx) == null ? null : entry.getValue();
111 public Object getIdentifier() {
115 @SuppressWarnings("checkstyle:IllegalCatch")
116 protected void closeSubtransactions() {
118 * We share one exception for all failures, which are added
119 * as supressedExceptions to it.
121 final var subtransaction = getSubtransaction();
122 if (subtransaction != null) {
124 subtransaction.close();
125 } catch (Exception e) {
126 // If we did not allocate failure we allocate it
127 throw new IllegalStateException("Uncaught exception occurred during closing transaction", e);