private void processRejoiningFragmentWork( FragmentTaskMessage ftask, HashMap<Integer, List<VoltTable>> dependencies) { assert (ftask.getFragmentCount() > 0); assert (m_rejoinState == RejoinState.REJOINING); FragmentResponseMessage response = new FragmentResponseMessage(ftask, m_hsId); response.setRecovering(true); response.setStatus(FragmentResponseMessage.SUCCESS, null); // log the work done for replay if (!ftask.isReadOnly() && !ftask.isSysProcTask()) { assert (m_notice.isReadOnly() == false); assert (m_loggedFragments != null); m_loggedFragments.appendFragmentTask(ftask); } // add a dummy table for all of the expected dependency ids for (int i = 0; i < ftask.getFragmentCount(); i++) { response.addDependency( ftask.getOutputDepId(i), new VoltTable(new VoltTable.ColumnInfo("DUMMY", VoltType.BIGINT))); } m_mbox.send(response.getDestinationSiteId(), response); // If we're not the coordinator, the transaction is read-only, // and this was the final task, then we can try to move on after // we've finished this work. if (!isCoordinator() && isReadOnly() && ftask.isFinalTask()) { m_done = true; } }
/** * Do the work necessary to turn the FragmentTaskMessage into a TransactionTask which can be * queued to the TransactionTaskQueue. This is reused by both the normal message handling path and * the repair path, and assumes that the caller has dealt with or ensured that the necessary ID, * SpHandles, and replication issues are resolved. */ private void doLocalFragmentOffer(FragmentTaskMessage msg) { TransactionState txn = m_outstandingTxns.get(msg.getTxnId()); boolean logThis = false; // bit of a hack...we will probably not want to create and // offer FragmentTasks for txn ids that don't match if we have // something in progress already if (txn == null) { txn = new ParticipantTransactionState(msg.getSpHandle(), msg); m_outstandingTxns.put(msg.getTxnId(), txn); // Only want to send things to the command log if it satisfies this predicate // AND we've never seen anything for this transaction before. We can't // actually log until we create a TransactionTask, though, so just keep track // of whether it needs to be done. logThis = (msg.getInitiateTask() != null && !msg.getInitiateTask().isReadOnly()); } // Check to see if this is the final task for this txn, and if so, if we can close it out early // Right now, this just means read-only. // NOTE: this overlaps slightly with CompleteTransactionMessage handling completion. It's so // tiny // that for now, meh, but if this scope grows then it should get refactored out if (msg.isFinalTask() && txn.isReadOnly()) { m_outstandingTxns.remove(msg.getTxnId()); } TransactionTask task; if (msg.isSysProcTask()) { task = new SysprocFragmentTask( m_mailbox, (ParticipantTransactionState) txn, m_pendingTasks, msg, null); } else { task = new FragmentTask(m_mailbox, (ParticipantTransactionState) txn, m_pendingTasks, msg, null); } if (logThis) { if (!m_cl.log(msg.getInitiateTask(), msg.getSpHandle(), m_durabilityListener, task)) { m_pendingTasks.offer(task); } else { /* Getting here means that the task is the first fragment of an MP txn and * synchronous command logging is on, so create a backlog for future tasks of * this MP arrived before it's marked durable. * * This is important for synchronous command logging and MP txn restart. Without * this, a restarted MP txn may not be gated by logging of the first fragment. */ assert !m_mpsPendingDurability.containsKey(task.getTxnId()); m_mpsPendingDurability.put(task.getTxnId(), new ArrayDeque<TransactionTask>()); } } else { queueOrOfferMPTask(task); } }
void processFragmentWork( FragmentTaskMessage ftask, HashMap<Integer, List<VoltTable>> dependencies) { assert (ftask.getFragmentCount() > 0); FragmentResponseMessage response = m_site.processFragmentTask(this, dependencies, ftask); if (response.getStatusCode() != FragmentResponseMessage.SUCCESS) { if (m_missingDependencies != null) m_missingDependencies.clear(); m_readyWorkUnits.clear(); if (m_isCoordinator) { // throw an exception which will back the runtime all the way // to the stored procedure invocation call, triggering undo // at that point if (response.getException() != null) { throw response.getException(); } else { throw new FragmentFailureException(); } } else { m_needsRollback = true; m_done = true; } } if (m_isCoordinator && (response.getDestinationSiteId() == response.getExecutorSiteId())) { processFragmentResponseDependencies(response); } else { m_mbox.send(response.getDestinationSiteId(), response); // If we're not the coordinator, the transaction is read-only, // and this was the final task, then we can try to move on after // we've finished this work. if (!isCoordinator() && isReadOnly() && ftask.isFinalTask()) { m_done = true; } } }