X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-distributed-datastore%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fcluster%2Fdatastore%2FAbstractFrontendHistory.java;h=072f8ede80c978987e78767f0df019f56efa6438;hb=7ad6a27e9b98861d9286977320198375a44a38f1;hp=1aad9e99823540ab9fd53fe9f8c89a82e67e3054;hpb=f984aadefd56f48aec345b8b7cc7ddf27b794f56;p=controller.git diff --git a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractFrontendHistory.java b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractFrontendHistory.java index 1aad9e9982..072f8ede80 100644 --- a/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractFrontendHistory.java +++ b/opendaylight/md-sal/sal-distributed-datastore/src/main/java/org/opendaylight/controller/cluster/datastore/AbstractFrontendHistory.java @@ -16,6 +16,7 @@ import com.google.common.primitives.UnsignedLong; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.SortedSet; import javax.annotation.Nullable; import org.opendaylight.controller.cluster.access.commands.AbstractReadTransactionRequest; import org.opendaylight.controller.cluster.access.commands.ClosedTransactionException; @@ -73,53 +74,15 @@ abstract class AbstractFrontendHistory implements Identifiable handleTransactionRequest(final TransactionRequest request, + @Nullable + final TransactionSuccess handleTransactionRequest(final TransactionRequest request, final RequestEnvelope envelope, final long now) throws RequestException { - final TransactionIdentifier id = request.getTarget(); - final UnsignedLong ul = UnsignedLong.fromLongBits(id.getTransactionId()); - if (request instanceof TransactionPurgeRequest) { - if (purgedTransactions.contains(ul)) { - // Retransmitted purge request: nothing to do - LOG.debug("{}: transaction {} already purged", persistenceId, id); - return new TransactionPurgeResponse(id, request.getSequence()); - } - - // We perform two lookups instead of a straight remove, because once the map becomes empty we switch it - // to an ImmutableMap, which does not allow remove(). - if (closedTransactions.containsKey(ul)) { - tree.purgeTransaction(id, () -> { - closedTransactions.remove(ul); - if (closedTransactions.isEmpty()) { - closedTransactions = ImmutableMap.of(); - } - - purgedTransactions.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); - LOG.debug("{}: finished purging inherited transaction {}", persistenceId(), id); - envelope.sendSuccess(new TransactionPurgeResponse(id, request.getSequence()), readTime() - now); - }); - return null; - } - - final FrontendTransaction tx = transactions.get(id); - if (tx == null) { - // This should never happen because the purge callback removes the transaction and puts it into - // purged transactions in one go. If it does, we warn about the situation and - LOG.warn("{}: transaction {} not tracked in {}, but not present in active transactions", persistenceId, - id, purgedTransactions); - purgedTransactions.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); - return new TransactionPurgeResponse(id, request.getSequence()); - } - - tree.purgeTransaction(id, () -> { - purgedTransactions.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); - transactions.remove(id); - LOG.debug("{}: finished purging transaction {}", persistenceId(), id); - envelope.sendSuccess(new TransactionPurgeResponse(id, request.getSequence()), readTime() - now); - }); - return null; + return handleTransactionPurgeRequest(request, envelope, now); } + final TransactionIdentifier id = request.getTarget(); + final UnsignedLong ul = UnsignedLong.fromLongBits(id.getTransactionId()); if (purgedTransactions.contains(ul)) { LOG.warn("{}: Request {} is contained purged transactions {}", persistenceId, request, purgedTransactions); throw new DeadTransactionException(purgedTransactions); @@ -154,31 +117,80 @@ abstract class AbstractFrontendHistory implements Identifiable handleTransactionPurgeRequest(final TransactionRequest request, + final RequestEnvelope envelope, final long now) { + final TransactionIdentifier id = request.getTarget(); + final UnsignedLong ul = UnsignedLong.fromLongBits(id.getTransactionId()); + if (purgedTransactions.contains(ul)) { + // Retransmitted purge request: nothing to do + LOG.debug("{}: transaction {} already purged", persistenceId, id); + return new TransactionPurgeResponse(id, request.getSequence()); + } + + // We perform two lookups instead of a straight remove, because once the map becomes empty we switch it + // to an ImmutableMap, which does not allow remove(). + if (closedTransactions.containsKey(ul)) { + tree.purgeTransaction(id, () -> { + closedTransactions.remove(ul); + if (closedTransactions.isEmpty()) { + closedTransactions = ImmutableMap.of(); + } + + purgedTransactions.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); + LOG.debug("{}: finished purging inherited transaction {}", persistenceId(), id); + envelope.sendSuccess(new TransactionPurgeResponse(id, request.getSequence()), readTime() - now); + }); + return null; + } + + final FrontendTransaction tx = transactions.get(id); + if (tx == null) { + // This should never happen because the purge callback removes the transaction and puts it into + // purged transactions in one go. If it does, we warn about the situation and + LOG.warn("{}: transaction {} not tracked in {}, but not present in active transactions", persistenceId, + id, purgedTransactions); + purgedTransactions.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); + return new TransactionPurgeResponse(id, request.getSequence()); + } + + tree.purgeTransaction(id, () -> { + purgedTransactions.add(Range.closedOpen(ul, UnsignedLong.ONE.plus(ul))); + transactions.remove(id); + LOG.debug("{}: finished purging transaction {}", persistenceId(), id); + envelope.sendSuccess(new TransactionPurgeResponse(id, request.getSequence()), readTime() - now); + }); + + return null; + } + + final void destroy(final long sequence, final RequestEnvelope envelope, final long now) { LOG.debug("{}: closing history {}", persistenceId(), getIdentifier()); tree.closeTransactionChain(getIdentifier(), () -> envelope.sendSuccess(new LocalHistorySuccess(getIdentifier(), sequence), readTime() - now)); } - void purge(final long sequence, final RequestEnvelope envelope, final long now) { + final void purge(final long sequence, final RequestEnvelope envelope, final long now) { LOG.debug("{}: purging history {}", persistenceId(), getIdentifier()); tree.purgeTransactionChain(getIdentifier(), () -> envelope.sendSuccess(new LocalHistorySuccess(getIdentifier(), sequence), readTime() - now)); } - private FrontendTransaction createTransaction(final TransactionRequest request, final TransactionIdentifier id) - throws RequestException { + final void retire() { + transactions.values().forEach(FrontendTransaction::retire); + tree.removeTransactionChain(getIdentifier()); + } + + private FrontendTransaction createTransaction(final TransactionRequest request, final TransactionIdentifier id) { if (request instanceof CommitLocalTransactionRequest) { LOG.debug("{}: allocating new ready transaction {}", persistenceId(), id); tree.getStats().incrementReadWriteTransactionCount(); return createReadyTransaction(id, ((CommitLocalTransactionRequest) request).getModification()); } - if (request instanceof AbstractReadTransactionRequest) { - if (((AbstractReadTransactionRequest) request).isSnapshotOnly()) { - LOG.debug("{}: allocating new open snapshot {}", persistenceId(), id); - tree.getStats().incrementReadOnlyTransactionCount(); - return createOpenSnapshot(id); - } + if (request instanceof AbstractReadTransactionRequest + && ((AbstractReadTransactionRequest) request).isSnapshotOnly()) { + LOG.debug("{}: allocating new open snapshot {}", persistenceId(), id); + tree.getStats().incrementReadOnlyTransactionCount(); + return createOpenSnapshot(id); } LOG.debug("{}: allocating new open transaction {}", persistenceId(), id); @@ -186,17 +198,18 @@ abstract class AbstractFrontendHistory implements Identifiable> participatingShardNames); @Override public String toString() {