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
9 package org.opendaylight.controller.cluster.datastore;
11 import com.google.common.base.Preconditions;
12 import java.util.Collections;
13 import java.util.List;
14 import java.util.concurrent.atomic.AtomicInteger;
15 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
16 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
17 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosedException;
18 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
19 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
20 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
21 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
22 import scala.concurrent.Future;
25 * TransactionChainProxy acts as a proxy for a DOMStoreTransactionChain created on a remote shard
27 public class TransactionChainProxy implements DOMStoreTransactionChain {
29 private interface State {
32 List<Future<Object>> getPreviousReadyFutures();
35 private static class Allocated implements State {
36 private final ChainedTransactionProxy transaction;
38 Allocated(ChainedTransactionProxy transaction) {
39 this.transaction = transaction;
43 public boolean isReady() {
44 return transaction.isReady();
48 public List<Future<Object>> getPreviousReadyFutures() {
49 return transaction.getReadyFutures();
53 private static abstract class AbstractDefaultState implements State {
55 public List<Future<Object>> getPreviousReadyFutures() {
56 return Collections.emptyList();
60 private static final State IDLE_STATE = new AbstractDefaultState() {
62 public boolean isReady() {
67 private static final State CLOSED_STATE = new AbstractDefaultState() {
69 public boolean isReady() {
70 throw new TransactionChainClosedException("Transaction chain has been closed");
74 private static final AtomicInteger counter = new AtomicInteger(0);
76 private final ActorContext actorContext;
77 private final String transactionChainId;
78 private volatile State currentState = IDLE_STATE;
80 public TransactionChainProxy(ActorContext actorContext) {
81 this.actorContext = actorContext;
82 transactionChainId = actorContext.getCurrentMemberName() + "-txn-chain-" + counter.incrementAndGet();
85 public String getTransactionChainId() {
86 return transactionChainId;
90 public DOMStoreReadTransaction newReadOnlyTransaction() {
91 State localState = currentState;
92 checkReadyState(localState);
94 return new ChainedTransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY,
95 transactionChainId, localState.getPreviousReadyFutures());
99 public DOMStoreReadWriteTransaction newReadWriteTransaction() {
100 actorContext.acquireTxCreationPermit();
101 return allocateWriteTransaction(TransactionProxy.TransactionType.READ_WRITE);
105 public DOMStoreWriteTransaction newWriteOnlyTransaction() {
106 actorContext.acquireTxCreationPermit();
107 return allocateWriteTransaction(TransactionProxy.TransactionType.WRITE_ONLY);
111 public void close() {
112 currentState = CLOSED_STATE;
114 // Send a close transaction chain request to each and every shard
115 actorContext.broadcast(new CloseTransactionChain(transactionChainId).toSerializable());
118 private ChainedTransactionProxy allocateWriteTransaction(TransactionProxy.TransactionType type) {
119 State localState = currentState;
121 checkReadyState(localState);
123 // Pass the ready Futures from the previous Tx.
124 ChainedTransactionProxy txProxy = new ChainedTransactionProxy(actorContext, type,
125 transactionChainId, localState.getPreviousReadyFutures());
127 currentState = new Allocated(txProxy);
132 private void checkReadyState(State state) {
133 Preconditions.checkState(state.isReady(), "Previous transaction is not ready yet");