1 /* Copyright (c) 2003-2007 MySQL AB
2 Use is subject to license terms
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #include "Cmvmi.hpp"
18
19 #include <Configuration.hpp>
20 #include <kernel_types.h>
21 #include <TransporterRegistry.hpp>
22 #include <NdbOut.hpp>
23 #include <NdbMem.h>
24
25 #include <SignalLoggerManager.hpp>
26 #include <FastScheduler.hpp>
27
28 #define DEBUG(x) { ndbout << "CMVMI::" << x << endl; }
29
30 #include <signaldata/TestOrd.hpp>
31 #include <signaldata/EventReport.hpp>
32 #include <signaldata/TamperOrd.hpp>
33 #include <signaldata/StartOrd.hpp>
34 #include <signaldata/CloseComReqConf.hpp>
35 #include <signaldata/SetLogLevelOrd.hpp>
36 #include <signaldata/EventSubscribeReq.hpp>
37 #include <signaldata/DumpStateOrd.hpp>
38 #include <signaldata/DisconnectRep.hpp>
39
40 #include <EventLogger.hpp>
41 #include <TimeQueue.hpp>
42
43 #include <NdbSleep.h>
44 #include <SafeCounter.hpp>
45
46 // Used here only to print event reports on stdout/console.
47 EventLogger g_eventLogger;
48 extern int simulate_error_during_shutdown;
49
Cmvmi(Block_context & ctx)50 Cmvmi::Cmvmi(Block_context& ctx) :
51 SimulatedBlock(CMVMI, ctx)
52 ,subscribers(subscriberPool)
53 {
54 BLOCK_CONSTRUCTOR(Cmvmi);
55
56 Uint32 long_sig_buffer_size;
57 const ndb_mgm_configuration_iterator * p =
58 m_ctx.m_config.getOwnConfigIterator();
59 ndbrequire(p != 0);
60
61 ndb_mgm_get_int_parameter(p, CFG_DB_LONG_SIGNAL_BUFFER,
62 &long_sig_buffer_size);
63
64 long_sig_buffer_size= long_sig_buffer_size / 256;
65 g_sectionSegmentPool.setSize(long_sig_buffer_size,
66 false,true,true,CFG_DB_LONG_SIGNAL_BUFFER);
67
68 // Add received signals
69 addRecSignal(GSN_CONNECT_REP, &Cmvmi::execCONNECT_REP);
70 addRecSignal(GSN_DISCONNECT_REP, &Cmvmi::execDISCONNECT_REP);
71
72 addRecSignal(GSN_NDB_TAMPER, &Cmvmi::execNDB_TAMPER, true);
73 addRecSignal(GSN_SET_LOGLEVELORD, &Cmvmi::execSET_LOGLEVELORD);
74 addRecSignal(GSN_EVENT_REP, &Cmvmi::execEVENT_REP);
75 addRecSignal(GSN_STTOR, &Cmvmi::execSTTOR);
76 addRecSignal(GSN_READ_CONFIG_REQ, &Cmvmi::execREAD_CONFIG_REQ);
77 addRecSignal(GSN_CLOSE_COMREQ, &Cmvmi::execCLOSE_COMREQ);
78 addRecSignal(GSN_ENABLE_COMORD, &Cmvmi::execENABLE_COMORD);
79 addRecSignal(GSN_OPEN_COMREQ, &Cmvmi::execOPEN_COMREQ);
80 addRecSignal(GSN_TEST_ORD, &Cmvmi::execTEST_ORD);
81
82 addRecSignal(GSN_TAMPER_ORD, &Cmvmi::execTAMPER_ORD);
83 addRecSignal(GSN_STOP_ORD, &Cmvmi::execSTOP_ORD);
84 addRecSignal(GSN_START_ORD, &Cmvmi::execSTART_ORD);
85 addRecSignal(GSN_EVENT_SUBSCRIBE_REQ,
86 &Cmvmi::execEVENT_SUBSCRIBE_REQ);
87
88 addRecSignal(GSN_DUMP_STATE_ORD, &Cmvmi::execDUMP_STATE_ORD);
89
90 addRecSignal(GSN_TESTSIG, &Cmvmi::execTESTSIG);
91 addRecSignal(GSN_NODE_START_REP, &Cmvmi::execNODE_START_REP, true);
92
93 subscriberPool.setSize(5);
94
95 const ndb_mgm_configuration_iterator * db = m_ctx.m_config.getOwnConfigIterator();
96 for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
97 Uint32 logLevel;
98 if(!ndb_mgm_get_int_parameter(db, CFG_MIN_LOGLEVEL+j, &logLevel)){
99 clogLevel.setLogLevel((LogLevel::EventCategory)j,
100 logLevel);
101 }
102 }
103
104 ndb_mgm_configuration_iterator * iter = m_ctx.m_config.getClusterConfigIterator();
105 for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
106 jam();
107 Uint32 nodeId;
108 Uint32 nodeType;
109
110 ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_NODE_ID, &nodeId));
111 ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_TYPE_OF_SECTION,&nodeType));
112
113 switch(nodeType){
114 case NodeInfo::DB:
115 c_dbNodes.set(nodeId);
116 break;
117 case NodeInfo::API:
118 case NodeInfo::MGM:
119 break;
120 default:
121 ndbrequire(false);
122 }
123 setNodeInfo(nodeId).m_type = nodeType;
124 }
125
126 setNodeInfo(getOwnNodeId()).m_connected = true;
127 setNodeInfo(getOwnNodeId()).m_version = ndbGetOwnVersion();
128 }
129
~Cmvmi()130 Cmvmi::~Cmvmi()
131 {
132 m_shared_page_pool.clear();
133 }
134
135 #ifdef ERROR_INSERT
136 NodeBitmask c_error_9000_nodes_mask;
137 extern Uint32 MAX_RECEIVED_SIGNALS;
138 #endif
139
execNDB_TAMPER(Signal * signal)140 void Cmvmi::execNDB_TAMPER(Signal* signal)
141 {
142 jamEntry();
143 SET_ERROR_INSERT_VALUE(signal->theData[0]);
144 if(ERROR_INSERTED(9999)){
145 CRASH_INSERTION(9999);
146 }
147
148 if(ERROR_INSERTED(9998)){
149 while(true) NdbSleep_SecSleep(1);
150 }
151
152 if(ERROR_INSERTED(9997)){
153 ndbrequire(false);
154 }
155
156 #ifndef NDB_WIN32
157 if(ERROR_INSERTED(9996)){
158 simulate_error_during_shutdown= SIGSEGV;
159 ndbrequire(false);
160 }
161
162 if(ERROR_INSERTED(9995)){
163 simulate_error_during_shutdown= SIGSEGV;
164 kill(getpid(), SIGABRT);
165 }
166 #endif
167
168 #ifdef ERROR_INSERT
169 if (signal->theData[0] == 9003)
170 {
171 if (MAX_RECEIVED_SIGNALS < 1024)
172 {
173 MAX_RECEIVED_SIGNALS = 1024;
174 }
175 else
176 {
177 MAX_RECEIVED_SIGNALS = 1 + (rand() % 128);
178 }
179 ndbout_c("MAX_RECEIVED_SIGNALS: %d", MAX_RECEIVED_SIGNALS);
180 CLEAR_ERROR_INSERT_VALUE;
181 }
182 #endif
183 }//execNDB_TAMPER()
184
execSET_LOGLEVELORD(Signal * signal)185 void Cmvmi::execSET_LOGLEVELORD(Signal* signal)
186 {
187 SetLogLevelOrd * const llOrd = (SetLogLevelOrd *)&signal->theData[0];
188 LogLevel::EventCategory category;
189 Uint32 level;
190 jamEntry();
191
192 for(unsigned int i = 0; i<llOrd->noOfEntries; i++){
193 category = (LogLevel::EventCategory)(llOrd->theData[i] >> 16);
194 level = llOrd->theData[i] & 0xFFFF;
195
196 clogLevel.setLogLevel(category, level);
197 }
198 }//execSET_LOGLEVELORD()
199
execEVENT_REP(Signal * signal)200 void Cmvmi::execEVENT_REP(Signal* signal)
201 {
202 //-----------------------------------------------------------------------
203 // This message is sent to report any types of events in NDB.
204 // Based on the log level they will be either ignored or
205 // reported. Currently they are printed, but they will be
206 // transferred to the management server for further distribution
207 // to the graphical management interface.
208 //-----------------------------------------------------------------------
209 EventReport * const eventReport = (EventReport *)&signal->theData[0];
210 Ndb_logevent_type eventType = eventReport->getEventType();
211 Uint32 nodeId= eventReport->getNodeId();
212 if (nodeId == 0)
213 {
214 nodeId= refToNode(signal->getSendersBlockRef());
215 eventReport->setNodeId(nodeId);
216 }
217
218 jamEntry();
219
220 /**
221 * If entry is not found
222 */
223 Uint32 threshold;
224 LogLevel::EventCategory eventCategory;
225 Logger::LoggerLevel severity;
226 EventLoggerBase::EventTextFunction textF;
227 if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity,textF))
228 return;
229
230 SubscriberPtr ptr;
231 for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
232 if(ptr.p->logLevel.getLogLevel(eventCategory) < threshold){
233 continue;
234 }
235
236 sendSignal(ptr.p->blockRef, GSN_EVENT_REP, signal, signal->length(), JBB);
237 }
238
239 if(clogLevel.getLogLevel(eventCategory) < threshold){
240 return;
241 }
242
243 // Print the event info
244 g_eventLogger.log(eventReport->getEventType(), signal->theData);
245
246 return;
247 }//execEVENT_REP()
248
249 void
execEVENT_SUBSCRIBE_REQ(Signal * signal)250 Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
251 EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0];
252 Uint32 senderRef = signal->getSendersBlockRef();
253 SubscriberPtr ptr;
254 jamEntry();
255 DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ");
256
257 /**
258 * Search for subcription
259 */
260 for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
261 if(ptr.p->blockRef == subReq->blockRef)
262 break;
263 }
264
265 if(ptr.i == RNIL){
266 /**
267 * Create a new one
268 */
269 if(subscribers.seize(ptr) == false){
270 sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
271 return;
272 }
273 ptr.p->logLevel.clear();
274 ptr.p->blockRef = subReq->blockRef;
275 }
276
277 if(subReq->noOfEntries == 0){
278 /**
279 * Cancel subscription
280 */
281 subscribers.release(ptr.i);
282 } else {
283 /**
284 * Update subscription
285 */
286 LogLevel::EventCategory category;
287 Uint32 level = 0;
288 for(Uint32 i = 0; i<subReq->noOfEntries; i++){
289 category = (LogLevel::EventCategory)(subReq->theData[i] >> 16);
290 level = subReq->theData[i] & 0xFFFF;
291 ptr.p->logLevel.setLogLevel(category, level);
292 DBUG_PRINT("info",("entry %d: level=%d, category= %d", i, level, category));
293 }
294 }
295
296 signal->theData[0] = ptr.i;
297 sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
298 DBUG_VOID_RETURN;
299 }
300
301 void
cancelSubscription(NodeId nodeId)302 Cmvmi::cancelSubscription(NodeId nodeId){
303
304 SubscriberPtr ptr;
305 subscribers.first(ptr);
306
307 while(ptr.i != RNIL){
308 Uint32 i = ptr.i;
309 BlockReference blockRef = ptr.p->blockRef;
310
311 subscribers.next(ptr);
312
313 if(refToNode(blockRef) == nodeId){
314 subscribers.release(i);
315 }
316 }
317 }
318
sendSTTORRY(Signal * signal)319 void Cmvmi::sendSTTORRY(Signal* signal)
320 {
321 jam();
322 signal->theData[3] = 1;
323 signal->theData[4] = 3;
324 signal->theData[5] = 8;
325 signal->theData[6] = 255;
326 sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
327 }//Cmvmi::sendSTTORRY
328
329
330 void
execREAD_CONFIG_REQ(Signal * signal)331 Cmvmi::execREAD_CONFIG_REQ(Signal* signal)
332 {
333 jamEntry();
334
335 const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
336
337 Uint32 ref = req->senderRef;
338 Uint32 senderData = req->senderData;
339
340 const ndb_mgm_configuration_iterator * p =
341 m_ctx.m_config.getOwnConfigIterator();
342 ndbrequire(p != 0);
343
344 Uint64 page_buffer = 64*1024*1024;
345 ndb_mgm_get_int64_parameter(p, CFG_DB_DISK_PAGE_BUFFER_MEMORY, &page_buffer);
346
347 Uint32 pages = 0;
348 pages += page_buffer / GLOBAL_PAGE_SIZE; // in pages
349 pages += LCP_RESTORE_BUFFER;
350 m_global_page_pool.setSize(pages + 64, true);
351
352 Uint64 shared_mem = 8*1024*1024;
353 ndb_mgm_get_int64_parameter(p, CFG_DB_SGA, &shared_mem);
354 shared_mem /= GLOBAL_PAGE_SIZE;
355 if (shared_mem)
356 {
357 Resource_limit rl;
358 rl.m_min = 0;
359 rl.m_max = shared_mem;
360 rl.m_resource_id = 0;
361 m_ctx.m_mm.set_resource_limit(rl);
362 }
363
364 ndbrequire(m_ctx.m_mm.init());
365 {
366 void* ptr = m_ctx.m_mm.get_memroot();
367 m_shared_page_pool.set((GlobalPage*)ptr, ~0);
368 }
369
370 ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
371 conf->senderRef = reference();
372 conf->senderData = senderData;
373 sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
374 ReadConfigConf::SignalLength, JBB);
375 }
376
execSTTOR(Signal * signal)377 void Cmvmi::execSTTOR(Signal* signal)
378 {
379 Uint32 theStartPhase = signal->theData[1];
380
381 jamEntry();
382 if (theStartPhase == 1){
383 jam();
384
385 if(m_ctx.m_config.lockPagesInMainMemory() == 1)
386 {
387 int res = NdbMem_MemLockAll(0);
388 if(res != 0){
389 g_eventLogger.warning("Failed to memlock pages");
390 warningEvent("Failed to memlock pages");
391 }
392 }
393
394 sendSTTORRY(signal);
395 return;
396 } else if (theStartPhase == 3) {
397 jam();
398 globalData.activateSendPacked = 1;
399 sendSTTORRY(signal);
400 } else if (theStartPhase == 8){
401 /*---------------------------------------------------*/
402 /* Open com to API + REP nodes */
403 /*---------------------------------------------------*/
404 signal->theData[0] = 0; // no answer
405 signal->theData[1] = 0; // no id
406 signal->theData[2] = NodeInfo::API;
407 execOPEN_COMREQ(signal);
408 globalData.theStartLevel = NodeState::SL_STARTED;
409 sendSTTORRY(signal);
410 }
411 }
412
execCLOSE_COMREQ(Signal * signal)413 void Cmvmi::execCLOSE_COMREQ(Signal* signal)
414 {
415 // Close communication with the node and halt input/output from
416 // other blocks than QMGR
417
418 CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
419
420 const BlockReference userRef = closeCom->xxxBlockRef;
421 Uint32 failNo = closeCom->failNo;
422 // Uint32 noOfNodes = closeCom->noOfNodes;
423
424 jamEntry();
425 for (unsigned i = 0; i < MAX_NODES; i++)
426 {
427 if(NodeBitmask::get(closeCom->theNodes, i))
428 {
429 jam();
430
431 //-----------------------------------------------------
432 // Report that the connection to the node is closed
433 //-----------------------------------------------------
434 signal->theData[0] = NDB_LE_CommunicationClosed;
435 signal->theData[1] = i;
436 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
437
438 globalTransporterRegistry.setIOState(i, HaltIO);
439 globalTransporterRegistry.do_disconnect(i);
440 }
441 }
442
443 if (failNo != 0)
444 {
445 jam();
446 signal->theData[0] = userRef;
447 signal->theData[1] = failNo;
448 sendSignal(QMGR_REF, GSN_CLOSE_COMCONF, signal, 19, JBA);
449 }
450 }
451
execOPEN_COMREQ(Signal * signal)452 void Cmvmi::execOPEN_COMREQ(Signal* signal)
453 {
454 // Connect to the specifed NDB node, only QMGR allowed communication
455 // so far with the node
456
457 const BlockReference userRef = signal->theData[0];
458 Uint32 tStartingNode = signal->theData[1];
459 Uint32 tData2 = signal->theData[2];
460 jamEntry();
461
462 const Uint32 len = signal->getLength();
463 if(len == 2)
464 {
465 #ifdef ERROR_INSERT
466 if (! ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
467 && c_error_9000_nodes_mask.get(tStartingNode)))
468 #endif
469 {
470 if (globalData.theStartLevel != NodeState::SL_STARTED &&
471 (getNodeInfo(tStartingNode).m_type != NodeInfo::DB &&
472 getNodeInfo(tStartingNode).m_type != NodeInfo::MGM))
473 {
474 jam();
475 goto done;
476 }
477
478 globalTransporterRegistry.do_connect(tStartingNode);
479 globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
480
481 //-----------------------------------------------------
482 // Report that the connection to the node is opened
483 //-----------------------------------------------------
484 signal->theData[0] = NDB_LE_CommunicationOpened;
485 signal->theData[1] = tStartingNode;
486 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
487 //-----------------------------------------------------
488 }
489 } else {
490 for(unsigned int i = 1; i < MAX_NODES; i++ )
491 {
492 jam();
493 if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2)
494 {
495 jam();
496
497 #ifdef ERROR_INSERT
498 if ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
499 && c_error_9000_nodes_mask.get(i))
500 continue;
501 #endif
502
503 globalTransporterRegistry.do_connect(i);
504 globalTransporterRegistry.setIOState(i, HaltIO);
505
506 signal->theData[0] = NDB_LE_CommunicationOpened;
507 signal->theData[1] = i;
508 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
509 }
510 }
511 }
512
513 done:
514 if (userRef != 0) {
515 jam();
516 signal->theData[0] = tStartingNode;
517 signal->theData[1] = tData2;
518 sendSignal(userRef, GSN_OPEN_COMCONF, signal, len - 1,JBA);
519 }
520 }
521
execENABLE_COMORD(Signal * signal)522 void Cmvmi::execENABLE_COMORD(Signal* signal)
523 {
524 // Enable communication with all our NDB blocks to this node
525
526 Uint32 tStartingNode = signal->theData[0];
527 globalTransporterRegistry.setIOState(tStartingNode, NoHalt);
528 setNodeInfo(tStartingNode).m_connected = true;
529 //-----------------------------------------------------
530 // Report that the version of the node
531 //-----------------------------------------------------
532 signal->theData[0] = NDB_LE_ConnectedApiVersion;
533 signal->theData[1] = tStartingNode;
534 signal->theData[2] = getNodeInfo(tStartingNode).m_version;
535
536 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 3, JBB);
537 //-----------------------------------------------------
538
539 jamEntry();
540 }
541
execDISCONNECT_REP(Signal * signal)542 void Cmvmi::execDISCONNECT_REP(Signal *signal)
543 {
544 const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
545 const Uint32 hostId = rep->nodeId;
546 const Uint32 errNo = rep->err;
547
548 jamEntry();
549
550 setNodeInfo(hostId).m_connected = false;
551 setNodeInfo(hostId).m_connectCount++;
552 const NodeInfo::NodeType type = getNodeInfo(hostId).getType();
553 ndbrequire(type != NodeInfo::INVALID);
554
555 sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
556 DisconnectRep::SignalLength, JBA);
557
558 cancelSubscription(hostId);
559
560 signal->theData[0] = NDB_LE_Disconnected;
561 signal->theData[1] = hostId;
562 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
563 }
564
execCONNECT_REP(Signal * signal)565 void Cmvmi::execCONNECT_REP(Signal *signal){
566 const Uint32 hostId = signal->theData[0];
567 jamEntry();
568
569 const NodeInfo::NodeType type = (NodeInfo::NodeType)getNodeInfo(hostId).m_type;
570 ndbrequire(type != NodeInfo::INVALID);
571 globalData.m_nodeInfo[hostId].m_version = 0;
572 globalData.m_nodeInfo[hostId].m_signalVersion = 0;
573
574 if(type == NodeInfo::DB || globalData.theStartLevel >= NodeState::SL_STARTED){
575 jam();
576
577 /**
578 * Inform QMGR that client has connected
579 */
580
581 signal->theData[0] = hostId;
582 sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
583 } else if(globalData.theStartLevel == NodeState::SL_CMVMI ||
584 globalData.theStartLevel == NodeState::SL_STARTING) {
585 jam();
586 /**
587 * Someone connected before start was finished
588 */
589 if(type == NodeInfo::MGM){
590 jam();
591 signal->theData[0] = hostId;
592 sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
593 } else {
594 /**
595 * Dont allow api nodes to connect
596 */
597 ndbout_c("%d %d %d", hostId, type, globalData.theStartLevel);
598 abort();
599 globalTransporterRegistry.do_disconnect(hostId);
600 }
601 }
602
603 /* Automatically subscribe events for MGM nodes.
604 */
605 if(type == NodeInfo::MGM){
606 jam();
607 globalTransporterRegistry.setIOState(hostId, NoHalt);
608 }
609
610 //------------------------------------------
611 // Also report this event to the Event handler
612 //------------------------------------------
613 signal->theData[0] = NDB_LE_Connected;
614 signal->theData[1] = hostId;
615 signal->header.theLength = 2;
616
617 execEVENT_REP(signal);
618 }
619
620 #ifdef VM_TRACE
621 void
modifySignalLogger(bool allBlocks,BlockNumber bno,TestOrd::Command cmd,TestOrd::SignalLoggerSpecification spec)622 modifySignalLogger(bool allBlocks, BlockNumber bno,
623 TestOrd::Command cmd,
624 TestOrd::SignalLoggerSpecification spec){
625 SignalLoggerManager::LogMode logMode;
626
627 /**
628 * Mapping between SignalLoggerManager::LogMode and
629 * TestOrd::SignalLoggerSpecification
630 */
631 switch(spec){
632 case TestOrd::InputSignals:
633 logMode = SignalLoggerManager::LogIn;
634 break;
635 case TestOrd::OutputSignals:
636 logMode = SignalLoggerManager::LogOut;
637 break;
638 case TestOrd::InputOutputSignals:
639 logMode = SignalLoggerManager::LogInOut;
640 break;
641 default:
642 return;
643 break;
644 }
645
646 switch(cmd){
647 case TestOrd::On:
648 globalSignalLoggers.logOn(allBlocks, bno, logMode);
649 break;
650 case TestOrd::Off:
651 globalSignalLoggers.logOff(allBlocks, bno, logMode);
652 break;
653 case TestOrd::Toggle:
654 globalSignalLoggers.logToggle(allBlocks, bno, logMode);
655 break;
656 case TestOrd::KeepUnchanged:
657 // Do nothing
658 break;
659 }
660 globalSignalLoggers.flushSignalLog();
661 }
662 #endif
663
664 void
execTEST_ORD(Signal * signal)665 Cmvmi::execTEST_ORD(Signal * signal){
666 jamEntry();
667
668 #ifdef VM_TRACE
669 TestOrd * const testOrd = (TestOrd *)&signal->theData[0];
670
671 TestOrd::Command cmd;
672
673 {
674 /**
675 * Process Trace command
676 */
677 TestOrd::TraceSpecification traceSpec;
678
679 testOrd->getTraceCommand(cmd, traceSpec);
680 unsigned long traceVal = traceSpec;
681 unsigned long currentTraceVal = globalSignalLoggers.getTrace();
682 switch(cmd){
683 case TestOrd::On:
684 currentTraceVal |= traceVal;
685 break;
686 case TestOrd::Off:
687 currentTraceVal &= (~traceVal);
688 break;
689 case TestOrd::Toggle:
690 currentTraceVal ^= traceVal;
691 break;
692 case TestOrd::KeepUnchanged:
693 // Do nothing
694 break;
695 }
696 globalSignalLoggers.setTrace(currentTraceVal);
697 }
698
699 {
700 /**
701 * Process Log command
702 */
703 TestOrd::SignalLoggerSpecification logSpec;
704 BlockNumber bno;
705 unsigned int loggers = testOrd->getNoOfSignalLoggerCommands();
706
707 if(loggers == (unsigned)~0){ // Apply command to all blocks
708 testOrd->getSignalLoggerCommand(0, bno, cmd, logSpec);
709 modifySignalLogger(true, bno, cmd, logSpec);
710 } else {
711 for(unsigned int i = 0; i<loggers; i++){
712 testOrd->getSignalLoggerCommand(i, bno, cmd, logSpec);
713 modifySignalLogger(false, bno, cmd, logSpec);
714 }
715 }
716 }
717
718 {
719 /**
720 * Process test command
721 */
722 testOrd->getTestCommand(cmd);
723 switch(cmd){
724 case TestOrd::On:{
725 SET_GLOBAL_TEST_ON;
726 }
727 break;
728 case TestOrd::Off:{
729 SET_GLOBAL_TEST_OFF;
730 }
731 break;
732 case TestOrd::Toggle:{
733 TOGGLE_GLOBAL_TEST_FLAG;
734 }
735 break;
736 case TestOrd::KeepUnchanged:
737 // Do nothing
738 break;
739 }
740 globalSignalLoggers.flushSignalLog();
741 }
742
743 #endif
744 }
745
execSTOP_ORD(Signal * signal)746 void Cmvmi::execSTOP_ORD(Signal* signal)
747 {
748 jamEntry();
749 globalData.theRestartFlag = perform_stop;
750 }//execSTOP_ORD()
751
752 void
execSTART_ORD(Signal * signal)753 Cmvmi::execSTART_ORD(Signal* signal) {
754
755 StartOrd * const startOrd = (StartOrd *)&signal->theData[0];
756 jamEntry();
757
758 Uint32 tmp = startOrd->restartInfo;
759 if(StopReq::getPerformRestart(tmp)){
760 jam();
761 /**
762 *
763 */
764 NdbRestartType type = NRT_Default;
765 if(StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
766 type = NRT_NoStart_InitialStart;
767 if(StopReq::getNoStart(tmp) && !StopReq::getInitialStart(tmp))
768 type = NRT_NoStart_Restart;
769 if(!StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
770 type = NRT_DoStart_InitialStart;
771 if(!StopReq::getNoStart(tmp)&&!StopReq::getInitialStart(tmp))
772 type = NRT_DoStart_Restart;
773 NdbShutdown(NST_Restart, type);
774 }
775
776 if(globalData.theRestartFlag == system_started){
777 jam()
778 /**
779 * START_ORD received when already started(ignored)
780 */
781 //ndbout << "START_ORD received when already started(ignored)" << endl;
782 return;
783 }
784
785 if(globalData.theRestartFlag == perform_stop){
786 jam()
787 /**
788 * START_ORD received when stopping(ignored)
789 */
790 //ndbout << "START_ORD received when stopping(ignored)" << endl;
791 return;
792 }
793
794 if(globalData.theStartLevel == NodeState::SL_NOTHING){
795 jam();
796 globalData.theStartLevel = NodeState::SL_CMVMI;
797 /**
798 * Open connections to management servers
799 */
800 for(unsigned int i = 1; i < MAX_NODES; i++ ){
801 if (getNodeInfo(i).m_type == NodeInfo::MGM){
802 if(!globalTransporterRegistry.is_connected(i)){
803 globalTransporterRegistry.do_connect(i);
804 globalTransporterRegistry.setIOState(i, NoHalt);
805 }
806 }
807 }
808
809 EXECUTE_DIRECT(QMGR, GSN_START_ORD, signal, 1);
810 return ;
811 }
812
813 if(globalData.theStartLevel == NodeState::SL_CMVMI){
814 jam();
815
816 if(m_ctx.m_config.lockPagesInMainMemory() == 2)
817 {
818 int res = NdbMem_MemLockAll(1);
819 if(res != 0)
820 {
821 g_eventLogger.warning("Failed to memlock pages");
822 warningEvent("Failed to memlock pages");
823 }
824 else
825 {
826 g_eventLogger.info("Locked future allocations");
827 }
828 }
829
830 globalData.theStartLevel = NodeState::SL_STARTING;
831 globalData.theRestartFlag = system_started;
832 /**
833 * StartLevel 1
834 *
835 * Do Restart
836 */
837
838 // Disconnect all nodes as part of the system restart.
839 // We need to ensure that we are starting up
840 // without any connected nodes.
841 for(unsigned int i = 1; i < MAX_NODES; i++ ){
842 if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM){
843 globalTransporterRegistry.do_disconnect(i);
844 globalTransporterRegistry.setIOState(i, HaltIO);
845 }
846 }
847
848 /**
849 * Start running startphases
850 */
851 sendSignal(NDBCNTR_REF, GSN_START_ORD, signal, 1, JBA);
852 return;
853 }
854 }//execSTART_ORD()
855
execTAMPER_ORD(Signal * signal)856 void Cmvmi::execTAMPER_ORD(Signal* signal)
857 {
858 jamEntry();
859 // TODO We should maybe introduce a CONF and REF signal
860 // to be able to indicate if we really introduced an error.
861 #ifdef ERROR_INSERT
862 TamperOrd* const tamperOrd = (TamperOrd*)&signal->theData[0];
863 signal->theData[2] = 0;
864 signal->theData[1] = tamperOrd->errorNo;
865 signal->theData[0] = 5;
866 sendSignal(DBDIH_REF, GSN_DIHNDBTAMPER, signal, 3,JBB);
867 #endif
868
869 }//execTAMPER_ORD()
870
871 #ifdef VM_TRACE
872 class RefSignalTest {
873 public:
874 enum ErrorCode {
875 OK = 0,
876 NF_FakeErrorREF = 7
877 };
878 Uint32 senderRef;
879 Uint32 senderData;
880 Uint32 errorCode;
881 };
882 #endif
883
884
885 static int iii;
886
887 static
888 int
recurse(char * buf,int loops,int arg)889 recurse(char * buf, int loops, int arg){
890 char * tmp = (char*)alloca(arg);
891 printf("tmp = %p\n", tmp);
892 for(iii = 0; iii<arg; iii += 1024){
893 tmp[iii] = (iii % 23 + (arg & iii));
894 }
895
896 if(loops == 0)
897 return tmp[345];
898 else
899 return tmp[arg/loops] + recurse(tmp, loops - 1, arg);
900 }
901
902 void
execDUMP_STATE_ORD(Signal * signal)903 Cmvmi::execDUMP_STATE_ORD(Signal* signal)
904 {
905
906 sendSignal(QMGR_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
907 sendSignal(NDBCNTR_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
908 sendSignal(DBTC_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
909 sendSignal(DBDIH_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
910 sendSignal(DBDICT_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
911 sendSignal(DBLQH_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
912 sendSignal(DBTUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
913 sendSignal(DBACC_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
914 sendSignal(NDBFS_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
915 sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
916 sendSignal(DBUTIL_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
917 sendSignal(SUMA_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
918 sendSignal(TRIX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
919 sendSignal(DBTUX_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
920 sendSignal(LGMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
921 sendSignal(TSMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
922 sendSignal(PGMAN_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
923
924 /**
925 *
926 * Here I can dump CMVMI state if needed
927 */
928 if(signal->theData[0] == 13){
929 #if 0
930 int loop = 100;
931 int len = (10*1024*1024);
932 if(signal->getLength() > 1)
933 loop = signal->theData[1];
934 if(signal->getLength() > 2)
935 len = signal->theData[2];
936
937 ndbout_c("recurse(%d loop, %dkb per recurse)", loop, len/1024);
938 int a = recurse(0, loop, len);
939 ndbout_c("after...%d", a);
940 #endif
941 }
942
943 DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
944 Uint32 arg = dumpState->args[0];
945 if (arg == DumpStateOrd::CmvmiDumpConnections){
946 for(unsigned int i = 1; i < MAX_NODES; i++ ){
947 const char* nodeTypeStr = "";
948 switch(getNodeInfo(i).m_type){
949 case NodeInfo::DB:
950 nodeTypeStr = "DB";
951 break;
952 case NodeInfo::API:
953 nodeTypeStr = "API";
954 break;
955 case NodeInfo::MGM:
956 nodeTypeStr = "MGM";
957 break;
958 case NodeInfo::INVALID:
959 nodeTypeStr = 0;
960 break;
961 default:
962 nodeTypeStr = "<UNKNOWN>";
963 }
964
965 if(nodeTypeStr == 0)
966 continue;
967
968 infoEvent("Connection to %d (%s) %s",
969 i,
970 nodeTypeStr,
971 globalTransporterRegistry.getPerformStateString(i));
972 }
973 }
974
975 if (arg == DumpStateOrd::CmvmiDumpSubscriptions)
976 {
977 SubscriberPtr ptr;
978 subscribers.first(ptr);
979 g_eventLogger.info("List subscriptions:");
980 while(ptr.i != RNIL)
981 {
982 g_eventLogger.info("Subscription: %u, nodeId: %u, ref: 0x%x",
983 ptr.i, refToNode(ptr.p->blockRef), ptr.p->blockRef);
984 for(Uint32 i = 0; i < LogLevel::LOGLEVEL_CATEGORIES; i++)
985 {
986 Uint32 level = ptr.p->logLevel.getLogLevel((LogLevel::EventCategory)i);
987 g_eventLogger.info("Category %u Level %u", i, level);
988 }
989 subscribers.next(ptr);
990 }
991 }
992
993 if (arg == DumpStateOrd::CmvmiDumpLongSignalMemory){
994 infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
995 g_sectionSegmentPool.getSize(),
996 g_sectionSegmentPool.getNoOfFree());
997 }
998
999 if (dumpState->args[0] == 1000)
1000 {
1001 Uint32 len = signal->getLength();
1002 if (signal->getLength() == 1)
1003 {
1004 signal->theData[1] = 0;
1005 signal->theData[2] = ~0;
1006 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
1007 return;
1008 }
1009 Uint32 id = signal->theData[1];
1010 Resource_limit rl;
1011 if (!m_ctx.m_mm.get_resource_limit(id, rl))
1012 len = 2;
1013 else
1014 {
1015 if (rl.m_min || rl.m_curr || rl.m_max)
1016 infoEvent("Resource %d min: %d max: %d curr: %d",
1017 id, rl.m_min, rl.m_max, rl.m_curr);
1018 }
1019
1020 if (len == 3)
1021 {
1022 signal->theData[0] = 1000;
1023 signal->theData[1] = id+1;
1024 signal->theData[2] = ~0;
1025 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
1026 }
1027 return;
1028 }
1029
1030 if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert)
1031 {
1032 if(signal->getLength() == 1)
1033 {
1034 Uint32 val = (Uint32)NRT_NoStart_Restart;
1035 const ndb_mgm_configuration_iterator * p =
1036 m_ctx.m_config.getOwnConfigIterator();
1037 ndbrequire(p != 0);
1038
1039 if(!ndb_mgm_get_int_parameter(p, CFG_DB_STOP_ON_ERROR_INSERT, &val))
1040 {
1041 m_ctx.m_config.setRestartOnErrorInsert(val);
1042 }
1043 }
1044 else
1045 {
1046 m_ctx.m_config.setRestartOnErrorInsert(signal->theData[1]);
1047 }
1048 }
1049
1050 if (arg == DumpStateOrd::CmvmiTestLongSigWithDelay) {
1051 unsigned i;
1052 Uint32 loopCount = dumpState->args[1];
1053 const unsigned len0 = 11;
1054 const unsigned len1 = 123;
1055 Uint32 sec0[len0];
1056 Uint32 sec1[len1];
1057 for (i = 0; i < len0; i++)
1058 sec0[i] = i;
1059 for (i = 0; i < len1; i++)
1060 sec1[i] = 16 * i;
1061 Uint32* sig = signal->getDataPtrSend();
1062 sig[0] = reference();
1063 sig[1] = 20; // test type
1064 sig[2] = 0;
1065 sig[3] = 0;
1066 sig[4] = loopCount;
1067 sig[5] = len0;
1068 sig[6] = len1;
1069 sig[7] = 0;
1070 LinearSectionPtr ptr[3];
1071 ptr[0].p = sec0;
1072 ptr[0].sz = len0;
1073 ptr[1].p = sec1;
1074 ptr[1].sz = len1;
1075 sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2);
1076 }
1077
1078 #ifdef ERROR_INSERT
1079 if (arg == 9000 || arg == 9002)
1080 {
1081 SET_ERROR_INSERT_VALUE(arg);
1082 for (Uint32 i = 1; i<signal->getLength(); i++)
1083 c_error_9000_nodes_mask.set(signal->theData[i]);
1084 }
1085
1086 if (arg == 9001)
1087 {
1088 CLEAR_ERROR_INSERT_VALUE;
1089 if (signal->getLength() == 1 || signal->theData[1])
1090 {
1091 for (Uint32 i = 0; i<MAX_NODES; i++)
1092 {
1093 if (c_error_9000_nodes_mask.get(i))
1094 {
1095 signal->theData[0] = 0;
1096 signal->theData[1] = i;
1097 EXECUTE_DIRECT(CMVMI, GSN_OPEN_COMREQ, signal, 2);
1098 }
1099 }
1100 }
1101 c_error_9000_nodes_mask.clear();
1102 }
1103 #endif
1104
1105 #ifdef VM_TRACE
1106 #if 0
1107 {
1108 SafeCounterManager mgr(* this); mgr.setSize(1);
1109 SafeCounterHandle handle;
1110
1111 {
1112 SafeCounter tmp(mgr, handle);
1113 tmp.init<RefSignalTest>(CMVMI, GSN_TESTSIG, /* senderData */ 13);
1114 tmp.setWaitingFor(3);
1115 ndbrequire(!tmp.done());
1116 ndbout_c("Allocted");
1117 }
1118 ndbrequire(!handle.done());
1119 {
1120 SafeCounter tmp(mgr, handle);
1121 tmp.clearWaitingFor(3);
1122 ndbrequire(tmp.done());
1123 ndbout_c("Deallocted");
1124 }
1125 ndbrequire(handle.done());
1126 }
1127 #endif
1128 #endif
1129
1130 if (arg == 9999)
1131 {
1132 Uint32 delay = 1000;
1133 switch(signal->getLength()){
1134 case 1:
1135 break;
1136 case 2:
1137 delay = signal->theData[1];
1138 break;
1139 default:{
1140 Uint32 dmin = signal->theData[1];
1141 Uint32 dmax = signal->theData[2];
1142 delay = dmin + (rand() % (dmax - dmin));
1143 break;
1144 }
1145 }
1146
1147 signal->theData[0] = 9999;
1148 if (delay == 0)
1149 {
1150 execNDB_TAMPER(signal);
1151 }
1152 else if (delay < 10)
1153 {
1154 sendSignal(reference(), GSN_NDB_TAMPER, signal, 1, JBB);
1155 }
1156 else
1157 {
1158 sendSignalWithDelay(reference(), GSN_NDB_TAMPER, signal, delay, 1);
1159 }
1160 }
1161 }//Cmvmi::execDUMP_STATE_ORD()
1162
1163 void
execNODE_START_REP(Signal * signal)1164 Cmvmi::execNODE_START_REP(Signal* signal)
1165 {
1166 #ifdef ERROR_INSERT
1167 if (ERROR_INSERTED(9002) && signal->theData[0] == getOwnNodeId())
1168 {
1169 signal->theData[0] = 9001;
1170 execDUMP_STATE_ORD(signal);
1171 }
1172 #endif
1173 }
1174
1175 BLOCK_FUNCTIONS(Cmvmi)
1176
1177 static Uint32 g_print;
1178 static LinearSectionPtr g_test[3];
1179
1180 void
execTESTSIG(Signal * signal)1181 Cmvmi::execTESTSIG(Signal* signal){
1182 Uint32 i;
1183 /**
1184 * Test of SafeCounter
1185 */
1186 jamEntry();
1187
1188 if(!assembleFragments(signal)){
1189 jam();
1190 return;
1191 }
1192
1193 Uint32 ref = signal->theData[0];
1194 Uint32 testType = signal->theData[1];
1195 Uint32 fragmentLength = signal->theData[2];
1196 g_print = signal->theData[3];
1197 // Uint32 returnCount = signal->theData[4];
1198 Uint32 * secSizes = &signal->theData[5];
1199
1200 if(g_print){
1201 SignalLoggerManager::printSignalHeader(stdout,
1202 signal->header,
1203 0,
1204 getOwnNodeId(),
1205 true);
1206 ndbout_c("-- Fixed section --");
1207 for(i = 0; i<signal->length(); i++){
1208 fprintf(stdout, "H'0x%.8x ", signal->theData[i]);
1209 if(((i + 1) % 6) == 0)
1210 fprintf(stdout, "\n");
1211 }
1212 fprintf(stdout, "\n");
1213
1214 for(i = 0; i<signal->header.m_noOfSections; i++){
1215 SegmentedSectionPtr ptr(0,0,0);
1216 ndbout_c("-- Section %d --", i);
1217 signal->getSection(ptr, i);
1218 ndbrequire(ptr.p != 0);
1219 print(ptr, stdout);
1220 ndbrequire(ptr.sz == secSizes[i]);
1221 }
1222 }
1223
1224 /**
1225 * Validate length:s
1226 */
1227 for(i = 0; i<signal->header.m_noOfSections; i++){
1228 SegmentedSectionPtr ptr;
1229 signal->getSection(ptr, i);
1230 ndbrequire(ptr.p != 0);
1231 ndbrequire(ptr.sz == secSizes[i]);
1232 }
1233
1234 /**
1235 * Testing send with delay.
1236 */
1237 if (testType == 20) {
1238 if (signal->theData[4] == 0) {
1239 releaseSections(signal);
1240 return;
1241 }
1242 signal->theData[4]--;
1243 sendSignalWithDelay(reference(), GSN_TESTSIG, signal, 100, 8);
1244 return;
1245 }
1246
1247 NodeReceiverGroup rg(CMVMI, c_dbNodes);
1248
1249 if(signal->getSendersBlockRef() == ref){
1250 /**
1251 * Signal from API (not via NodeReceiverGroup)
1252 */
1253 if((testType % 2) == 1){
1254 signal->theData[4] = 1;
1255 } else {
1256 signal->theData[1] --;
1257 signal->theData[4] = rg.m_nodes.count();
1258 }
1259 }
1260
1261 switch(testType){
1262 case 1:
1263 sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
1264 break;
1265 case 2:
1266 sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
1267 break;
1268 case 3:
1269 case 4:{
1270 LinearSectionPtr ptr[3];
1271 const Uint32 secs = signal->getNoOfSections();
1272 for(i = 0; i<secs; i++){
1273 SegmentedSectionPtr sptr(0,0,0);
1274 signal->getSection(sptr, i);
1275 ptr[i].sz = sptr.sz;
1276 ptr[i].p = new Uint32[sptr.sz];
1277 copy(ptr[i].p, sptr);
1278 }
1279
1280 if(testType == 3){
1281 sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB, ptr, secs);
1282 } else {
1283 sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB, ptr, secs);
1284 }
1285 for(Uint32 i = 0; i<secs; i++){
1286 delete[] ptr[i].p;
1287 }
1288 break;
1289 }
1290 case 5:
1291 case 6:{
1292
1293 NodeReceiverGroup tmp;
1294 if(testType == 5){
1295 tmp = ref;
1296 } else {
1297 tmp = rg;
1298 }
1299
1300 FragmentSendInfo fragSend;
1301 sendFirstFragment(fragSend,
1302 tmp,
1303 GSN_TESTSIG,
1304 signal,
1305 signal->length(),
1306 JBB,
1307 fragmentLength);
1308 int count = 1;
1309 while(fragSend.m_status != FragmentSendInfo::SendComplete){
1310 count++;
1311 if(g_print)
1312 ndbout_c("Sending fragment %d", count);
1313 sendNextSegmentedFragment(signal, fragSend);
1314 }
1315 break;
1316 }
1317 case 7:
1318 case 8:{
1319 LinearSectionPtr ptr[3];
1320 const Uint32 secs = signal->getNoOfSections();
1321 for(i = 0; i<secs; i++){
1322 SegmentedSectionPtr sptr(0,0,0);
1323 signal->getSection(sptr, i);
1324 ptr[i].sz = sptr.sz;
1325 ptr[i].p = new Uint32[sptr.sz];
1326 copy(ptr[i].p, sptr);
1327 }
1328
1329 NodeReceiverGroup tmp;
1330 if(testType == 7){
1331 tmp = ref;
1332 } else {
1333 tmp = rg;
1334 }
1335
1336 FragmentSendInfo fragSend;
1337 sendFirstFragment(fragSend,
1338 tmp,
1339 GSN_TESTSIG,
1340 signal,
1341 signal->length(),
1342 JBB,
1343 ptr,
1344 secs,
1345 fragmentLength);
1346
1347 int count = 1;
1348 while(fragSend.m_status != FragmentSendInfo::SendComplete){
1349 count++;
1350 if(g_print)
1351 ndbout_c("Sending fragment %d", count);
1352 sendNextLinearFragment(signal, fragSend);
1353 }
1354
1355 for(i = 0; i<secs; i++){
1356 delete[] ptr[i].p;
1357 }
1358 break;
1359 }
1360 case 9:
1361 case 10:{
1362
1363 Callback m_callBack;
1364 m_callBack.m_callbackFunction =
1365 safe_cast(&Cmvmi::sendFragmentedComplete);
1366
1367 if(testType == 9){
1368 m_callBack.m_callbackData = 9;
1369 sendFragmentedSignal(ref,
1370 GSN_TESTSIG, signal, signal->length(), JBB,
1371 m_callBack,
1372 fragmentLength);
1373 } else {
1374 m_callBack.m_callbackData = 10;
1375 sendFragmentedSignal(rg,
1376 GSN_TESTSIG, signal, signal->length(), JBB,
1377 m_callBack,
1378 fragmentLength);
1379 }
1380 break;
1381 }
1382 case 11:
1383 case 12:{
1384
1385 const Uint32 secs = signal->getNoOfSections();
1386 memset(g_test, 0, sizeof(g_test));
1387 for(i = 0; i<secs; i++){
1388 SegmentedSectionPtr sptr(0,0,0);
1389 signal->getSection(sptr, i);
1390 g_test[i].sz = sptr.sz;
1391 g_test[i].p = new Uint32[sptr.sz];
1392 copy(g_test[i].p, sptr);
1393 }
1394
1395
1396 Callback m_callBack;
1397 m_callBack.m_callbackFunction =
1398 safe_cast(&Cmvmi::sendFragmentedComplete);
1399
1400 if(testType == 11){
1401 m_callBack.m_callbackData = 11;
1402 sendFragmentedSignal(ref,
1403 GSN_TESTSIG, signal, signal->length(), JBB,
1404 g_test, secs,
1405 m_callBack,
1406 fragmentLength);
1407 } else {
1408 m_callBack.m_callbackData = 12;
1409 sendFragmentedSignal(rg,
1410 GSN_TESTSIG, signal, signal->length(), JBB,
1411 g_test, secs,
1412 m_callBack,
1413 fragmentLength);
1414 }
1415 break;
1416 }
1417 case 13:{
1418 ndbrequire(signal->getNoOfSections() == 0);
1419 Uint32 loop = signal->theData[9];
1420 if(loop > 0){
1421 signal->theData[9] --;
1422 sendSignal(CMVMI_REF, GSN_TESTSIG, signal, signal->length(), JBB);
1423 return;
1424 }
1425 sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
1426 return;
1427 }
1428 case 14:{
1429 Uint32 count = signal->theData[8];
1430 signal->theData[10] = count * rg.m_nodes.count();
1431 for(i = 0; i<count; i++){
1432 sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
1433 }
1434 return;
1435 }
1436
1437 default:
1438 ndbrequire(false);
1439 }
1440 return;
1441 }
1442
1443 void
sendFragmentedComplete(Signal * signal,Uint32 data,Uint32 returnCode)1444 Cmvmi::sendFragmentedComplete(Signal* signal, Uint32 data, Uint32 returnCode){
1445 if(g_print)
1446 ndbout_c("sendFragmentedComplete: %d", data);
1447 if(data == 11 || data == 12){
1448 for(Uint32 i = 0; i<3; i++){
1449 if(g_test[i].p != 0)
1450 delete[] g_test[i].p;
1451 }
1452 }
1453 }
1454