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