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;
    }
  }
Exemplo n.º 2
0
  /**
   * 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;
      }
    }
  }