Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*/
package org.opendaylight.controller.cluster.datastore;
import static com.google.common.base.Preconditions.checkState;
import static java.util.Objects.requireNonNull;
import akka.actor.ActorSelection;
import akka.dispatch.Futures;
import akka.dispatch.OnComplete;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier;
import org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier;
import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo;
import org.opendaylight.mdsal.dom.api.DOMTransactionChainClosedException;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadTransaction;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreReadWriteTransaction;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreTransactionChain;
import org.opendaylight.mdsal.dom.spi.store.DOMStoreWriteTransaction;
import org.opendaylight.yangtools.yang.data.tree.api.ReadOnlyDataTree;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import scala.concurrent.Future;
import scala.concurrent.Promise;
/**
* A chain of {@link TransactionProxy}s. It allows a single open transaction to be open
* at a time. For remote transactions, it also tracks the outstanding readiness requests
* towards the shard and unblocks operations only after all have completed.
*/
final class TransactionChainProxy extends AbstractTransactionContextFactory
implements DOMStoreTransactionChain {
private abstract static class State {
/**
* Check if it is okay to allocate a new transaction.
* @throws IllegalStateException if a transaction may not be allocated.
*/
abstract void checkReady();
/**
* Return the future which needs to be waited for before shard information
* is returned (which unblocks remote transactions).
* @return Future to wait for, or null of no wait is necessary
*/
abstract Future> previousFuture();
}
private abstract static class Pending extends State {
private final TransactionIdentifier transaction;
private final Future> previousFuture;
Pending(final TransactionIdentifier transaction, final Future> previousFuture) {
this.previousFuture = previousFuture;
this.transaction = requireNonNull(transaction);
}
@Override
final Future> previousFuture() {
return previousFuture;
}
final TransactionIdentifier getIdentifier() {
return transaction;
}
}
private static final class Allocated extends Pending {
Allocated(final TransactionIdentifier transaction, final Future> previousFuture) {
super(transaction, previousFuture);
}
@Override
void checkReady() {
throw new IllegalStateException(String.format("Previous transaction %s is not ready yet", getIdentifier()));
}
}
private static final class Submitted extends Pending {
Submitted(final TransactionIdentifier transaction, final Future> previousFuture) {
super(transaction, previousFuture);
}
@Override
void checkReady() {
// Okay to allocate
}
}
private abstract static class DefaultState extends State {
@Override
final Future> previousFuture() {
return null;
}
}
private static final State IDLE_STATE = new DefaultState() {
@Override
void checkReady() {
// Okay to allocate
}
};
private static final State CLOSED_STATE = new DefaultState() {
@Override
void checkReady() {
throw new DOMTransactionChainClosedException("Transaction chain has been closed");
}
};
private static final Logger LOG = LoggerFactory.getLogger(TransactionChainProxy.class);
private static final AtomicReferenceFieldUpdater STATE_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(TransactionChainProxy.class, State.class, "currentState");
private final TransactionContextFactory parent;
private volatile State currentState = IDLE_STATE;
/**
* This map holds Promise instances for each read-only tx. It is used to maintain ordering of tx creates
* wrt to read-only tx's between this class and a LocalTransactionChain since they're bridged by
* asynchronous futures. Otherwise, in the following scenario, eg:
*
* 1) Create write tx1 on chain
* 2) do write and submit
* 3) Create read-only tx2 on chain and issue read
* 4) Create write tx3 on chain, do write but do not submit
*
* if the sequence/timing is right, tx3 may create its local tx on the LocalTransactionChain before tx2,
* which results in tx2 failing b/c tx3 isn't ready yet. So maintaining ordering prevents this issue
* (see Bug 4774).
*
* A Promise is added via newReadOnlyTransaction. When the parent class completes the primary shard
* lookup and creates the TransactionContext (either success or failure), onTransactionContextCreated is
* called which completes the Promise. A write tx that is created prior to completion will wait on the
* Promise's Future via findPrimaryShard.
*/
private final ConcurrentMap> priorReadOnlyTxPromises =
new ConcurrentHashMap<>();
TransactionChainProxy(final TransactionContextFactory parent, final LocalHistoryIdentifier historyId) {
super(parent.getActorUtils(), historyId);
this.parent = parent;
}
@Override
public DOMStoreReadTransaction newReadOnlyTransaction() {
currentState.checkReady();
TransactionProxy transactionProxy = new TransactionProxy(this, TransactionType.READ_ONLY);
priorReadOnlyTxPromises.put(transactionProxy.getIdentifier(), Futures.