1 /*
2 Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
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, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #include "Cmvmi.hpp"
26
27 #include <Configuration.hpp>
28 #include <kernel_types.h>
29 #include <TransporterRegistry.hpp>
30 #include <NdbOut.hpp>
31 #include <NdbMem.h>
32 #include <NdbTick.h>
33
34 #include <SignalLoggerManager.hpp>
35 #include <FastScheduler.hpp>
36
37 #define DEBUG(x) { ndbout << "CMVMI::" << x << endl; }
38
39 #include <signaldata/TestOrd.hpp>
40 #include <signaldata/EventReport.hpp>
41 #include <signaldata/TamperOrd.hpp>
42 #include <signaldata/StartOrd.hpp>
43 #include <signaldata/CloseComReqConf.hpp>
44 #include <signaldata/SetLogLevelOrd.hpp>
45 #include <signaldata/EventSubscribeReq.hpp>
46 #include <signaldata/DumpStateOrd.hpp>
47 #include <signaldata/DisconnectRep.hpp>
48 #include <signaldata/EnableCom.hpp>
49 #include <signaldata/RouteOrd.hpp>
50 #include <signaldata/DbinfoScan.hpp>
51 #include <signaldata/Sync.hpp>
52 #include <signaldata/AllocMem.hpp>
53 #include <signaldata/NodeStateSignalData.hpp>
54 #include <signaldata/GetConfig.hpp>
55
56 #include <EventLogger.hpp>
57 #include <TimeQueue.hpp>
58
59 #include <NdbSleep.h>
60 #include <SafeCounter.hpp>
61
62 #define ZREPORT_MEMORY_USAGE 1000
63
64 // Used here only to print event reports on stdout/console.
65 extern EventLogger * g_eventLogger;
66 extern int simulate_error_during_shutdown;
67
68 // Index pages used by ACC instances
69 Uint32 g_acc_pages_used[1 + MAX_NDBMT_LQH_WORKERS];
70
71 extern void mt_set_section_chunk_size();
72
Cmvmi(Block_context & ctx)73 Cmvmi::Cmvmi(Block_context& ctx) :
74 SimulatedBlock(CMVMI, ctx)
75 ,subscribers(subscriberPool)
76 {
77 BLOCK_CONSTRUCTOR(Cmvmi);
78
79 Uint32 long_sig_buffer_size;
80 const ndb_mgm_configuration_iterator * p =
81 m_ctx.m_config.getOwnConfigIterator();
82 ndbrequire(p != 0);
83
84 ndb_mgm_get_int_parameter(p, CFG_DB_LONG_SIGNAL_BUFFER,
85 &long_sig_buffer_size);
86
87 /* Ensure that aligned allocation will result in 64-bit
88 * aligned offset for theData
89 */
90 STATIC_ASSERT((sizeof(SectionSegment) % 8) == 0);
91 STATIC_ASSERT((offsetof(SectionSegment, theData) % 8) == 0);
92
93 long_sig_buffer_size= long_sig_buffer_size / sizeof(SectionSegment);
94 g_sectionSegmentPool.setSize(long_sig_buffer_size,
95 true,true,true,CFG_DB_LONG_SIGNAL_BUFFER);
96
97 mt_set_section_chunk_size();
98
99 // Add received signals
100 addRecSignal(GSN_CONNECT_REP, &Cmvmi::execCONNECT_REP);
101 addRecSignal(GSN_DISCONNECT_REP, &Cmvmi::execDISCONNECT_REP);
102
103 addRecSignal(GSN_NDB_TAMPER, &Cmvmi::execNDB_TAMPER, true);
104 addRecSignal(GSN_SET_LOGLEVELORD, &Cmvmi::execSET_LOGLEVELORD);
105 addRecSignal(GSN_EVENT_REP, &Cmvmi::execEVENT_REP);
106 addRecSignal(GSN_STTOR, &Cmvmi::execSTTOR);
107 addRecSignal(GSN_READ_CONFIG_REQ, &Cmvmi::execREAD_CONFIG_REQ);
108 addRecSignal(GSN_CLOSE_COMREQ, &Cmvmi::execCLOSE_COMREQ);
109 addRecSignal(GSN_ENABLE_COMREQ, &Cmvmi::execENABLE_COMREQ);
110 addRecSignal(GSN_OPEN_COMREQ, &Cmvmi::execOPEN_COMREQ);
111 addRecSignal(GSN_TEST_ORD, &Cmvmi::execTEST_ORD);
112
113 addRecSignal(GSN_TAMPER_ORD, &Cmvmi::execTAMPER_ORD);
114 addRecSignal(GSN_STOP_ORD, &Cmvmi::execSTOP_ORD);
115 addRecSignal(GSN_START_ORD, &Cmvmi::execSTART_ORD);
116 addRecSignal(GSN_EVENT_SUBSCRIBE_REQ,
117 &Cmvmi::execEVENT_SUBSCRIBE_REQ);
118
119 addRecSignal(GSN_DUMP_STATE_ORD, &Cmvmi::execDUMP_STATE_ORD);
120
121 addRecSignal(GSN_TESTSIG, &Cmvmi::execTESTSIG);
122 addRecSignal(GSN_NODE_START_REP, &Cmvmi::execNODE_START_REP, true);
123
124 addRecSignal(GSN_CONTINUEB, &Cmvmi::execCONTINUEB);
125 addRecSignal(GSN_ROUTE_ORD, &Cmvmi::execROUTE_ORD);
126 addRecSignal(GSN_DBINFO_SCANREQ, &Cmvmi::execDBINFO_SCANREQ);
127
128 addRecSignal(GSN_SYNC_REQ, &Cmvmi::execSYNC_REQ, true);
129 addRecSignal(GSN_SYNC_REF, &Cmvmi::execSYNC_REF);
130 addRecSignal(GSN_SYNC_CONF, &Cmvmi::execSYNC_CONF);
131
132 addRecSignal(GSN_ALLOC_MEM_REF, &Cmvmi::execALLOC_MEM_REF);
133 addRecSignal(GSN_ALLOC_MEM_CONF, &Cmvmi::execALLOC_MEM_CONF);
134
135 addRecSignal(GSN_GET_CONFIG_REQ, &Cmvmi::execGET_CONFIG_REQ);
136
137 subscriberPool.setSize(5);
138 c_syncReqPool.setSize(5);
139
140 const ndb_mgm_configuration_iterator * db = m_ctx.m_config.getOwnConfigIterator();
141 for(unsigned j = 0; j<LogLevel::LOGLEVEL_CATEGORIES; j++){
142 Uint32 logLevel;
143 if(!ndb_mgm_get_int_parameter(db, CFG_MIN_LOGLEVEL+j, &logLevel)){
144 clogLevel.setLogLevel((LogLevel::EventCategory)j,
145 logLevel);
146 }
147 }
148
149 ndb_mgm_configuration_iterator * iter = m_ctx.m_config.getClusterConfigIterator();
150 for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
151 jam();
152 Uint32 nodeId;
153 Uint32 nodeType;
154
155 ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_NODE_ID, &nodeId));
156 ndbrequire(!ndb_mgm_get_int_parameter(iter,CFG_TYPE_OF_SECTION,&nodeType));
157
158 switch(nodeType){
159 case NodeInfo::DB:
160 c_dbNodes.set(nodeId);
161 break;
162 case NodeInfo::API:
163 case NodeInfo::MGM:
164 break;
165 default:
166 ndbrequire(false);
167 }
168 setNodeInfo(nodeId).m_type = nodeType;
169 }
170
171 setNodeInfo(getOwnNodeId()).m_connected = true;
172 setNodeInfo(getOwnNodeId()).m_version = ndbGetOwnVersion();
173 setNodeInfo(getOwnNodeId()).m_mysql_version = NDB_MYSQL_VERSION_D;
174
175 c_memusage_report_frequency = 0;
176
177 m_start_time = NdbTick_CurrentMillisecond() / 1000; // seconds
178
179 bzero(g_acc_pages_used, sizeof(g_acc_pages_used));
180
181 }
182
~Cmvmi()183 Cmvmi::~Cmvmi()
184 {
185 m_shared_page_pool.clear();
186 }
187
188 #ifdef ERROR_INSERT
189 NodeBitmask c_error_9000_nodes_mask;
190 extern Uint32 MAX_RECEIVED_SIGNALS;
191 #endif
192
execNDB_TAMPER(Signal * signal)193 void Cmvmi::execNDB_TAMPER(Signal* signal)
194 {
195 jamEntry();
196 SET_ERROR_INSERT_VALUE(signal->theData[0]);
197 if(ERROR_INSERTED(9999)){
198 CRASH_INSERTION(9999);
199 }
200
201 if(ERROR_INSERTED(9998)){
202 while(true) NdbSleep_SecSleep(1);
203 }
204
205 if(ERROR_INSERTED(9997)){
206 ndbrequire(false);
207 }
208
209 #ifndef NDB_WIN32
210 if(ERROR_INSERTED(9996)){
211 simulate_error_during_shutdown= SIGSEGV;
212 ndbrequire(false);
213 }
214
215 if(ERROR_INSERTED(9995)){
216 simulate_error_during_shutdown= SIGSEGV;
217 kill(getpid(), SIGABRT);
218 }
219 #endif
220
221 #ifdef ERROR_INSERT
222 if (signal->theData[0] == 9003)
223 {
224 if (MAX_RECEIVED_SIGNALS < 1024)
225 {
226 MAX_RECEIVED_SIGNALS = 1024;
227 }
228 else
229 {
230 MAX_RECEIVED_SIGNALS = 1 + (rand() % 128);
231 }
232 ndbout_c("MAX_RECEIVED_SIGNALS: %d", MAX_RECEIVED_SIGNALS);
233 CLEAR_ERROR_INSERT_VALUE;
234 }
235 #endif
236 }//execNDB_TAMPER()
237
238 static Uint32 blocks[] =
239 {
240 QMGR_REF,
241 NDBCNTR_REF,
242 DBTC_REF,
243 DBDIH_REF,
244 DBDICT_REF,
245 DBLQH_REF,
246 DBTUP_REF,
247 DBACC_REF,
248 NDBFS_REF,
249 BACKUP_REF,
250 DBUTIL_REF,
251 SUMA_REF,
252 TRIX_REF,
253 DBTUX_REF,
254 LGMAN_REF,
255 TSMAN_REF,
256 PGMAN_REF,
257 DBINFO_REF,
258 DBSPJ_REF,
259 0
260 };
261
262 void
execSYNC_REQ(Signal * signal)263 Cmvmi::execSYNC_REQ(Signal* signal)
264 {
265 jamEntry();
266 SyncReq req = * CAST_CONSTPTR(SyncReq, signal->getDataPtr());
267 Ptr<SyncRecord> ptr;
268 if (!c_syncReqPool.seize(ptr))
269 {
270 jam();
271 SyncRecord tmp;
272 ptr.p = &tmp;
273 tmp.m_senderRef = req.senderRef;
274 tmp.m_senderData = req.senderData;
275 tmp.m_prio = req.prio;
276 tmp.m_error = SyncRef::SR_OUT_OF_MEMORY;
277 sendSYNC_REP(signal, ptr);
278 return;
279 }
280
281 ptr.p->m_senderRef = req.senderRef;
282 ptr.p->m_senderData = req.senderData;
283 ptr.p->m_prio = req.prio;
284 ptr.p->m_error = 0;
285
286 SyncReq* out = CAST_PTR(SyncReq, signal->getDataPtrSend());
287 out->senderRef = reference();
288 out->senderData = ptr.i;
289 out->prio = ptr.p->m_prio;
290 Uint32 i = 0;
291 for (i = 0; blocks[i] != 0; i++)
292 {
293 sendSignal(blocks[i], GSN_SYNC_REQ, signal, SyncReq::SignalLength,
294 JobBufferLevel(ptr.p->m_prio));
295 }
296 ptr.p->m_cnt = i;
297 }
298
299 void
execSYNC_CONF(Signal * signal)300 Cmvmi::execSYNC_CONF(Signal* signal)
301 {
302 jamEntry();
303 SyncConf conf = * CAST_CONSTPTR(SyncConf, signal->getDataPtr());
304
305 Ptr<SyncRecord> ptr;
306 c_syncReqPool.getPtr(ptr, conf.senderData);
307 ndbrequire(ptr.p->m_cnt > 0);
308 ptr.p->m_cnt--;
309 if (ptr.p->m_cnt == 0)
310 {
311 jam();
312
313 sendSYNC_REP(signal, ptr);
314 c_syncReqPool.release(ptr);
315 }
316 }
317
318 void
execSYNC_REF(Signal * signal)319 Cmvmi::execSYNC_REF(Signal* signal)
320 {
321 jamEntry();
322 SyncRef ref = * CAST_CONSTPTR(SyncRef, signal->getDataPtr());
323
324 Ptr<SyncRecord> ptr;
325 c_syncReqPool.getPtr(ptr, ref.senderData);
326 ndbrequire(ptr.p->m_cnt > 0);
327 ptr.p->m_cnt--;
328
329 if (ptr.p->m_error == 0)
330 {
331 jam();
332 ptr.p->m_error = ref.errorCode;
333 }
334
335 if (ptr.p->m_cnt == 0)
336 {
337 jam();
338
339 sendSYNC_REP(signal, ptr);
340 c_syncReqPool.release(ptr);
341 }
342 }
343
344 void
sendSYNC_REP(Signal * signal,Ptr<SyncRecord> ptr)345 Cmvmi::sendSYNC_REP(Signal * signal, Ptr<SyncRecord> ptr)
346 {
347 if (ptr.p->m_error == 0)
348 {
349 jam();
350 SyncConf* conf = CAST_PTR(SyncConf, signal->getDataPtrSend());
351 conf->senderRef = reference();
352 conf->senderData = ptr.p->m_senderData;
353 sendSignal(ptr.p->m_senderRef, GSN_SYNC_CONF, signal,
354 SyncConf::SignalLength,
355 JobBufferLevel(ptr.p->m_prio));
356 }
357 else
358 {
359 jam();
360 SyncRef* ref = CAST_PTR(SyncRef, signal->getDataPtrSend());
361 ref->senderRef = reference();
362 ref->senderData = ptr.p->m_senderData;
363 ref->errorCode = ptr.p->m_error;
364 sendSignal(ptr.p->m_senderRef, GSN_SYNC_REF, signal, SyncRef::SignalLength,
365 JobBufferLevel(ptr.p->m_prio));
366 }
367 }
368
execSET_LOGLEVELORD(Signal * signal)369 void Cmvmi::execSET_LOGLEVELORD(Signal* signal)
370 {
371 SetLogLevelOrd * const llOrd = (SetLogLevelOrd *)&signal->theData[0];
372 LogLevel::EventCategory category;
373 Uint32 level;
374 jamEntry();
375
376 for(unsigned int i = 0; i<llOrd->noOfEntries; i++){
377 category = (LogLevel::EventCategory)(llOrd->theData[i] >> 16);
378 level = llOrd->theData[i] & 0xFFFF;
379
380 clogLevel.setLogLevel(category, level);
381 }
382 }//execSET_LOGLEVELORD()
383
384 struct SavedEvent
385 {
386 Uint32 m_len;
387 Uint32 m_seq;
388 Uint32 m_time;
389 Uint32 m_data[25];
390
391 STATIC_CONST( HeaderLength = 3 );
392 };
393
394 static
395 struct SavedEventBuffer
396 {
SavedEventBufferSavedEventBuffer397 SavedEventBuffer() {
398 m_read_pos = m_write_pos = 0;
399 m_sequence = 0;
400 m_buffer_len = 0;
401 m_data = 0;
402 }
403
initSavedEventBuffer404 void init(Uint32 bytes) {
405 if (bytes < 128)
406 {
407 return; // min size...unless set to 0
408 }
409 Uint32 words = bytes / 4;
410 m_data = new Uint32[words];
411 if (m_data)
412 {
413 m_buffer_len = words;
414 }
415 }
416
417 Uint32 m_sequence;
418 Uint16 m_write_pos;
419 Uint16 m_read_pos;
420 Uint32 m_buffer_len;
421 Uint32 * m_data;
422
423 void alloc(Uint32 len);
424 void purge();
425 void save(const Uint32 * theData, Uint32 len);
426
427 Uint32 free() const;
428
429 Uint32 m_scan_pos;
430 void startScan();
431 int scan(SavedEvent * dst, Uint32 filter[]);
432 } m_saved_event_buffer;
433
434 void
alloc(Uint32 len)435 SavedEventBuffer::alloc(Uint32 len)
436 {
437 assert(m_buffer_len > 0);
438
439 while (free() <= len)
440 purge();
441 }
442
443 Uint32
free() const444 SavedEventBuffer::free() const
445 {
446 if (m_write_pos == m_read_pos)
447 return m_buffer_len;
448 else if (m_write_pos > m_read_pos)
449 return (m_buffer_len - m_write_pos) + m_read_pos;
450 else
451 return m_read_pos - m_write_pos;
452 }
453
454 void
purge()455 SavedEventBuffer::purge()
456 {
457 const Uint32 * ptr = m_data + m_read_pos;
458 const SavedEvent * header = (SavedEvent*)ptr;
459 Uint32 len = SavedEvent::HeaderLength + header->m_len;
460 m_read_pos = (m_read_pos + len) % m_buffer_len;
461 }
462
463 void
save(const Uint32 * theData,Uint32 len)464 SavedEventBuffer::save(const Uint32 * theData, Uint32 len)
465 {
466 if (m_buffer_len == 0)
467 return;
468
469 Uint32 total = len + SavedEvent::HeaderLength;
470 alloc(total);
471
472 SavedEvent s;
473 s.m_len = len; // size of SavedEvent
474 s.m_seq = m_sequence++;
475 s.m_time = (Uint32)time(0);
476 const Uint32 * src = (const Uint32*)&s;
477 Uint32 * dst = m_data + m_write_pos;
478
479 Uint32 remain = m_buffer_len - m_write_pos;
480 if (remain >= total)
481 {
482 memcpy(dst, src, 4 * SavedEvent::HeaderLength);
483 memcpy(dst+SavedEvent::HeaderLength, theData, 4*len);
484 }
485 else
486 {
487 memcpy(s.m_data, theData, 4 * len);
488 memcpy(dst, src, 4 * remain);
489 memcpy(m_data, src + remain, 4 * (total - remain));
490 }
491 m_write_pos = (m_write_pos + total) % m_buffer_len;
492 }
493
494 void
startScan()495 SavedEventBuffer::startScan()
496 {
497 m_scan_pos = m_read_pos;
498 }
499
500 int
scan(SavedEvent * _dst,Uint32 filter[])501 SavedEventBuffer::scan(SavedEvent* _dst, Uint32 filter[])
502 {
503 Uint32 * dst = (Uint32*)_dst;
504 while (m_scan_pos != m_write_pos)
505 {
506 const Uint32 * ptr = m_data + m_scan_pos;
507 SavedEvent * s = (SavedEvent*)ptr;
508 assert(s->m_len <= 25);
509 Uint32 total = s->m_len + SavedEvent::HeaderLength;
510 if (m_scan_pos + total <= m_buffer_len)
511 {
512 memcpy(dst, s, 4 * total);
513 }
514 else
515 {
516 Uint32 remain = m_buffer_len - m_scan_pos;
517 memcpy(dst, s, 4 * remain);
518 memcpy(dst + remain, m_data, 4 * (total - remain));
519 }
520 m_scan_pos = (m_scan_pos + total) % m_buffer_len;
521 return 1;
522 }
523 return 0;
524 }
525
execEVENT_REP(Signal * signal)526 void Cmvmi::execEVENT_REP(Signal* signal)
527 {
528 //-----------------------------------------------------------------------
529 // This message is sent to report any types of events in NDB.
530 // Based on the log level they will be either ignored or
531 // reported. Currently they are printed, but they will be
532 // transferred to the management server for further distribution
533 // to the graphical management interface.
534 //-----------------------------------------------------------------------
535 EventReport * const eventReport = (EventReport *)&signal->theData[0];
536 Ndb_logevent_type eventType = eventReport->getEventType();
537 Uint32 nodeId= eventReport->getNodeId();
538 if (nodeId == 0)
539 {
540 nodeId= refToNode(signal->getSendersBlockRef());
541
542 if (nodeId == 0)
543 {
544 /* Event reporter supplied no node id,
545 * assume it was local
546 */
547 nodeId= getOwnNodeId();
548 }
549
550 eventReport->setNodeId(nodeId);
551 }
552
553 jamEntry();
554
555 /**
556 * If entry is not found
557 */
558 Uint32 threshold;
559 LogLevel::EventCategory eventCategory;
560 Logger::LoggerLevel severity;
561 EventLoggerBase::EventTextFunction textF;
562 if (EventLoggerBase::event_lookup(eventType,eventCategory,threshold,severity,textF))
563 return;
564
565 SubscriberPtr ptr;
566 for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
567 if(ptr.p->logLevel.getLogLevel(eventCategory) < threshold){
568 continue;
569 }
570
571 sendSignal(ptr.p->blockRef, GSN_EVENT_REP, signal, signal->length(), JBB);
572 }
573
574 m_saved_event_buffer.save(signal->theData, signal->getLength());
575
576 if(clogLevel.getLogLevel(eventCategory) < threshold){
577 return;
578 }
579
580 // Print the event info
581 g_eventLogger->log(eventReport->getEventType(),
582 signal->theData, signal->getLength(), 0, 0);
583
584 return;
585 }//execEVENT_REP()
586
587 void
execEVENT_SUBSCRIBE_REQ(Signal * signal)588 Cmvmi::execEVENT_SUBSCRIBE_REQ(Signal * signal){
589 EventSubscribeReq * subReq = (EventSubscribeReq *)&signal->theData[0];
590 Uint32 senderRef = signal->getSendersBlockRef();
591 SubscriberPtr ptr;
592 jamEntry();
593 DBUG_ENTER("Cmvmi::execEVENT_SUBSCRIBE_REQ");
594
595 /**
596 * Search for subcription
597 */
598 for(subscribers.first(ptr); ptr.i != RNIL; subscribers.next(ptr)){
599 if(ptr.p->blockRef == subReq->blockRef)
600 break;
601 }
602
603 if(ptr.i == RNIL){
604 /**
605 * Create a new one
606 */
607 if(subscribers.seize(ptr) == false){
608 sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_REF, signal, 1, JBB);
609 return;
610 }
611 ptr.p->logLevel.clear();
612 ptr.p->blockRef = subReq->blockRef;
613 }
614
615 if(subReq->noOfEntries == 0){
616 /**
617 * Cancel subscription
618 */
619 subscribers.release(ptr.i);
620 } else {
621 /**
622 * Update subscription
623 */
624 LogLevel::EventCategory category;
625 Uint32 level = 0;
626 for(Uint32 i = 0; i<subReq->noOfEntries; i++){
627 category = (LogLevel::EventCategory)(subReq->theData[i] >> 16);
628 level = subReq->theData[i] & 0xFFFF;
629 ptr.p->logLevel.setLogLevel(category, level);
630 DBUG_PRINT("info",("entry %d: level=%d, category= %d", i, level, category));
631 }
632 }
633
634 signal->theData[0] = ptr.i;
635 sendSignal(senderRef, GSN_EVENT_SUBSCRIBE_CONF, signal, 1, JBB);
636 DBUG_VOID_RETURN;
637 }
638
639 void
cancelSubscription(NodeId nodeId)640 Cmvmi::cancelSubscription(NodeId nodeId){
641
642 SubscriberPtr ptr;
643 subscribers.first(ptr);
644
645 while(ptr.i != RNIL){
646 Uint32 i = ptr.i;
647 BlockReference blockRef = ptr.p->blockRef;
648
649 subscribers.next(ptr);
650
651 if(refToNode(blockRef) == nodeId){
652 subscribers.release(i);
653 }
654 }
655 }
656
sendSTTORRY(Signal * signal)657 void Cmvmi::sendSTTORRY(Signal* signal)
658 {
659 jam();
660 signal->theData[3] = 1;
661 signal->theData[4] = 3;
662 signal->theData[5] = 8;
663 signal->theData[6] = 255;
664 sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 7, JBB);
665 }//Cmvmi::sendSTTORRY
666
667
668 static Uint32 f_accpages = 0;
669 extern Uint32 compute_acc_32kpages(const ndb_mgm_configuration_iterator * p);
670
671 static Uint32 f_read_config_ref = 0;
672 static Uint32 f_read_config_data = 0;
673
674 void
execREAD_CONFIG_REQ(Signal * signal)675 Cmvmi::execREAD_CONFIG_REQ(Signal* signal)
676 {
677 jamEntry();
678
679 const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
680
681 Uint32 ref = req->senderRef;
682 Uint32 senderData = req->senderData;
683
684 const ndb_mgm_configuration_iterator * p =
685 m_ctx.m_config.getOwnConfigIterator();
686 ndbrequire(p != 0);
687
688 {
689 void* ptr = m_ctx.m_mm.get_memroot();
690 m_shared_page_pool.set((GlobalPage*)ptr, ~0);
691 }
692
693 f_accpages = compute_acc_32kpages(p);
694
695 Uint32 eventlog = 4096;
696 ndb_mgm_get_int_parameter(p, CFG_DB_EVENTLOG_BUFFER_SIZE, &eventlog);
697 m_saved_event_buffer.init(eventlog);
698
699 c_memusage_report_frequency = 0;
700 ndb_mgm_get_int_parameter(p, CFG_DB_MEMREPORT_FREQUENCY,
701 &c_memusage_report_frequency);
702
703 Uint32 late_alloc = 1;
704 ndb_mgm_get_int_parameter(p, CFG_DB_LATE_ALLOC,
705 &late_alloc);
706 if (late_alloc)
707 {
708 jam();
709 f_read_config_ref = ref;
710 f_read_config_data = senderData;
711
712
713 AllocMemReq * req = CAST_PTR(AllocMemReq, signal->getDataPtrSend());
714 req->senderData = 0;
715 req->senderRef = reference();
716 req->requestInfo = AllocMemReq::RT_MAP;
717 if (m_ctx.m_config.lockPagesInMainMemory())
718 {
719 req->requestInfo |= AllocMemReq::RT_MEMLOCK;
720 }
721
722 req->bytes_hi = 0;
723 req->bytes_lo = 0;
724 sendSignal(NDBFS_REF, GSN_ALLOC_MEM_REQ, signal,
725 AllocMemReq::SignalLength, JBB);
726
727 /**
728 * Assume this takes time...
729 * Set sp0 complete (even though it hasn't) but it makes
730 * ndb_mgm -e "show" show starting instead of not-started
731 */
732 {
733 NodeStateRep * rep = CAST_PTR(NodeStateRep, signal->getDataPtrSend());
734 NodeState newState(NodeState::SL_STARTING, 0,
735 NodeState::ST_ILLEGAL_TYPE);
736 rep->nodeState = newState;
737 rep->nodeState.masterNodeId = 0;
738 rep->nodeState.setNodeGroup(0);
739 sendSignal(QMGR_REF, GSN_NODE_STATE_REP, signal,
740 NodeStateRep::SignalLength, JBB);
741 }
742 return;
743 }
744
745 init_global_page_pool();
746
747 ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
748 conf->senderRef = reference();
749 conf->senderData = senderData;
750 sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
751 ReadConfigConf::SignalLength, JBB);
752 }
753
754 void
init_global_page_pool()755 Cmvmi::init_global_page_pool()
756 {
757 /**
758 * This subroutine takes page from m_shared_page_pool and
759 * moves them into m_global_page_pool
760 * (that is currently used by pgman(dbtup) and restore
761 */
762 void* ptr = m_ctx.m_mm.get_memroot();
763 m_global_page_pool.set((GlobalPage*)ptr, ~0);
764
765 Resource_limit rl;
766 ndbrequire(m_ctx.m_mm.get_resource_limit(RG_DISK_PAGE_BUFFER, rl));
767 while (rl.m_max)
768 {
769 Uint32 ptrI;
770 Uint32 cnt = rl.m_max;
771 m_ctx.m_mm.alloc_pages(RG_DISK_PAGE_BUFFER, &ptrI, &cnt, 1);
772 ndbrequire(cnt);
773 for (Uint32 i = 0; i<cnt; i++)
774 {
775 Ptr<GlobalPage> pagePtr;
776 m_shared_page_pool.getPtr(pagePtr, ptrI + i);
777 m_global_page_pool.release(pagePtr);
778 }
779 rl.m_max -= cnt;
780 }
781 }
782
execSTTOR(Signal * signal)783 void Cmvmi::execSTTOR(Signal* signal)
784 {
785 Uint32 theStartPhase = signal->theData[1];
786
787 jamEntry();
788 if (theStartPhase == 1){
789 jam();
790
791 if (m_ctx.m_config.lockPagesInMainMemory())
792 {
793 jam();
794 /**
795 * Notify watchdog that we're locking memory...
796 * which can be equally "heavy" as allocating it
797 */
798 refresh_watch_dog(9);
799 int res = NdbMem_MemLockAll(1);
800 if (res != 0)
801 {
802 char buf[100];
803 BaseString::snprintf(buf, sizeof(buf),
804 "Failed to memlock pages, error: %d (%s)",
805 errno, strerror(errno));
806 g_eventLogger->warning("%s", buf);
807 warningEvent("%s", buf);
808 }
809 else
810 {
811 g_eventLogger->info("Using locked memory");
812 }
813 }
814
815 /**
816 * Install "normal" watchdog value
817 */
818 {
819 Uint32 db_watchdog_interval = 0;
820 const ndb_mgm_configuration_iterator * p =
821 m_ctx.m_config.getOwnConfigIterator();
822 ndb_mgm_get_int_parameter(p, CFG_DB_WATCHDOG_INTERVAL,
823 &db_watchdog_interval);
824 ndbrequire(db_watchdog_interval);
825 update_watch_dog_timer(db_watchdog_interval);
826 }
827
828 /**
829 * Start auto-mem reporting
830 */
831 signal->theData[0] = ZREPORT_MEMORY_USAGE;
832 signal->theData[1] = 0;
833 signal->theData[2] = 0;
834 signal->theData[3] = 0;
835 execCONTINUEB(signal);
836
837 sendSTTORRY(signal);
838 return;
839 } else if (theStartPhase == 3) {
840 jam();
841 globalData.activateSendPacked = 1;
842 sendSTTORRY(signal);
843 } else if (theStartPhase == 8){
844 #ifdef ERROR_INSERT
845 if (ERROR_INSERTED(9004))
846 {
847 Uint32 len = signal->getLength();
848 Uint32 db = c_dbNodes.find(0);
849 if (db == getOwnNodeId())
850 db = c_dbNodes.find(db);
851 Uint32 i = c_error_9000_nodes_mask.find(0);
852 Uint32 tmp[25];
853 memcpy(tmp, signal->theData, sizeof(tmp));
854 signal->theData[0] = i;
855 sendSignal(calcQmgrBlockRef(db),GSN_API_FAILREQ, signal, 1, JBA);
856 ndbout_c("stopping %u using %u", i, db);
857 CLEAR_ERROR_INSERT_VALUE;
858 memcpy(signal->theData, tmp, sizeof(tmp));
859 sendSignalWithDelay(reference(), GSN_STTOR,
860 signal, 100, len);
861 return;
862 }
863 #endif
864 globalData.theStartLevel = NodeState::SL_STARTED;
865 sendSTTORRY(signal);
866 }
867 }
868
execCLOSE_COMREQ(Signal * signal)869 void Cmvmi::execCLOSE_COMREQ(Signal* signal)
870 {
871 // Close communication with the node and halt input/output from
872 // other blocks than QMGR
873
874 CloseComReqConf * const closeCom = (CloseComReqConf *)&signal->theData[0];
875
876 const BlockReference userRef = closeCom->xxxBlockRef;
877 Uint32 requestType = closeCom->requestType;
878 Uint32 failNo = closeCom->failNo;
879 // Uint32 noOfNodes = closeCom->noOfNodes;
880
881 jamEntry();
882 for (unsigned i = 0; i < MAX_NODES; i++)
883 {
884 if(NodeBitmask::get(closeCom->theNodes, i))
885 {
886 jam();
887
888 //-----------------------------------------------------
889 // Report that the connection to the node is closed
890 //-----------------------------------------------------
891 signal->theData[0] = NDB_LE_CommunicationClosed;
892 signal->theData[1] = i;
893 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
894
895 globalTransporterRegistry.setIOState(i, HaltIO);
896 globalTransporterRegistry.do_disconnect(i);
897 }
898 }
899 if (requestType != CloseComReqConf::RT_NO_REPLY)
900 {
901 ndbassert((requestType == CloseComReqConf::RT_API_FAILURE) ||
902 ((requestType == CloseComReqConf::RT_NODE_FAILURE) &&
903 (failNo != 0)));
904 jam();
905 CloseComReqConf* closeComConf = (CloseComReqConf *)signal->getDataPtrSend();
906 closeComConf->xxxBlockRef = userRef;
907 closeComConf->requestType = requestType;
908 closeComConf->failNo = failNo;
909
910 /* Note assumption that noOfNodes and theNodes
911 * bitmap is not trampled above
912 * signals received from the remote node.
913 */
914 sendSignal(QMGR_REF, GSN_CLOSE_COMCONF, signal, 19, JBA);
915 }
916 }
917
execOPEN_COMREQ(Signal * signal)918 void Cmvmi::execOPEN_COMREQ(Signal* signal)
919 {
920 // Connect to the specifed NDB node, only QMGR allowed communication
921 // so far with the node
922
923 const BlockReference userRef = signal->theData[0];
924 Uint32 tStartingNode = signal->theData[1];
925 Uint32 tData2 = signal->theData[2];
926 jamEntry();
927
928 const Uint32 len = signal->getLength();
929 if(len == 2)
930 {
931 #ifdef ERROR_INSERT
932 if (! ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
933 && c_error_9000_nodes_mask.get(tStartingNode)))
934 #endif
935 {
936 globalTransporterRegistry.do_connect(tStartingNode);
937 globalTransporterRegistry.setIOState(tStartingNode, HaltIO);
938
939 //-----------------------------------------------------
940 // Report that the connection to the node is opened
941 //-----------------------------------------------------
942 signal->theData[0] = NDB_LE_CommunicationOpened;
943 signal->theData[1] = tStartingNode;
944 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
945 //-----------------------------------------------------
946 }
947 } else {
948 for(unsigned int i = 1; i < MAX_NODES; i++ )
949 {
950 jam();
951 if (i != getOwnNodeId() && getNodeInfo(i).m_type == tData2)
952 {
953 jam();
954
955 #ifdef ERROR_INSERT
956 if ((ERROR_INSERTED(9000) || ERROR_INSERTED(9002))
957 && c_error_9000_nodes_mask.get(i))
958 continue;
959 #endif
960 globalTransporterRegistry.do_connect(i);
961 globalTransporterRegistry.setIOState(i, HaltIO);
962
963 signal->theData[0] = NDB_LE_CommunicationOpened;
964 signal->theData[1] = i;
965 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
966 }
967 }
968 }
969
970 if (userRef != 0)
971 {
972 jam();
973 signal->theData[0] = tStartingNode;
974 signal->theData[1] = tData2;
975 sendSignal(userRef, GSN_OPEN_COMCONF, signal, len - 1,JBA);
976 }
977 }
978
execENABLE_COMREQ(Signal * signal)979 void Cmvmi::execENABLE_COMREQ(Signal* signal)
980 {
981 jamEntry();
982 const EnableComReq *enableComReq = (const EnableComReq *)signal->getDataPtr();
983
984 /* Need to copy out signal data to not clobber it with sendSignal(). */
985 Uint32 senderRef = enableComReq->m_senderRef;
986 Uint32 senderData = enableComReq->m_senderData;
987 Uint32 nodes[NodeBitmask::Size];
988 MEMCOPY_NO_WORDS(nodes, enableComReq->m_nodeIds, NodeBitmask::Size);
989
990 /* Enable communication with all our NDB blocks to these nodes. */
991 Uint32 search_from = 0;
992 for (;;)
993 {
994 Uint32 tStartingNode = NodeBitmask::find(nodes, search_from);
995 if (tStartingNode == NodeBitmask::NotFound)
996 break;
997 search_from = tStartingNode + 1;
998
999 globalTransporterRegistry.setIOState(tStartingNode, NoHalt);
1000 setNodeInfo(tStartingNode).m_connected = true;
1001
1002 //-----------------------------------------------------
1003 // Report that the version of the node
1004 //-----------------------------------------------------
1005 signal->theData[0] = NDB_LE_ConnectedApiVersion;
1006 signal->theData[1] = tStartingNode;
1007 signal->theData[2] = getNodeInfo(tStartingNode).m_version;
1008 signal->theData[3] = getNodeInfo(tStartingNode).m_mysql_version;
1009
1010 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 4, JBB);
1011 //-----------------------------------------------------
1012 }
1013
1014 EnableComConf *enableComConf = (EnableComConf *)signal->getDataPtrSend();
1015 enableComConf->m_senderRef = reference();
1016 enableComConf->m_senderData = senderData;
1017 MEMCOPY_NO_WORDS(enableComConf->m_nodeIds, nodes, NodeBitmask::Size);
1018 sendSignal(senderRef, GSN_ENABLE_COMCONF, signal,
1019 EnableComConf::SignalLength, JBA);
1020 }
1021
execDISCONNECT_REP(Signal * signal)1022 void Cmvmi::execDISCONNECT_REP(Signal *signal)
1023 {
1024 const DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
1025 const Uint32 hostId = rep->nodeId;
1026 jamEntry();
1027
1028 setNodeInfo(hostId).m_connected = false;
1029 setNodeInfo(hostId).m_connectCount++;
1030 const NodeInfo::NodeType type = getNodeInfo(hostId).getType();
1031 ndbrequire(type != NodeInfo::INVALID);
1032
1033 sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
1034 DisconnectRep::SignalLength, JBA);
1035
1036 cancelSubscription(hostId);
1037
1038 signal->theData[0] = NDB_LE_Disconnected;
1039 signal->theData[1] = hostId;
1040 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, 2, JBB);
1041 }
1042
execCONNECT_REP(Signal * signal)1043 void Cmvmi::execCONNECT_REP(Signal *signal){
1044 const Uint32 hostId = signal->theData[0];
1045 jamEntry();
1046
1047 const NodeInfo::NodeType type = (NodeInfo::NodeType)getNodeInfo(hostId).m_type;
1048 ndbrequire(type != NodeInfo::INVALID);
1049 globalData.m_nodeInfo[hostId].m_version = 0;
1050 globalData.m_nodeInfo[hostId].m_mysql_version = 0;
1051
1052 /**
1053 * Inform QMGR that client has connected
1054 */
1055 signal->theData[0] = hostId;
1056 if (ERROR_INSERTED(9005))
1057 {
1058 sendSignalWithDelay(QMGR_REF, GSN_CONNECT_REP, signal, 50, 1);
1059 }
1060 else
1061 {
1062 sendSignal(QMGR_REF, GSN_CONNECT_REP, signal, 1, JBA);
1063 }
1064
1065 /* Automatically subscribe events for MGM nodes.
1066 */
1067 if(type == NodeInfo::MGM)
1068 {
1069 jam();
1070 globalTransporterRegistry.setIOState(hostId, NoHalt);
1071 }
1072
1073 //------------------------------------------
1074 // Also report this event to the Event handler
1075 //------------------------------------------
1076 signal->theData[0] = NDB_LE_Connected;
1077 signal->theData[1] = hostId;
1078 signal->header.theLength = 2;
1079
1080 execEVENT_REP(signal);
1081 }
1082
1083 #ifdef VM_TRACE
1084 void
modifySignalLogger(bool allBlocks,BlockNumber bno,TestOrd::Command cmd,TestOrd::SignalLoggerSpecification spec)1085 modifySignalLogger(bool allBlocks, BlockNumber bno,
1086 TestOrd::Command cmd,
1087 TestOrd::SignalLoggerSpecification spec){
1088 SignalLoggerManager::LogMode logMode;
1089
1090 /**
1091 * Mapping between SignalLoggerManager::LogMode and
1092 * TestOrd::SignalLoggerSpecification
1093 */
1094 switch(spec){
1095 case TestOrd::InputSignals:
1096 logMode = SignalLoggerManager::LogIn;
1097 break;
1098 case TestOrd::OutputSignals:
1099 logMode = SignalLoggerManager::LogOut;
1100 break;
1101 case TestOrd::InputOutputSignals:
1102 logMode = SignalLoggerManager::LogInOut;
1103 break;
1104 default:
1105 return;
1106 break;
1107 }
1108
1109 switch(cmd){
1110 case TestOrd::On:
1111 globalSignalLoggers.logOn(allBlocks, bno, logMode);
1112 break;
1113 case TestOrd::Off:
1114 globalSignalLoggers.logOff(allBlocks, bno, logMode);
1115 break;
1116 case TestOrd::Toggle:
1117 globalSignalLoggers.logToggle(allBlocks, bno, logMode);
1118 break;
1119 case TestOrd::KeepUnchanged:
1120 // Do nothing
1121 break;
1122 }
1123 globalSignalLoggers.flushSignalLog();
1124 }
1125 #endif
1126
1127 void
execTEST_ORD(Signal * signal)1128 Cmvmi::execTEST_ORD(Signal * signal){
1129 jamEntry();
1130
1131 #ifdef VM_TRACE
1132 TestOrd * const testOrd = (TestOrd *)&signal->theData[0];
1133
1134 TestOrd::Command cmd;
1135
1136 {
1137 /**
1138 * Process Trace command
1139 */
1140 TestOrd::TraceSpecification traceSpec;
1141
1142 testOrd->getTraceCommand(cmd, traceSpec);
1143 unsigned long traceVal = traceSpec;
1144 unsigned long currentTraceVal = globalSignalLoggers.getTrace();
1145 switch(cmd){
1146 case TestOrd::On:
1147 currentTraceVal |= traceVal;
1148 break;
1149 case TestOrd::Off:
1150 currentTraceVal &= (~traceVal);
1151 break;
1152 case TestOrd::Toggle:
1153 currentTraceVal ^= traceVal;
1154 break;
1155 case TestOrd::KeepUnchanged:
1156 // Do nothing
1157 break;
1158 }
1159 globalSignalLoggers.setTrace(currentTraceVal);
1160 }
1161
1162 {
1163 /**
1164 * Process Log command
1165 */
1166 TestOrd::SignalLoggerSpecification logSpec;
1167 BlockNumber bno;
1168 unsigned int loggers = testOrd->getNoOfSignalLoggerCommands();
1169
1170 if(loggers == (unsigned)~0){ // Apply command to all blocks
1171 testOrd->getSignalLoggerCommand(0, bno, cmd, logSpec);
1172 modifySignalLogger(true, bno, cmd, logSpec);
1173 } else {
1174 for(unsigned int i = 0; i<loggers; i++){
1175 testOrd->getSignalLoggerCommand(i, bno, cmd, logSpec);
1176 modifySignalLogger(false, bno, cmd, logSpec);
1177 }
1178 }
1179 }
1180
1181 {
1182 /**
1183 * Process test command
1184 */
1185 testOrd->getTestCommand(cmd);
1186 switch(cmd){
1187 case TestOrd::On:{
1188 SET_GLOBAL_TEST_ON;
1189 }
1190 break;
1191 case TestOrd::Off:{
1192 SET_GLOBAL_TEST_OFF;
1193 }
1194 break;
1195 case TestOrd::Toggle:{
1196 TOGGLE_GLOBAL_TEST_FLAG;
1197 }
1198 break;
1199 case TestOrd::KeepUnchanged:
1200 // Do nothing
1201 break;
1202 }
1203 globalSignalLoggers.flushSignalLog();
1204 }
1205
1206 #endif
1207 }
1208
execSTOP_ORD(Signal * signal)1209 void Cmvmi::execSTOP_ORD(Signal* signal)
1210 {
1211 jamEntry();
1212 globalData.theRestartFlag = perform_stop;
1213 }//execSTOP_ORD()
1214
1215 void
execSTART_ORD(Signal * signal)1216 Cmvmi::execSTART_ORD(Signal* signal) {
1217 StartOrd * const startOrd = (StartOrd *)&signal->theData[0];
1218 jamEntry();
1219
1220 Uint32 tmp = startOrd->restartInfo;
1221 if(StopReq::getPerformRestart(tmp)){
1222 jam();
1223 /**
1224 *
1225 */
1226 NdbRestartType type = NRT_Default;
1227 if(StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
1228 type = NRT_NoStart_InitialStart;
1229 if(StopReq::getNoStart(tmp) && !StopReq::getInitialStart(tmp))
1230 type = NRT_NoStart_Restart;
1231 if(!StopReq::getNoStart(tmp) && StopReq::getInitialStart(tmp))
1232 type = NRT_DoStart_InitialStart;
1233 if(!StopReq::getNoStart(tmp)&&!StopReq::getInitialStart(tmp))
1234 type = NRT_DoStart_Restart;
1235 NdbShutdown(0, NST_Restart, type);
1236 }
1237
1238 if(globalData.theRestartFlag == system_started){
1239 jam();
1240 /**
1241 * START_ORD received when already started(ignored)
1242 */
1243 //ndbout << "START_ORD received when already started(ignored)" << endl;
1244 return;
1245 }
1246
1247 if(globalData.theRestartFlag == perform_stop){
1248 jam();
1249 /**
1250 * START_ORD received when stopping(ignored)
1251 */
1252 //ndbout << "START_ORD received when stopping(ignored)" << endl;
1253 return;
1254 }
1255
1256 if(globalData.theStartLevel == NodeState::SL_NOTHING)
1257 {
1258 jam();
1259
1260 for(unsigned int i = 1; i < MAX_NODES; i++ )
1261 {
1262 if (getNodeInfo(i).m_type == NodeInfo::MGM)
1263 {
1264 jam();
1265 globalTransporterRegistry.do_connect(i);
1266 }
1267 }
1268
1269 globalData.theStartLevel = NodeState::SL_CMVMI;
1270 sendSignal(QMGR_REF, GSN_START_ORD, signal, 1, JBA);
1271 return ;
1272 }
1273
1274 if(globalData.theStartLevel == NodeState::SL_CMVMI)
1275 {
1276 jam();
1277
1278 globalData.theStartLevel = NodeState::SL_STARTING;
1279 globalData.theRestartFlag = system_started;
1280 /**
1281 * StartLevel 1
1282 *
1283 * Do Restart
1284 */
1285
1286 // Disconnect all nodes as part of the system restart.
1287 // We need to ensure that we are starting up
1288 // without any connected nodes.
1289 for(unsigned int i = 1; i < MAX_NODES; i++ )
1290 {
1291 if (i != getOwnNodeId() && getNodeInfo(i).m_type != NodeInfo::MGM)
1292 {
1293 globalTransporterRegistry.do_disconnect(i);
1294 globalTransporterRegistry.setIOState(i, HaltIO);
1295 }
1296 }
1297
1298 CRASH_INSERTION(9994);
1299
1300 /**
1301 * Start running startphases
1302 */
1303 sendSignal(NDBCNTR_REF, GSN_START_ORD, signal, 1, JBA);
1304 return;
1305 }
1306 }//execSTART_ORD()
1307
execTAMPER_ORD(Signal * signal)1308 void Cmvmi::execTAMPER_ORD(Signal* signal)
1309 {
1310 jamEntry();
1311 // TODO We should maybe introduce a CONF and REF signal
1312 // to be able to indicate if we really introduced an error.
1313 #ifdef ERROR_INSERT
1314 TamperOrd* const tamperOrd = (TamperOrd*)&signal->theData[0];
1315 Uint32 errNo = tamperOrd->errorNo;
1316
1317 if (errNo == 0)
1318 {
1319 jam();
1320 signal->theData[0] = 0;
1321 for (Uint32 i = 0; blocks[i] != 0; i++)
1322 {
1323 sendSignal(blocks[i], GSN_NDB_TAMPER, signal, 1, JBB);
1324 }
1325 return;
1326 }
1327
1328 Uint32 tuserblockref = 0;
1329 if (errNo < 1000)
1330 {
1331 /*--------------------------------------------------------------------*/
1332 // Insert errors into QMGR.
1333 /*--------------------------------------------------------------------*/
1334 jam();
1335 tuserblockref = QMGR_REF;
1336 }
1337 else if (errNo < 2000)
1338 {
1339 /*--------------------------------------------------------------------*/
1340 // Insert errors into NDBCNTR.
1341 /*--------------------------------------------------------------------*/
1342 jam();
1343 tuserblockref = NDBCNTR_REF;
1344 }
1345 else if (errNo < 3000)
1346 {
1347 /*--------------------------------------------------------------------*/
1348 // Insert errors into NDBFS.
1349 /*--------------------------------------------------------------------*/
1350 jam();
1351 tuserblockref = NDBFS_REF;
1352 }
1353 else if (errNo < 4000)
1354 {
1355 /*--------------------------------------------------------------------*/
1356 // Insert errors into DBACC.
1357 /*--------------------------------------------------------------------*/
1358 jam();
1359 tuserblockref = DBACC_REF;
1360 }
1361 else if (errNo < 5000)
1362 {
1363 /*--------------------------------------------------------------------*/
1364 // Insert errors into DBTUP.
1365 /*--------------------------------------------------------------------*/
1366 jam();
1367 tuserblockref = DBTUP_REF;
1368 }
1369 else if (errNo < 6000)
1370 {
1371 /*---------------------------------------------------------------------*/
1372 // Insert errors into DBLQH.
1373 /*---------------------------------------------------------------------*/
1374 jam();
1375 tuserblockref = DBLQH_REF;
1376 }
1377 else if (errNo < 7000)
1378 {
1379 /*---------------------------------------------------------------------*/
1380 // Insert errors into DBDICT.
1381 /*---------------------------------------------------------------------*/
1382 jam();
1383 tuserblockref = DBDICT_REF;
1384 }
1385 else if (errNo < 8000)
1386 {
1387 /*---------------------------------------------------------------------*/
1388 // Insert errors into DBDIH.
1389 /*--------------------------------------------------------------------*/
1390 jam();
1391 tuserblockref = DBDIH_REF;
1392 }
1393 else if (errNo < 9000)
1394 {
1395 /*--------------------------------------------------------------------*/
1396 // Insert errors into DBTC.
1397 /*--------------------------------------------------------------------*/
1398 jam();
1399 tuserblockref = DBTC_REF;
1400 }
1401 else if (errNo < 10000)
1402 {
1403 /*--------------------------------------------------------------------*/
1404 // Insert errors into CMVMI.
1405 /*--------------------------------------------------------------------*/
1406 jam();
1407 tuserblockref = CMVMI_REF;
1408 }
1409 else if (errNo < 11000)
1410 {
1411 jam();
1412 tuserblockref = BACKUP_REF;
1413 }
1414 else if (errNo < 12000)
1415 {
1416 // DBUTIL_REF ?
1417 jam();
1418 }
1419 else if (errNo < 13000)
1420 {
1421 jam();
1422 tuserblockref = DBTUX_REF;
1423 }
1424 else if (errNo < 14000)
1425 {
1426 jam();
1427 tuserblockref = SUMA_REF;
1428 }
1429 else if (errNo < 15000)
1430 {
1431 jam();
1432 tuserblockref = DBDICT_REF;
1433 }
1434 else if (errNo < 16000)
1435 {
1436 jam();
1437 tuserblockref = LGMAN_REF;
1438 }
1439 else if (errNo < 17000)
1440 {
1441 jam();
1442 tuserblockref = TSMAN_REF;
1443 }
1444 else if (errNo < 18000)
1445 {
1446 jam();
1447 tuserblockref = DBSPJ_REF;
1448 }
1449 else if (errNo < 19000)
1450 {
1451 jam();
1452 tuserblockref = TRIX_REF;
1453 }
1454 else if (errNo < 30000)
1455 {
1456 /*--------------------------------------------------------------------*/
1457 // Ignore errors in the 20000-range.
1458 /*--------------------------------------------------------------------*/
1459 jam();
1460 return;
1461 }
1462 else if (errNo < 40000)
1463 {
1464 jam();
1465 /*--------------------------------------------------------------------*/
1466 // Redirect errors to master DIH in the 30000-range.
1467 /*--------------------------------------------------------------------*/
1468
1469 /**
1470 * since CMVMI doesnt keep track of master,
1471 * send to local DIH
1472 */
1473 signal->theData[0] = 5;
1474 signal->theData[1] = errNo;
1475 signal->theData[2] = 0;
1476 sendSignal(DBDIH_REF, GSN_DIHNDBTAMPER, signal, 3, JBB);
1477 return;
1478 }
1479 else if (errNo < 50000)
1480 {
1481 jam();
1482
1483 /**
1484 * since CMVMI doesnt keep track of master,
1485 * send to local DIH
1486 */
1487 signal->theData[0] = 5;
1488 signal->theData[1] = errNo;
1489 signal->theData[2] = 0;
1490 sendSignal(DBDIH_REF, GSN_DIHNDBTAMPER, signal, 3, JBB);
1491 return;
1492 }
1493
1494 ndbassert(tuserblockref != 0); // mapping missing ??
1495 if (tuserblockref != 0)
1496 {
1497 signal->theData[0] = errNo;
1498 sendSignal(tuserblockref, GSN_NDB_TAMPER, signal, 1, JBB);
1499 }
1500 #endif
1501 }//execTAMPER_ORD()
1502
1503 #ifdef VM_TRACE
1504 class RefSignalTest {
1505 public:
1506 enum ErrorCode {
1507 OK = 0,
1508 NF_FakeErrorREF = 7
1509 };
1510 Uint32 senderRef;
1511 Uint32 senderData;
1512 Uint32 errorCode;
1513 };
1514 #endif
1515
1516
1517 static int iii;
1518
1519 static
1520 int
recurse(char * buf,int loops,int arg)1521 recurse(char * buf, int loops, int arg){
1522 char * tmp = (char*)alloca(arg);
1523 printf("tmp = %p\n", tmp);
1524 for(iii = 0; iii<arg; iii += 1024){
1525 tmp[iii] = (iii % 23 + (arg & iii));
1526 }
1527
1528 if(loops == 0)
1529 return tmp[345];
1530 else
1531 return tmp[arg/loops] + recurse(tmp, loops - 1, arg);
1532 }
1533
1534 #define check_block(block,val) \
1535 (((val) >= DumpStateOrd::_ ## block ## Min) && ((val) <= DumpStateOrd::_ ## block ## Max))
1536
1537 void
execDUMP_STATE_ORD(Signal * signal)1538 Cmvmi::execDUMP_STATE_ORD(Signal* signal)
1539 {
1540 jamEntry();
1541 Uint32 val = signal->theData[0];
1542 if (val >= DumpStateOrd::OneBlockOnly)
1543 {
1544 if (check_block(Backup, val))
1545 {
1546 sendSignal(BACKUP_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
1547 }
1548 else if (check_block(TC, val))
1549 {
1550 }
1551 else if (check_block(LQH, val))
1552 {
1553 sendSignal(DBLQH_REF, GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
1554 }
1555 return;
1556 }
1557
1558 for (Uint32 i = 0; blocks[i] != 0; i++)
1559 {
1560 sendSignal(blocks[i], GSN_DUMP_STATE_ORD, signal, signal->length(), JBB);
1561 }
1562
1563 /**
1564 *
1565 * Here I can dump CMVMI state if needed
1566 */
1567 if(signal->theData[0] == 13){
1568 #if 0
1569 int loop = 100;
1570 int len = (10*1024*1024);
1571 if(signal->getLength() > 1)
1572 loop = signal->theData[1];
1573 if(signal->getLength() > 2)
1574 len = signal->theData[2];
1575
1576 ndbout_c("recurse(%d loop, %dkb per recurse)", loop, len/1024);
1577 int a = recurse(0, loop, len);
1578 ndbout_c("after...%d", a);
1579 #endif
1580 }
1581
1582 DumpStateOrd * const & dumpState = (DumpStateOrd *)&signal->theData[0];
1583 Uint32 arg = dumpState->args[0];
1584 if (arg == DumpStateOrd::CmvmiDumpConnections){
1585 for(unsigned int i = 1; i < MAX_NODES; i++ ){
1586 const char* nodeTypeStr = "";
1587 switch(getNodeInfo(i).m_type){
1588 case NodeInfo::DB:
1589 nodeTypeStr = "DB";
1590 break;
1591 case NodeInfo::API:
1592 nodeTypeStr = "API";
1593 break;
1594 case NodeInfo::MGM:
1595 nodeTypeStr = "MGM";
1596 break;
1597 case NodeInfo::INVALID:
1598 nodeTypeStr = 0;
1599 break;
1600 default:
1601 nodeTypeStr = "<UNKNOWN>";
1602 }
1603
1604 if(nodeTypeStr == 0)
1605 continue;
1606
1607 infoEvent("Connection to %d (%s) %s",
1608 i,
1609 nodeTypeStr,
1610 globalTransporterRegistry.getPerformStateString(i));
1611 }
1612 }
1613
1614 if (arg == DumpStateOrd::CmvmiDumpSubscriptions)
1615 {
1616 SubscriberPtr ptr;
1617 subscribers.first(ptr);
1618 g_eventLogger->info("List subscriptions:");
1619 while(ptr.i != RNIL)
1620 {
1621 g_eventLogger->info("Subscription: %u, nodeId: %u, ref: 0x%x",
1622 ptr.i, refToNode(ptr.p->blockRef), ptr.p->blockRef);
1623 for(Uint32 i = 0; i < LogLevel::LOGLEVEL_CATEGORIES; i++)
1624 {
1625 Uint32 level = ptr.p->logLevel.getLogLevel((LogLevel::EventCategory)i);
1626 g_eventLogger->info("Category %u Level %u", i, level);
1627 }
1628 subscribers.next(ptr);
1629 }
1630 }
1631
1632 if (arg == DumpStateOrd::CmvmiDumpLongSignalMemory){
1633 infoEvent("Cmvmi: g_sectionSegmentPool size: %d free: %d",
1634 g_sectionSegmentPool.getSize(),
1635 g_sectionSegmentPool.getNoOfFree());
1636 }
1637
1638 if (dumpState->args[0] == DumpStateOrd::DumpPageMemory)
1639 {
1640 const Uint32 len = signal->getLength();
1641 if (len == 1)
1642 {
1643 // Start dumping resource limits
1644 signal->theData[1] = 0;
1645 signal->theData[2] = ~0;
1646 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
1647
1648 // Dump data and index memory
1649 reportDMUsage(signal, 0);
1650 reportIMUsage(signal, 0);
1651 return;
1652 }
1653
1654 if (len == 2)
1655 {
1656 // Dump data and index memory to specific ref
1657 Uint32 result_ref = signal->theData[1];
1658 reportDMUsage(signal, 0, result_ref);
1659 reportIMUsage(signal, 0, result_ref);
1660 return;
1661 }
1662
1663 Uint32 id = signal->theData[1];
1664 Resource_limit rl;
1665 if (m_ctx.m_mm.get_resource_limit(id, rl))
1666 {
1667 if (rl.m_min || rl.m_curr || rl.m_max)
1668 {
1669 infoEvent("Resource %d min: %d max: %d curr: %d",
1670 id, rl.m_min, rl.m_max, rl.m_curr);
1671 }
1672
1673 signal->theData[0] = 1000;
1674 signal->theData[1] = id+1;
1675 signal->theData[2] = ~0;
1676 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 3, JBB);
1677 }
1678 return;
1679 }
1680 if (arg == DumpStateOrd::CmvmiSchedulerExecutionTimer)
1681 {
1682 Uint32 exec_time = signal->theData[1];
1683 globalEmulatorData.theConfiguration->schedulerExecutionTimer(exec_time);
1684 }
1685 if (arg == DumpStateOrd::CmvmiSchedulerSpinTimer)
1686 {
1687 Uint32 spin_time = signal->theData[1];
1688 globalEmulatorData.theConfiguration->schedulerSpinTimer(spin_time);
1689 }
1690 if (arg == DumpStateOrd::CmvmiRealtimeScheduler)
1691 {
1692 bool realtime_on = signal->theData[1];
1693 globalEmulatorData.theConfiguration->realtimeScheduler(realtime_on);
1694 }
1695 if (arg == DumpStateOrd::CmvmiExecuteLockCPU)
1696 {
1697 }
1698 if (arg == DumpStateOrd::CmvmiMaintLockCPU)
1699 {
1700 }
1701 if (arg == DumpStateOrd::CmvmiSetRestartOnErrorInsert)
1702 {
1703 if(signal->getLength() == 1)
1704 {
1705 Uint32 val = (Uint32)NRT_NoStart_Restart;
1706 const ndb_mgm_configuration_iterator * p =
1707 m_ctx.m_config.getOwnConfigIterator();
1708 ndbrequire(p != 0);
1709
1710 if(!ndb_mgm_get_int_parameter(p, CFG_DB_STOP_ON_ERROR_INSERT, &val))
1711 {
1712 m_ctx.m_config.setRestartOnErrorInsert(val);
1713 }
1714 }
1715 else
1716 {
1717 m_ctx.m_config.setRestartOnErrorInsert(signal->theData[1]);
1718 }
1719 }
1720
1721 if (arg == DumpStateOrd::CmvmiTestLongSigWithDelay) {
1722 unsigned i;
1723 Uint32 testType = dumpState->args[1];
1724 Uint32 loopCount = dumpState->args[2];
1725 Uint32 print = dumpState->args[3];
1726 const unsigned len0 = 11;
1727 const unsigned len1 = 123;
1728 Uint32 sec0[len0];
1729 Uint32 sec1[len1];
1730 for (i = 0; i < len0; i++)
1731 sec0[i] = i;
1732 for (i = 0; i < len1; i++)
1733 sec1[i] = 16 * i;
1734 Uint32* sig = signal->getDataPtrSend();
1735 sig[0] = reference();
1736 sig[1] = testType;
1737 sig[2] = 0;
1738 sig[3] = print;
1739 sig[4] = loopCount;
1740 sig[5] = len0;
1741 sig[6] = len1;
1742 sig[7] = 0;
1743 LinearSectionPtr ptr[3];
1744 ptr[0].p = sec0;
1745 ptr[0].sz = len0;
1746 ptr[1].p = sec1;
1747 ptr[1].sz = len1;
1748 sendSignal(reference(), GSN_TESTSIG, signal, 8, JBB, ptr, 2);
1749 }
1750
1751 if (arg == DumpStateOrd::DumpEventLog)
1752 {
1753 Uint32 result_ref = signal->theData[1];
1754 m_saved_event_buffer.startScan();
1755 SavedEvent s;
1756 Uint32 cnt = 0;
1757 EventReport * rep = CAST_PTR(EventReport, signal->getDataPtrSend());
1758 rep->setEventType(NDB_LE_SavedEvent);
1759 rep->setNodeId(getOwnNodeId());
1760 while (m_saved_event_buffer.scan(&s, 0))
1761 {
1762 jam();
1763 cnt++;
1764 signal->theData[1] = s.m_len;
1765 signal->theData[2] = s.m_seq;
1766 signal->theData[3] = s.m_time;
1767 if (s.m_len <= 21)
1768 {
1769 jam();
1770 memcpy(signal->theData+4, s.m_data, 4*s.m_len);
1771 sendSignal(result_ref, GSN_EVENT_REP, signal, 4 + s.m_len, JBB);
1772 }
1773 else
1774 {
1775 jam();
1776 LinearSectionPtr ptr[3];
1777 ptr[0].p = s.m_data;
1778 ptr[0].sz = s.m_len;
1779 sendSignal(result_ref, GSN_EVENT_REP, signal, 4, JBB, ptr, 1);
1780 }
1781 }
1782 signal->theData[1] = 0; // end of stream
1783 sendSignal(result_ref, GSN_EVENT_REP, signal, 2, JBB);
1784 return;
1785 }
1786
1787 if (arg == DumpStateOrd::CmvmiTestLongSig)
1788 {
1789 /* Forward as GSN_TESTSIG to self */
1790 Uint32 numArgs= signal->length() - 1;
1791 memmove(signal->getDataPtrSend(),
1792 signal->getDataPtrSend() + 1,
1793 numArgs << 2);
1794 sendSignal(reference(), GSN_TESTSIG, signal, numArgs, JBB);
1795 }
1796
1797 #ifdef ERROR_INSERT
1798 if (arg == 9000 || arg == 9002)
1799 {
1800 SET_ERROR_INSERT_VALUE(arg);
1801 for (Uint32 i = 1; i<signal->getLength(); i++)
1802 c_error_9000_nodes_mask.set(signal->theData[i]);
1803 }
1804
1805 if (arg == 9001)
1806 {
1807 CLEAR_ERROR_INSERT_VALUE;
1808 if (signal->getLength() == 1 || signal->theData[1])
1809 {
1810 for (Uint32 i = 0; i<MAX_NODES; i++)
1811 {
1812 if (c_error_9000_nodes_mask.get(i))
1813 {
1814 signal->theData[0] = 0;
1815 signal->theData[1] = i;
1816 EXECUTE_DIRECT(CMVMI, GSN_OPEN_COMREQ, signal, 2);
1817 }
1818 }
1819 }
1820 c_error_9000_nodes_mask.clear();
1821 }
1822
1823 if (arg == 9004 && signal->getLength() == 2)
1824 {
1825 SET_ERROR_INSERT_VALUE(9004);
1826 c_error_9000_nodes_mask.clear();
1827 c_error_9000_nodes_mask.set(signal->theData[1]);
1828 }
1829
1830 if (arg == 9004 && signal->getLength() == 2)
1831 {
1832 SET_ERROR_INSERT_VALUE(9004);
1833 c_error_9000_nodes_mask.clear();
1834 c_error_9000_nodes_mask.set(signal->theData[1]);
1835 }
1836 #endif
1837
1838 #ifdef VM_TRACE
1839 #if 0
1840 {
1841 SafeCounterManager mgr(* this); mgr.setSize(1);
1842 SafeCounterHandle handle;
1843
1844 {
1845 SafeCounter tmp(mgr, handle);
1846 tmp.init<RefSignalTest>(CMVMI, GSN_TESTSIG, /* senderData */ 13);
1847 tmp.setWaitingFor(3);
1848 ndbrequire(!tmp.done());
1849 ndbout_c("Allocted");
1850 }
1851 ndbrequire(!handle.done());
1852 {
1853 SafeCounter tmp(mgr, handle);
1854 tmp.clearWaitingFor(3);
1855 ndbrequire(tmp.done());
1856 ndbout_c("Deallocted");
1857 }
1858 ndbrequire(handle.done());
1859 }
1860 #endif
1861 #endif
1862
1863 #ifdef ERROR_INSERT
1864 /* <Target NodeId> dump 9992 <NodeId list>
1865 * On Target NodeId, block receiving signals from NodeId list
1866 *
1867 * <Target NodeId> dump 9993 <NodeId list>
1868 * On Target NodeId, resume receiving signals from NodeId list
1869 *
1870 * <Target NodeId> dump 9991
1871 * On Target NodeId, resume receiving signals from any blocked node
1872 *
1873 *
1874 * See also code in QMGR for blocking receive from nodes based
1875 * on HB roles.
1876 *
1877 */
1878 if((arg == 9993) || /* Unblock recv from nodeid */
1879 (arg == 9992)) /* Block recv from nodeid */
1880 {
1881 bool block = (arg == 9992);
1882 for (Uint32 n = 1; n < signal->getLength(); n++)
1883 {
1884 Uint32 nodeId = signal->theData[n];
1885
1886 if ((nodeId > 0) &&
1887 (nodeId < MAX_NODES))
1888 {
1889 if (block)
1890 {
1891 ndbout_c("CMVMI : Blocking receive from node %u", nodeId);
1892
1893 globalTransporterRegistry.blockReceive(nodeId);
1894 }
1895 else
1896 {
1897 ndbout_c("CMVMI : Unblocking receive from node %u", nodeId);
1898
1899 globalTransporterRegistry.unblockReceive(nodeId);
1900 }
1901 }
1902 else
1903 {
1904 ndbout_c("CMVMI : Ignoring dump %u for node %u",
1905 arg, nodeId);
1906 }
1907 }
1908 }
1909 if (arg == 9990) /* Block recv from all ndbd matching pattern */
1910 {
1911 Uint32 pattern = 0;
1912 if (signal->getLength() > 1)
1913 {
1914 pattern = signal->theData[1];
1915 ndbout_c("CMVMI : Blocking receive from all ndbds matching pattern -%s-",
1916 ((pattern == 1)? "Other side":"Unknown"));
1917 }
1918
1919 for (Uint32 node = 1; node < MAX_NDB_NODES; node++)
1920 {
1921 if (globalTransporterRegistry.is_connected(node))
1922 {
1923 if (getNodeInfo(node).m_type == NodeInfo::DB)
1924 {
1925 if (!globalTransporterRegistry.isBlocked(node))
1926 {
1927 switch (pattern)
1928 {
1929 case 1:
1930 {
1931 /* Match if given node is on 'other side' of
1932 * 2-replica cluster
1933 */
1934 if ((getOwnNodeId() & 1) != (node & 1))
1935 {
1936 /* Node is on the 'other side', match */
1937 break;
1938 }
1939 /* Node is on 'my side', don't match */
1940 continue;
1941 }
1942 default:
1943 break;
1944 }
1945 ndbout_c("CMVMI : Blocking receive from node %u", node);
1946 globalTransporterRegistry.blockReceive(node);
1947 }
1948 }
1949 }
1950 }
1951 }
1952 if (arg == 9991) /* Unblock recv from all blocked */
1953 {
1954 for (Uint32 node = 0; node < MAX_NODES; node++)
1955 {
1956 if (globalTransporterRegistry.isBlocked(node))
1957 {
1958 ndbout_c("CMVMI : Unblocking receive from node %u", node);
1959 globalTransporterRegistry.unblockReceive(node);
1960 }
1961 }
1962 }
1963 #endif
1964
1965 if (arg == 9999)
1966 {
1967 Uint32 delay = 1000;
1968 switch(signal->getLength()){
1969 case 1:
1970 break;
1971 case 2:
1972 delay = signal->theData[1];
1973 break;
1974 default:{
1975 Uint32 dmin = signal->theData[1];
1976 Uint32 dmax = signal->theData[2];
1977 delay = dmin + (rand() % (dmax - dmin));
1978 break;
1979 }
1980 }
1981
1982 signal->theData[0] = 9999;
1983 if (delay == 0)
1984 {
1985 execNDB_TAMPER(signal);
1986 }
1987 else if (delay < 10)
1988 {
1989 sendSignal(reference(), GSN_NDB_TAMPER, signal, 1, JBB);
1990 }
1991 else
1992 {
1993 sendSignalWithDelay(reference(), GSN_NDB_TAMPER, signal, delay, 1);
1994 }
1995 }
1996
1997 if (signal->theData[0] == 666)
1998 {
1999 jam();
2000 Uint32 mb = 100;
2001 if (signal->getLength() > 1)
2002 mb = signal->theData[1];
2003
2004 Uint64 bytes = Uint64(mb) * 1024 * 1024;
2005 AllocMemReq * req = CAST_PTR(AllocMemReq, signal->getDataPtrSend());
2006 req->senderData = 666;
2007 req->senderRef = reference();
2008 req->requestInfo = AllocMemReq::RT_EXTEND;
2009 req->bytes_hi = Uint32(bytes >> 32);
2010 req->bytes_lo = Uint32(bytes);
2011 sendSignal(NDBFS_REF, GSN_ALLOC_MEM_REQ, signal,
2012 AllocMemReq::SignalLength, JBB);
2013 }
2014 }//Cmvmi::execDUMP_STATE_ORD()
2015
2016 void
execALLOC_MEM_REF(Signal * signal)2017 Cmvmi::execALLOC_MEM_REF(Signal* signal)
2018 {
2019 jamEntry();
2020 const AllocMemRef * ref = CAST_CONSTPTR(AllocMemRef, signal->getDataPtr());
2021
2022 if (ref->senderData == 0)
2023 {
2024 jam();
2025 ndbrequire(false);
2026 }
2027 }
2028
2029 void
execALLOC_MEM_CONF(Signal * signal)2030 Cmvmi::execALLOC_MEM_CONF(Signal* signal)
2031 {
2032 jamEntry();
2033 const AllocMemConf * conf = CAST_CONSTPTR(AllocMemConf, signal->getDataPtr());
2034
2035 if (conf->senderData == 0)
2036 {
2037 jam();
2038
2039 init_global_page_pool();
2040
2041 ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
2042 conf->senderRef = reference();
2043 conf->senderData = f_read_config_data;
2044 sendSignal(f_read_config_ref, GSN_READ_CONFIG_CONF, signal,
2045 ReadConfigConf::SignalLength, JBB);
2046 return;
2047 }
2048 }
2049
execDBINFO_SCANREQ(Signal * signal)2050 void Cmvmi::execDBINFO_SCANREQ(Signal *signal)
2051 {
2052 DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
2053 const Ndbinfo::ScanCursor* cursor =
2054 CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
2055 Ndbinfo::Ratelimit rl;
2056
2057 jamEntry();
2058
2059 switch(req.tableId){
2060 case Ndbinfo::TRANSPORTERS_TABLEID:
2061 {
2062 jam();
2063 Uint32 rnode = cursor->data[0];
2064 if (rnode == 0)
2065 rnode++; // Skip node 0
2066
2067 while(rnode < MAX_NODES)
2068 {
2069 switch(getNodeInfo(rnode).m_type)
2070 {
2071 default:
2072 {
2073 jam();
2074 Ndbinfo::Row row(signal, req);
2075 row.write_uint32(getOwnNodeId()); // Node id
2076 row.write_uint32(rnode); // Remote node id
2077 row.write_uint32(globalTransporterRegistry.getPerformState(rnode)); // State
2078 ndbinfo_send_row(signal, req, row, rl);
2079 break;
2080 }
2081
2082 case NodeInfo::INVALID:
2083 jam();
2084 break;
2085 }
2086
2087 rnode++;
2088 if (rl.need_break(req))
2089 {
2090 jam();
2091 ndbinfo_send_scan_break(signal, req, rl, rnode);
2092 return;
2093 }
2094 }
2095 break;
2096 }
2097
2098 case Ndbinfo::RESOURCES_TABLEID:
2099 {
2100 jam();
2101 Uint32 resource_id = cursor->data[0];
2102 Resource_limit resource_limit;
2103
2104 while(m_ctx.m_mm.get_resource_limit(resource_id, resource_limit))
2105 {
2106 jam();
2107 Ndbinfo::Row row(signal, req);
2108 row.write_uint32(getOwnNodeId()); // Node id
2109 row.write_uint32(resource_id);
2110
2111 row.write_uint32(resource_limit.m_min);
2112 row.write_uint32(resource_limit.m_curr);
2113 row.write_uint32(resource_limit.m_max);
2114 row.write_uint32(0); //TODO
2115 ndbinfo_send_row(signal, req, row, rl);
2116 resource_id++;
2117
2118 if (rl.need_break(req))
2119 {
2120 jam();
2121 ndbinfo_send_scan_break(signal, req, rl, resource_id);
2122 return;
2123 }
2124 }
2125 break;
2126 }
2127
2128 case Ndbinfo::NODES_TABLEID:
2129 {
2130 jam();
2131 const NodeState& nodeState = getNodeState();
2132 const Uint32 start_level = nodeState.startLevel;
2133 const NDB_TICKS uptime = (NdbTick_CurrentMillisecond()/1000) - m_start_time;
2134 Uint32 generation = m_ctx.m_config.get_config_generation();
2135
2136 Ndbinfo::Row row(signal, req);
2137 row.write_uint32(getOwnNodeId()); // Node id
2138
2139 row.write_uint64(uptime); // seconds
2140 row.write_uint32(start_level);
2141 row.write_uint32(start_level == NodeState::SL_STARTING ?
2142 nodeState.starting.startPhase : 0);
2143 row.write_uint32(generation);
2144 ndbinfo_send_row(signal, req, row, rl);
2145 break;
2146 }
2147
2148 case Ndbinfo::POOLS_TABLEID:
2149 {
2150 jam();
2151
2152 Resource_limit res_limit;
2153 m_ctx.m_mm.get_resource_limit(RG_DATAMEM, res_limit);
2154
2155 const Uint32 tup_pages_used = res_limit.m_curr - f_accpages;
2156 const Uint32 tup_pages_total = res_limit.m_min - f_accpages;
2157
2158 Ndbinfo::pool_entry pools[] =
2159 {
2160 { "Data memory",
2161 tup_pages_used,
2162 tup_pages_total,
2163 sizeof(GlobalPage),
2164 0,
2165 { CFG_DB_DATA_MEM,0,0,0 }},
2166 { NULL, 0,0,0,0,{ 0,0,0,0 }}
2167 };
2168
2169 static const size_t num_config_params =
2170 sizeof(pools[0].config_params)/sizeof(pools[0].config_params[0]);
2171 Uint32 pool = cursor->data[0];
2172 BlockNumber bn = blockToMain(number());
2173 while(pools[pool].poolname)
2174 {
2175 jam();
2176 Ndbinfo::Row row(signal, req);
2177 row.write_uint32(getOwnNodeId());
2178 row.write_uint32(bn); // block number
2179 row.write_uint32(instance()); // block instance
2180 row.write_string(pools[pool].poolname);
2181
2182 row.write_uint64(pools[pool].used);
2183 row.write_uint64(pools[pool].total);
2184 row.write_uint64(pools[pool].used_hi);
2185 row.write_uint64(pools[pool].entry_size);
2186 for (size_t i = 0; i < num_config_params; i++)
2187 row.write_uint32(pools[pool].config_params[i]);
2188 ndbinfo_send_row(signal, req, row, rl);
2189 pool++;
2190 if (rl.need_break(req))
2191 {
2192 jam();
2193 ndbinfo_send_scan_break(signal, req, rl, pool);
2194 return;
2195 }
2196 }
2197 }
2198
2199 default:
2200 break;
2201 }
2202
2203 ndbinfo_send_scan_conf(signal, req, rl);
2204 }
2205
2206
2207 void
execNODE_START_REP(Signal * signal)2208 Cmvmi::execNODE_START_REP(Signal* signal)
2209 {
2210 #ifdef ERROR_INSERT
2211 if (ERROR_INSERTED(9002) && signal->theData[0] == getOwnNodeId())
2212 {
2213 signal->theData[0] = 9001;
2214 execDUMP_STATE_ORD(signal);
2215 }
2216 #endif
2217 }
2218
BLOCK_FUNCTIONS(Cmvmi)2219 BLOCK_FUNCTIONS(Cmvmi)
2220
2221 void
2222 Cmvmi::startFragmentedSend(Signal* signal,
2223 Uint32 variant,
2224 Uint32 numSigs,
2225 NodeReceiverGroup rg)
2226 {
2227 Uint32* sigData = signal->getDataPtrSend();
2228 const Uint32 sigLength = 6;
2229 const Uint32 sectionWords = 240;
2230 Uint32 sectionData[ sectionWords ];
2231
2232 for (Uint32 i = 0; i < sectionWords; i++)
2233 sectionData[ i ] = i;
2234
2235 const Uint32 secCount = 1;
2236 LinearSectionPtr ptr[3];
2237 ptr[0].sz = sectionWords;
2238 ptr[0].p = §ionData[0];
2239
2240 for (Uint32 i = 0; i < numSigs; i++)
2241 {
2242 sigData[0] = variant;
2243 sigData[1] = 31;
2244 sigData[2] = 0;
2245 sigData[3] = 1; // print
2246 sigData[4] = 0;
2247 sigData[5] = sectionWords;
2248
2249 if ((i & 1) == 0)
2250 {
2251 DEBUG("Starting linear fragmented send (" << i + 1
2252 << "/" << numSigs << ")");
2253
2254 /* Linear send */
2255 /* Todo : Avoid reading from invalid stackptr in CONTINUEB */
2256 sendFragmentedSignal(rg,
2257 GSN_TESTSIG,
2258 signal,
2259 sigLength,
2260 JBB,
2261 ptr,
2262 secCount,
2263 TheEmptyCallback,
2264 90); // messageSize
2265 }
2266 else
2267 {
2268 /* Segmented send */
2269 DEBUG("Starting segmented fragmented send (" << i + 1
2270 << "/" << numSigs << ")");
2271 Ptr<SectionSegment> segPtr;
2272 ndbrequire(import(segPtr, sectionData, sectionWords));
2273 SectionHandle handle(this, segPtr.i);
2274
2275 sendFragmentedSignal(rg,
2276 GSN_TESTSIG,
2277 signal,
2278 sigLength,
2279 JBB,
2280 &handle,
2281 TheEmptyCallback,
2282 90); // messageSize
2283 }
2284 }
2285 }
2286
2287 void
testNodeFailureCleanupCallback(Signal * signal,Uint32 data,Uint32 elementsCleaned)2288 Cmvmi::testNodeFailureCleanupCallback(Signal* signal, Uint32 data, Uint32 elementsCleaned)
2289 {
2290 DEBUG("testNodeFailureCleanupCallback");
2291 DEBUG("Data : " << data
2292 << " elementsCleaned : " << elementsCleaned);
2293
2294 debugPrintFragmentCounts();
2295
2296 Uint32 variant = data & 0xffff;
2297 Uint32 testType = (data >> 16) & 0xffff;
2298
2299 DEBUG("Sending trigger(" << testType
2300 << ") variant " << variant
2301 << " to self to cleanup any fragments that arrived "
2302 << "before send was cancelled");
2303
2304 Uint32* sigData = signal->getDataPtrSend();
2305 sigData[0] = variant;
2306 sigData[1] = testType;
2307 sendSignal(reference(), GSN_TESTSIG, signal, 2, JBB);
2308
2309 return;
2310 }
2311
2312 void
testFragmentedCleanup(Signal * signal,SectionHandle * handle,Uint32 testType,Uint32 variant)2313 Cmvmi::testFragmentedCleanup(Signal* signal, SectionHandle* handle, Uint32 testType, Uint32 variant)
2314 {
2315 DEBUG("TestType " << testType << " variant " << variant);
2316 debugPrintFragmentCounts();
2317
2318 /* Variants :
2319 * Local fragmented send Multicast fragmented send
2320 * 0 : Immediate cleanup Immediate cleanup
2321 * 1 : Continued cleanup Immediate cleanup
2322 * 2 : Immediate cleanup Continued cleanup
2323 * 3 : Continued cleanup Continued cleanup
2324 */
2325 const Uint32 NUM_VARIANTS = 4;
2326 if (variant >= NUM_VARIANTS)
2327 {
2328 DEBUG("Unsupported variant");
2329 releaseSections(*handle);
2330 return;
2331 }
2332
2333 /* Test from ndb_mgm with
2334 * <node(s)> DUMP 2605 0 30
2335 *
2336 * Use
2337 * <node(s)> DUMP 2605 0 39 to get fragment resource usage counts
2338 * Use
2339 * <node(s)> DUMP 2601 to get segment usage counts in clusterlog
2340 */
2341 if (testType == 30)
2342 {
2343 /* Send the first fragment of a fragmented signal to self
2344 * Receiver will allocate assembly hash entries
2345 * which must be freed when node failure cleanup
2346 * executes later
2347 */
2348 const Uint32 sectionWords = 240;
2349 Uint32 sectionData[ sectionWords ];
2350
2351 for (Uint32 i = 0; i < sectionWords; i++)
2352 sectionData[ i ] = i;
2353
2354 const Uint32 secCount = 1;
2355 LinearSectionPtr ptr[3];
2356 ptr[0].sz = sectionWords;
2357 ptr[0].p = §ionData[0];
2358
2359 /* Send signal with testType == 31 */
2360 NodeReceiverGroup me(reference());
2361 Uint32* sigData = signal->getDataPtrSend();
2362 const Uint32 sigLength = 6;
2363 const Uint32 numPartialSigs = 4;
2364 /* Not too many as CMVMI's fragInfo hash is limited size */
2365 // TODO : Consider making it debug-larger to get
2366 // more coverage on CONTINUEB path
2367
2368 for (Uint32 i = 0; i < numPartialSigs; i++)
2369 {
2370 /* Fill in messy TESTSIG format */
2371 sigData[0] = variant;
2372 sigData[1] = 31;
2373 sigData[2] = 0;
2374 sigData[3] = 0; // print
2375 sigData[4] = 0;
2376 sigData[5] = sectionWords;
2377
2378 FragmentSendInfo fsi;
2379
2380 DEBUG("Sending first fragment to self");
2381 sendFirstFragment(fsi,
2382 me,
2383 GSN_TESTSIG,
2384 signal,
2385 sigLength,
2386 JBB,
2387 ptr,
2388 secCount,
2389 90); // FragmentLength
2390
2391 DEBUG("Cancelling remainder to free internal section");
2392 fsi.m_status = FragmentSendInfo::SendCancelled;
2393 sendNextLinearFragment(signal, fsi);
2394 };
2395
2396 /* Ok, now send short signal with testType == 32
2397 * to trigger 'remote-side' actions in middle of
2398 * multiple fragment assembly
2399 */
2400 sigData[0] = variant;
2401 sigData[1] = 32;
2402
2403 DEBUG("Sending node fail trigger to self");
2404 sendSignal(me, GSN_TESTSIG, signal, 2, JBB);
2405 return;
2406 }
2407
2408 if (testType == 31)
2409 {
2410 /* Just release sections - execTESTSIG() has shown sections received */
2411 releaseSections(*handle);
2412 return;
2413 }
2414
2415 if (testType == 32)
2416 {
2417 /* 'Remote side' trigger to clean up fragmented signal resources */
2418 BlockReference senderRef = signal->getSendersBlockRef();
2419 Uint32 sendingNode = refToNode(senderRef);
2420
2421 /* Start sending some linear and fragmented responses to the
2422 * sender, to exercise frag-send cleanup code when we execute
2423 * node-failure later
2424 */
2425 DEBUG("Starting fragmented send using continueB back to self");
2426
2427 NodeReceiverGroup sender(senderRef);
2428 startFragmentedSend(signal, variant, 6, sender);
2429
2430 debugPrintFragmentCounts();
2431
2432 Uint32 cbData= (((Uint32) 33) << 16) | variant;
2433 Callback cb = { safe_cast(&Cmvmi::testNodeFailureCleanupCallback),
2434 cbData };
2435
2436 Callback* cbPtr = NULL;
2437
2438 bool passCallback = variant & 1;
2439
2440 if (passCallback)
2441 {
2442 DEBUG("Running simBlock failure code WITH CALLBACK for node "
2443 << sendingNode);
2444 cbPtr = &cb;
2445 }
2446 else
2447 {
2448 DEBUG("Running simBlock failure code IMMEDIATELY (no callback) for node "
2449 << sendingNode);
2450 cbPtr = &TheEmptyCallback;
2451 }
2452
2453 Uint32 elementsCleaned = simBlockNodeFailure(signal, sendingNode, *cbPtr);
2454
2455 DEBUG("Elements cleaned by call : " << elementsCleaned);
2456
2457 debugPrintFragmentCounts();
2458
2459 if (! passCallback)
2460 {
2461 DEBUG("Variant " << variant << " manually executing callback");
2462 /* We call the callback inline here to continue processing */
2463 testNodeFailureCleanupCallback(signal,
2464 cbData,
2465 elementsCleaned);
2466 }
2467
2468 return;
2469 }
2470
2471 if (testType == 33)
2472 {
2473 /* Original side - receive cleanup trigger from 'remote' side
2474 * after node failure cleanup performed there. We may have
2475 * fragments it managed to send before the cleanup completed
2476 * so we'll get rid of them.
2477 * This would not be necessary in reality as this node would
2478 * be failed
2479 */
2480 Uint32 sendingNode = refToNode(signal->getSendersBlockRef());
2481 DEBUG("Running simBlock failure code for node " << sendingNode);
2482
2483 Uint32 elementsCleaned = simBlockNodeFailure(signal, sendingNode);
2484
2485 DEBUG("Elements cleaned : " << elementsCleaned);
2486
2487 /* Should have no fragment resources in use now */
2488 ndbrequire(debugPrintFragmentCounts() == 0);
2489
2490 /* Now use ReceiverGroup to multicast a fragmented signal to
2491 * all database nodes
2492 */
2493 DEBUG("Starting to send fragmented continueB to all nodes inc. self : ");
2494 NodeReceiverGroup allNodes(CMVMI, c_dbNodes);
2495
2496 unsigned nodeId = 0;
2497 while((nodeId = c_dbNodes.find(nodeId+1)) != BitmaskImpl::NotFound)
2498 {
2499 DEBUG("Node " << nodeId);
2500 }
2501
2502 startFragmentedSend(signal, variant, 8, allNodes);
2503
2504 debugPrintFragmentCounts();
2505
2506 Uint32 cbData= (((Uint32) 34) << 16) | variant;
2507 Callback cb = { safe_cast(&Cmvmi::testNodeFailureCleanupCallback),
2508 cbData };
2509
2510 Callback* cbPtr = NULL;
2511
2512 bool passCallback = variant & 2;
2513
2514 if (passCallback)
2515 {
2516 DEBUG("Running simBlock failure code for self WITH CALLBACK ("
2517 << getOwnNodeId() << ")");
2518 cbPtr= &cb;
2519 }
2520 else
2521 {
2522 DEBUG("Running simBlock failure code for self IMMEDIATELY (no callback) ("
2523 << getOwnNodeId() << ")");
2524 cbPtr= &TheEmptyCallback;
2525 }
2526
2527
2528 /* Fragmented signals being sent will have this node removed
2529 * from their receiver group, but will keep sending to the
2530 * other node(s).
2531 * Other node(s) should therefore receive the complete signals.
2532 * We will then receive only the first fragment of each of
2533 * the signals which must be removed later.
2534 */
2535 elementsCleaned = simBlockNodeFailure(signal, getOwnNodeId(), *cbPtr);
2536
2537 DEBUG("Elements cleaned : " << elementsCleaned);
2538
2539 debugPrintFragmentCounts();
2540
2541 /* Callback will send a signal to self to clean up fragments that
2542 * were sent to self before the send was cancelled.
2543 * (Again, unnecessary in a 'real' situation
2544 */
2545 if (!passCallback)
2546 {
2547 DEBUG("Variant " << variant << " manually executing callback");
2548
2549 testNodeFailureCleanupCallback(signal,
2550 cbData,
2551 elementsCleaned);
2552 }
2553
2554 return;
2555 }
2556
2557 if (testType == 34)
2558 {
2559 /* Cleanup fragments which were sent before send was cancelled. */
2560 Uint32 elementsCleaned = simBlockNodeFailure(signal, getOwnNodeId());
2561
2562 DEBUG("Elements cleaned " << elementsCleaned);
2563
2564 /* All FragInfo should be clear, may still be sending some
2565 * to other node(s)
2566 */
2567 debugPrintFragmentCounts();
2568
2569 DEBUG("Variant " << variant << " completed.");
2570
2571 if (++variant < NUM_VARIANTS)
2572 {
2573 DEBUG("Re-executing with variant " << variant);
2574 Uint32* sigData = signal->getDataPtrSend();
2575 sigData[0] = variant;
2576 sigData[1] = 30;
2577 sendSignal(reference(), GSN_TESTSIG, signal, 2, JBB);
2578 }
2579 // else
2580 // {
2581 // // Infinite loop to test for leaks
2582 // DEBUG("Back to zero");
2583 // Uint32* sigData = signal->getDataPtrSend();
2584 // sigData[0] = 0;
2585 // sigData[1] = 30;
2586 // sendSignal(reference(), GSN_TESTSIG, signal, 2, JBB);
2587 // }
2588 }
2589 }
2590
2591 static Uint32 g_print;
2592 static LinearSectionPtr g_test[3];
2593
2594 /* See above for how to generate TESTSIG using DUMP 2603
2595 * (e.g. : <All/NodeId> DUMP 2603 <TestId> <LoopCount> <Print>
2596 * LoopCount : How many times test should loop (0-n)
2597 * Print : Whether signals should be printed : 0=no 1=yes
2598 *
2599 * TestIds
2600 * 20 : Test sendDelayed with 1 milli delay, LoopCount times
2601 * 1-16 : See vm/testLongSig.cpp
2602 */
2603 void
execTESTSIG(Signal * signal)2604 Cmvmi::execTESTSIG(Signal* signal){
2605 Uint32 i;
2606 /**
2607 * Test of SafeCounter
2608 */
2609 jamEntry();
2610
2611 if(!assembleFragments(signal)){
2612 jam();
2613 return;
2614 }
2615
2616 Uint32 ref = signal->theData[0];
2617 Uint32 testType = signal->theData[1];
2618 Uint32 fragmentLength = signal->theData[2];
2619 g_print = signal->theData[3];
2620 // Uint32 returnCount = signal->theData[4];
2621 Uint32 * secSizes = &signal->theData[5];
2622
2623 SectionHandle handle(this, signal);
2624
2625 if(g_print){
2626 SignalLoggerManager::printSignalHeader(stdout,
2627 signal->header,
2628 0,
2629 getOwnNodeId(),
2630 true);
2631 ndbout_c("-- Fixed section --");
2632 for(i = 0; i<signal->length(); i++){
2633 fprintf(stdout, "H'0x%.8x ", signal->theData[i]);
2634 if(((i + 1) % 6) == 0)
2635 fprintf(stdout, "\n");
2636 }
2637 fprintf(stdout, "\n");
2638
2639 for(i = 0; i<handle.m_cnt; i++){
2640 SegmentedSectionPtr ptr(0,0,0);
2641 ndbout_c("-- Section %d --", i);
2642 handle.getSection(ptr, i);
2643 ndbrequire(ptr.p != 0);
2644 print(ptr, stdout);
2645 ndbrequire(ptr.sz == secSizes[i]);
2646 }
2647 }
2648
2649 /**
2650 * Validate length:s
2651 */
2652 for(i = 0; i<handle.m_cnt; i++){
2653 SegmentedSectionPtr ptr;
2654 handle.getSection(ptr, i);
2655 ndbrequire(ptr.p != 0);
2656 ndbrequire(ptr.sz == secSizes[i]);
2657 }
2658
2659 /**
2660 * Testing send with delay.
2661 */
2662 if (testType == 20) {
2663 if (signal->theData[4] == 0) {
2664 releaseSections(handle);
2665 return;
2666 }
2667 signal->theData[4]--;
2668 sendSignalWithDelay(reference(), GSN_TESTSIG, signal, 100, 8, &handle);
2669 return;
2670 }
2671
2672 if (g_print)
2673 ndbout_c("TestType=%u signal->theData[4]=%u, sendersBlockRef=%u ref=%u\n",
2674 testType, signal->theData[4], signal->getSendersBlockRef(), ref);
2675
2676 NodeReceiverGroup rg(CMVMI, c_dbNodes);
2677
2678 /**
2679 * Testing SimulatedBlock fragment assembly cleanup
2680 */
2681 if ((testType >= 30) &&
2682 (testType < 40))
2683 {
2684 testFragmentedCleanup(signal, &handle, testType, ref);
2685 return;
2686 }
2687
2688 if(signal->getSendersBlockRef() == ref){
2689 /**
2690 * Signal from API (not via NodeReceiverGroup)
2691 */
2692 if((testType % 2) == 1){
2693 signal->theData[4] = 1; // No further signals after this
2694 } else {
2695 // Change testType to UniCast, and set loopCount to the
2696 // number of nodes.
2697 signal->theData[1] --;
2698 signal->theData[4] = rg.m_nodes.count();
2699 }
2700 }
2701
2702 switch(testType){
2703 case 1:
2704 /* Unicast to self */
2705 sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB,
2706 &handle);
2707 break;
2708 case 2:
2709 /* Multicast to all nodes */
2710 sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB,
2711 &handle);
2712 break;
2713 case 3:
2714 case 4:{
2715 LinearSectionPtr ptr[3];
2716 const Uint32 secs = handle.m_cnt;
2717 for(i = 0; i<secs; i++){
2718 SegmentedSectionPtr sptr(0,0,0);
2719 handle.getSection(sptr, i);
2720 ptr[i].sz = sptr.sz;
2721 ptr[i].p = new Uint32[sptr.sz];
2722 copy(ptr[i].p, sptr);
2723 }
2724
2725 if(testType == 3){
2726 /* Unicast linear sections to self */
2727 sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB, ptr, secs);
2728 } else {
2729 /* Boradcast linear sections to all nodes */
2730 sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB, ptr, secs);
2731 }
2732 for(Uint32 i = 0; i<secs; i++){
2733 delete[] ptr[i].p;
2734 }
2735 releaseSections(handle);
2736 break;
2737 }
2738 /* Send fragmented segmented sections direct send */
2739 case 5:
2740 case 6:{
2741
2742 NodeReceiverGroup tmp;
2743 if(testType == 5){
2744 /* Unicast */
2745 tmp = ref;
2746 } else {
2747 /* Multicast */
2748 tmp = rg;
2749 }
2750
2751 FragmentSendInfo fragSend;
2752 sendFirstFragment(fragSend,
2753 tmp,
2754 GSN_TESTSIG,
2755 signal,
2756 signal->length(),
2757 JBB,
2758 &handle,
2759 false, // Release sections on send
2760 fragmentLength);
2761
2762 int count = 1;
2763 while(fragSend.m_status != FragmentSendInfo::SendComplete){
2764 count++;
2765 if(g_print)
2766 ndbout_c("Sending fragment %d", count);
2767 sendNextSegmentedFragment(signal, fragSend);
2768 }
2769 break;
2770 }
2771 /* Send fragmented linear sections direct send */
2772 case 7:
2773 case 8:{
2774 LinearSectionPtr ptr[3];
2775 const Uint32 secs = handle.m_cnt;
2776 for(i = 0; i<secs; i++){
2777 SegmentedSectionPtr sptr(0,0,0);
2778 handle.getSection(sptr, i);
2779 ptr[i].sz = sptr.sz;
2780 ptr[i].p = new Uint32[sptr.sz];
2781 copy(ptr[i].p, sptr);
2782 }
2783
2784 NodeReceiverGroup tmp;
2785 if(testType == 7){
2786 /* Unicast */
2787 tmp = ref;
2788 } else {
2789 /* Multicast */
2790 tmp = rg;
2791 }
2792
2793 FragmentSendInfo fragSend;
2794 sendFirstFragment(fragSend,
2795 tmp,
2796 GSN_TESTSIG,
2797 signal,
2798 signal->length(),
2799 JBB,
2800 ptr,
2801 secs,
2802 fragmentLength);
2803
2804 int count = 1;
2805 while(fragSend.m_status != FragmentSendInfo::SendComplete){
2806 count++;
2807 if(g_print)
2808 ndbout_c("Sending fragment %d", count);
2809 sendNextLinearFragment(signal, fragSend);
2810 }
2811
2812 for(i = 0; i<secs; i++){
2813 delete[] ptr[i].p;
2814 }
2815 releaseSections(handle);
2816 break;
2817 }
2818 /* Test fragmented segmented send with callback */
2819 case 9:
2820 case 10:{
2821
2822 Callback m_callBack;
2823 m_callBack.m_callbackFunction =
2824 safe_cast(&Cmvmi::sendFragmentedComplete);
2825
2826 if(testType == 9){
2827 /* Unicast */
2828 m_callBack.m_callbackData = 9;
2829 sendFragmentedSignal(ref,
2830 GSN_TESTSIG, signal, signal->length(), JBB,
2831 &handle,
2832 m_callBack,
2833 fragmentLength);
2834 } else {
2835 /* Multicast */
2836 m_callBack.m_callbackData = 10;
2837 sendFragmentedSignal(rg,
2838 GSN_TESTSIG, signal, signal->length(), JBB,
2839 &handle,
2840 m_callBack,
2841 fragmentLength);
2842 }
2843 break;
2844 }
2845 /* Test fragmented linear send with callback */
2846 case 11:
2847 case 12:{
2848
2849 const Uint32 secs = handle.m_cnt;
2850 memset(g_test, 0, sizeof(g_test));
2851 for(i = 0; i<secs; i++){
2852 SegmentedSectionPtr sptr(0,0,0);
2853 handle.getSection(sptr, i);
2854 g_test[i].sz = sptr.sz;
2855 g_test[i].p = new Uint32[sptr.sz];
2856 copy(g_test[i].p, sptr);
2857 }
2858
2859 releaseSections(handle);
2860
2861 Callback m_callBack;
2862 m_callBack.m_callbackFunction =
2863 safe_cast(&Cmvmi::sendFragmentedComplete);
2864
2865 if(testType == 11){
2866 /* Unicast */
2867 m_callBack.m_callbackData = 11;
2868 sendFragmentedSignal(ref,
2869 GSN_TESTSIG, signal, signal->length(), JBB,
2870 g_test, secs,
2871 m_callBack,
2872 fragmentLength);
2873 } else {
2874 /* Multicast */
2875 m_callBack.m_callbackData = 12;
2876 sendFragmentedSignal(rg,
2877 GSN_TESTSIG, signal, signal->length(), JBB,
2878 g_test, secs,
2879 m_callBack,
2880 fragmentLength);
2881 }
2882 break;
2883 }
2884 /* Send fragmented segmented sections direct send no-release */
2885 case 13:
2886 case 14:{
2887 NodeReceiverGroup tmp;
2888 if(testType == 13){
2889 /* Unicast */
2890 tmp = ref;
2891 } else {
2892 /* Multicast */
2893 tmp = rg;
2894 }
2895
2896 FragmentSendInfo fragSend;
2897 sendFirstFragment(fragSend,
2898 tmp,
2899 GSN_TESTSIG,
2900 signal,
2901 signal->length(),
2902 JBB,
2903 &handle,
2904 true, // Don't release sections
2905 fragmentLength);
2906
2907 int count = 1;
2908 while(fragSend.m_status != FragmentSendInfo::SendComplete){
2909 count++;
2910 if(g_print)
2911 ndbout_c("Sending fragment %d", count);
2912 sendNextSegmentedFragment(signal, fragSend);
2913 }
2914
2915 if (g_print)
2916 ndbout_c("Free sections : %u\n", g_sectionSegmentPool.getNoOfFree());
2917 releaseSections(handle);
2918 //handle.clear(); // Use instead of releaseSections to Leak sections
2919 break;
2920 }
2921 /* Loop decrementing signal->theData[9] */
2922 case 15:{
2923 releaseSections(handle);
2924 ndbrequire(signal->getNoOfSections() == 0);
2925 Uint32 loop = signal->theData[9];
2926 if(loop > 0){
2927 signal->theData[9] --;
2928 sendSignal(CMVMI_REF, GSN_TESTSIG, signal, signal->length(), JBB);
2929 return;
2930 }
2931 sendSignal(ref, GSN_TESTSIG, signal, signal->length(), JBB);
2932 return;
2933 }
2934 case 16:{
2935 releaseSections(handle);
2936 Uint32 count = signal->theData[8];
2937 signal->theData[10] = count * rg.m_nodes.count();
2938 for(i = 0; i<count; i++){
2939 sendSignal(rg, GSN_TESTSIG, signal, signal->length(), JBB);
2940 }
2941 return;
2942 }
2943
2944 default:
2945 ndbrequire(false);
2946 }
2947 return;
2948 }
2949
2950 void
sendFragmentedComplete(Signal * signal,Uint32 data,Uint32 returnCode)2951 Cmvmi::sendFragmentedComplete(Signal* signal, Uint32 data, Uint32 returnCode){
2952 if(g_print)
2953 ndbout_c("sendFragmentedComplete: %d", data);
2954 if(data == 11 || data == 12){
2955 for(Uint32 i = 0; i<3; i++){
2956 if(g_test[i].p != 0)
2957 delete[] g_test[i].p;
2958 }
2959 }
2960 }
2961
2962
2963 static Uint32
calc_percent(Uint32 used,Uint32 total)2964 calc_percent(Uint32 used, Uint32 total)
2965 {
2966 return (total ? (used * 100)/total : 0);
2967 }
2968
2969
2970 static Uint32
sum_array(const Uint32 array[],unsigned sz)2971 sum_array(const Uint32 array[], unsigned sz)
2972 {
2973 Uint32 sum = 0;
2974 for (unsigned i = 0; i < sz; i++)
2975 sum += array[i];
2976 return sum;
2977 }
2978
2979
2980 /*
2981 Check if any of the given thresholds has been
2982 passed since last
2983
2984 Returns:
2985 -1 no threshold passed
2986 0 - 100 threshold passed
2987 */
2988
2989 static int
check_threshold(Uint32 last,Uint32 now)2990 check_threshold(Uint32 last, Uint32 now)
2991 {
2992 assert(last <= 100 && now <= 100);
2993
2994 static const Uint32 thresholds[] = { 100, 99, 90, 80, 0 };
2995
2996 Uint32 passed;
2997 for (size_t i = 0; i < NDB_ARRAY_SIZE(thresholds); i++)
2998 {
2999 if (now >= thresholds[i])
3000 {
3001 passed = thresholds[i];
3002 break;
3003 }
3004 }
3005 assert(passed <= 100);
3006
3007 if (passed == last)
3008 return -1; // Already reported this level
3009
3010 return passed;
3011 }
3012
3013
3014 void
execCONTINUEB(Signal * signal)3015 Cmvmi::execCONTINUEB(Signal* signal)
3016 {
3017 switch(signal->theData[0]){
3018 case ZREPORT_MEMORY_USAGE:
3019 {
3020 jam();
3021 Uint32 cnt = signal->theData[1];
3022 Uint32 tup_percent_last = signal->theData[2];
3023 Uint32 acc_percent_last = signal->theData[3];
3024
3025 {
3026 // Data memory threshold
3027 Resource_limit rl;
3028 m_ctx.m_mm.get_resource_limit(RG_DATAMEM, rl);
3029
3030 const Uint32 tup_pages_used = rl.m_curr - f_accpages;
3031 const Uint32 tup_pages_total = rl.m_min - f_accpages;
3032 const Uint32 tup_percent_now = calc_percent(tup_pages_used,
3033 tup_pages_total);
3034
3035 int passed;
3036 if ((passed = check_threshold(tup_percent_last, tup_percent_now)) != -1)
3037 {
3038 jam();
3039 reportDMUsage(signal, tup_percent_now >= tup_percent_last ? 1 : -1);
3040 tup_percent_last = passed;
3041 }
3042 }
3043
3044 {
3045 // Index memory threshold
3046 const Uint32 acc_pages_used =
3047 sum_array(g_acc_pages_used, NDB_ARRAY_SIZE(g_acc_pages_used));
3048 const Uint32 acc_pages_total = f_accpages * 4;
3049 const Uint32 acc_percent_now = calc_percent(acc_pages_used,
3050 acc_pages_total);
3051
3052 int passed;
3053 if ((passed = check_threshold(acc_percent_last, acc_percent_now)) != -1)
3054 {
3055 jam();
3056 reportIMUsage(signal, acc_percent_now >= acc_percent_last ? 1 : -1);
3057 acc_percent_last = passed;
3058 }
3059 }
3060
3061 // Index and data memory report frequency
3062 if(c_memusage_report_frequency &&
3063 cnt + 1 == c_memusage_report_frequency)
3064 {
3065 jam();
3066 reportDMUsage(signal, 0);
3067 reportIMUsage(signal, 0);
3068 cnt = 0;
3069 }
3070 else
3071 {
3072 jam();
3073 cnt++;
3074 }
3075 signal->theData[0] = ZREPORT_MEMORY_USAGE;
3076 signal->theData[1] = cnt; // seconds since last report
3077 signal->theData[2] = tup_percent_last; // last reported threshold for TUP
3078 signal->theData[3] = acc_percent_last; // last reported threshold for ACC
3079 sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 1000, 4);
3080 return;
3081 }
3082 }
3083 }
3084
3085 void
reportDMUsage(Signal * signal,int incDec,BlockReference ref)3086 Cmvmi::reportDMUsage(Signal* signal, int incDec, BlockReference ref)
3087 {
3088 Resource_limit rl;
3089 m_ctx.m_mm.get_resource_limit(RG_DATAMEM, rl);
3090
3091 const Uint32 tup_pages_used = rl.m_curr - f_accpages;
3092 const Uint32 tup_pages_total = rl.m_min - f_accpages;
3093
3094 signal->theData[0] = NDB_LE_MemoryUsage;
3095 signal->theData[1] = incDec;
3096 signal->theData[2] = sizeof(GlobalPage);
3097 signal->theData[3] = tup_pages_used;
3098 signal->theData[4] = tup_pages_total;
3099 signal->theData[5] = DBTUP;
3100 sendSignal(ref, GSN_EVENT_REP, signal, 6, JBB);
3101 }
3102
3103
3104 void
reportIMUsage(Signal * signal,int incDec,BlockReference ref)3105 Cmvmi::reportIMUsage(Signal* signal, int incDec, BlockReference ref)
3106 {
3107 const Uint32 acc_pages_used =
3108 sum_array(g_acc_pages_used, NDB_ARRAY_SIZE(g_acc_pages_used));
3109
3110 signal->theData[0] = NDB_LE_MemoryUsage;
3111 signal->theData[1] = incDec;
3112 signal->theData[2] = 8192;
3113 signal->theData[3] = acc_pages_used;
3114 signal->theData[4] = f_accpages * 4;
3115 signal->theData[5] = DBACC;
3116 sendSignal(ref, GSN_EVENT_REP, signal, 6, JBB);
3117 }
3118
3119
3120 /**
3121 * execROUTE_ORD
3122 * Allows other blocks to route signals as if they
3123 * came from Cmvmi
3124 * Useful in ndbmtd for synchronising signals w.r.t
3125 * external signals received from other nodes which
3126 * arrive from the same thread that runs CMVMI.
3127 */
3128 void
execROUTE_ORD(Signal * signal)3129 Cmvmi::execROUTE_ORD(Signal* signal)
3130 {
3131 jamEntry();
3132 if(!assembleFragments(signal)){
3133 jam();
3134 return;
3135 }
3136
3137 SectionHandle handle(this, signal);
3138
3139 RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
3140 Uint32 dstRef = ord->dstRef;
3141 Uint32 srcRef = ord->srcRef;
3142 Uint32 gsn = ord->gsn;
3143 /* ord->cnt ignored */
3144
3145 Uint32 nodeId = refToNode(dstRef);
3146
3147 if (likely((nodeId == 0) ||
3148 getNodeInfo(nodeId).m_connected))
3149 {
3150 jam();
3151 Uint32 secCount = handle.m_cnt;
3152 ndbrequire(secCount >= 1 && secCount <= 3);
3153
3154 jamLine(secCount);
3155
3156 /**
3157 * Put section 0 in signal->theData
3158 */
3159 Uint32 sigLen = handle.m_ptr[0].sz;
3160 ndbrequire(sigLen <= 25);
3161 copy(signal->theData, handle.m_ptr[0]);
3162
3163 SegmentedSectionPtr save = handle.m_ptr[0];
3164 for (Uint32 i = 0; i < secCount - 1; i++)
3165 handle.m_ptr[i] = handle.m_ptr[i+1];
3166 handle.m_cnt--;
3167
3168 sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle);
3169
3170 handle.m_cnt = 1;
3171 handle.m_ptr[0] = save;
3172 releaseSections(handle);
3173 return ;
3174 }
3175
3176 releaseSections(handle);
3177 warningEvent("Unable to route GSN: %d from %x to %x",
3178 gsn, srcRef, dstRef);
3179 }
3180
3181
execGET_CONFIG_REQ(Signal * signal)3182 void Cmvmi::execGET_CONFIG_REQ(Signal *signal)
3183 {
3184 jamEntry();
3185 const GetConfigReq* const req = (const GetConfigReq *)signal->getDataPtr();
3186
3187 Uint32 error = 0;
3188 Uint32 retRef = req->senderRef; // mgm servers ref
3189
3190 if (retRef != signal->header.theSendersBlockRef)
3191 {
3192 error = GetConfigRef::WrongSender;
3193 }
3194
3195 if (req->nodeId != getOwnNodeId())
3196 {
3197 error = GetConfigRef::WrongNodeId;
3198 }
3199
3200 const Uint32 config_length = m_ctx.m_config.m_clusterConfigPacked.length();
3201 if (config_length == 0)
3202 {
3203 error = GetConfigRef::NoConfig;
3204 }
3205
3206 if (error)
3207 {
3208 warningEvent("execGET_CONFIG_REQ: failed %u", error);
3209 GetConfigRef *ref = (GetConfigRef *)signal->getDataPtrSend();
3210 ref->error = error;
3211 sendSignal(retRef, GSN_GET_CONFIG_REF, signal,
3212 GetConfigRef::SignalLength, JBB);
3213 return;
3214 }
3215
3216 const Uint32 nSections= 1;
3217 LinearSectionPtr ptr[3];
3218 ptr[0].p = (Uint32*)(m_ctx.m_config.m_clusterConfigPacked.get_data());
3219 ptr[0].sz = (config_length + 3) / 4;
3220
3221 GetConfigConf *conf = (GetConfigConf *)signal->getDataPtrSend();
3222
3223 conf->configLength = config_length;
3224
3225 sendFragmentedSignal(retRef,
3226 GSN_GET_CONFIG_CONF,
3227 signal,
3228 GetConfigConf::SignalLength,
3229 JBB,
3230 ptr,
3231 nSections,
3232 TheEmptyCallback);
3233 }
3234