use of org.voltdb.dtxn.TransactionState in project voltdb by VoltDB.
the class SpScheduler method handleFragmentResponseMessage.
// Eventually, the master for a partition set will need to be able to dedupe
// FragmentResponses from its replicas.
private void handleFragmentResponseMessage(FragmentResponseMessage message) {
final TransactionState txnState = m_outstandingTxns.get(message.getTxnId());
final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.SPI);
// Send the message to the duplicate counter, if any
DuplicateCounter counter = m_duplicateCounters.get(new DuplicateCounterKey(message.getTxnId(), message.getSpHandle()));
final TransactionState txn = m_outstandingTxns.get(message.getTxnId());
if (counter != null) {
String traceName = "recvfragment";
if (message.m_sourceHSId != m_mailbox.getHSId()) {
traceName = "replicatefragment";
}
String finalTraceName = traceName;
if (traceLog != null) {
traceLog.add(() -> VoltTrace.endAsync(finalTraceName, MiscUtils.hsIdPairTxnIdToString(m_mailbox.getHSId(), message.m_sourceHSId, message.getSpHandle(), message.getTxnId()), "status", message.getStatusCode()));
}
int result = counter.offer(message);
if (result == DuplicateCounter.DONE) {
if (txn != null && txn.isDone()) {
setRepairLogTruncationHandle(txn.m_spHandle);
}
m_duplicateCounters.remove(new DuplicateCounterKey(message.getTxnId(), message.getSpHandle()));
FragmentResponseMessage resp = (FragmentResponseMessage) counter.getLastResponse();
// MPI is tracking deps per partition HSID. We need to make
// sure we write ours into the message getting sent to the MPI
resp.setExecutorSiteId(m_mailbox.getHSId());
m_mailbox.send(counter.m_destinationId, resp);
} else if (result == DuplicateCounter.MISMATCH) {
VoltDB.crashGlobalVoltDB("HASH MISMATCH running multi-part procedure.", true, null);
} else if (result == DuplicateCounter.ABORT) {
VoltDB.crashGlobalVoltDB("PARTIAL ROLLBACK/ABORT running multi-part procedure.", true, null);
}
// doing duplicate suppression: all done.
return;
}
// K-safety: read-only queries (on master) or write queries (on replica).
if (m_defaultConsistencyReadLevel == ReadLevel.SAFE && m_isLeader && m_sendToHSIds.length > 0 && message.getRespBufferable() && (txn == null || txn.isReadOnly())) {
// on k-safety leader with safe reads configuration: one shot reads + normal multi-fragments MP reads
// we will have to buffer these reads until previous writes acked in the cluster.
long readTxnId = txn == null ? message.getSpHandle() : txn.m_spHandle;
m_bufferedReadLog.offer(m_mailbox, message, readTxnId, m_repairLogTruncationHandle);
return;
}
// for complete writes txn, we will advance the transaction point
if (txn != null && !txn.isReadOnly() && txn.isDone()) {
setRepairLogTruncationHandle(txn.m_spHandle);
}
if (traceLog != null) {
traceLog.add(() -> VoltTrace.endAsync("recvfragment", MiscUtils.hsIdPairTxnIdToString(m_mailbox.getHSId(), message.m_sourceHSId, message.getSpHandle(), message.getTxnId()), "status", message.getStatusCode()));
}
m_mailbox.send(message.getDestinationSiteId(), message);
}
use of org.voltdb.dtxn.TransactionState in project voltdb by VoltDB.
the class TransactionTaskQueue method offer.
/**
* If necessary, stick this task in the backlog.
* Many network threads may be racing to reach here, synchronize to
* serialize queue order
* @param task
* @return true if this task was stored, false if not
*/
synchronized boolean offer(TransactionTask task) {
Iv2Trace.logTransactionTaskQueueOffer(task);
TransactionState txnState = task.getTransactionState();
boolean retval = false;
if (!m_backlog.isEmpty()) {
/*
* This branch happens during regular execution when a multi-part is in progress.
* The first task for the multi-part is the head of the queue, and all the single parts
* are being queued behind it. The txnid check catches tasks that are part of the multi-part
* and immediately queues them for execution.
*/
if (task.getTxnId() != m_backlog.getFirst().getTxnId()) {
m_backlog.addLast(task);
retval = true;
} else {
taskQueueOffer(task);
}
} else {
/*
* Base case nothing queued nothing in progress
* If the task is a multipart then put an entry in the backlog which
* will act as a barrier for single parts, queuing them for execution after the
* multipart
*/
if (!txnState.isSinglePartition()) {
m_backlog.addLast(task);
retval = true;
}
taskQueueOffer(task);
}
return retval;
}
use of org.voltdb.dtxn.TransactionState in project voltdb by VoltDB.
the class SpScheduler method handleBorrowTaskMessage.
// BorrowTaskMessages encapsulate a FragmentTaskMessage along with
// input dependency tables. The MPI issues borrows to a local site
// to perform replicated reads or aggregation fragment work.
private void handleBorrowTaskMessage(BorrowTaskMessage message) {
// borrows do not advance the sp handle. The handle would
// move backwards anyway once the next message is received
// from the SP leader.
long newSpHandle = getMaxScheduledTxnSpHandle();
Iv2Trace.logFragmentTaskMessage(message.getFragmentTaskMessage(), m_mailbox.getHSId(), newSpHandle, true);
final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.SPI);
if (traceLog != null) {
traceLog.add(() -> VoltTrace.beginAsync("recvfragment", MiscUtils.hsIdPairTxnIdToString(m_mailbox.getHSId(), m_mailbox.getHSId(), newSpHandle, 0), "txnId", TxnEgo.txnIdToString(message.getTxnId()), "partition", m_partitionId, "hsId", CoreUtils.hsIdToString(m_mailbox.getHSId())));
}
TransactionState txn = m_outstandingTxns.get(message.getTxnId());
if (txn == null) {
// If the borrow is the first fragment for a transaction, run it as
// a single partition fragment; Must not engage/pause this
// site on a MP transaction before the SP instructs to do so.
// Do not track the borrow task as outstanding - it completes
// immediately and is not a valid transaction state for
// full MP participation (it claims everything can run as SP).
txn = new BorrowTransactionState(newSpHandle, message);
}
// and its response (FragmentResponseMessage) should not be buffered
if (message.getFragmentTaskMessage().isSysProcTask()) {
final SysprocFragmentTask task = new SysprocFragmentTask(m_mailbox, (ParticipantTransactionState) txn, m_pendingTasks, message.getFragmentTaskMessage(), message.getInputDepMap());
task.setResponseNotBufferable();
m_pendingTasks.offer(task);
} else {
final FragmentTask task = new FragmentTask(m_mailbox, (ParticipantTransactionState) txn, m_pendingTasks, message.getFragmentTaskMessage(), message.getInputDepMap());
task.setResponseNotBufferable();
m_pendingTasks.offer(task);
}
}
use of org.voltdb.dtxn.TransactionState in project voltdb by VoltDB.
the class SpScheduler method handleCompleteTransactionResponseMessage.
private void handleCompleteTransactionResponseMessage(CompleteTransactionResponseMessage msg) {
final DuplicateCounterKey duplicateCounterKey = new DuplicateCounterKey(msg.getTxnId(), msg.getSpHandle());
DuplicateCounter counter = m_duplicateCounters.get(duplicateCounterKey);
boolean txnDone = true;
if (msg.isRestart()) {
// Don't mark txn done for restarts
txnDone = false;
}
if (counter != null) {
txnDone = counter.offer(msg) == DuplicateCounter.DONE;
}
if (txnDone) {
assert !msg.isRestart();
final TransactionState txn = m_outstandingTxns.remove(msg.getTxnId());
m_duplicateCounters.remove(duplicateCounterKey);
if (txn != null) {
// fragment is done before the MP txn is fully committed.
assert txn.isDone() : "Counter " + counter + ", leader " + m_isLeader + ", " + msg;
setRepairLogTruncationHandle(txn.m_spHandle);
}
}
// committed the transaction.
if (!m_isLeader) {
m_mailbox.send(msg.getSPIHSId(), msg);
}
}
Aggregations