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()