Search in sources :

Example 31 with TransactionIdentifier

use of org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier in project controller by opendaylight.

the class ShardDataTree method applyReplicatedPayload.

/**
 * Apply a payload coming from the leader, which could actually be us. This method assumes the leader and follower
 * SchemaContexts match and does not perform any pruning.
 *
 * @param identifier Payload identifier as returned from RaftActor
 * @param payload Payload
 * @throws IOException when the snapshot fails to deserialize
 * @throws DataValidationFailedException when the snapshot fails to apply
 */
void applyReplicatedPayload(final Identifier identifier, final Payload payload) throws IOException, DataValidationFailedException {
    /*
         * This is a bit more involved than it needs to be due to to the fact we do not want to be touching the payload
         * if we are the leader and it has originated with us.
         *
         * The identifier will only ever be non-null when we were the leader which achieved consensus. Unfortunately,
         * though, this may not be the case anymore, as we are being called some time afterwards and we may not be
         * acting in that capacity anymore.
         *
         * In any case, we know that this is an entry coming from replication, hence we can be sure we will not observe
         * pre-Boron state -- which limits the number of options here.
         */
    if (payload instanceof CommitTransactionPayload) {
        final TransactionIdentifier txId;
        if (identifier == null) {
            final Entry<TransactionIdentifier, DataTreeCandidate> e = ((CommitTransactionPayload) payload).getCandidate();
            txId = e.getKey();
            applyReplicatedCandidate(txId, e.getValue());
        } else {
            Verify.verify(identifier instanceof TransactionIdentifier);
            txId = (TransactionIdentifier) identifier;
            payloadReplicationComplete(txId);
        }
        allMetadataCommittedTransaction(txId);
    } else if (payload instanceof AbortTransactionPayload) {
        if (identifier != null) {
            payloadReplicationComplete((AbortTransactionPayload) payload);
        }
        allMetadataAbortedTransaction(((AbortTransactionPayload) payload).getIdentifier());
    } else if (payload instanceof PurgeTransactionPayload) {
        if (identifier != null) {
            payloadReplicationComplete((PurgeTransactionPayload) payload);
        }
        allMetadataPurgedTransaction(((PurgeTransactionPayload) payload).getIdentifier());
    } else if (payload instanceof CloseLocalHistoryPayload) {
        if (identifier != null) {
            payloadReplicationComplete((CloseLocalHistoryPayload) payload);
        }
        allMetadataClosedLocalHistory(((CloseLocalHistoryPayload) payload).getIdentifier());
    } else if (payload instanceof CreateLocalHistoryPayload) {
        if (identifier != null) {
            payloadReplicationComplete((CreateLocalHistoryPayload) payload);
        }
        allMetadataCreatedLocalHistory(((CreateLocalHistoryPayload) payload).getIdentifier());
    } else if (payload instanceof PurgeLocalHistoryPayload) {
        if (identifier != null) {
            payloadReplicationComplete((PurgeLocalHistoryPayload) payload);
        }
        allMetadataPurgedLocalHistory(((PurgeLocalHistoryPayload) payload).getIdentifier());
    } else {
        LOG.warn("{}: ignoring unhandled identifier {} payload {}", logContext, identifier, payload);
    }
}
Also used : DataTreeCandidate(org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeCandidate) CreateLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.CreateLocalHistoryPayload) CloseLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.CloseLocalHistoryPayload) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) PurgeTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.PurgeTransactionPayload) CommitTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload) PurgeLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.PurgeLocalHistoryPayload) AbortTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.AbortTransactionPayload)

Example 32 with TransactionIdentifier

use of org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier in project controller by opendaylight.

the class ShardDataTree method startCommit.

void startCommit(final SimpleShardDataTreeCohort cohort, final DataTreeCandidate candidate) {
    final CommitEntry entry = pendingCommits.peek();
    Preconditions.checkState(entry != null, "Attempted to start commit of %s when no transactions pending", cohort);
    final SimpleShardDataTreeCohort current = entry.cohort;
    if (!cohort.equals(current)) {
        LOG.debug("{}: Transaction {} scheduled for commit step", logContext, cohort.getIdentifier());
        return;
    }
    LOG.debug("{}: Starting commit for transaction {}", logContext, current.getIdentifier());
    final TransactionIdentifier txId = cohort.getIdentifier();
    final Payload payload;
    try {
        payload = CommitTransactionPayload.create(txId, candidate);
    } catch (IOException e) {
        LOG.error("{}: Failed to encode transaction {} candidate {}", logContext, txId, candidate, e);
        pendingCommits.poll().cohort.failedCommit(e);
        processNextPending();
        return;
    }
    // We process next transactions pending canCommit before we call persistPayload to possibly progress subsequent
    // transactions to the COMMIT_PENDING state so the payloads can be batched for replication. This is done for
    // single-shard transactions that immediately transition from canCommit to preCommit to commit. Note that
    // if the next pending transaction is progressed to COMMIT_PENDING and this method (startCommit) is called,
    // the next transaction will not attempt to replicate b/c the current transaction is still at the head of the
    // pendingCommits queue.
    processNextPendingTransaction();
    // After processing next pending transactions, we can now remove the current transaction from pendingCommits.
    // Note this must be done before the call to peekNextPendingCommit below so we check the next transaction
    // in order to properly determine the batchHint flag for the call to persistPayload.
    pendingCommits.remove();
    pendingFinishCommits.add(entry);
    // See if the next transaction is pending commit (ie in the COMMIT_PENDING state) so it can be batched with
    // this transaction for replication.
    boolean replicationBatchHint = peekNextPendingCommit();
    // Once completed, we will continue via payloadReplicationComplete
    shard.persistPayload(txId, payload, replicationBatchHint);
    entry.lastAccess = shard.ticker().read();
    LOG.debug("{}: Transaction {} submitted to persistence", logContext, txId);
    // Process the next transaction pending commit, if any. If there is one it will be batched with this
    // transaction for replication.
    processNextPendingCommit();
}
Also used : TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier) CommitTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.CommitTransactionPayload) CloseLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.CloseLocalHistoryPayload) AbortTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.AbortTransactionPayload) PurgeLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.PurgeLocalHistoryPayload) AbstractIdentifiablePayload(org.opendaylight.controller.cluster.datastore.persisted.AbstractIdentifiablePayload) CreateLocalHistoryPayload(org.opendaylight.controller.cluster.datastore.persisted.CreateLocalHistoryPayload) PurgeTransactionPayload(org.opendaylight.controller.cluster.datastore.persisted.PurgeTransactionPayload) Payload(org.opendaylight.controller.cluster.raft.protobuff.client.messages.Payload) IOException(java.io.IOException)

Example 33 with TransactionIdentifier

use of org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier in project controller by opendaylight.

the class AbstractFrontendHistory method handleTransactionPurgeRequest.

private TransactionSuccess<?> 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());
    }
    // 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;
}
Also used : TransactionPurgeResponse(org.opendaylight.controller.cluster.access.commands.TransactionPurgeResponse) UnsignedLong(com.google.common.primitives.UnsignedLong) TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)

Example 34 with TransactionIdentifier

use of org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier in project controller by opendaylight.

the class ProxyHistory method createTransactionProxy.

AbstractProxyTransaction createTransactionProxy(final TransactionIdentifier txId, final boolean snapshotOnly, final boolean isDone) {
    lock.lock();
    try {
        if (successor != null) {
            return successor.createTransactionProxy(txId, snapshotOnly, isDone);
        }
        final TransactionIdentifier proxyId = new TransactionIdentifier(identifier, txId.getTransactionId());
        final AbstractProxyTransaction ret = doCreateTransactionProxy(connection, proxyId, snapshotOnly, isDone);
        proxies.put(proxyId, ret);
        LOG.debug("Allocated proxy {} for transaction {}", proxyId, txId);
        return ret;
    } finally {
        lock.unlock();
    }
}
Also used : TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)

Example 35 with TransactionIdentifier

use of org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier in project controller by opendaylight.

the class SingleClientHistory method doCreateSnapshot.

@Override
ClientSnapshot doCreateSnapshot() {
    final TransactionIdentifier txId = new TransactionIdentifier(getIdentifier(), nextTx());
    LOG.debug("{}: creating a new snapshot {}", this, txId);
    return new ClientSnapshot(this, txId);
}
Also used : TransactionIdentifier(org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)

Aggregations

TransactionIdentifier (org.opendaylight.controller.cluster.access.concepts.TransactionIdentifier)57 Test (org.junit.Test)37 FiniteDuration (scala.concurrent.duration.FiniteDuration)17 CanCommitTransaction (org.opendaylight.controller.cluster.datastore.messages.CanCommitTransaction)16 CommitTransaction (org.opendaylight.controller.cluster.datastore.messages.CommitTransaction)12 DataTreeModification (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTreeModification)11 CanCommitTransactionReply (org.opendaylight.controller.cluster.datastore.messages.CanCommitTransactionReply)10 ActorRef (akka.actor.ActorRef)8 FollowerInitialSyncUpStatus (org.opendaylight.controller.cluster.raft.base.messages.FollowerInitialSyncUpStatus)8 YangInstanceIdentifier (org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier)8 BatchedModifications (org.opendaylight.controller.cluster.datastore.messages.BatchedModifications)7 WriteModification (org.opendaylight.controller.cluster.datastore.modification.WriteModification)7 ContainerNode (org.opendaylight.yangtools.yang.data.api.schema.ContainerNode)7 DataTree (org.opendaylight.yangtools.yang.data.api.schema.tree.DataTree)7 LocalHistoryIdentifier (org.opendaylight.controller.cluster.access.concepts.LocalHistoryIdentifier)6 CanCommit (org.opendaylight.controller.cluster.datastore.DataTreeCohortActor.CanCommit)6 Failure (akka.actor.Status.Failure)5 Timeout (akka.util.Timeout)5 Response (org.opendaylight.controller.cluster.access.concepts.Response)5 ReadyLocalTransaction (org.opendaylight.controller.cluster.datastore.messages.ReadyLocalTransaction)5