MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Dbinfo.cpp
1 /* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
15 
16 #include "Dbinfo.hpp"
17 
18 #include <signaldata/NodeFailRep.hpp>
19 #include <signaldata/ReadNodesConf.hpp>
20 
21 #include <signaldata/DumpStateOrd.hpp>
22 #include <signaldata/DbinfoScan.hpp>
23 #include <signaldata/TransIdAI.hpp>
24 
25 //#define DBINFO_SCAN_TRACE
26 #ifdef DBINFO_SCAN_TRACE
27 #include <debugger/DebuggerNames.hpp>
28 #endif
29 
30 Uint32 dbinfo_blocks[] = { DBACC, DBTUP, BACKUP, DBTC, SUMA, DBUTIL,
31  TRIX, DBTUX, DBDICT, CMVMI, DBLQH, LGMAN,
32  PGMAN, DBSPJ, 0};
33 
34 Dbinfo::Dbinfo(Block_context& ctx) :
35  SimulatedBlock(DBINFO, ctx)
36 {
37  BLOCK_CONSTRUCTOR(Dbinfo);
38 
39  STATIC_ASSERT(sizeof(DbinfoScanCursor) == sizeof(Ndbinfo::ScanCursor));
40 
41  /* Add Received Signals */
42  addRecSignal(GSN_STTOR, &Dbinfo::execSTTOR);
43  addRecSignal(GSN_DUMP_STATE_ORD, &Dbinfo::execDUMP_STATE_ORD);
44  addRecSignal(GSN_READ_CONFIG_REQ, &Dbinfo::execREAD_CONFIG_REQ, true);
45 
46  addRecSignal(GSN_DBINFO_SCANREQ, &Dbinfo::execDBINFO_SCANREQ);
47  addRecSignal(GSN_DBINFO_SCANCONF, &Dbinfo::execDBINFO_SCANCONF);
48 
49  addRecSignal(GSN_NODE_FAILREP, &Dbinfo::execNODE_FAILREP);
50  addRecSignal(GSN_INCL_NODEREQ, &Dbinfo::execINCL_NODEREQ);
51 
52 }
53 
54 Dbinfo::~Dbinfo()
55 {
56 }
57 
58 BLOCK_FUNCTIONS(Dbinfo)
59 
60 void Dbinfo::execSTTOR(Signal *signal)
61 {
62  jamEntry();
63  sendSTTORRY(signal);
64  return;
65 }
66 
67 void Dbinfo::execREAD_CONFIG_REQ(Signal *signal)
68 {
69  jamEntry();
70  const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
71  Uint32 ref = req->senderRef;
72  Uint32 senderData = req->senderData;
73 
74  /* In the future, do something sensible here. */
75 
76  ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
77  conf->senderRef = reference();
78  conf->senderData = senderData;
79  sendSignal(ref, GSN_READ_CONFIG_CONF, signal,
80  ReadConfigConf::SignalLength, JBB);
81 }
82 
83 void Dbinfo::sendSTTORRY(Signal* signal)
84 {
85  signal->theData[0] = 0;
86  signal->theData[3] = 1;
87  signal->theData[4] = 3;
88  signal->theData[5] = 255; // No more start phases from missra
89  sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 6, JBB);
90 }
91 
92 void Dbinfo::execDUMP_STATE_ORD(Signal* signal)
93 {
94  jamEntry();
95 
96  switch(signal->theData[0])
97  {
98  case DumpStateOrd::DbinfoListTables:
99  jam();
100  ndbout_c("--- BEGIN NDB$INFO.TABLES ---");
101  for(int i = 0; i < Ndbinfo::getNumTables(); i++)
102  {
103  const Ndbinfo::Table& tab = Ndbinfo::getTable(i);
104  ndbout_c("%d,%s", i, tab.m.name);
105  }
106  ndbout_c("--- END NDB$INFO.TABLES ---");
107  break;
108 
109  case DumpStateOrd::DbinfoListColumns:
110  jam();
111  ndbout_c("--- BEGIN NDB$INFO.COLUMNS ---");
112  for(int i = 0; i < Ndbinfo::getNumTables(); i++)
113  {
114  const Ndbinfo::Table& tab = Ndbinfo::getTable(i);
115 
116  for(int j = 0; j < tab.m.ncols; j++)
117  ndbout_c("%d,%d,%s,%d", i, j,
118  tab.col[j].name, tab.col[j].coltype);
119  }
120  ndbout_c("--- END NDB$INFO.COLUMNS ---");
121  break;
122 
123  };
124 }
125 
126 
127 Uint32 Dbinfo::find_next_block(Uint32 block) const
128 {
129  int i = 0;
130  // Find current blocks position
131  while (dbinfo_blocks[i] != block &&
132  dbinfo_blocks[i] != 0)
133  i++;
134 
135  // Make sure current block was found
136  ndbrequire(dbinfo_blocks[i]);
137 
138  // Return the next block(which might be 0)
139  return dbinfo_blocks[++i];
140 }
141 
142 static Uint32
143 switchRef(Uint32 block, Uint32 node)
144 {
145  const Uint32 ref = numberToRef(block, node);
146 #ifdef DBINFO_SCAN_TRACE
147  ndbout_c("Dbinfo: switching to %s in node %d, ref: 0x%.8x",
148  getBlockName(block, "<unknown>"), node, ref);
149 #endif
150  return ref;
151 }
152 
153 
154 bool Dbinfo::find_next(Ndbinfo::ScanCursor* cursor) const
155 {
156  Uint32 node = refToNode(cursor->currRef);
157  Uint32 block = refToBlock(cursor->currRef);
158  const Uint32 instance = refToInstance(cursor->currRef);
159  ndbrequire(instance == 0);
160 
161  if (node == 0)
162  {
163  jam();
164  // First 'find_next'
165  ndbrequire(block == 0);
166  cursor->currRef = switchRef(dbinfo_blocks[0], getOwnNodeId());
167  return true;
168  }
169 
170  if (block)
171  {
172  jam();
173  // Find next block
174  ndbrequire(node == getOwnNodeId());
175  block = find_next_block(block);
176  if (block)
177  {
178  jam();
179  cursor->currRef = switchRef(block, node);
180  return true;
181  }
182  }
183 
184  // Nothing more to scan
185  cursor->currRef = 0;
186  return false;
187 }
188 
189 void Dbinfo::execDBINFO_SCANREQ(Signal *signal)
190 {
191  jamEntry();
192  DbinfoScanReq* req_ptr = (DbinfoScanReq*)signal->getDataPtrSend();
193  const Uint32 senderRef = signal->header.theSendersBlockRef;
194 
195  // Copy signal on stack
196  DbinfoScanReq req = *req_ptr;
197 
198  const Uint32 resultData = req.resultData;
199  const Uint32 transId0 = req.transId[0];
200  const Uint32 transId1 = req.transId[1];
201  const Uint32 resultRef = req.resultRef;
202 
203  // Validate tableId
204  const Uint32 tableId = req.tableId;
205  if (tableId >= (Uint32)Ndbinfo::getNumTables())
206  {
207  jam();
208  DbinfoScanRef *ref= (DbinfoScanRef*)signal->getDataPtrSend();
209  ref->resultData = resultData;
210  ref->transId[0] = transId0;
211  ref->transId[1] = transId1;
212  ref->resultRef = resultRef;
213  ref->errorCode= DbinfoScanRef::NoTable;
214  sendSignal(senderRef, GSN_DBINFO_SCANREF, signal,
215  DbinfoScanRef::SignalLength, JBB);
216  return;
217  }
218 
219  // TODO Check all scan parameters
220  Ndbinfo::ScanCursor* cursor =
221  CAST_PTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtrSend(&req));
222 
223  Uint32 signal_length = signal->getLength();
224  if (signal_length == DbinfoScanReq::SignalLength)
225  {
226  // Initialize cursor
227  jam();
228  cursor->senderRef = senderRef;
229  cursor->saveSenderRef = 0;
230  cursor->currRef = 0;
231  cursor->saveCurrRef = 0;
232  // Reset all data holders
233  memset(cursor->data, 0, sizeof(cursor->data));
234  cursor->flags = 0;
235  cursor->totalRows = 0;
236  cursor->totalBytes = 0;
237  req.cursor_sz = Ndbinfo::ScanCursor::Length;
238  signal_length += req.cursor_sz;
239  }
240  ndbrequire(signal_length ==
241  DbinfoScanReq::SignalLength + Ndbinfo::ScanCursor::Length);
242  ndbrequire(req.cursor_sz == Ndbinfo::ScanCursor::Length);
243 
244  switch(tableId)
245  {
246  case Ndbinfo::TABLES_TABLEID:
247  {
248  jam();
249 
251  Uint32 tableId = cursor->data[0];
252 
253  while(tableId < (Uint32)Ndbinfo::getNumTables())
254  {
255  jam();
256  const Ndbinfo::Table& tab = Ndbinfo::getTable(tableId);
257  Ndbinfo::Row row(signal, req);
258  row.write_uint32(tableId);
259  row.write_string(tab.m.name);
260  row.write_string(tab.m.comment);
261  ndbinfo_send_row(signal, req, row, rl);
262 
263  tableId++;
264 
265  if (rl.need_break(req))
266  {
267  jam();
268  ndbinfo_send_scan_break(signal, req, rl, tableId);
269  return;
270  }
271  }
272 
273  // All tables sent
274  req.cursor_sz = 0; // Close cursor
275  ndbinfo_send_scan_conf(signal, req, rl);
276  return;
277 
278  break;
279  }
280 
281  case Ndbinfo::COLUMNS_TABLEID:
282  {
283  jam();
284 
286  Uint32 tableId = cursor->data[0];
287  Uint32 columnId = cursor->data[1];
288 
289  while(tableId < (Uint32)Ndbinfo::getNumTables())
290  {
291  jam();
292  const Ndbinfo::Table& tab = Ndbinfo::getTable(tableId);
293  while(columnId < (Uint32)tab.m.ncols)
294  {
295  jam();
296  Ndbinfo::Row row(signal, req);
297  row.write_uint32(tableId);
298  row.write_uint32(columnId);
299  row.write_string(tab.col[columnId].name);
300  row.write_uint32(tab.col[columnId].coltype);
301  row.write_string(tab.col[columnId].comment);
302  ndbinfo_send_row(signal, req, row, rl);
303 
304  assert(columnId < 256);
305  columnId++;
306 
307  if(rl.need_break(req))
308  {
309  jam();
310  ndbinfo_send_scan_break(signal, req, rl, tableId, columnId);
311  return;
312  }
313  }
314  columnId = 0;
315  tableId++;
316  }
317 
318  // All tables and columns sent
319  req.cursor_sz = 0; // Close cursor
320  ndbinfo_send_scan_conf(signal, req, rl);
321 
322  break;
323  }
324 
325  default:
326  {
327  jam();
328 
329  ndbassert(tableId > 1);
330 
331  //printSignalHeader(stdout, signal->header, 99, 98, true);
332  //printDBINFO_SCAN(stdout, signal->theData, signal->getLength(), 0);
333 
334  if (Ndbinfo::ScanCursor::getHasMoreData(cursor->flags) ||
335  find_next(cursor))
336  {
337  jam();
338  ndbrequire(cursor->currRef);
339 
340  // CONF or REF should be sent back here
341  cursor->senderRef = reference();
342 
343  // Send SCANREQ
344  MEMCOPY_NO_WORDS(req_ptr,
345  &req, signal_length);
346  sendSignal(cursor->currRef,
347  GSN_DBINFO_SCANREQ,
348  signal, signal_length, JBB);
349  }
350  else
351  {
352  // Scan is done, send SCANCONF back to caller
353  jam();
354  DbinfoScanConf *apiconf= (DbinfoScanConf*)signal->getDataPtrSend();
355  MEMCOPY_NO_WORDS(apiconf, &req, DbinfoScanConf::SignalLength);
356  // Set cursor_sz back to 0 to indicate end of scan
357  apiconf->cursor_sz = 0;
358  sendSignal(resultRef, GSN_DBINFO_SCANCONF, signal,
359  DbinfoScanConf::SignalLength, JBB);
360  }
361  break;
362  }
363  }
364 }
365 
366 void Dbinfo::execDBINFO_SCANCONF(Signal *signal)
367 {
368  const DbinfoScanConf* conf_ptr= (const DbinfoScanConf*)signal->getDataPtr();
369  // Copy signal on stack
370  DbinfoScanConf conf= *conf_ptr;
371 
372  jamEntry();
373 
374  //printDBINFO_SCAN(stdout, signal->theData, signal->getLength(), 0);
375 
376  Uint32 signal_length = signal->getLength();
377  ndbrequire(signal_length ==
378  DbinfoScanReq::SignalLength+Ndbinfo::ScanCursor::Length);
379  ndbrequire(conf.cursor_sz == Ndbinfo::ScanCursor::Length);
380 
381  // Validate tableId
382  const Uint32 tableId= conf.tableId;
383  ndbassert(tableId < (Uint32)Ndbinfo::getNumTables());
384 
385  const Uint32 resultRef = conf.resultRef;
386 
387  // Copy cursor on stack
388  ndbrequire(conf.cursor_sz);
389  Ndbinfo::ScanCursor* cursor =
390  CAST_PTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtrSend(&conf));
391 
392  if (Ndbinfo::ScanCursor::getHasMoreData(cursor->flags) || conf.returnedRows)
393  {
394  // Rate limit break, pass through to API
395  jam();
396  ndbrequire(cursor->currRef);
397  DbinfoScanConf *apiconf = (DbinfoScanConf*) signal->getDataPtrSend();
398  MEMCOPY_NO_WORDS(apiconf, &conf, signal_length);
399  sendSignal(resultRef, GSN_DBINFO_SCANCONF, signal, signal_length, JBB);
400  return;
401  }
402 
403  if (find_next(cursor))
404  {
405  jam();
406  ndbrequire(cursor->currRef);
407 
408  // CONF or REF should be sent back here
409  cursor->senderRef = reference();
410 
411  // Send SCANREQ
412  MEMCOPY_NO_WORDS(signal->getDataPtrSend(),
413  &conf, signal_length);
414  sendSignal(cursor->currRef,
415  GSN_DBINFO_SCANREQ,
416  signal, signal_length, JBB);
417  return;
418  }
419 
420  // Scan is done, send SCANCONF back to caller
421  jam();
422  DbinfoScanConf *apiconf = (DbinfoScanConf*) signal->getDataPtrSend();
423  MEMCOPY_NO_WORDS(apiconf, &conf, DbinfoScanConf::SignalLength);
424 
425  // Set cursor_sz back to 0 to indicate end of scan
426  apiconf->cursor_sz = 0;
427  sendSignal(resultRef, GSN_DBINFO_SCANCONF, signal,
428  DbinfoScanConf::SignalLength, JBB);
429  return;
430 }
431 
432 
433 void Dbinfo::execINCL_NODEREQ(Signal* signal)
434 {
435  jamEntry();
436 
437  const Uint32 senderRef = signal->theData[0];
438  const Uint32 inclNode = signal->theData[1];
439 
440  signal->theData[0] = inclNode;
441  signal->theData[1] = reference();
442  sendSignal(senderRef, GSN_INCL_NODECONF, signal, 2, JBB);
443 }
444 
445 void Dbinfo::execNODE_FAILREP(Signal* signal)
446 {
447  jamEntry();
448 
449  NodeFailRep * rep = (NodeFailRep*)signal->getDataPtr();
450 
451  Uint32 theFailedNodes[NdbNodeBitmask::Size];
452  for (Uint32 i = 0; i < NdbNodeBitmask::Size; i++)
453  theFailedNodes[i] = rep->theNodes[i];
454 
455  for (Uint32 i = 0; i < MAX_NDB_NODES; i++)
456  {
457  if (NdbNodeBitmask::get(theFailedNodes, i))
458  {
459  Uint32 elementsCleaned = simBlockNodeFailure(signal, i); // No callback
460  ndbassert(elementsCleaned == 0); // DbInfo should have no distributed frag signals
461  (void) elementsCleaned; // Remove compiler warning
462  }
463  }
464 }