use of org.voltdb.messaging.FragmentResponseMessage in project voltdb by VoltDB.
the class MpTransactionTaskQueue method repair.
// repair is used by MPI repair to inject a repair task into the
// SiteTaskerQueue. Before it does this, it unblocks the MP transaction
// that may be running in the Site thread and causes it to rollback by
// faking an unsuccessful FragmentResponseMessage.
synchronized void repair(SiteTasker task, List<Long> masters, Map<Integer, Long> partitionMasters) {
// We know that every Site assigned to the MPI (either the main writer or
// any of the MP read pool) will only have one active transaction at a time,
// and that we either have active reads or active writes, but never both.
// Figure out which we're doing, and then poison all of the appropriate sites.
Map<Long, TransactionTask> currentSet;
if (!m_currentReads.isEmpty()) {
assert (m_currentWrites.isEmpty());
tmLog.debug("MpTTQ: repairing reads");
for (Long txnId : m_currentReads.keySet()) {
m_sitePool.repair(txnId, task);
}
currentSet = m_currentReads;
} else {
tmLog.debug("MpTTQ: repairing writes");
m_taskQueue.offer(task);
currentSet = m_currentWrites;
}
for (Entry<Long, TransactionTask> e : currentSet.entrySet()) {
if (e.getValue() instanceof MpProcedureTask) {
MpProcedureTask next = (MpProcedureTask) e.getValue();
tmLog.debug("MpTTQ: poisoning task: " + next);
next.doRestart(masters, partitionMasters);
MpTransactionState txn = (MpTransactionState) next.getTransactionState();
// inject poison pill
FragmentTaskMessage dummy = new FragmentTaskMessage(0L, 0L, 0L, 0L, false, false, false);
FragmentResponseMessage poison = // Don't care about source HSID here
new FragmentResponseMessage(dummy, 0L);
// Provide a TransactionRestartException which will be converted
// into a ClientResponse.RESTART, so that the MpProcedureTask can
// detect the restart and take the appropriate actions.
TransactionRestartException restart = new TransactionRestartException("Transaction being restarted due to fault recovery or shutdown.", next.getTxnId());
poison.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, restart);
txn.offerReceivedFragmentResponse(poison);
} else {
// Don't think that EveryPartitionTasks need to do anything here, since they
// don't actually run java, they just exist for sequencing. Any cleanup should be
// to the duplicate counter in MpScheduler for this transaction.
}
}
// Now, iterate through the backlog and update the partition masters
// for all ProcedureTasks
Iterator<TransactionTask> iter = m_backlog.iterator();
while (iter.hasNext()) {
TransactionTask tt = iter.next();
if (tt instanceof MpProcedureTask) {
MpProcedureTask next = (MpProcedureTask) tt;
tmLog.debug("Repair updating task: " + next + " with masters: " + masters);
next.updateMasters(masters, partitionMasters);
} else if (tt instanceof EveryPartitionTask) {
EveryPartitionTask next = (EveryPartitionTask) tt;
tmLog.debug("Repair updating EPT task: " + next + " with masters: " + masters);
next.updateMasters(masters);
}
}
}
use of org.voltdb.messaging.FragmentResponseMessage in project voltdb by VoltDB.
the class TestSpSchedulerDedupe method testPrimaryFragmentTaskResponseNoReplicas.
@Test
public void testPrimaryFragmentTaskResponseNoReplicas() throws Exception {
long txnid = TxnEgo.makeZero(0).getTxnId();
long primary_hsid = 1111l;
createObjs();
dut.setLeaderState(true);
dut.updateReplicas(new ArrayList<Long>(), null);
FragmentTaskMessage sptask = createFrag(txnid, true, primary_hsid);
dut.deliver(sptask);
// verify no response sent yet
verify(mbox, times(0)).send(anyLong(), (VoltMessage) anyObject());
verify(mbox, times(0)).send(new long[] { anyLong() }, (VoltMessage) anyObject());
FragmentResponseMessage resp = new FragmentResponseMessage(sptask, 0l);
dut.deliver(resp);
verify(mbox, times(1)).send(eq(primary_hsid), eq(resp));
}
use of org.voltdb.messaging.FragmentResponseMessage in project voltdb by VoltDB.
the class TestSpSchedulerDedupe method testReplicaFragmentTaskResponse.
@Test
public void testReplicaFragmentTaskResponse() throws Exception {
long txnid = TxnEgo.makeZero(0).getTxnId();
long primary_hsid = 1111l;
createObjs();
// read only message will not be received on replicas.
FragmentTaskMessage sptask = createFrag(txnid, false, primary_hsid);
dut.deliver(sptask);
// verify no response sent yet
verify(mbox, times(0)).send(anyLong(), (VoltMessage) anyObject());
verify(mbox, times(0)).send(new long[] { anyLong() }, (VoltMessage) anyObject());
FragmentResponseMessage resp = new FragmentResponseMessage(sptask, 0l);
dut.deliver(resp);
verify(mbox, times(1)).send(eq(primary_hsid), eq(resp));
}
use of org.voltdb.messaging.FragmentResponseMessage in project voltdb by VoltDB.
the class FragmentTask method runForRejoin.
/**
* Produce a rejoining response.
*/
@Override
public void runForRejoin(SiteProcedureConnection siteConnection, TaskLog taskLog) throws IOException {
if (!m_txnState.isReadOnly()) {
taskLog.logTask(m_fragmentMsg);
}
final FragmentResponseMessage response = new FragmentResponseMessage(m_fragmentMsg, m_initiator.getHSId());
response.setRecovering(true);
response.setStatus(FragmentResponseMessage.SUCCESS, null);
// on elastic join, so the fragment response message is actually going to the MPI.
for (int frag = 0; frag < m_fragmentMsg.getFragmentCount(); frag++) {
final int outputDepId = m_fragmentMsg.getOutputDepId(frag);
response.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, m_rawDummyResponse, 0, m_rawDummyResponse.length));
}
deliverResponse(response);
completeFragment();
}
use of org.voltdb.messaging.FragmentResponseMessage in project voltdb by VoltDB.
the class FragmentTask method processFragmentTask.
// Cut and pasted from ExecutionSite processFragmentTask(), then
// modifed to work in the new world
public FragmentResponseMessage processFragmentTask(SiteProcedureConnection siteConnection) {
// Ensure default procs loaded here
// Also used for LoadMultipartitionTable
String procNameToLoad = m_fragmentMsg.getProcNameToLoad();
if (procNameToLoad != null) {
// this will ensure proc is loaded
ProcedureRunner runner = siteConnection.getProcedureRunner(procNameToLoad);
assert (runner != null);
}
// IZZY: actually need the "executor" HSId these days?
final FragmentResponseMessage currentFragResponse = new FragmentResponseMessage(m_fragmentMsg, m_initiator.getHSId());
currentFragResponse.setStatus(FragmentResponseMessage.SUCCESS, null);
if (m_inputDeps != null) {
siteConnection.stashWorkUnitDependencies(m_inputDeps);
}
if (m_fragmentMsg.isEmptyForRestart()) {
int outputDepId = m_fragmentMsg.getOutputDepId(0);
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, m_rawDummyResponse, 0, m_rawDummyResponse.length));
return currentFragResponse;
}
ProcedureRunner currRunner = siteConnection.getProcedureRunner(m_fragmentMsg.getProcedureName());
long[] executionTimes = null;
int succeededFragmentsCount = 0;
if (currRunner != null) {
currRunner.getExecutionEngine().setPerFragmentTimingEnabled(m_fragmentMsg.isPerFragmentStatsRecording());
if (m_fragmentMsg.isPerFragmentStatsRecording()) {
// At this point, we will execute the fragments one by one.
executionTimes = new long[1];
}
}
for (int frag = 0; frag < m_fragmentMsg.getFragmentCount(); frag++) {
byte[] planHash = m_fragmentMsg.getPlanHash(frag);
final int outputDepId = m_fragmentMsg.getOutputDepId(frag);
ParameterSet params = m_fragmentMsg.getParameterSetForFragment(frag);
final int inputDepId = m_fragmentMsg.getOnlyInputDepId(frag);
long fragmentId = 0;
byte[] fragmentPlan = null;
/*
* Currently the error path when executing plan fragments
* does not adequately distinguish between fatal errors and
* abort type errors that should result in a roll back.
* Assume that it is ninja: succeeds or doesn't return.
* No roll back support.
*
* AW in 2012, the preceding comment might be wrong,
* I am pretty sure what we don't support is partial rollback.
* The entire procedure will roll back successfully on failure
*/
VoltTable dependency = null;
try {
FastDeserializer fragResult;
fragmentPlan = m_fragmentMsg.getFragmentPlan(frag);
String stmtText = null;
// if custom fragment, load the plan and get local fragment id
if (fragmentPlan != null) {
// statement text for unplanned fragments are pulled from the message,
// to ensure that we get the correct constants from the most recent
// invocation.
stmtText = m_fragmentMsg.getStmtText(frag);
fragmentId = ActivePlanRepository.loadOrAddRefPlanFragment(planHash, fragmentPlan, null);
} else // otherwise ask the plan source for a local fragment id
{
fragmentId = ActivePlanRepository.getFragmentIdForPlanHash(planHash);
stmtText = ActivePlanRepository.getStmtTextForPlanHash(planHash);
}
// set up the batch context for the fragment set
siteConnection.setBatch(m_fragmentMsg.getCurrentBatchIndex());
fragResult = siteConnection.executePlanFragments(1, new long[] { fragmentId }, new long[] { inputDepId }, new ParameterSet[] { params }, null, // for long-running queries
stmtText == null ? null : new String[] { stmtText }, // FragmentTasks don't generate statement hashes,
new boolean[] { false }, null, m_txnState.txnId, m_txnState.m_spHandle, m_txnState.uniqueId, m_txnState.isReadOnly(), VoltTrace.log(VoltTrace.Category.EE) != null);
// get a copy of the result buffers from the cache buffer so we can post the
// fragment response to the network
final int tableSize;
final byte[] fullBacking;
try {
// read the complete size of the buffer used
fragResult.readInt();
// read number of dependencies (1)
fragResult.readInt();
// read the dependencyId() -1;
fragResult.readInt();
tableSize = fragResult.readInt();
fullBacking = new byte[tableSize];
// get a copy of the buffer
fragResult.readFully(fullBacking);
} catch (final IOException ex) {
LOG.error("Failed to deserialze result table" + ex);
throw new EEException(ExecutionEngine.ERRORCODE_WRONG_SERIALIZED_BYTES);
}
if (hostLog.isTraceEnabled()) {
hostLog.l7dlog(Level.TRACE, LogKeys.org_voltdb_ExecutionSite_SendingDependency.name(), new Object[] { outputDepId }, null);
}
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, fullBacking, 0, tableSize));
} catch (final EEException e) {
hostLog.l7dlog(Level.TRACE, LogKeys.host_ExecutionSite_ExceptionExecutingPF.name(), new Object[] { Encoder.hexEncode(planHash) }, e);
currentFragResponse.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, e);
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, m_rawDummyResult, 0, m_rawDummyResult.length));
}
break;
} catch (final SQLException e) {
hostLog.l7dlog(Level.TRACE, LogKeys.host_ExecutionSite_ExceptionExecutingPF.name(), new Object[] { Encoder.hexEncode(planHash) }, e);
currentFragResponse.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, e);
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, m_rawDummyResult, 0, m_rawDummyResult.length));
}
break;
} catch (final InterruptException e) {
hostLog.l7dlog(Level.TRACE, LogKeys.host_ExecutionSite_ExceptionExecutingPF.name(), new Object[] { Encoder.hexEncode(planHash) }, e);
currentFragResponse.setStatus(FragmentResponseMessage.UNEXPECTED_ERROR, e);
if (currentFragResponse.getTableCount() == 0) {
// Make sure the response has at least 1 result with a valid DependencyId
currentFragResponse.addDependency(new DependencyPair.BufferDependencyPair(outputDepId, m_rawDummyResult, 0, m_rawDummyResult.length));
}
break;
} finally {
// ensure adhoc plans are unloaded
if (fragmentPlan != null) {
ActivePlanRepository.decrefPlanFragmentById(fragmentId);
}
// The single-partition stored procedure handler is in the ProcedureRunner.
if (currRunner != null) {
succeededFragmentsCount = currRunner.getExecutionEngine().extractPerFragmentStats(1, executionTimes);
long stmtDuration = 0;
int stmtResultSize = 0;
int stmtParameterSetSize = 0;
if (m_fragmentMsg.isPerFragmentStatsRecording()) {
stmtDuration = executionTimes == null ? 0 : executionTimes[0];
stmtResultSize = dependency == null ? 0 : dependency.getSerializedSize();
stmtParameterSetSize = params == null ? 0 : params.getSerializedSize();
}
currRunner.getStatsCollector().endFragment(m_fragmentMsg.getStmtName(frag), m_fragmentMsg.isCoordinatorTask(), succeededFragmentsCount == 0, m_fragmentMsg.isPerFragmentStatsRecording(), stmtDuration, stmtResultSize, stmtParameterSetSize);
}
}
}
return currentFragResponse;
}
Aggregations