use of org.voltdb.exceptions.TransactionRestartException 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.exceptions.TransactionRestartException in project voltdb by VoltDB.
the class MpTransactionState method pollForResponses.
private FragmentResponseMessage pollForResponses() {
FragmentResponseMessage msg = null;
try {
final String snapShotRestoreProcName = "@SnapshotRestore";
while (msg == null) {
msg = m_newDeps.poll(60L * 5, TimeUnit.SECONDS);
if (msg == null && !snapShotRestoreProcName.equals(m_initiationMsg.getStoredProcedureName())) {
tmLog.warn("Possible multipartition transaction deadlock detected for: " + m_initiationMsg);
if (m_remoteWork == null) {
tmLog.warn("Waiting on local BorrowTask response from site: " + CoreUtils.hsIdToString(m_buddyHSId));
} else {
tmLog.warn("Waiting on remote dependencies: ");
for (Entry<Integer, Set<Long>> e : m_remoteDeps.entrySet()) {
tmLog.warn("Dep ID: " + e.getKey() + " waiting on: " + CoreUtils.hsIdCollectionToString(e.getValue()));
}
}
m_mbox.send(com.google_voltpatches.common.primitives.Longs.toArray(m_useHSIds), new DumpMessage());
}
}
} catch (InterruptedException e) {
// could retry; but this is unexpected. Crash.
throw new RuntimeException(e);
}
SerializableException se = msg.getException();
if (se != null && se instanceof TransactionRestartException) {
// If this is a restart exception, we don't need to match up the DependencyId
setNeedsRollback(true);
throw se;
}
return msg;
}
Aggregations