MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DbtupDebug.cpp
1 /*
2  Copyright (c) 2003, 2011, 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 
19 #define DBTUP_C
20 #define DBTUP_DEBUG_CPP
21 #include "Dbtup.hpp"
22 #include <RefConvert.hpp>
23 #include <ndb_limits.h>
24 #include <pc.hpp>
25 #include <signaldata/DropTab.hpp>
26 #include <signaldata/DumpStateOrd.hpp>
27 #include <signaldata/EventReport.hpp>
28 #include <Vector.hpp>
29 
30 #include <signaldata/DbinfoScan.hpp>
31 #include <signaldata/TransIdAI.hpp>
32 
33 
34 /* **************************************************************** */
35 /* ---------------------------------------------------------------- */
36 /* ------------------------ DEBUG MODULE -------------------------- */
37 /* ---------------------------------------------------------------- */
38 /* **************************************************************** */
39 void Dbtup::execDEBUG_SIG(Signal* signal)
40 {
41  PagePtr regPagePtr;
42  jamEntry();
43  regPagePtr.i = signal->theData[0];
44  c_page_pool.getPtr(regPagePtr);
45 }//Dbtup::execDEBUG_SIG()
46 
47 #ifdef TEST_MR
48 #include <time.h>
49 
50 void startTimer(struct timespec *tp)
51 {
52  clock_gettime(CLOCK_REALTIME, tp);
53 }//startTimer()
54 
55 int stopTimer(struct timespec *tp)
56 {
57  double timer_count;
58  struct timespec theStopTime;
59  clock_gettime(CLOCK_REALTIME, &theStopTime);
60  timer_count = (double)(1000000*((double)theStopTime.tv_sec - (double)tp->tv_sec)) +
61  (double)((double)((double)theStopTime.tv_nsec - (double)tp->tv_nsec)/(double)1000);
62  return (int)timer_count;
63 }//stopTimer()
64 
65 #endif // end TEST_MR
66 
67 struct Chunk {
68  Uint32 pageId;
69  Uint32 pageCount;
70 };
71 
72 void Dbtup::execDBINFO_SCANREQ(Signal* signal)
73 {
74  jamEntry();
75  DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
77  CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
78 
80 
81  switch(req.tableId){
82  case Ndbinfo::POOLS_TABLEID:
83  {
84  jam();
85  Ndbinfo::pool_entry pools[] =
86  {
87  { "Scan Lock",
88  c_scanLockPool.getUsed(),
89  c_scanLockPool.getSize(),
90  c_scanLockPool.getEntrySize(),
91  c_scanLockPool.getUsedHi(),
92  { CFG_DB_NO_LOCAL_SCANS,CFG_DB_BATCH_SIZE,0,0 }},
93  { "Scan Operation",
94  c_scanOpPool.getUsed(),
95  c_scanOpPool.getSize(),
96  c_scanOpPool.getEntrySize(),
97  c_scanOpPool.getUsedHi(),
98  { CFG_DB_NO_LOCAL_SCANS,0,0,0 }},
99  { "Trigger",
100  c_triggerPool.getUsed(),
101  c_triggerPool.getSize(),
102  c_triggerPool.getEntrySize(),
103  c_triggerPool.getUsedHi(),
104  { CFG_DB_NO_TRIGGERS,0,0,0 }},
105  { "Stored Proc",
106  c_storedProcPool.getUsed(),
107  c_storedProcPool.getSize(),
108  c_storedProcPool.getEntrySize(),
109  c_storedProcPool.getUsedHi(),
110  { CFG_DB_NO_LOCAL_SCANS,0,0,0 }},
111  { "Build Index",
112  c_buildIndexPool.getUsed(),
113  c_buildIndexPool.getSize(),
114  c_buildIndexPool.getEntrySize(),
115  c_buildIndexPool.getUsedHi(),
116  { 0,0,0,0 }},
117  { "Operation",
118  c_operation_pool.getUsed(),
119  c_operation_pool.getSize(),
120  c_operation_pool.getEntrySize(),
121  c_operation_pool.getUsedHi(),
122  { CFG_DB_NO_LOCAL_OPS,CFG_DB_NO_OPS,0,0 }},
123  { "Data memory",
124  m_pages_allocated,
125  0, // Allocated from global resource group RG_DATAMEM
126  sizeof(Page),
127  m_pages_allocated_max,
128  { CFG_DB_DATA_MEM,0,0,0 }},
129  { NULL, 0,0,0,0, { 0,0,0,0 }}
130  };
131 
132  const size_t num_config_params =
133  sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
134  Uint32 pool = cursor->data[0];
135  BlockNumber bn = blockToMain(number());
136  while(pools[pool].poolname)
137  {
138  jam();
139  Ndbinfo::Row row(signal, req);
140  row.write_uint32(getOwnNodeId());
141  row.write_uint32(bn); // block number
142  row.write_uint32(instance()); // block instance
143  row.write_string(pools[pool].poolname);
144 
145  row.write_uint64(pools[pool].used);
146  row.write_uint64(pools[pool].total);
147  row.write_uint64(pools[pool].used_hi);
148  row.write_uint64(pools[pool].entry_size);
149  for (size_t i = 0; i < num_config_params; i++)
150  row.write_uint32(pools[pool].config_params[i]);
151  ndbinfo_send_row(signal, req, row, rl);
152  pool++;
153  if (rl.need_break(req))
154  {
155  jam();
156  ndbinfo_send_scan_break(signal, req, rl, pool);
157  return;
158  }
159  }
160  break;
161  }
162  case Ndbinfo::TEST_TABLEID:
163  {
164  Uint32 counter = cursor->data[0];
165  BlockNumber bn = blockToMain(number());
166  while(counter < 1000)
167  {
168  jam();
169  Ndbinfo::Row row(signal, req);
170  row.write_uint32(getOwnNodeId());
171  row.write_uint32(bn); // block number
172  row.write_uint32(instance()); // block instance
173  row.write_uint32(counter);
174  Uint64 counter2 = counter;
175  counter2 = counter2 << 32;
176  row.write_uint64(counter2);
177  ndbinfo_send_row(signal, req, row, rl);
178  counter++;
179  if (rl.need_break(req))
180  {
181  jam();
182  ndbinfo_send_scan_break(signal, req, rl, counter);
183  return;
184  }
185  }
186  break;
187  }
188  default:
189  break;
190  }
191 
192  ndbinfo_send_scan_conf(signal, req, rl);
193 }
194 
195 #ifdef VM_TRACE
196 static Uint32 fc_left = 0, fc_right = 0, fc_remove = 0;
197 #endif
198 
199 void
200 Dbtup::execDUMP_STATE_ORD(Signal* signal)
201 {
202  Uint32 type = signal->theData[0];
203  DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
204 
205 #if 0
206  if (type == 100) {
207  RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
208  req->primaryTableId = 2;
209  req->secondaryTableId = RNIL;
210  req->userPtr = 2;
211  req->userRef = DBDICT_REF;
212  sendSignal(cownref, GSN_REL_TABMEMREQ, signal,
213  RelTabMemReq::SignalLength, JBB);
214  return;
215  }//if
216  if (type == 101) {
217  RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
218  req->primaryTableId = 4;
219  req->secondaryTableId = 5;
220  req->userPtr = 4;
221  req->userRef = DBDICT_REF;
222  sendSignal(cownref, GSN_REL_TABMEMREQ, signal,
223  RelTabMemReq::SignalLength, JBB);
224  return;
225  }//if
226  if (type == 102) {
227  RelTabMemReq * const req = (RelTabMemReq *)signal->getDataPtrSend();
228  req->primaryTableId = 6;
229  req->secondaryTableId = 8;
230  req->userPtr = 6;
231  req->userRef = DBDICT_REF;
232  sendSignal(cownref, GSN_REL_TABMEMREQ, signal,
233  RelTabMemReq::SignalLength, JBB);
234  return;
235  }//if
236  if (type == 103) {
237  DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
238  req->primaryTableId = 2;
239  req->secondaryTableId = RNIL;
240  req->userPtr = 2;
241  req->userRef = DBDICT_REF;
242  sendSignal(cownref, GSN_DROP_TABFILEREQ, signal,
243  DropTabFileReq::SignalLength, JBB);
244  return;
245  }//if
246  if (type == 104) {
247  DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
248  req->primaryTableId = 4;
249  req->secondaryTableId = 5;
250  req->userPtr = 4;
251  req->userRef = DBDICT_REF;
252  sendSignal(cownref, GSN_DROP_TABFILEREQ, signal,
253  DropTabFileReq::SignalLength, JBB);
254  return;
255  }//if
256  if (type == 105) {
257  DropTabFileReq * const req = (DropTabFileReq *)signal->getDataPtrSend();
258  req->primaryTableId = 6;
259  req->secondaryTableId = 8;
260  req->userPtr = 6;
261  req->userRef = DBDICT_REF;
262  sendSignal(cownref, GSN_DROP_TABFILEREQ, signal,
263  DropTabFileReq::SignalLength, JBB);
264  return;
265  }//if
266 #endif
267 #ifdef ERROR_INSERT
268  if (type == DumpStateOrd::EnableUndoDelayDataWrite) {
269  ndbout << "Dbtup:: delay write of datapages for table = "
270  << dumpState->args[1]<< endl;
271  c_errorInsert4000TableId = dumpState->args[1];
272  SET_ERROR_INSERT_VALUE(4000);
273  return;
274  }//if
275 #endif
276 #if defined VM_TRACE
277  if (type == 1211 || type == 1212 || type == 1213){
278  Uint32 seed = (Uint32)time(0);
279  if (signal->getLength() > 1)
280  seed = signal->theData[1];
281  ndbout_c("Startar modul test av Page Manager (seed: 0x%x)", seed);
282  srand(seed);
283 
284  Vector<Chunk> chunks;
285  const Uint32 LOOPS = 1000;
286  Uint32 sum_req = 0;
287  Uint32 sum_conf = 0;
288  Uint32 sum_loop = 0;
289  Uint32 max_loop = 0;
290  for(Uint32 i = 0; i<LOOPS; i++){
291 
292  // Case
293  Uint32 c = (rand() % 3);
294  Resource_limit rl;
295  m_ctx.m_mm.get_resource_limit(RG_DATAMEM, rl);
296  const Uint32 free = rl.m_max - rl.m_curr;
297 
298  Uint32 alloc = 0;
299  if(free <= 1){
300  c = 0;
301  alloc = 1;
302  } else
303  alloc = 1 + (rand() % (free - 1));
304 
305  if(chunks.size() == 0 && c == 0){
306  c = 1 + rand() % 2;
307  }
308 
309  if (type == 1211)
310  ndbout_c("loop=%d case=%d free=%d alloc=%d", i, c, free, alloc);
311 
312  if (type == 1213)
313  {
314  c = 1;
315  alloc = 2 + (sum_conf >> 3) + (sum_conf >> 4);
316  }
317  switch(c){
318  case 0:{ // Release
319  const int ch = rand() % chunks.size();
320  Chunk chunk = chunks[ch];
321  chunks.erase(ch);
322  returnCommonArea(chunk.pageId, chunk.pageCount);
323  }
324  break;
325  case 2: { // Seize(n) - fail
326  alloc += free;
327  // Fall through
328  sum_req += free;
329  goto doalloc;
330  }
331  case 1: { // Seize(n) (success)
332  sum_req += alloc;
333  doalloc:
334  Chunk chunk;
335  allocConsPages(alloc, chunk.pageCount, chunk.pageId);
336  ndbrequire(chunk.pageCount <= alloc);
337  if(chunk.pageCount != 0){
338  chunks.push_back(chunk);
339  if(chunk.pageCount != alloc) {
340  if (type == 1211)
341  ndbout_c(" Tried to allocate %d - only allocated %d - free: %d",
342  alloc, chunk.pageCount, free);
343  }
344  } else {
345  ndbout_c(" Failed to alloc %d pages with %d pages free",
346  alloc, free);
347  }
348 
349  sum_conf += chunk.pageCount;
350  Uint32 tot = fc_left + fc_right + fc_remove;
351  sum_loop += tot;
352  if (tot > max_loop)
353  max_loop = tot;
354 
355  for(Uint32 i = 0; i<chunk.pageCount; i++){
356  PagePtr pagePtr;
357  pagePtr.i = chunk.pageId + i;
358  c_page_pool.getPtr(pagePtr);
359  }
360 
361  if(alloc == 1 && free > 0)
362  {
363  ndbrequire(chunk.pageCount == alloc);
364  }
365  }
366  break;
367  }
368  }
369  while(chunks.size() > 0){
370  Chunk chunk = chunks.back();
371  returnCommonArea(chunk.pageId, chunk.pageCount);
372  chunks.erase(chunks.size() - 1);
373  }
374 
375  ndbout_c("Got %u%% of requested allocs, loops : %u 100*avg: %u max: %u",
376  (100 * sum_conf) / sum_req, sum_loop, 100*sum_loop / LOOPS,
377  max_loop);
378  }
379 #endif
380 
381  if (signal->theData[0] == DumpStateOrd::SchemaResourceSnapshot)
382  {
383  {
384  Uint64 defaultValueWords= 0;
385  if (DefaultValuesFragment.i != RNIL)
386  defaultValueWords= calculate_used_var_words(DefaultValuesFragment.p);
387  Uint32 defaultValueWordsHi= (Uint32) (defaultValueWords >> 32);
388  Uint32 defaultValueWordsLo= (Uint32) (defaultValueWords & 0xFFFFFFFF);
389  RSS_OP_SNAPSHOT_SAVE(defaultValueWordsHi);
390  RSS_OP_SNAPSHOT_SAVE(defaultValueWordsLo);
391  }
392  RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragoprec);
393  RSS_OP_SNAPSHOT_SAVE(cnoOfFreeFragrec);
394  RSS_OP_SNAPSHOT_SAVE(cnoOfFreeTabDescrRec);
395 
396  RSS_AP_SNAPSHOT_SAVE2(c_storedProcPool, c_storedProcCountNonAPI);
397  return;
398  }
399 
400  if (signal->theData[0] == DumpStateOrd::SchemaResourceCheckLeak)
401  {
402  {
403  Uint64 defaultValueWords= 0;
404  if (DefaultValuesFragment.i != RNIL)
405  defaultValueWords= calculate_used_var_words(DefaultValuesFragment.p);
406  Uint32 defaultValueWordsHi= (Uint32) (defaultValueWords >> 32);
407  Uint32 defaultValueWordsLo= (Uint32) (defaultValueWords & 0xFFFFFFFF);
408  RSS_OP_SNAPSHOT_CHECK(defaultValueWordsHi);
409  RSS_OP_SNAPSHOT_CHECK(defaultValueWordsLo);
410  }
411  RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragoprec);
412  RSS_OP_SNAPSHOT_CHECK(cnoOfFreeFragrec);
413  RSS_OP_SNAPSHOT_CHECK(cnoOfFreeTabDescrRec);
414 
415  RSS_AP_SNAPSHOT_CHECK2(c_storedProcPool, c_storedProcCountNonAPI);
416  return;
417  }
418 }//Dbtup::execDUMP_STATE_ORD()
419 
420 /* ---------------------------------------------------------------- */
421 /* --------- MEMORY CHECK ----------------------- */
422 /* ---------------------------------------------------------------- */
423 void Dbtup::execMEMCHECKREQ(Signal* signal)
424 {
425  TablerecPtr regTabPtr;
426  regTabPtr.i = 2;
427  ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
428  if(tablerec && regTabPtr.p->tableStatus == DEFINED)
429  validate_page(regTabPtr.p, 0);
430 
431 #if 0
432  const Dbtup::Tablerec& tab = *tup->tabptr.p;
433 
434  PagePtr regPagePtr;
435  Uint32* data = &signal->theData[0];
436 
437  jamEntry();
438  BlockReference blockref = signal->theData[0];
439  Uint32 i;
440  for (i = 0; i < 25; i++) {
441  jam();
442  data[i] = 0;
443  }//for
444  for (i = 0; i < 16; i++) {
445  regPagePtr.i = cfreepageList[i];
446  jam();
447  while (regPagePtr.i != RNIL) {
448  jam();
449  ptrCheckGuard(regPagePtr, cnoOfPage, cpage);
450  regPagePtr.i = regPagePtr.p->next_page;
451  data[0]++;
452  }//while
453  }//for
454  sendSignal(blockref, GSN_MEMCHECKCONF, signal, 25, JBB);
455 #endif
456 }//Dbtup::memCheck()
457 
458 // ------------------------------------------------------------------------
459 // Help function to be used when debugging. Prints out a tuple page.
460 // printLimit is the number of bytes that is printed out from the page. A
461 // page is of size 32768 bytes as of March 2003.
462 // ------------------------------------------------------------------------
463 void Dbtup::printoutTuplePage(Uint32 fragid, Uint32 pageid, Uint32 printLimit)
464 {
465  PagePtr tmpPageP;
466  FragrecordPtr tmpFragP;
467  TablerecPtr tmpTableP;
468 
469  c_page_pool.getPtr(tmpPageP, pageid);
470 
471  tmpFragP.i = fragid;
472  ptrCheckGuard(tmpFragP, cnoOfFragrec, fragrecord);
473 
474  tmpTableP.i = tmpFragP.p->fragTableId;
475  ptrCheckGuard(tmpTableP, cnoOfTablerec, tablerec);
476 
477  ndbout << "Fragid: " << fragid << " Pageid: " << pageid << endl
478  << "----------------------------------------" << endl;
479 
480  ndbout << "PageHead : ";
481  ndbout << endl;
482 }//Dbtup::printoutTuplePage
483 
484 #ifdef VM_TRACE
485 NdbOut&
486 operator<<(NdbOut& out, const Dbtup::Operationrec& op)
487 {
488  out << "[Operationrec " << hex << &op;
489  // table
490  out << " [fragmentPtr " << hex << op.fragmentPtr << "]";
491  // type
492  out << " [op_type " << dec << op.op_struct.op_type << "]";
493  out << " [delete_insert_flag " << dec;
494  out << op.op_struct.delete_insert_flag << "]";
495  // state
496  out << " [tuple_state " << dec << op.op_struct.tuple_state << "]";
497  out << " [trans_state " << dec << op.op_struct.trans_state << "]";
498  out << " [in_active_list " << dec << op.op_struct.in_active_list << "]";
499  // links
500  out << " [prevActiveOp " << hex << op.prevActiveOp << "]";
501  out << " [nextActiveOp " << hex << op.nextActiveOp << "]";
502  // tuples
503  out << " [tupVersion " << hex << op.tupVersion << "]";
504  out << " [m_tuple_location " << op.m_tuple_location << "]";
505  out << " [m_copy_tuple_location " << op.m_copy_tuple_location << "]";
506  out << "]";
507  return out;
508 }
509 
510 // uses global tabptr
511 NdbOut&
512 operator<<(NdbOut& out, const Dbtup::Th& th)
513 {
514  unsigned i = 0;
515  out << "[Th " << hex << &th;
516  out << " [op " << hex << th.data[i++] << "]";
517  out << " [version " << hex << (Uint16)th.data[i++] << "]";
518  out << "]";
519  return out;
520 }
521 #endif
522 
523 #ifdef VM_TRACE
524 template class Vector<Chunk>;
525 #endif
526 // uses global tabptr
527 
528 NdbOut&
529 operator<<(NdbOut& out, const Local_key & key)
530 {
531  out << "[ m_page_no: " << dec << key.m_page_no
532  << " m_file_no: " << dec << key.m_file_no
533  << " m_page_idx: " << dec << key.m_page_idx << "]";
534  return out;
535 }
536 
537 static
538 NdbOut&
539 operator<<(NdbOut& out, const Dbtup::Tablerec::Tuple_offsets& off)
540 {
541  out << "[ null_words: " << (Uint32)off.m_null_words
542  << " null off: " << (Uint32)off.m_null_offset
543  << " disk_off: " << off.m_disk_ref_offset
544  << " fixheadsz: " << off.m_fix_header_size
545  << " max_var_off: " << off.m_max_var_offset
546  << " ]";
547 
548  return out;
549 }
550 
551 NdbOut&
552 operator<<(NdbOut& out, const Dbtup::Tablerec& tab)
553 {
554  out << "[ total_rec_size: " << tab.total_rec_size
555  << " checksum: " << !!(tab.m_bits & Dbtup::Tablerec::TR_Checksum)
556  << " attr: " << tab.m_no_of_attributes
557  << " disk: " << tab.m_no_of_disk_attributes
558  << " mm: " << tab.m_offsets[Dbtup::MM]
559  << " [ fix: " << tab.m_attributes[Dbtup::MM].m_no_of_fixsize
560  << " var: " << tab.m_attributes[Dbtup::MM].m_no_of_varsize << "]"
561 
562  << " dd: " << tab.m_offsets[Dbtup::DD]
563  << " [ fix: " << tab.m_attributes[Dbtup::DD].m_no_of_fixsize
564  << " var: " << tab.m_attributes[Dbtup::DD].m_no_of_varsize << "]"
565  << " ]" << endl;
566  return out;
567 }
568 
569 NdbOut&
570 operator<<(NdbOut& out, const AttributeDescriptor& off)
571 {
572  Uint32 word;
573  memcpy(&word, &off, 4);
574  return out;
575 }
576 
577 #include "AttributeOffset.hpp"
578 
579 NdbOut&
580 operator<<(NdbOut& out, const AttributeOffset& off)
581 {
582  Uint32 word;
583  memcpy(&word, &off, 4);
584  out << "[ offset: " << AttributeOffset::getOffset(word)
585  << " nullpos: " << AttributeOffset::getNullFlagPos(word);
586  if(AttributeOffset::getCharsetFlag(word))
587  out << " charset: %d" << AttributeOffset::getCharsetPos(word);
588  out << " ]";
589  return out;
590 }
591