a09da38734e03c070a76f6a359356993985c6f17
[mdsal.git] / dom / mdsal-dom-broker / src / main / java / org / opendaylight / mdsal / dom / broker / AbstractDOMForwardedTransactionFactory.java
1 /*
2  * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.dom.broker;
9
10 import com.google.common.base.Preconditions;
11 import com.google.common.util.concurrent.CheckedFuture;
12 import java.util.Collection;
13 import java.util.EnumMap;
14 import java.util.Map;
15 import java.util.Map.Entry;
16 import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
17 import org.opendaylight.mdsal.common.api.LogicalDatastoreType;
18 import org.opendaylight.mdsal.common.api.TransactionCommitFailedException;
19 import org.opendaylight.mdsal.dom.api.DOMDataTreeReadTransaction;
20 import org.opendaylight.mdsal.dom.api.DOMDataTreeWriteTransaction;
21 import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadTransaction;
22 import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadWriteTransaction;
23 import org.opendaylight.mdsal.dom.spi.store.DOMStoreThreePhaseCommitCohort;
24 import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionFactory;
25 import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
26
27 /**
28  *
29  * Abstract composite transaction factory.
30  *
31  * Provides an convenience common implementation for composite DOM Transactions,
32  * where subtransaction is identified by {@link LogicalDatastoreType} type and
33  * implementation of subtransaction is provided by
34  * {@link DOMStoreTransactionFactory}.
35  *
36  * <b>Note:</b>This class does not have thread-safe implementation of  {@link #close()},
37  *   implementation may allow accessing and allocating new transactions during closing
38  *   this instance.
39  *
40  * @param <T>
41  *            Type of {@link DOMStoreTransactionFactory} factory.
42  */
43 abstract class AbstractDOMForwardedTransactionFactory<T extends DOMStoreTransactionFactory> implements AutoCloseable {
44     @SuppressWarnings("rawtypes")
45     private static final AtomicIntegerFieldUpdater<AbstractDOMForwardedTransactionFactory> UPDATER =
46             AtomicIntegerFieldUpdater.newUpdater(AbstractDOMForwardedTransactionFactory.class, "closed");
47     private final Map<LogicalDatastoreType, T> storeTxFactories;
48     private volatile int closed = 0;
49
50     protected AbstractDOMForwardedTransactionFactory(final Map<LogicalDatastoreType, ? extends T> txFactories) {
51         this.storeTxFactories = new EnumMap<>(txFactories);
52     }
53
54     /**
55      * Implementations must return unique identifier for each and every call of
56      * this method;
57      *
58      * @return new Unique transaction identifier.
59      */
60     protected abstract Object newTransactionIdentifier();
61
62     /**
63      * User-supplied implementation of {@link DOMDataTreeWriteTransaction#submit()} for transaction.
64      *
65      * Callback invoked when {@link DOMDataTreeWriteTransaction#submit()} is invoked on transaction
66      * created by this factory.
67      *
68      * @param transaction Transaction on which {@link DOMDataTreeWriteTransaction#submit()} was invoked.
69      * @param cohorts Iteratable of cohorts for subtransactions associated with the transaction
70      *        being committed.
71      * @return a CheckedFuture. if commit coordination on cohorts finished successfully, nothing is
72      *         returned from the Future, On failure, the Future fails with a
73      *         {@link TransactionCommitFailedException}.
74      */
75     protected abstract CheckedFuture<Void,TransactionCommitFailedException> submit(final DOMDataTreeWriteTransaction transaction,
76             final Collection<DOMStoreThreePhaseCommitCohort> cohorts);
77
78     /**
79      * Creates a new composite read-only transaction
80      *
81      * Creates a new composite read-only transaction backed by one transaction per factory in
82      * {@link #getTxFactories()}.
83      *
84      * Subtransaction for reading is selected by supplied {@link LogicalDatastoreType} as parameter
85      * for
86      * {@link DOMDataTreeReadTransaction#read(LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)}
87      * .
88      *
89      * Id of returned transaction is retrieved via {@link #newTransactionIdentifier()}.
90      *
91      * @return New composite read-only transaction.
92      */
93     public final DOMDataTreeReadTransaction newReadOnlyTransaction() {
94         checkNotClosed();
95
96         final Map<LogicalDatastoreType, DOMStoreReadTransaction> txns = new EnumMap<>(LogicalDatastoreType.class);
97         for (final Entry<LogicalDatastoreType, T> store : storeTxFactories.entrySet()) {
98             txns.put(store.getKey(), store.getValue().newReadOnlyTransaction());
99         }
100         return new DOMForwardedReadOnlyTransaction(newTransactionIdentifier(), txns);
101     }
102
103     /**
104      * Creates a new composite write-only transaction
105      *
106      * <p>
107      * Creates a new composite write-only transaction backed by one write-only transaction per
108      * factory in {@link #getTxFactories()}.
109      *
110      * <p>
111      * Implementation of composite Write-only transaction is following:
112      *
113      * <ul>
114      * <li>
115      * {@link DOMDataTreeWriteTransaction#put(LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
116      * - backing subtransaction is selected by {@link LogicalDatastoreType},
117      * {@link DOMStoreWriteTransaction#write(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
118      * is invoked on selected subtransaction.</li>
119      * <li>
120      * {@link DOMDataTreeWriteTransaction#merge(LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
121      * - backing subtransaction is selected by {@link LogicalDatastoreType},
122      * {@link DOMStoreWriteTransaction#merge(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier, org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode)}
123      * is invoked on selected subtransaction.</li>
124      * <li>
125      * {@link DOMDataTreeWriteTransaction#delete(LogicalDatastoreType, org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)}
126      * - backing subtransaction is selected by {@link LogicalDatastoreType},
127      * {@link DOMStoreWriteTransaction#delete(org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)}
128      * is invoked on selected subtransaction.
129      * <li> {@link DOMDataTreeWriteTransaction#submit()} - results in invoking
130      * {@link DOMStoreWriteTransaction#ready()}, gathering all resulting cohorts and then invoking
131      * finalized implementation callback {@link #submit(DOMDataTreeWriteTransaction, Collection)} with
132      * transaction which was commited and gathered results.</li>
133      * </ul>
134      *
135      * Id of returned transaction is generated via {@link #newTransactionIdentifier()}.
136      *
137      * @return New composite write-only transaction associated with this factory.
138      */
139     public final DOMDataTreeWriteTransaction newWriteOnlyTransaction() {
140         checkNotClosed();
141
142         final Map<LogicalDatastoreType, DOMStoreWriteTransaction> txns = new EnumMap<>(LogicalDatastoreType.class);
143         for (final Entry<LogicalDatastoreType, T> store : storeTxFactories.entrySet()) {
144             txns.put(store.getKey(), store.getValue().newWriteOnlyTransaction());
145         }
146         return new DOMForwardedWriteTransaction<DOMStoreWriteTransaction>(newTransactionIdentifier(), txns, this);
147     }
148
149     /**
150      * Convenience accessor of backing factories intended to be used only by
151      * finalization of this class.
152      *
153      * <b>Note:</b>
154      * Finalization of this class may want to access other functionality of
155      * supplied Transaction factories.
156      *
157      * @return Map of backing transaction factories.
158      */
159     protected final Map<LogicalDatastoreType, T> getTxFactories() {
160         return storeTxFactories;
161     }
162
163     /**
164      * Checks if instance is not closed.
165      *
166      * @throws IllegalStateException If instance of this class was closed.
167      *
168      */
169     protected final void checkNotClosed() {
170         Preconditions.checkState(closed == 0, "Transaction factory was closed. No further operations allowed.");
171     }
172
173     @Override
174     public void close() {
175         final boolean success = UPDATER.compareAndSet(this, 0, 1);
176         Preconditions.checkState(success, "Transaction factory was already closed");
177     }
178 }
179