public ListenableFuture<Boolean> canCommit() {
try {
dataTree.getDataTree().validate(dataTreeModification());
- LOG.debug("Transaction {} validated", transaction);
+ LOG.trace("Transaction {} validated", transaction);
return TRUE_FUTURE;
} catch (Exception e) {
return Futures.immediateFailedFuture(e);
* FIXME: this is the place where we should be interacting with persistence, specifically by invoking
* persist on the candidate (which gives us a Future).
*/
- LOG.debug("Transaction {} prepared candidate {}", transaction, candidate);
+ LOG.trace("Transaction {} prepared candidate {}", transaction, candidate);
return VOID_FUTURE;
} catch (Exception e) {
LOG.debug("Transaction {} failed to prepare", transaction, e);
return Futures.immediateFailedFuture(e);
}
- LOG.debug("Transaction {} committed, proceeding to notify", transaction);
+ LOG.trace("Transaction {} committed, proceeding to notify", transaction);
dataTree.notifyListeners(candidate);
return VOID_FUTURE;
}
import java.util.Collection;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+import org.opendaylight.controller.cluster.datastore.identifiers.TransactionChainIdentifier;
import org.opendaylight.controller.cluster.datastore.identifiers.TransactionIdentifier;
import org.opendaylight.controller.cluster.datastore.messages.CloseTransactionChain;
import org.opendaylight.controller.cluster.datastore.messages.PrimaryShardInfo;
private static final AtomicReferenceFieldUpdater<TransactionChainProxy, State> STATE_UPDATER =
AtomicReferenceFieldUpdater.newUpdater(TransactionChainProxy.class, State.class, "currentState");
- private final String transactionChainId;
+ private final TransactionChainIdentifier transactionChainId;
private final TransactionContextFactory parent;
private volatile State currentState = IDLE_STATE;
TransactionChainProxy(final TransactionContextFactory parent) {
super(parent.getActorContext());
- transactionChainId = parent.getActorContext().getCurrentMemberName() + "-txn-chain-" + CHAIN_COUNTER.incrementAndGet();
+
+ transactionChainId = new TransactionChainIdentifier(parent.getActorContext().getCurrentMemberName(), CHAIN_COUNTER.incrementAndGet());
this.parent = parent;
}
public String getTransactionChainId() {
- return transactionChainId;
+ return transactionChainId.toString();
}
@Override
currentState = CLOSED_STATE;
// Send a close transaction chain request to each and every shard
- getActorContext().broadcast(new CloseTransactionChain(transactionChainId).toSerializable());
+ getActorContext().broadcast(new CloseTransactionChain(transactionChainId.toString()).toSerializable());
}
private TransactionProxy allocateWriteTransaction(final TransactionType type) {
return parent.findPrimaryShard(shardName);
}
- LOG.debug("Waiting for ready futures for on chain {}", getTransactionChainId());
+ final String previousTransactionId;
+
+ if(localState instanceof Pending){
+ previousTransactionId = ((Pending) localState).getIdentifier().toString();
+ LOG.debug("Waiting for ready futures with pending Tx {}", previousTransactionId);
+ } else {
+ previousTransactionId = "";
+ LOG.debug("Waiting for ready futures on chain {}", getTransactionChainId());
+ }
// Add a callback for completion of the combined Futures.
final Promise<PrimaryShardInfo> returnPromise = akka.dispatch.Futures.promise();
public void onComplete(final Throwable failure, final Object notUsed) {
if (failure != null) {
// A Ready Future failed so fail the returned Promise.
+ LOG.error("Ready future failed for Tx {}", previousTransactionId);
returnPromise.failure(failure);
} else {
- LOG.debug("Previous Tx readied - proceeding to FindPrimaryShard on chain {}",
- getTransactionChainId());
+ LOG.debug("Previous Tx {} readied - proceeding to FindPrimaryShard",
+ previousTransactionId);
// Send the FindPrimaryShard message and use the resulting Future to complete the
// returned Promise.
@Override
protected TransactionIdentifier nextIdentifier() {
- return TransactionIdentifier.create(getMemberName(), TX_COUNTER.getAndIncrement(), transactionChainId);
+ return transactionChainId.newTransactionIdentifier();
}
}
@Override
protected TransactionIdentifier nextIdentifier() {
- return TransactionIdentifier.create(getMemberName(), TX_COUNTER.getAndIncrement(), null);
+ return TransactionIdentifier.create(getMemberName(), TX_COUNTER.getAndIncrement());
}
@Override
package org.opendaylight.controller.cluster.datastore.identifiers;
import com.google.common.base.Preconditions;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
/**
* A TransactionIdentifier which is tied to a backend transaction chain.
*/
public class ChainedTransactionIdentifier extends TransactionIdentifier {
private final String chainId;
+ private Supplier<String> stringRepresentation;
- public ChainedTransactionIdentifier(final String memberName, final long counter, final String chainId) {
- super(memberName, counter);
- this.chainId = Preconditions.checkNotNull(chainId);
+ public ChainedTransactionIdentifier(final TransactionChainIdentifier chainId, final long txnCounter) {
+ super(chainId.getMemberName(), txnCounter);
+ Preconditions.checkNotNull(chainId);
+ this.chainId = chainId.toString();
+ stringRepresentation = Suppliers.memoize(new Supplier<String>() {
+ @Override
+ public String get() {
+ return new StringBuilder(chainId.toString().length() + TX_SEPARATOR.length() + 10).
+ append(chainId).append(TX_SEPARATOR).append(getCounter()).toString();
+ }
+ });
}
+
@Override
public String getChainId() {
return chainId;
}
+
+ @Override
+ public String toString() {
+ return stringRepresentation.get();
+ }
+
}
--- /dev/null
+/*
+ * 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.identifiers;
+
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import java.util.concurrent.atomic.AtomicLong;
+
+public class TransactionChainIdentifier {
+
+ protected static final String CHAIN_SEPARATOR = "-chn-";
+
+ private final AtomicLong txnCounter = new AtomicLong();
+ private final Supplier<String> stringRepresentation;
+ private final String memberName;
+
+ public TransactionChainIdentifier(final String memberName, final long counter) {
+ this.memberName = memberName;
+ stringRepresentation = Suppliers.memoize(new Supplier<String>() {
+ @Override
+ public String get() {
+ final StringBuilder sb = new StringBuilder();
+ sb.append(memberName).append(CHAIN_SEPARATOR);
+ sb.append(counter);
+ return sb.toString();
+ }
+ });
+ }
+ @Override
+ public String toString() {
+ return stringRepresentation.get();
+ }
+
+ public TransactionIdentifier newTransactionIdentifier(){
+ return new ChainedTransactionIdentifier(this, txnCounter.incrementAndGet());
+ }
+
+ public String getMemberName() {
+ return memberName;
+ }
+}
package org.opendaylight.controller.cluster.datastore.identifiers;
import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
public class TransactionIdentifier {
- private static final String TX_SEPARATOR = "-txn-";
+ protected static final String TX_SEPARATOR = "-txn-";
+
+ protected String getMemberName() {
+ return memberName;
+ }
+
+ protected long getCounter() {
+ return counter;
+ }
private final String memberName;
private final long counter;
return "";
}
- public static TransactionIdentifier create(String memberName, long counter, String chainId) {
- if (Strings.isNullOrEmpty(chainId)) {
- return new TransactionIdentifier(memberName, counter);
- } else {
- return new ChainedTransactionIdentifier(memberName, counter, chainId);
- }
+ public static TransactionIdentifier create(String memberName, long counter) {
+ return new TransactionIdentifier(memberName, counter);
}
@Override
return stringRepresentation;
}
+
}
List<Future<Object>> expCohortFutures = new ArrayList<>();
doReturn(expCohortFutures).when(mockDelegate).getCohortFutures();
- TransactionIdentifier transactionId = TransactionIdentifier.create("1", 1, "");
+ TransactionIdentifier transactionId = TransactionIdentifier.create("1", 1);
Throwable debugContext = new RuntimeException("mock");
DebugThreePhaseCommitCohort cohort = new DebugThreePhaseCommitCohort(transactionId , mockDelegate , debugContext );
verifyOneBatchedModification(txActorRef1, new WriteModification(TestModel.TEST_PATH, writeNode1), true);
- String tx2MemberName = "tx2MemberName";
- doReturn(tx2MemberName).when(mockActorContext).getCurrentMemberName();
+ String tx2MemberName = "mock-member";
ActorRef shardActorRef2 = setupActorContextWithoutInitialCreateTransaction(getSystem());
ActorRef txActorRef2 = setupActorContextWithInitialCreateTransaction(getSystem(), READ_WRITE,
DataStoreVersions.CURRENT_VERSION, tx2MemberName, shardActorRef2);
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.identifiers;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class ChainedTransactionIdentifierTest {
+
+ @Test
+ public void testToString(){
+ TransactionChainIdentifier chainId = new TransactionChainIdentifier("member-1", 99);
+ ChainedTransactionIdentifier chainedTransactionIdentifier = new ChainedTransactionIdentifier(chainId, 100);
+
+ String txnId = chainedTransactionIdentifier.toString();
+
+ assertTrue(txnId.contains("member-1"));
+ assertTrue(txnId.contains("100"));
+ assertTrue(txnId.contains("99"));
+
+ assertEquals("member-1-chn-99-txn-100", txnId);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.opendaylight.controller.cluster.datastore.identifiers;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class TransactionChainIdentifierTest {
+ @Test
+ public void testToString(){
+ TransactionChainIdentifier transactionChainIdentifier = new TransactionChainIdentifier("member-1", 99);
+
+ String id = transactionChainIdentifier.toString();
+
+ assertEquals("member-1-chn-99", id);
+ }
+
+ @Test
+ public void testNewTransactionIdentifier(){
+ TransactionChainIdentifier transactionChainIdentifier = new TransactionChainIdentifier("member-1", 99);
+
+ TransactionIdentifier txId1 = transactionChainIdentifier.newTransactionIdentifier();
+
+ assertEquals("member-1-chn-99-txn-1", txId1.toString());
+
+ TransactionIdentifier txId2 = transactionChainIdentifier.newTransactionIdentifier();
+
+ assertEquals("member-1-chn-99-txn-2", txId2.toString());
+ }
+
+}
\ No newline at end of file