Do not implement concepts.Builder
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / ShardDataTreeTransactionChain.java
1 /*
2  * Copyright (c) 2015 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.controller.cluster.datastore;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.base.MoreObjects;
14 import java.util.Optional;
15 import java.util.SortedSet;
16 import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
17 import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
18 import org.opendaylight.yangtools.concepts.Identifiable;
19 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeModification;
20 import org.opendaylight.yangtools.yang.data.tree.api.DataTreeSnapshot;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24 /**
25  * A transaction chain attached to a Shard. This class is NOT thread-safe.
26  */
27 final class ShardDataTreeTransactionChain extends ShardDataTreeTransactionParent
28         implements Identifiable<LocalHistoryIdentifier> {
29
30     private static final Logger LOG = LoggerFactory.getLogger(ShardDataTreeTransactionChain.class);
31     private final LocalHistoryIdentifier chainId;
32     private final ShardDataTree dataTree;
33
34     private ReadWriteShardDataTreeTransaction previousTx;
35     private ReadWriteShardDataTreeTransaction openTransaction;
36     private boolean closed;
37
38     ShardDataTreeTransactionChain(final LocalHistoryIdentifier localHistoryIdentifier, final ShardDataTree dataTree) {
39         chainId = requireNonNull(localHistoryIdentifier);
40         this.dataTree = requireNonNull(dataTree);
41     }
42
43     private DataTreeSnapshot getSnapshot() {
44         checkState(!closed, "TransactionChain %s has been closed", this);
45         checkState(openTransaction == null, "Transaction %s is open", openTransaction);
46
47         if (previousTx == null) {
48             LOG.debug("Opening an unchained snapshot in {}", chainId);
49             return dataTree.takeSnapshot();
50         }
51
52         LOG.debug("Reusing a chained snapshot in {}", chainId);
53         return previousTx.getSnapshot();
54     }
55
56     ReadOnlyShardDataTreeTransaction newReadOnlyTransaction(final TransactionIdentifier txId) {
57         final DataTreeSnapshot snapshot = getSnapshot();
58         LOG.debug("Allocated read-only transaction {} snapshot {}", txId, snapshot);
59
60         return new ReadOnlyShardDataTreeTransaction(this, txId, snapshot);
61     }
62
63     ReadWriteShardDataTreeTransaction newReadWriteTransaction(final TransactionIdentifier txId) {
64         final DataTreeSnapshot snapshot = getSnapshot();
65         LOG.debug("Allocated read-write transaction {} snapshot {}", txId, snapshot);
66
67         openTransaction = new ReadWriteShardDataTreeTransaction(this, txId, snapshot.newModification());
68         return openTransaction;
69     }
70
71     void close() {
72         closed = true;
73         LOG.debug("Closing chain {}", chainId);
74     }
75
76     @Override
77     void abortFromTransactionActor(final AbstractShardDataTreeTransaction<?> transaction) {
78         if (transaction instanceof ReadWriteShardDataTreeTransaction) {
79             checkState(openTransaction != null, "Attempted to abort transaction %s while none is outstanding",
80                     transaction);
81             LOG.debug("Aborted open transaction {}", transaction);
82             openTransaction = null;
83         }
84     }
85
86     @Override
87     void abortTransaction(final AbstractShardDataTreeTransaction<?> transaction, final Runnable callback) {
88         abortFromTransactionActor(transaction);
89         dataTree.abortTransaction(transaction, callback);
90     }
91
92     @Override
93     ShardDataTreeCohort finishTransaction(final ReadWriteShardDataTreeTransaction transaction,
94             final Optional<SortedSet<String>> participatingShardNames) {
95         checkState(openTransaction != null, "Attempted to finish transaction %s while none is outstanding",
96                 transaction);
97
98         // dataTree is finalizing ready the transaction, we just record it for the next
99         // transaction in chain
100         final ShardDataTreeCohort delegate = dataTree.finishTransaction(transaction, participatingShardNames);
101         openTransaction = null;
102         previousTx = transaction;
103         LOG.debug("Committing transaction {}", transaction);
104
105         return new ChainedCommitCohort(this, transaction, delegate);
106     }
107
108     @Override
109     public String toString() {
110         return MoreObjects.toStringHelper(this).add("id", chainId).toString();
111     }
112
113     void clearTransaction(final ReadWriteShardDataTreeTransaction transaction) {
114         if (transaction.equals(previousTx)) {
115             previousTx = null;
116         }
117     }
118
119     @Override
120     public LocalHistoryIdentifier getIdentifier() {
121         return chainId;
122     }
123
124     @Override
125     ShardDataTreeCohort createFailedCohort(final TransactionIdentifier txId, final DataTreeModification mod,
126             final Exception failure) {
127         return dataTree.createFailedCohort(txId, mod, failure);
128     }
129
130     @Override
131     ShardDataTreeCohort createReadyCohort(final TransactionIdentifier txId, final DataTreeModification mod,
132             final Optional<SortedSet<String>> participatingShardNames) {
133         return dataTree.createReadyCohort(txId, mod, participatingShardNames);
134     }
135 }