void Cmvmi::execDUMP_STATE_ORD()

in storage/ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp [1295:2067]


void Cmvmi::execDUMP_STATE_ORD(Signal *signal) {
  jamEntry();
  Uint32 val = signal->theData[0];
  if (val >= DumpStateOrd::OneBlockOnly) {
    if (check_block(Backup, val)) {
      sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
    } else if (check_block(TC, val)) {
      sendSignal(DBTC_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
    } else if (check_block(LQH, val)) {
      sendSignal(DBLQH_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
    } else if (check_block(CMVMI, val)) {
      /**
       * Handle here since we are already in CMVMI, mostly used for
       * online config changes.
       */
      DumpStateOrd *const &dumpState = (DumpStateOrd *)&signal->theData[0];
      Uint32 arg = dumpState->args[0];
      Uint32 first_val = dumpState->args[1];
      if (signal->length() > 0) {
        if (val == DumpStateOrd::SetSchedulerResponsiveness) {
          if (signal->length() != 2) {
            g_eventLogger->info(
                "dump 103000 X, where X is between 0 and 10"
                " to set transactional priority");
          } else if (arg == DumpStateOrd::SetSchedulerResponsiveness) {
            if (first_val > 10) {
              g_eventLogger->info(
                  "Trying to set SchedulerResponsiveness outside 0-10");
            } else {
              g_eventLogger->info("Setting SchedulerResponsiveness to %u",
                                  first_val);
              Configuration *conf = globalEmulatorData.theConfiguration;
              conf->setSchedulerResponsiveness(first_val);
            }
          }
        } else if (val == DumpStateOrd::EnableEventLoggerDebug) {
          g_eventLogger->info("Enable Debug level in node log");
          g_eventLogger->enable(Logger::LL_DEBUG);
        } else if (val == DumpStateOrd::DisableEventLoggerDebug) {
          g_eventLogger->info("Disable Debug level in node log");
          g_eventLogger->disable(Logger::LL_DEBUG);
        } else if (val == DumpStateOrd::CmvmiRelayDumpStateOrd) {
          /* MGMD have no transporter to API nodes.  To be able to send a
           * dump command to an API node MGMD send the dump signal via a
           * data node using CmvmiRelay command.  The first argument is the
           * destination node, the rest is the dump command that should be
           * sent.
           *
           * args: dest-node dump-state-ord-code dump-state-ord-arg#1 ...
           */
          jam();
          const Uint32 length = signal->length();
          if (length < 3) {
            // Not enough words for sending DUMP_STATE_ORD
            jam();
            return;
          }
          const Uint32 node_id = signal->theData[1];
          const Uint32 ref = numberToRef(CMVMI, node_id);
          std::memmove(&signal->theData[0], &signal->theData[2],
                       (length - 2) * sizeof(Uint32));
          sendSignal(ref, GSN_DUMP_STATE_ORD, signal, length - 2, JBB);
        } else if (val == DumpStateOrd::CmvmiDummySignal) {
          /* Log in event logger that signal sent by dump command
           * CmvmiSendDummySignal is received.  Include information about
           * signal size and its sections and which node sent it.
           */
          jam();
          const Uint32 node_id = signal->theData[2];
          const Uint32 num_secs = signal->getNoOfSections();
          SectionHandle handle(this, signal);
          SegmentedSectionPtr ptr[3];
          for (Uint32 i = 0; i < num_secs; i++) {
            ndbrequire(handle.getSection(ptr[i], i));
          }
          char msg[24 * 4];
          snprintf(msg, sizeof(msg),
                   "Receiving CmvmiDummySignal"
                   " (size %u+%u+%u+%u+%u) from %u to %u.",
                   signal->getLength(), num_secs,
                   (num_secs > 0) ? ptr[0].sz : 0,
                   (num_secs > 1) ? ptr[1].sz : 0,
                   (num_secs > 2) ? ptr[2].sz : 0, node_id, getOwnNodeId());
          g_eventLogger->info("%s", msg);
          infoEvent("%s", msg);
          releaseSections(handle);
        } else if (val == DumpStateOrd::CmvmiSendDummySignal) {
          /* Send a CmvmiDummySignal to specified node with specified size and
           * sections.  This is used to verify that messages with certain
           * signal sizes and sections can be sent and received.
           *
           * The sending is also logged in event logger.  This log entry should
           * be matched with corresponding log when receiving the
           * CmvmiDummySignal dump command.  See preceding dump command above.
           *
           * args: rep-node dest-node padding frag-size
           *       #secs sec#1-len sec#2-len sec#3-len
           */
          jam();
          if (signal->length() < 5) {
            // Not enough words to send a dummy signal
            jam();
            return;
          }
          const Uint32 node_id = signal->theData[2];
          const Uint32 ref = (getNodeInfo(node_id).m_type == NodeInfo::DB)
                                 ? numberToRef(CMVMI, node_id)
                                 : numberToRef(API_CLUSTERMGR, node_id);
          const Uint32 fill_word = signal->theData[3];
          const Uint32 frag_size = signal->theData[4];
          if (frag_size != 0) {
            // Fragmented signals not supported yet.
            jam();
            return;
          }
          const Uint32 num_secs =
              (signal->length() > 5) ? signal->theData[5] : 0;
          if (num_secs > 3) {
            jam();
            return;
          }
          Uint32 tot_len = signal->length();
          LinearSectionPtr ptr[3];
          for (Uint32 i = 0; i < num_secs; i++) {
            const Uint32 sec_len = signal->theData[6 + i];
            ptr[i].sz = sec_len;
            tot_len += sec_len;
          }
          Uint32 *sec_alloc = NULL;
          Uint32 *sec_data = &signal->theData[signal->length()];
          if (tot_len > NDB_ARRAY_SIZE(signal->theData)) {
            sec_data = sec_alloc = new Uint32[tot_len];
          }
          signal->theData[0] = DumpStateOrd::CmvmiDummySignal;
          signal->theData[2] = getOwnNodeId();
          for (Uint32 i = 0; i < tot_len; i++) {
            sec_data[i] = fill_word;
          }
          for (Uint32 i = 0; i < num_secs; i++) {
            const Uint32 sec_len = signal->theData[6 + i];
            ptr[i].p = sec_data;
            sec_data += sec_len;
          }
          char msg[24 * 4];
          snprintf(msg, sizeof(msg),
                   "Sending CmvmiDummySignal"
                   " (size %u+%u+%u+%u+%u) from %u to %u.",
                   signal->getLength(), num_secs,
                   (num_secs > 0) ? ptr[0].sz : 0,
                   (num_secs > 1) ? ptr[1].sz : 0,
                   (num_secs > 2) ? ptr[2].sz : 0, getOwnNodeId(), node_id);
          infoEvent("%s", msg);
          sendSignal(ref, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB,
                     ptr, num_secs);
          delete[] sec_alloc;
        }
      }
    } else if (check_block(THRMAN, val)) {
      sendSignal(THRMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
    }
    return;
  }

  for (Uint32 i = 0; blocks[i] != 0; i++) {
    sendSignal(blocks[i], GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
  }

  /**
   *
   * Here I can dump CMVMI state if needed
   */
  DumpStateOrd *const &dumpState = (DumpStateOrd *)&signal->theData[0];
  Uint32 arg = dumpState->args[0];
  if (arg == DumpStateOrd::CmvmiDumpConnections) {
    for (TrpId trpId = 1; trpId <= globalTransporterRegistry.get_num_trps();
         trpId++) {
      const char *nodeTypeStr = "";
      const NodeId nodeId =
          globalTransporterRegistry.get_transporter_node_id(trpId);
      if (nodeId == 0) continue;

      switch (getNodeInfo(nodeId).m_type) {
        case NodeInfo::DB:
          nodeTypeStr = "DB";
          break;
        case NodeInfo::API:
          nodeTypeStr = "API";
          break;
        case NodeInfo::MGM:
          nodeTypeStr = "MGM";
          break;
        case NodeInfo::INVALID:
          nodeTypeStr = 0;
          break;
        default:
          nodeTypeStr = "<UNKNOWN>";
      }
      infoEvent("Connection to %u (%s), transporter %u is %s", nodeId,
                nodeTypeStr, trpId,
                globalTransporterRegistry.getPerformStateString(trpId));
    }
  }

  if (arg == DumpStateOrd::CmvmiDumpSubscriptions) {
    SubscriberPtr ptr;
    subscribers.first(ptr);
    g_eventLogger->info("List subscriptions:");
    while (ptr.i != RNIL) {
      g_eventLogger->info("Subscription: %u, nodeId: %u, ref: 0x%x", ptr.i,
                          refToNode(ptr.p->blockRef), ptr.p->blockRef);
      for (Uint32 i = 0; i < LogLevel::LOGLEVEL_CATEGORIES; i++) {
        Uint32 level = ptr.p->logLevel.getLogLevel((LogLevel::EventCategory)i);
        g_eventLogger->info("Category %u Level %u", i, level);
      }
      subscribers.next(ptr);
    }
  }

  if (arg == DumpStateOrd::CmvmiDumpLongSignalMemory) {
    infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
              g_sectionSegmentPool.getSize(),
              g_sectionSegmentPool.getNoOfFree());
  }

  if (arg == DumpStateOrd::CmvmiLongSignalMemorySnapshotStart) {
#if defined VM_TRACE || defined ERROR_INSERT
    f_free_segment_pos = 0;
    std::memset(f_free_segments, 0, sizeof(f_free_segments));
#endif
  }

  if (arg == DumpStateOrd::CmvmiLongSignalMemorySnapshot) {
#if defined VM_TRACE || defined ERROR_INSERT
    if (f_free_segment_pos < NDB_ARRAY_SIZE(f_free_segments)) {
      f_free_segments[f_free_segment_pos++] =
          g_sectionSegmentPool.getNoOfFree();
    } else {
      g_eventLogger->warning(
          "CmvmiLongSignalMemorySnapshot IGNORED"
          ", exceeded the max %zu snapshots",
          NDB_ARRAY_SIZE(f_free_segments));
    }
#endif
  }

  if (arg == DumpStateOrd::CmvmiLongSignalMemorySnapshotCheck) {
#if defined VM_TRACE || defined ERROR_INSERT
    Uint32 start = 1;
    Uint32 stop = f_free_segment_pos;
    Uint32 cnt_dec = 0;
    Uint32 cnt_inc = 0;
    Uint32 cnt_same = 0;
    for (Uint32 i = start; i < stop; i++) {
      Uint32 prev = (i - 1);
      if (f_free_segments[prev] == f_free_segments[i])
        cnt_same++;
      else if (f_free_segments[prev] > f_free_segments[i])
        cnt_dec++;
      else
        cnt_inc++;
    }

    printf("snapshots: ");
    for (Uint32 i = 0; i < stop; i++) {
      printf("%u ", f_free_segments[i]);
    }
    printf("\n");
    printf("summary: #same: %u #increase: %u #decrease: %u\n", cnt_same,
           cnt_inc, cnt_dec);

    if (cnt_dec > 1) {
      /**
       * If memory decreased more than once...
       *   it must also increase at least once
       */
      ndbrequire(cnt_inc > 0);
    }

    if (cnt_dec == 1) {
      // it decreased once...this is ok
      return;
    }
    if (cnt_same >= (cnt_inc + cnt_dec)) {
      // it was frequently the same...this is ok
      return;
    }
    if (cnt_same + cnt_dec >= cnt_inc) {
      // it was frequently the same or less...this is ok
      return;
    }

    ndbabort();
#endif
  }

  if (arg == DumpStateOrd::CmvmiLongSignalMemorySnapshotCheck2) {
    g_eventLogger->info("CmvmiLongSignalMemorySnapshotCheck2");

#if defined VM_TRACE || defined ERROR_INSERT
    Uint32 orig_idx =
        (f_free_segment_pos - 1) % NDB_ARRAY_SIZE(f_free_segments);

    Uint32 poolsize = g_sectionSegmentPool.getSize();
    Uint32 orig_level = f_free_segments[orig_idx];
    Uint32 orig_used = poolsize - orig_level;
    Uint32 curr_level = g_sectionSegmentPool.getNoOfFree();
    Uint32 curr_used = poolsize - curr_level;

    g_eventLogger->info("  Total : %u", poolsize);
    g_eventLogger->info("  Orig free level : %u (%u pct)", orig_level,
                        orig_level * 100 / poolsize);
    g_eventLogger->info("  Curr free level : %u (%u pct)", curr_level,
                        curr_level * 100 / poolsize);
    g_eventLogger->info("  Orig in-use : %u (%u pct)", orig_used,
                        orig_used * 100 / poolsize);
    g_eventLogger->info("  Curr in-use : %u (%u pct)", curr_used,
                        curr_used * 100 / poolsize);

    if (curr_used > 2 * orig_used) {
      g_eventLogger->info(
          "  ERROR : in-use has grown by more than a factor of 2");
      ndbabort();
    } else {
      g_eventLogger->info("  Snapshot ok");
    }
#endif
  }

  if (arg == DumpStateOrd::CmvmiShowLongSignalOwnership) {
#ifdef NDB_DEBUG_RES_OWNERSHIP
    g_eventLogger->info("CMVMI dump LSB usage");
    Uint32 buffs = g_sectionSegmentPool.getSize();
    Uint32 *buffOwners = (Uint32 *)malloc(buffs * sizeof(Uint32));
    Uint64 *buffOwnersCount = (Uint64 *)malloc(buffs * sizeof(Uint64));

    std::memset(buffOwnersCount, 0, buffs * sizeof(Uint64));

    g_eventLogger->info("  Filling owners list");
    Uint32 zeroOwners = 0;
    lock_global_ssp();
    {
      /* Fill owners list */
      Ptr<SectionSegment> tmp;
      for (tmp.i = 0; tmp.i < buffs; tmp.i++) {
        g_sectionSegmentPool.getPtrIgnoreAlloc(tmp);
        buffOwners[tmp.i] = tmp.p->m_ownerRef;
        if (buffOwners[tmp.i] == 0) zeroOwners++;

        /* Expensive, ideally find a hacky way to iterate the freelist */
        if (!g_sectionSegmentPool.findId(tmp.i)) {
          buffOwners[tmp.i] = 0;
        }
      }
    }
    unlock_global_ssp();

    g_eventLogger->info("  Summing by owner");
    /* Use a linear hash to find items */

    Uint32 free = 0;
    Uint32 numOwners = 0;
    for (Uint32 i = 0; i < buffs; i++) {
      Uint32 owner = buffOwners[i];
      if (owner == 0) {
        free++;
      } else {
        Uint32 ownerHash = 17 + 37 * owner;
        Uint32 start = ownerHash % buffs;

        Uint32 y = 0;
        for (; y < buffs; y++) {
          Uint32 pos = (start + y) % buffs;
          if (buffOwnersCount[pos] == 0) {
            numOwners++;
            buffOwnersCount[pos] = (Uint64(owner) << 32 | 1);
            break;
          } else if ((buffOwnersCount[pos] >> 32) == owner) {
            buffOwnersCount[pos]++;
            break;
          }
        }
        ndbrequire(y != buffs);
      }
    }

    g_eventLogger->info("  Summary");
    g_eventLogger->info(
        "    Warning, free buffers in thread caches considered used here");
    g_eventLogger->info("    ndbd avoids this problem");
    g_eventLogger->info("    Zero owners : %u", zeroOwners);
    g_eventLogger->info("    Num free : %u", free);
    g_eventLogger->info("    Num owners : %u", numOwners);

    for (Uint32 i = 0; i < buffs; i++) {
      Uint64 entry = buffOwnersCount[i];
      if (entry != 0) {
        /* Breakdown assuming Block ref + GSN format */
        Uint32 count = Uint32(entry & 0xffffffff);
        Uint32 ownerId = Uint32(entry >> 32);
        Uint32 block = (ownerId >> 16) & 0x1ff;
        Uint32 instance = ownerId >> 25;
        Uint32 gsn = ownerId & 0xffff;
        g_eventLogger->info(
            "      Count : %u : OwnerId : 0x%x (0x%x:%u/%u) %s %s", count,
            ownerId, block, instance, gsn,
            block == 1 ? "RECV" : getBlockName(block, "Unknown"),
            getSignalName(gsn, "Unknown"));
      }
    }

    g_eventLogger->info("Done");

    ::free(buffOwners);
    ::free(buffOwnersCount);
#else
    g_eventLogger->info(
        "CMVMI :: ShowLongSignalOwnership.  Not compiled "
        "with NDB_DEBUG_RES_OWNERSHIP");
#endif
  }

  if (dumpState->args[0] == DumpStateOrd::DumpPageMemory) {
    const Uint32 len = signal->getLength();
    if (len == 1)  // DUMP 1000
    {
      // Start dumping resource limits
      signal->theData[1] = 0;
      signal->theData[2] = ~0;
      sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);

      // Dump data and index memory
      reportDMUsage(signal, 0);
      reportIMUsage(signal, 0);
      return;
    }

    if (len == 2)  // DUMP 1000 node-ref
    {
      // Dump data and index memory to specific ref
      Uint32 result_ref = signal->theData[1];
      /* Validate ref */
      {
        Uint32 node = refToNode(result_ref);
        if (node == 0 || node >= MAX_NODES) {
          g_eventLogger->info("Bad node in ref to DUMP %u : %u %u",
                              DumpStateOrd::DumpPageMemory, node, result_ref);
          return;
        }
      }
      reportDMUsage(signal, 0, result_ref);
      reportIMUsage(signal, 0, result_ref);
      return;
    }

    // DUMP 1000 0 0
    Uint32 id = signal->theData[1];
    if (id == 0) {
      infoEvent("Resource global total: %u used: %u",
                m_ctx.m_mm.get_allocated(), m_ctx.m_mm.get_in_use());
      infoEvent("Resource reserved total: %u used: %u",
                m_ctx.m_mm.get_reserved(), m_ctx.m_mm.get_reserved_in_use());
      infoEvent("Resource shared total: %u used: %u spare: %u",
                m_ctx.m_mm.get_shared(), m_ctx.m_mm.get_shared_in_use(),
                m_ctx.m_mm.get_spare());
      id++;
    }
    Resource_limit rl;
    for (; id <= RG_COUNT; id++) {
      if (!m_ctx.m_mm.get_resource_limit(id, rl)) {
        continue;
      }
      if (rl.m_min || rl.m_curr || rl.m_max || rl.m_spare) {
        infoEvent("Resource %u min: %u max: %u curr: %u spare: %u", id,
                  rl.m_min, rl.m_max, rl.m_curr, rl.m_spare);
      }
    }
    m_ctx.m_mm.dump(false);  // To data node log
    return;
  }
  if (dumpState->args[0] == DumpStateOrd::DumpPageMemoryOnFail) {
    const Uint32 len = signal->getLength();
    const bool dump_on_fail = (len >= 2) ? (signal->theData[1] != 0) : true;
    m_ctx.m_mm.dump_on_alloc_fail(dump_on_fail);
    return;
  }
  if (arg == DumpStateOrd::CmvmiSchedulerExecutionTimer) {
    Uint32 exec_time = signal->theData[1];
    globalEmulatorData.theConfiguration->schedulerExecutionTimer(exec_time);
  }
  if (arg == DumpStateOrd::CmvmiSchedulerSpinTimer) {
    Uint32 spin_time = signal->theData[1];
    globalEmulatorData.theConfiguration->schedulerSpinTimer(spin_time);
  }
  if (arg == DumpStateOrd::CmvmiRealtimeScheduler) {
    bool realtime_on = signal->theData[1];
    globalEmulatorData.theConfiguration->realtimeScheduler(realtime_on);
  }
  if (arg == DumpStateOrd::CmvmiExecuteLockCPU) {
  }
  if (arg == DumpStateOrd::CmvmiMaintLockCPU) {
  }
  if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert) {
    if (signal->getLength() == 1) {
      Uint32 val = (Uint32)NRT_NoStart_Restart;
      const ndb_mgm_configuration_iterator *p =
          m_ctx.m_config.getOwnConfigIterator();
      ndbrequire(p != 0);

      if (!ndb_mgm_get_int_parameter(p, CFG_DB_STOP_ON_ERROR_INSERT, &val)) {
        m_ctx.m_config.setRestartOnErrorInsert(val);
      }
    } else {
      m_ctx.m_config.setRestartOnErrorInsert(signal->theData[1]);
    }
  }

  if (arg == DumpStateOrd::CmvmiTestLongSigWithDelay) {
    unsigned i;
    Uint32 testType = dumpState->args[1];
    Uint32 loopCount = dumpState->args[2];
    Uint32 print = dumpState->args[3];
    const unsigned len0 = 11;
    const unsigned len1 = 123;
    Uint32 sec0[len0];
    Uint32 sec1[len1];
    for (i = 0; i < len0; i++) sec0[i] = i;
    for (i = 0; i < len1; i++) sec1[i] = 16 * i;
    Uint32 *sig = signal->getDataPtrSend();
    sig[0] = reference();
    sig[1] = testType;
    sig[2] = 0;
    sig[3] = print;
    sig[4] = loopCount;
    sig[5] = len0;
    sig[6] = len1;
    sig[7] = 0;
    LinearSectionPtr ptr[3];
    ptr[0].p = sec0;
    ptr[0].sz = len0;
    ptr[1].p = sec1;
    ptr[1].sz = len1;
    sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2);
  }

  if (arg == DumpStateOrd::DumpEventLog) {
    /**
     * Array with m_saved_event_buffer indexes sorted by time and
     */
    Uint32 cnt = 0;
    Uint32 sorted[NDB_ARRAY_SIZE(m_saved_event_buffer)];

    /**
     * insert
     */
    for (Uint32 i = 0; i < NDB_ARRAY_SIZE(m_saved_event_buffer); i++) {
      if (m_saved_event_buffer[i].startScan()) continue;

      sorted[cnt] = i;
      cnt++;
    }

    /*
     * qsort
     */
    qsort(sorted, cnt, sizeof(Uint32), cmp_event_buf);

    Uint32 result_ref = signal->theData[1];
    SavedEvent s;
    EventReport *rep = CAST_PTR(EventReport, signal->getDataPtrSend());
    rep->setEventType(NDB_LE_SavedEvent);
    rep->setNodeId(getOwnNodeId());
    while (cnt > 0) {
      jam();

      bool done = m_saved_event_buffer[sorted[0]].scan(&s, 0);
      signal->theData[1] = s.m_len;
      signal->theData[2] = s.m_seq;
      signal->theData[3] = s.m_time;
      if (s.m_len <= 21) {
        jam();
        memcpy(signal->theData + 4, s.m_data, 4 * s.m_len);
        sendSignal(result_ref, GSN_EVENT_REP, signal, 4 + s.m_len, JBB);
      } else {
        jam();
        LinearSectionPtr ptr[3];
        ptr[0].p = s.m_data;
        ptr[0].sz = s.m_len;
        sendSignal(result_ref, GSN_EVENT_REP, signal, 4, JBB, ptr, 1);
      }

      if (done) {
        jam();
        memmove(sorted, sorted + 1, (cnt - 1) * sizeof(Uint32));
        cnt--;
      } else {
        jam();
        /**
         * sloppy...use qsort to re-sort
         */
        qsort(sorted, cnt, sizeof(Uint32), cmp_event_buf);
      }
    }
    signal->theData[1] = 0;  // end of stream
    sendSignal(result_ref, GSN_EVENT_REP, signal, 2, JBB);
    return;
  }

  if (arg == DumpStateOrd::CmvmiTestLongSig) {
    /* Forward as GSN_TESTSIG to self */
    Uint32 numArgs = signal->length() - 1;
    memmove(signal->getDataPtrSend(), signal->getDataPtrSend() + 1,
            numArgs << 2);
    sendSignal(reference(), GSN_TESTSIG, signal, numArgs, JBB);
  }

  if (arg == DumpStateOrd::CmvmiSetKillerWatchdog) {
    bool val = true;
    if (signal->length() >= 2) {
      val = (signal->theData[1] != 0);
    }
    globalEmulatorData.theWatchDog->setKillSwitch(val);
    return;
  }

  if (arg == DumpStateOrd::CmvmiSetWatchdogInterval) {
    Uint32 val = 6000;
    const ndb_mgm_configuration_iterator *p =
        m_ctx.m_config.getOwnConfigIterator();
    ndb_mgm_get_int_parameter(p, CFG_DB_WATCHDOG_INTERVAL, &val);

    if (signal->length() >= 2) {
      val = signal->theData[1];
    }
    g_eventLogger->info("Cmvmi : Setting watchdog interval to %u", val);
    update_watch_dog_timer(val);
  }

#ifdef ERROR_INSERT
  if (arg == DumpStateOrd::CmvmiSetErrorHandlingError) {
    Uint32 val = 0;
    Uint32 extra = 0;
    if (signal->length() >= 2) {
      val = signal->theData[1];
      if (signal->length() >= 3) {
        extra = signal->theData[2];
      }
    }
    g_eventLogger->info("Cmvmi : Setting ShutdownErrorHandling to %u %u", val,
                        extra);
    globalEmulatorData.theConfiguration->setShutdownHandlingFault(val, extra);
  }
#endif

#ifdef VM_TRACE
#if 0
  {
    SafeCounterManager mgr(* this); mgr.setSize(1);
    SafeCounterHandle handle;

    {
      SafeCounter tmp(mgr, handle);
      tmp.init<RefSignalTest>(CMVMI, GSN_TESTSIG, /* senderData */ 13);
      tmp.setWaitingFor(3);
      ndbrequire(!tmp.done());
      g_eventLogger->info("Allocated");
    }
    ndbrequire(!handle.done());
    {
      SafeCounter tmp(mgr, handle);
      tmp.clearWaitingFor(3);
      ndbrequire(tmp.done());
      g_eventLogger->info("Deallocated");
    }
    ndbrequire(handle.done());
  }
#endif
#endif

  if (arg == 9999) {
    Uint32 delay = 1000;
    switch (signal->getLength()) {
      case 1:
        break;
      case 2:
        delay = signal->theData[1];
        break;
      default: {
        Uint32 dmin = signal->theData[1];
        Uint32 dmax = signal->theData[2];
        delay = dmin + (rand() % (dmax - dmin));
        break;
      }
    }
    signal->theData[0] = arg;
    if (delay == 0) {
      execNDB_TAMPER(signal);
    } else if (delay < 10) {
      sendSignal(reference(), GSN_NDB_TAMPER, signal, 1, JBB);
    } else {
      sendSignalWithDelay(reference(), GSN_NDB_TAMPER, signal, delay, 1);
    }
  }

  if (signal->theData[0] == 666) {
    jam();
    Uint32 mb = 100;
    if (signal->getLength() > 1) mb = signal->theData[1];

    Uint64 bytes = Uint64(mb) * 1024 * 1024;
    AllocMemReq *req = CAST_PTR(AllocMemReq, signal->getDataPtrSend());
    req->senderData = 666;
    req->senderRef = reference();
    req->requestInfo = AllocMemReq::RT_EXTEND;
    req->bytes_hi = Uint32(bytes >> 32);
    req->bytes_lo = Uint32(bytes);
    sendSignal(NDBFS_REF, GSN_ALLOC_MEM_REQ, signal, AllocMemReq::SignalLength,
               JBB);
  }

#ifdef ERROR_INSERT
  if (signal->theData[0] == 667) {
    jam();
    Uint32 numFiles = 100;
    if (signal->getLength() == 2) {
      jam();
      numFiles = signal->theData[1];
    }

    /* Send a number of concurrent file open requests
     * for 'bound' files to NdbFS to test that it
     * copes
     * None are closed before all are open
     */
    g_remaining_responses = numFiles;

    g_eventLogger->info("CMVMI : Bulk open %u files", numFiles);
    FsOpenReq *openReq = (FsOpenReq *)&signal->theData[0];
    openReq->userReference = reference();
    openReq->userPointer = 0;
    openReq->fileNumber[0] = ~Uint32(0);
    openReq->fileNumber[1] = ~Uint32(0);
    openReq->fileNumber[2] = 0;
    openReq->fileNumber[3] = ~Uint32(0);
    FsOpenReq::setVersion(openReq->fileNumber, FsOpenReq::V_BLOCK);
    FsOpenReq::setSuffix(openReq->fileNumber, FsOpenReq::S_FRAGLOG);
    openReq->fileFlags = FsOpenReq::OM_WRITEONLY | FsOpenReq::OM_CREATE |
                         FsOpenReq::OM_TRUNCATE |
                         FsOpenReq::OM_ZEROS_ARE_SPARSE;

    openReq->page_size = 0;
    openReq->file_size_hi = UINT32_MAX;
    openReq->file_size_lo = UINT32_MAX;
    openReq->auto_sync_size = 0;

    for (Uint32 i = 0; i < numFiles; i++) {
      jam();
      openReq->fileNumber[2] = i;
      sendSignal(NDBFS_REF, GSN_FSOPENREQ, signal, FsOpenReq::SignalLength,
                 JBB);
    }
    g_eventLogger->info("CMVMI : %u requests sent", numFiles);
  }

  if (signal->theData[0] == 668) {
    jam();

    g_eventLogger->info("CMVMI : missing responses %u", g_remaining_responses);
    /* Check that all files were opened */
    ndbrequire(g_remaining_responses == 0);
  }
#endif  // ERROR_INSERT

}  // Cmvmi::execDUMP_STATE_ORD()