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 akka.actor.ActorSelection;
12 import com.google.common.base.Preconditions;
13 import java.util.Collections;
14 import java.util.List;
15 import java.util.concurrent.atomic.AtomicInteger;
16 import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
17 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
18 import org.opendaylight.controller.md.sal.common.api.data.TransactionChainClosedException;
19 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadTransaction;
20 import org.opendaylight.controller.sal.core.spi.data.DOMStoreReadWriteTransaction;
21 import org.opendaylight.controller.sal.core.spi.data.DOMStoreTransactionChain;
22 import org.opendaylight.controller.sal.core.spi.data.DOMStoreWriteTransaction;
23 import scala.concurrent.Future;
26 * TransactionChainProxy acts as a proxy for a DOMStoreTransactionChain created on a remote shard
28 public class TransactionChainProxy implements DOMStoreTransactionChain {
30 private interface State {
33 List<Future<ActorSelection>> getPreviousReadyFutures();
36 private static class Allocated implements State {
37 private final ChainedTransactionProxy transaction;
39 Allocated(ChainedTransactionProxy transaction) {
40 this.transaction = transaction;
44 public boolean isReady() {
45 return transaction.isReady();
49 public List<Future<ActorSelection>> getPreviousReadyFutures() {
50 return transaction.getReadyFutures();
54 private static abstract class AbstractDefaultState implements State {
56 public List<Future<ActorSelection>> getPreviousReadyFutures() {
57 return Collections.emptyList();
61 private static final State IDLE_STATE = new AbstractDefaultState() {
63 public boolean isReady() {
68 private static final State CLOSED_STATE = new AbstractDefaultState() {
70 public boolean isReady() {
71 throw new TransactionChainClosedException("Transaction chain has been closed");
75 private static final AtomicInteger counter = new AtomicInteger(0);
77 private final ActorContext actorContext;
78 private final String transactionChainId;
79 private volatile State currentState = IDLE_STATE;
81 public TransactionChainProxy(ActorContext actorContext) {
82 this.actorContext = actorContext;
83 transactionChainId = actorContext.getCurrentMemberName() + "-txn-chain-" + counter.incrementAndGet();
86 public String getTransactionChainId() {
87 return transactionChainId;
91 public DOMStoreReadTransaction newReadOnlyTransaction() {
92 State localState = currentState;
93 checkReadyState(localState);
95 return new ChainedTransactionProxy(actorContext, TransactionProxy.TransactionType.READ_ONLY,
96 transactionChainId, localState.getPreviousReadyFutures());
100 public DOMStoreReadWriteTransaction newReadWriteTransaction() {
101 actorContext.acquireTxCreationPermit();
102 return allocateWriteTransaction(TransactionProxy.TransactionType.READ_WRITE);
106 public DOMStoreWriteTransaction newWriteOnlyTransaction() {
107 actorContext.acquireTxCreationPermit();
108 return allocateWriteTransaction(TransactionProxy.TransactionType.WRITE_ONLY);
112 public void close() {
113 currentState = CLOSED_STATE;
115 // Send a close transaction chain request to each and every shard
116 actorContext.broadcast(new CloseTransactionChain(transactionChainId));
119 private ChainedTransactionProxy allocateWriteTransaction(TransactionProxy.TransactionType type) {
120 State localState = currentState;
122 checkReadyState(localState);
124 // Pass the ready Futures from the previous Tx.
125 ChainedTransactionProxy txProxy = new ChainedTransactionProxy(actorContext, type,
126 transactionChainId, localState.getPreviousReadyFutures());
128 currentState = new Allocated(txProxy);
133 private void checkReadyState(State state) {
134 Preconditions.checkState(state.isReady(), "Previous transaction is not ready yet");