use of org.voltdb.messaging.Iv2InitiateTaskMessage in project voltdb by VoltDB.
the class InvocationDispatcher method createTransaction.
// Wrap API to SimpleDtxnInitiator - mostly for the future
public boolean createTransaction(final long connectionId, final long txnId, final long uniqueId, final StoredProcedureInvocation invocation, final boolean isReadOnly, final boolean isSinglePartition, final boolean isEveryPartition, final int partition, final int messageSize, long nowNanos, final boolean isForReplay) {
assert (!isSinglePartition || (partition >= 0));
final ClientInterfaceHandleManager cihm = m_cihm.get(connectionId);
if (cihm == null) {
hostLog.rateLimitedLog(60, Level.WARN, null, "InvocationDispatcher.createTransaction request rejected. " + "This is likely due to VoltDB ceasing client communication as it " + "shuts down.");
return false;
}
Long initiatorHSId = null;
boolean isShortCircuitRead = false;
/*
* ReadLevel.FAST:
* If this is a read only single part, check if there is a local replica,
* if there is, send it to the replica as a short circuit read
*
* ReadLevel.SAFE:
* Send the read to the partition leader only
*/
if (isSinglePartition && !isEveryPartition) {
if (isReadOnly && (m_defaultConsistencyReadLevel == ReadLevel.FAST)) {
initiatorHSId = m_localReplicas.get().get(partition);
}
if (initiatorHSId != null) {
isShortCircuitRead = true;
} else {
initiatorHSId = m_cartographer.getHSIdForSinglePartitionMaster(partition);
}
} else {
// Multi-part transactions go to the multi-part coordinator
initiatorHSId = m_cartographer.getHSIdForMultiPartitionInitiator();
// from their arrival order due to the MP Read-only execution pool
if (isReadOnly) {
isShortCircuitRead = true;
}
}
long handle = cihm.getHandle(isSinglePartition, partition, invocation.getClientHandle(), messageSize, nowNanos, invocation.getProcName(), initiatorHSId, isReadOnly, isShortCircuitRead);
Iv2InitiateTaskMessage workRequest = new Iv2InitiateTaskMessage(m_siteId, initiatorHSId, Iv2InitiateTaskMessage.UNUSED_TRUNC_HANDLE, txnId, uniqueId, isReadOnly, isSinglePartition, invocation, handle, connectionId, isForReplay);
Long finalInitiatorHSId = initiatorHSId;
final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.CI);
if (traceLog != null) {
traceLog.add(() -> VoltTrace.instantAsync("inittxn", invocation.getClientHandle(), "clientHandle", Long.toString(invocation.getClientHandle()), "ciHandle", Long.toString(handle), "partition", Integer.toString(partition), "dest", CoreUtils.hsIdToString(finalInitiatorHSId)));
}
Iv2Trace.logCreateTransaction(workRequest);
m_mailbox.send(initiatorHSId, workRequest);
return true;
}
use of org.voltdb.messaging.Iv2InitiateTaskMessage in project voltdb by VoltDB.
the class MpScheduler method handleIv2InitiateTaskMessage.
// MpScheduler expects to see initiations for multipartition procedures and
// system procedures which are "every-partition", meaning that they run as
// single-partition procedures at every partition, and the results are
// aggregated/deduped here at the MPI.
public void handleIv2InitiateTaskMessage(Iv2InitiateTaskMessage message) {
final String procedureName = message.getStoredProcedureName();
/*
* If this is CL replay, use the txnid from the CL and use it to update the current txnid
*/
long mpTxnId;
//Timestamp is actually a pre-IV2ish style time based transaction id
long timestamp = Long.MIN_VALUE;
// Update UID if it's for replay
if (message.isForReplay()) {
timestamp = message.getUniqueId();
m_uniqueIdGenerator.updateMostRecentlyGeneratedUniqueId(timestamp);
} else {
timestamp = m_uniqueIdGenerator.getNextUniqueId();
}
TxnEgo ego = advanceTxnEgo();
mpTxnId = ego.getTxnId();
// Thread name has to be materialized here
final String threadName = Thread.currentThread().getName();
final VoltTrace.TraceEventBatch traceLog = VoltTrace.log(VoltTrace.Category.MPI);
if (traceLog != null) {
traceLog.add(() -> VoltTrace.meta("process_name", "name", CoreUtils.getHostnameOrAddress())).add(() -> VoltTrace.meta("thread_name", "name", threadName)).add(() -> VoltTrace.meta("thread_sort_index", "sort_index", Integer.toString(100))).add(() -> VoltTrace.beginAsync("initmp", mpTxnId, "txnId", TxnEgo.txnIdToString(mpTxnId), "ciHandle", message.getClientInterfaceHandle(), "name", procedureName, "read", message.isReadOnly()));
}
// Don't have an SP HANDLE at the MPI, so fill in the unused value
Iv2Trace.logIv2InitiateTaskMessage(message, m_mailbox.getHSId(), mpTxnId, Long.MIN_VALUE);
// Handle every-site system procedures (at the MPI)
final Config sysprocConfig = SystemProcedureCatalog.listing.get(procedureName);
if (sysprocConfig != null && sysprocConfig.getEverysite()) {
// Send an SP initiate task to all remote sites
final Long localId = m_mailbox.getHSId();
Iv2InitiateTaskMessage sp = new Iv2InitiateTaskMessage(// make the MPI the initiator.
localId, message.getCoordinatorHSId(), m_repairLogTruncationHandle, mpTxnId, timestamp, message.isReadOnly(), // isSinglePartition
true, message.getStoredProcedureInvocation(), message.getClientInterfaceHandle(), message.getConnectionId(), message.isForReplay());
DuplicateCounter counter = new DuplicateCounter(message.getInitiatorHSId(), mpTxnId, m_iv2Masters, message);
safeAddToDuplicateCounterMap(mpTxnId, counter);
EveryPartitionTask eptask = new EveryPartitionTask(m_mailbox, m_pendingTasks, sp, m_iv2Masters);
m_pendingTasks.offer(eptask);
return;
}
// Create a copy so we can overwrite the txnID so the InitiateResponse will be
// correctly tracked.
Iv2InitiateTaskMessage mp = new Iv2InitiateTaskMessage(message.getInitiatorHSId(), message.getCoordinatorHSId(), m_repairLogTruncationHandle, mpTxnId, timestamp, message.isReadOnly(), message.isSinglePartition(), message.getStoredProcedureInvocation(), message.getClientInterfaceHandle(), message.getConnectionId(), message.isForReplay());
// Multi-partition initiation (at the MPI)
MpProcedureTask task = null;
if (isNpTxn(message) && NpProcedureTaskConstructor != null) {
Set<Integer> involvedPartitions = getBalancePartitions(message);
if (involvedPartitions != null) {
HashMap<Integer, Long> involvedPartitionMasters = Maps.newHashMap(m_partitionMasters);
involvedPartitionMasters.keySet().retainAll(involvedPartitions);
task = instantiateNpProcedureTask(m_mailbox, procedureName, m_pendingTasks, mp, involvedPartitionMasters, m_buddyHSIds.get(m_nextBuddy), false);
}
// if cannot figure out the involved partitions, run it as an MP txn
}
if (task == null) {
task = new MpProcedureTask(m_mailbox, procedureName, m_pendingTasks, mp, m_iv2Masters, m_partitionMasters, m_buddyHSIds.get(m_nextBuddy), false);
}
m_nextBuddy = (m_nextBuddy++) % m_buddyHSIds.size();
m_outstandingTxns.put(task.m_txnState.txnId, task.m_txnState);
m_pendingTasks.offer(task);
}
use of org.voltdb.messaging.Iv2InitiateTaskMessage in project voltdb by VoltDB.
the class Site method replayFromTaskLog.
boolean replayFromTaskLog(MinimumRatioMaintainer mrm) throws IOException {
// not yet time to catch-up.
if (m_rejoinState != kStateReplayingRejoin) {
return false;
}
TransactionInfoBaseMessage tibm = m_rejoinTaskLog.getNextMessage();
if (tibm != null) {
mrm.didUnrestricted();
if (tibm instanceof Iv2InitiateTaskMessage) {
Iv2InitiateTaskMessage m = (Iv2InitiateTaskMessage) tibm;
SpProcedureTask t = new SpProcedureTask(m_initiatorMailbox, m.getStoredProcedureName(), null, m);
if (!filter(tibm)) {
m_currentTxnId = t.getTxnId();
m_lastTxnTime = EstTime.currentTimeMillis();
t.runFromTaskLog(this);
}
} else if (tibm instanceof FragmentTaskMessage) {
FragmentTaskMessage m = (FragmentTaskMessage) tibm;
if (global_replay_mpTxn == null) {
global_replay_mpTxn = new ParticipantTransactionState(m.getTxnId(), m);
} else if (global_replay_mpTxn.txnId != m.getTxnId()) {
VoltDB.crashLocalVoltDB("Started a MP transaction during replay before completing " + " open transaction.", false, null);
}
TransactionTask t;
if (m.isSysProcTask()) {
t = new SysprocFragmentTask(m_initiatorMailbox, m, global_replay_mpTxn);
} else {
t = new FragmentTask(m_initiatorMailbox, m, global_replay_mpTxn);
}
if (!filter(tibm)) {
m_currentTxnId = t.getTxnId();
m_lastTxnTime = EstTime.currentTimeMillis();
t.runFromTaskLog(this);
}
} else if (tibm instanceof CompleteTransactionMessage) {
// Only complete transactions that are open...
if (global_replay_mpTxn != null) {
CompleteTransactionMessage m = (CompleteTransactionMessage) tibm;
CompleteTransactionTask t = new CompleteTransactionTask(m_initiatorMailbox, global_replay_mpTxn, null, m);
if (!m.isRestart()) {
global_replay_mpTxn = null;
}
if (!filter(tibm)) {
t.runFromTaskLog(this);
}
}
} else {
VoltDB.crashLocalVoltDB("Can not replay message type " + tibm + " during live rejoin. Unexpected error.", false, null);
}
}
// is wrong. Run MP txns fully kStateRejoining or fully kStateRunning.
if (m_rejoinTaskLog.isEmpty() && global_replay_mpTxn == null) {
setReplayRejoinComplete();
}
return tibm != null;
}
use of org.voltdb.messaging.Iv2InitiateTaskMessage in project voltdb by VoltDB.
the class RepairLog method deliver.
// Offer a new message to the repair log. This will truncate
// the repairLog if the message includes a truncation hint.
public void deliver(VoltMessage msg) {
if (!m_isLeader && msg instanceof Iv2InitiateTaskMessage) {
final Iv2InitiateTaskMessage m = (Iv2InitiateTaskMessage) msg;
// We can't repair read only SP transactions. Just don't log them to the repair log.
if (m.isReadOnly()) {
return;
}
m_lastSpHandle = m.getSpHandle();
truncate(m.getTruncationHandle(), IS_SP);
m_logSP.add(new Item(IS_SP, m, m.getSpHandle(), m.getTxnId()));
} else if (msg instanceof FragmentTaskMessage) {
final FragmentTaskMessage m = (FragmentTaskMessage) msg;
// We can't repair read only SP transactions. Just don't log them to the repair log.
if (m.isReadOnly()) {
return;
}
truncate(m.getTruncationHandle(), IS_MP);
// only log the first fragment of a procedure (and handle 1st case)
if (m.getTxnId() > m_lastMpHandle || m_lastMpHandle == Long.MAX_VALUE) {
m_logMP.add(new Item(IS_MP, m, m.getSpHandle(), m.getTxnId()));
m_lastMpHandle = m.getTxnId();
m_lastSpHandle = m.getSpHandle();
}
} else if (msg instanceof CompleteTransactionMessage) {
// a CompleteTransactionMessage which indicates restart is not the end of the
// transaction. We don't want to log it in the repair log.
CompleteTransactionMessage ctm = (CompleteTransactionMessage) msg;
// Restart transaction do not need to be repaired here, don't log them as well.
if (ctm.isReadOnly() || ctm.isRestart()) {
return;
}
truncate(ctm.getTruncationHandle(), IS_MP);
m_logMP.add(new Item(IS_MP, ctm, ctm.getSpHandle(), ctm.getTxnId()));
//Restore will send a complete transaction message with a lower mp transaction id because
//the restore transaction precedes the loading of the right mp transaction id from the snapshot
//Hence Math.max
m_lastMpHandle = Math.max(m_lastMpHandle, ctm.getTxnId());
m_lastSpHandle = ctm.getSpHandle();
} else if (msg instanceof DumpMessage) {
String who = CoreUtils.hsIdToString(m_HSId);
tmLog.warn("Repair log dump for site: " + who + ", isLeader: " + m_isLeader + ", " + who + ": lastSpHandle: " + m_lastSpHandle + ", lastMpHandle: " + m_lastMpHandle);
for (Iv2RepairLogResponseMessage il : contents(0l, false)) {
tmLog.warn("[Repair log contents]" + who + ": msg: " + il);
}
} else if (msg instanceof RepairLogTruncationMessage) {
final RepairLogTruncationMessage truncateMsg = (RepairLogTruncationMessage) msg;
truncate(truncateMsg.getHandle(), IS_SP);
}
}
use of org.voltdb.messaging.Iv2InitiateTaskMessage in project voltdb by VoltDB.
the class TestClientInterface method checkInitMsgSent.
private Iv2InitiateTaskMessage checkInitMsgSent(String procName, Object partitionParam, boolean isReadonly, boolean isSinglePart) {
ArgumentCaptor<Long> destinationCaptor = ArgumentCaptor.forClass(Long.class);
ArgumentCaptor<Iv2InitiateTaskMessage> messageCaptor = ArgumentCaptor.forClass(Iv2InitiateTaskMessage.class);
verify(m_messenger).send(destinationCaptor.capture(), messageCaptor.capture());
Iv2InitiateTaskMessage message = messageCaptor.getValue();
// readonly
assertEquals(isReadonly, message.isReadOnly());
// single-part
assertEquals(isSinglePart, message.isSinglePartition());
assertEquals(procName, message.getStoredProcedureName());
if (isSinglePart) {
int expected = TheHashinator.getPartitionForParameter(VoltType.typeFromObject(partitionParam).getValue(), partitionParam);
assertEquals(new Long(m_cartographer.getHSIdForMaster(expected)), destinationCaptor.getValue());
} else {
assertEquals(new Long(m_cartographer.getHSIdForMultiPartitionInitiator()), destinationCaptor.getValue());
}
return message;
}
Aggregations