예제 #1
0
 public static void logIv2InitiateTaskMessage(
     Iv2InitiateTaskMessage itask, long localHSId, long txnid, long spHandle) {
   if (iv2log.isTraceEnabled()) {
     String logmsg = "rxInitMsg %s from %s ciHandle %s txnId %s spHandle %s trunc %s";
     if (itask.getTxnId() != Long.MIN_VALUE && itask.getTxnId() != txnid) {
       iv2log.error(
           "Iv2InitiateTaskMessage TXN ID conflict.  Message: "
               + itask.getTxnId()
               + ", locally held: "
               + txnid);
     }
     if (itask.getSpHandle() != Long.MIN_VALUE && itask.getSpHandle() != spHandle) {
       iv2log.error(
           "Iv2InitiateTaskMessage SP HANDLE conflict.  Message: "
               + itask.getSpHandle()
               + ", locally held: "
               + spHandle);
     }
     iv2log.trace(
         String.format(
             logmsg,
             CoreUtils.hsIdToString(localHSId),
             CoreUtils.hsIdToString(itask.m_sourceHSId),
             ClientInterfaceHandleManager.handleToString(itask.getClientInterfaceHandle()),
             txnIdToString(txnid),
             txnIdToString(spHandle),
             txnIdToString(itask.getTruncationHandle())));
   }
 }
예제 #2
0
  private void handleIv2InitiateTaskMessageRepair(
      List<Long> needsRepair, Iv2InitiateTaskMessage message) {
    if (!message.isSinglePartition()) {
      throw new RuntimeException(
          "SpScheduler.handleIv2InitiateTaskMessageRepair "
              + "should never receive multi-partition initiations.");
    }

    // set up duplicate counter. expect exactly the responses corresponding
    // to needsRepair. These may, or may not, include the local site.

    // We currently send the final response into the ether, since we don't
    // have the original ClientInterface HSID stored.  It would be more
    // useful to have the original ClienInterface HSId somewhere handy.

    List<Long> expectedHSIds = new ArrayList<Long>(needsRepair);
    DuplicateCounter counter =
        new DuplicateCounter(
            HostMessenger.VALHALLA,
            message.getTxnId(),
            expectedHSIds,
            message.getStoredProcedureName());
    m_duplicateCounters.put(
        new DuplicateCounterKey(message.getTxnId(), message.getSpHandle()), counter);

    m_uniqueIdGenerator.updateMostRecentlyGeneratedUniqueId(message.getUniqueId());
    // is local repair necessary?
    if (needsRepair.contains(m_mailbox.getHSId())) {
      needsRepair.remove(m_mailbox.getHSId());
      // make a copy because handleIv2 non-repair case does?
      Iv2InitiateTaskMessage localWork =
          new Iv2InitiateTaskMessage(
              message.getInitiatorHSId(), message.getCoordinatorHSId(), message);
      doLocalInitiateOffer(localWork);
    }

    // is remote repair necessary?
    if (!needsRepair.isEmpty()) {
      Iv2InitiateTaskMessage replmsg =
          new Iv2InitiateTaskMessage(m_mailbox.getHSId(), m_mailbox.getHSId(), message);
      m_mailbox.send(com.google.common.primitives.Longs.toArray(needsRepair), replmsg);
    }
  }
예제 #3
0
  // SpScheduler expects to see InitiateTaskMessages corresponding to single-partition
  // procedures only.
  public void handleIv2InitiateTaskMessage(Iv2InitiateTaskMessage message) {
    if (!message.isSinglePartition()) {
      throw new RuntimeException(
          "SpScheduler.handleIv2InitiateTaskMessage "
              + "should never receive multi-partition initiations.");
    }

    final String procedureName = message.getStoredProcedureName();
    long newSpHandle;
    long uniqueId = Long.MIN_VALUE;
    Iv2InitiateTaskMessage msg = message;
    if (m_isLeader || message.isReadOnly()) {
      /*
       * A short circuit read is a read where the client interface is local to
       * this node. The CI will let a replica perform a read in this case and
       * it does looser tracking of client handles since it can't be
       * partitioned from the local replica.
       */
      if (!m_isLeader
          && CoreUtils.getHostIdFromHSId(msg.getInitiatorHSId())
              != CoreUtils.getHostIdFromHSId(m_mailbox.getHSId())) {
        VoltDB.crashLocalVoltDB("Only allowed to do short circuit reads locally", true, null);
      }

      /*
       * If this is for CL replay or DR, update the unique ID generator
       */
      if (message.isForReplay()) {
        uniqueId = message.getUniqueId();
        try {
          m_uniqueIdGenerator.updateMostRecentlyGeneratedUniqueId(uniqueId);
        } catch (Exception e) {
          hostLog.fatal(e.getMessage());
          hostLog.fatal("Invocation: " + message);
          VoltDB.crashLocalVoltDB(e.getMessage(), true, e);
        }
      } else if (message.isForDR()) {
        uniqueId = message.getStoredProcedureInvocation().getOriginalUniqueId();
        // @LoadSinglepartitionTable does not have a valid uid
        if (UniqueIdGenerator.getPartitionIdFromUniqueId(uniqueId) == m_partitionId) {
          m_uniqueIdGenerator.updateMostRecentlyGeneratedUniqueId(uniqueId);
        }
      }

      /*
       * If this is CL replay use the txnid from the CL and also
       * update the txnid to match the one from the CL
       */
      if (message.isForReplay()) {
        newSpHandle = message.getTxnId();
        setMaxSeenTxnId(newSpHandle);
      } else if (m_isLeader) {
        TxnEgo ego = advanceTxnEgo();
        newSpHandle = ego.getTxnId();
        uniqueId = m_uniqueIdGenerator.getNextUniqueId();
      } else {
        /*
         * The short circuit read case. Since we are not a master
         * we can't create new transaction IDs, so reuse the last seen
         * txnid. For a timestamp, might as well give a reasonable one
         * for a read heavy workload so time isn't bursty.
         */
        uniqueId =
            UniqueIdGenerator.makeIdFromComponents(
                Math.max(System.currentTimeMillis(), m_uniqueIdGenerator.lastUsedTime),
                0,
                m_uniqueIdGenerator.partitionId);
        // Don't think it wise to make a new one for a short circuit read
        newSpHandle = getCurrentTxnId();
      }

      // Need to set the SP handle on the received message
      // Need to copy this or the other local sites handling
      // the same initiate task message will overwrite each
      // other's memory -- the message isn't copied on delivery
      // to other local mailboxes.
      msg =
          new Iv2InitiateTaskMessage(
              message.getInitiatorHSId(),
              message.getCoordinatorHSId(),
              m_repairLogTruncationHandle,
              message.getTxnId(),
              message.getUniqueId(),
              message.isReadOnly(),
              message.isSinglePartition(),
              message.getStoredProcedureInvocation(),
              message.getClientInterfaceHandle(),
              message.getConnectionId(),
              message.isForReplay());

      msg.setSpHandle(newSpHandle);

      // Also, if this is a vanilla single-part procedure, make the TXNID
      // be the SpHandle (for now)
      // Only system procedures are every-site, so we'll check through the SystemProcedureCatalog
      if (SystemProcedureCatalog.listing.get(procedureName) == null
          || !SystemProcedureCatalog.listing.get(procedureName).getEverysite()) {
        msg.setTxnId(newSpHandle);
        msg.setUniqueId(uniqueId);
      }

      // Don't replicate reads, this really assumes that DML validation
      // is going to be integrated soonish
      if (m_isLeader && !msg.isReadOnly() && m_sendToHSIds.length > 0) {
        Iv2InitiateTaskMessage replmsg =
            new Iv2InitiateTaskMessage(
                m_mailbox.getHSId(),
                m_mailbox.getHSId(),
                m_repairLogTruncationHandle,
                msg.getTxnId(),
                msg.getUniqueId(),
                msg.isReadOnly(),
                msg.isSinglePartition(),
                msg.getStoredProcedureInvocation(),
                msg.getClientInterfaceHandle(),
                msg.getConnectionId(),
                msg.isForReplay());
        // Update the handle in the copy since the constructor doesn't set it
        replmsg.setSpHandle(newSpHandle);
        m_mailbox.send(m_sendToHSIds, replmsg);
        DuplicateCounter counter =
            new DuplicateCounter(
                msg.getInitiatorHSId(),
                msg.getTxnId(),
                m_replicaHSIds,
                msg.getStoredProcedureName());
        m_duplicateCounters.put(new DuplicateCounterKey(msg.getTxnId(), newSpHandle), counter);
      }
    } else {
      setMaxSeenTxnId(msg.getSpHandle());
      newSpHandle = msg.getSpHandle();
      uniqueId = msg.getUniqueId();
    }
    Iv2Trace.logIv2InitiateTaskMessage(message, m_mailbox.getHSId(), msg.getTxnId(), newSpHandle);
    doLocalInitiateOffer(msg);
    return;
  }
예제 #4
0
  // 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;
      // We can't repair read only SP transactions. Just don't log them to the repair log.
      // 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);
    }
  }