MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Ndblist.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 "API.hpp"
19 
20 void
21 Ndb::checkFailedNode()
22 {
23  DBUG_ENTER("Ndb::checkFailedNode");
24  Uint32 *the_release_ind= theImpl->the_release_ind;
25  if (the_release_ind[0] == 0)
26  {
27  DBUG_VOID_RETURN;
28  }
29  Uint32 tNoOfDbNodes = theImpl->theNoOfDBnodes;
30  Uint8 *theDBnodes= theImpl->theDBnodes;
31 
32  DBUG_PRINT("enter", ("theNoOfDBnodes: %d", tNoOfDbNodes));
33 
34  DBUG_ASSERT(tNoOfDbNodes < MAX_NDB_NODES);
35  for (Uint32 i = 0; i < tNoOfDbNodes; i++){
36  const NodeId node_id = theDBnodes[i];
37  DBUG_PRINT("info", ("i: %d, node_id: %d", i, node_id));
38 
39  DBUG_ASSERT(node_id < MAX_NDB_NODES);
40  if (the_release_ind[node_id] == 1){
41 
45  NdbTransaction * tNdbCon = theConnectionArray[node_id];
46  theConnectionArray[node_id] = NULL;
47  while (tNdbCon != NULL) {
48  NdbTransaction* tempNdbCon = tNdbCon;
49  tNdbCon = tNdbCon->next();
50  releaseNdbCon(tempNdbCon);
51  }
52  the_release_ind[node_id] = 0;
53  }
54  }
55  DBUG_VOID_RETURN;
56 }
57 
58 /***************************************************************************
59  * int createConIdleList(int aNrOfCon);
60  *
61  * Return Value: Return the number of created connection object
62  * if createConIdleList was succesful
63  * Return -1: In all other case.
64  * Parameters: aNrOfCon : Number of connections offered to the application.
65  * Remark: Create connection idlelist with NdbTransaction objects.
66  ***************************************************************************/
67 int
68 Ndb::createConIdleList(int aNrOfCon)
69 {
70  if (theImpl->theConIdleList.fill(this, aNrOfCon))
71  {
72  return -1;
73  }
74  return aNrOfCon;
75 }
76 
77 /***************************************************************************
78  * int createOpIdleList(int aNrOfOp);
79  *
80  * Return Value: Return the number of created operation object if
81  * createOpIdleList was succesful.
82  * Return -1: In all other case.
83  * Parameters: aNrOfOp: Number of operations offered to the application.
84  * Remark: Create operation idlelist with NdbOperation objects..
85  ***************************************************************************/
86 int
87 Ndb::createOpIdleList(int aNrOfOp)
88 {
89  if (theImpl->theOpIdleList.fill(this, aNrOfOp))
90  {
91  return -1;
92  }
93  return aNrOfOp;
94 }
95 
96 /***************************************************************************
97  * NdbBranch* NdbBranch();
98  *
99  * Return Value: Return a NdbBranch if the getNdbBranch was successful.
100  * Return NULL : In all other case.
101  * Remark: Get a NdbBranch from theBranchList and return the object .
102  ***************************************************************************/
103 NdbBranch*
104 Ndb::getNdbBranch()
105 {
106  return theImpl->theBranchList.seize(this);
107 }
108 
109 /***************************************************************************
110  * NdbCall* NdbCall();
111  *
112  * Return Value: Return a NdbCall if the getNdbCall was successful.
113  * Return NULL : In all other case.
114  * Remark: Get a NdbCall from theCallList and return the object .
115  ***************************************************************************/
116 NdbCall*
117 Ndb::getNdbCall()
118 {
119  return theImpl->theCallList.seize(this);
120 }
121 
122 /***************************************************************************
123  * NdbTransaction* getNdbCon();
124  *
125  * Return Value: Return a connection if the getNdbCon was successful.
126  * Return NULL : In all other case.
127  * Remark: Get a connection from theConIdleList and return the object .
128  ***************************************************************************/
130 Ndb::getNdbCon()
131 {
132  NdbTransaction* tNdbCon = theImpl->theConIdleList.seize(this);
133  tNdbCon->theMagicNumber = 0x37412619;
134  return tNdbCon;
135 }
136 
137 /***************************************************************************
138  * NdbLabel* getNdbLabel();
139  *
140  * Return Value: Return a NdbLabel if the getNdbLabel was successful.
141  * Return NULL : In all other case.
142  * Remark: Get a NdbLabel from theLabelList and return the object .
143  ***************************************************************************/
144 NdbLabel*
145 Ndb::getNdbLabel()
146 {
147  return theImpl->theLabelList.seize(this);
148 }
149 
150 /***************************************************************************
151  * NdbScanReceiver* getNdbScanRec()
152  *
153  * Return Value: Return a NdbScanReceiver
154  * Return NULL : In all other case.
155  * Remark: Get a NdbScanReceiver from theScanRecList and return the
156  * object .
157  ****************************************************************************/
159 Ndb::getNdbScanRec()
160 {
161  return theImpl->theScanList.seize(this);
162 }
163 
164 /***************************************************************************
165  * NdbSubroutine* getNdbSubroutine();
166  *
167  * Return Value: Return a NdbSubroutine if the getNdbSubroutine was successful.
168  * Return NULL : In all other case.
169  * Remark: Get a NdbSubroutine from theSubroutineList and return the object .
170  ***************************************************************************/
172 Ndb::getNdbSubroutine()
173 {
174  return theImpl->theSubroutineList.seize(this);
175 }
176 
177 /***************************************************************************
178 NdbOperation* getOperation();
179 
180 Return Value: Return theOpList : if the getOperation was succesful.
181  Return NULL : In all other case.
182 Remark: Get an operation from theOpIdleList and return the object .
183 ***************************************************************************/
185 Ndb::getOperation()
186 {
187  return theImpl->theOpIdleList.seize(this);
188 }
189 
190 /***************************************************************************
191 NdbScanOperation* getScanOperation();
192 
193 Return Value: Return theOpList : if the getScanOperation was succesful.
194  Return NULL : In all other case.
195 Remark: Get an operation from theScanOpIdleList and return the object .
196 ***************************************************************************/
198 Ndb::getScanOperation()
199 {
200  return theImpl->theScanOpIdleList.seize(this);
201 }
202 
203 /***************************************************************************
204 NdbIndexOperation* getIndexOperation();
205 
206 Return Value: Return theOpList : if the getIndexOperation was succesful.
207  Return NULL : In all other case.
208 Remark: Get an operation from theIndexOpIdleList and return the object .
209 ***************************************************************************/
211 Ndb::getIndexOperation()
212 {
213  return theImpl->theIndexOpIdleList.seize(this);
214 }
215 
216 /***************************************************************************
217 NdbRecAttr* getRecAttr();
218 
219 Return Value: Return a reference to a receive attribute object.
220  Return NULL if it's not possible to get a receive attribute object.
221 ***************************************************************************/
222 NdbRecAttr*
223 Ndb::getRecAttr()
224 {
225  NdbRecAttr* tRecAttr = theImpl->theRecAttrIdleList.seize(this);
226  if (tRecAttr != NULL)
227  {
228  tRecAttr->init();
229  return tRecAttr;
230  }
231 
232  return NULL;
233 }
234 
235 /***************************************************************************
236 NdbApiSignal* getSignal();
237 
238 Return Value: Return a reference to a signal object.
239  Return NULL if not possible to get a signal object.
240 ***************************************************************************/
242 Ndb::getSignal()
243 {
244  return theImpl->theSignalIdleList.seize(this);
245 }
246 
247 NdbBlob*
248 Ndb::getNdbBlob()
249 {
250  NdbBlob* tBlob = theImpl->theNdbBlobIdleList.seize(this);
251  if(tBlob)
252  {
253  tBlob->init();
254  }
255  return tBlob;
256 }
257 
259 Ndb::getLockHandle()
260 {
261  NdbLockHandle* lh = theImpl->theLockHandleList.seize(this);
262  if (lh)
263  {
264  lh->init();
265  }
266 
267  return lh;
268 }
269 
270 /***************************************************************************
271 void releaseNdbBranch(NdbBranch* aNdbBranch);
272 
273 Parameters: NdbBranch: The NdbBranch object.
274 Remark: Add a NdbBranch object into the Branch idlelist.
275 ***************************************************************************/
276 void
277 Ndb::releaseNdbBranch(NdbBranch* aNdbBranch)
278 {
279  theImpl->theBranchList.release(aNdbBranch);
280 }
281 
282 /***************************************************************************
283 void releaseNdbCall(NdbCall* aNdbCall);
284 
285 Parameters: NdbBranch: The NdbBranch object.
286 Remark: Add a NdbBranch object into the Branch idlelist.
287 ***************************************************************************/
288 void
289 Ndb::releaseNdbCall(NdbCall* aNdbCall)
290 {
291  theImpl->theCallList.release(aNdbCall);
292 }
293 
294 /***************************************************************************
295 void releaseNdbCon(NdbTransaction* aNdbCon);
296 
297 Parameters: aNdbCon: The NdbTransaction object.
298 Remark: Add a Connection object into the signal idlelist.
299 ***************************************************************************/
300 void
301 Ndb::releaseNdbCon(NdbTransaction* aNdbCon)
302 {
303  aNdbCon->theMagicNumber = 0xFE11DD;
304  theImpl->theConIdleList.release(aNdbCon);
305 }
306 
307 /***************************************************************************
308 void releaseNdbLabel(NdbLabel* aNdbLabel);
309 
310 Parameters: NdbLabel: The NdbLabel object.
311 Remark: Add a NdbLabel object into the Label idlelist.
312 ***************************************************************************/
313 void
314 Ndb::releaseNdbLabel(NdbLabel* aNdbLabel)
315 {
316  theImpl->theLabelList.release(aNdbLabel);
317 }
318 
319 /***************************************************************************
320 void releaseNdbScanRec(NdbScanReceiver* aNdbScanRec);
321 
322 Parameters: aNdbScanRec: The NdbScanReceiver object.
323 Remark: Add a NdbScanReceiver object into the Scan idlelist.
324 ***************************************************************************/
325 void
326 Ndb::releaseNdbScanRec(NdbReceiver* aNdbScanRec)
327 {
328  theImpl->theScanList.release(aNdbScanRec);
329 }
330 
331 /***************************************************************************
332 void releaseNdbSubroutine(NdbSubroutine* aNdbSubroutine);
333 
334 Parameters: NdbSubroutine: The NdbSubroutine object.
335 Remark: Add a NdbSubroutine object into theSubroutine idlelist.
336 ***************************************************************************/
337 void
338 Ndb::releaseNdbSubroutine(NdbSubroutine* aNdbSubroutine)
339 {
340  theImpl->theSubroutineList.release(aNdbSubroutine);
341 }
342 
343 /***************************************************************************
344 void releaseOperation(NdbOperation* anOperation);
345 
346 Parameters: anOperation : The released NdbOperation object.
347 Remark: Add a NdbOperation object into the signal idlelist.
348 ***************************************************************************/
349 void
350 Ndb::releaseOperation(NdbOperation* anOperation)
351 {
352  if(anOperation->m_tcReqGSN == GSN_TCKEYREQ){
353  anOperation->theNdbCon = NULL;
354  anOperation->theMagicNumber = 0xFE11D0;
355  theImpl->theOpIdleList.release(anOperation);
356  } else {
357  assert(anOperation->m_tcReqGSN == GSN_TCINDXREQ);
358  anOperation->theNdbCon = NULL;
359  anOperation->theMagicNumber = 0xFE11D1;
360  theImpl->theIndexOpIdleList.release((NdbIndexOperation*)anOperation);
361  }
362 }
363 
364 /***************************************************************************
365 void releaseScanOperation(NdbScanOperation* aScanOperation);
366 
367 Parameters: aScanOperation : The released NdbScanOperation object.
368 Remark: Add a NdbScanOperation object into the signal idlelist.
369 ***************************************************************************/
370 void
371 Ndb::releaseScanOperation(NdbIndexScanOperation* aScanOperation)
372 {
373  DBUG_ENTER("Ndb::releaseScanOperation");
374  DBUG_PRINT("enter", ("op: 0x%lx", (long) aScanOperation));
375 #ifdef ndb_release_check_dup
376  { NdbIndexScanOperation* tOp = theScanOpIdleList;
377  while (tOp != NULL) {
378  assert(tOp != aScanOperation);
379  tOp = (NdbIndexScanOperation*)tOp->theNext;
380  }
381  }
382 #endif
383  aScanOperation->theNdbCon = NULL;
384  aScanOperation->theMagicNumber = 0xFE11D2;
385  theImpl->theScanOpIdleList.release(aScanOperation);
386  DBUG_VOID_RETURN;
387 }
388 
389 /***************************************************************************
390 void releaseRecAttr(NdbRecAttr* aRecAttr);
391 
392 Parameters: aRecAttr : The released NdbRecAttr object.
393 Remark: Add a NdbRecAttr object into the RecAtt idlelist.
394 ***************************************************************************/
395 void
396 Ndb::releaseRecAttr(NdbRecAttr* aRecAttr)
397 {
398  aRecAttr->release();
399  theImpl->theRecAttrIdleList.release(aRecAttr);
400 }
401 
402 /***************************************************************************
403 void releaseSignal(NdbApiSignal* aSignal);
404 
405 Parameters: aSignal : The released NdbApiSignal object.
406 Remark: Add a NdbApiSignal object into the signal idlelist.
407 ***************************************************************************/
408 void
409 Ndb::releaseSignal(NdbApiSignal* aSignal)
410 {
411 #if defined VM_TRACE
412  // Check that signal is not null
413  assert(aSignal != NULL);
414 #if 0
415  // Check that signal is not already in list
416  NdbApiSignal* tmp = theSignalIdleList;
417  while (tmp != NULL){
418  assert(tmp != aSignal);
419  tmp = tmp->next();
420  }
421 #endif
422 #endif
423 #ifdef POORMANSPURIFY
424  creleaseSignals++;
425 #endif
426  theImpl->theSignalIdleList.release(aSignal);
427 }
428 
429 void
430 Ndb::releaseSignals(Uint32 cnt, NdbApiSignal* head, NdbApiSignal* tail)
431 {
432 #ifdef POORMANSPURIFY
433  creleaseSignals += cnt;
434 #endif
435  theImpl->theSignalIdleList.release(cnt, head, tail);
436 }
437 
438 void
439 Ndb::releaseSignalsInList(NdbApiSignal** pList){
440  NdbApiSignal* tmp;
441  while (*pList != NULL){
442  tmp = *pList;
443  *pList = (*pList)->next();
444  releaseSignal(tmp);
445  }
446 }
447 
448 void
449 Ndb::releaseNdbBlob(NdbBlob* aBlob)
450 {
451  aBlob->release();
452  theImpl->theNdbBlobIdleList.release(aBlob);
453 }
454 
455 void
456 Ndb::releaseLockHandle(NdbLockHandle* lh)
457 {
458  lh->release(this);
459  theImpl->theLockHandleList.release(lh);
460 };
461 
462 /****************************************************************************
463 int releaseConnectToNdb(NdbTransaction* aConnectConnection);
464 
465 Return Value: -1 if error
466 Parameters: aConnectConnection : Seized schema connection to DBTC
467 Remark: Release and disconnect from DBTC a connection and seize it to theConIdleList.
468 *****************************************************************************/
469 void
470 Ndb::releaseConnectToNdb(NdbTransaction* a_con)
471 {
472  DBUG_ENTER("Ndb::releaseConnectToNdb");
473  NdbApiSignal tSignal(theMyRef);
474  int tConPtr;
475 
476 // I need to close the connection irrespective of whether I
477 // manage to reach NDB or not.
478 
479  if (a_con == NULL)
480  DBUG_VOID_RETURN;
481 
482  Uint32 node_id = a_con->getConnectedNodeId();
483  Uint32 conn_seq = a_con->theNodeSequence;
484  tSignal.setSignal(GSN_TCRELEASEREQ, refToBlock(a_con->m_tcRef));
485  tSignal.setData((tConPtr = a_con->getTC_ConnectPtr()), 1);
486  tSignal.setData(theMyRef, 2);
487  tSignal.setData(a_con->ptr2int(), 3);
488  a_con->Status(NdbTransaction::DisConnecting);
489  a_con->theMagicNumber = 0x37412619;
490  int ret_code = sendRecSignal(node_id,
491  WAIT_TC_RELEASE,
492  &tSignal,
493  conn_seq);
494  if (ret_code == 0) {
495  ;
496  } else if (ret_code == -1) {
497  TRACE_DEBUG("Time-out when TCRELEASE sent");
498  } else if (ret_code == -2) {
499  TRACE_DEBUG("Node failed when TCRELEASE sent");
500  } else if (ret_code == -3) {
501  TRACE_DEBUG("Send failed when TCRELEASE sent");
502  } else if (ret_code == -4) {
503  TRACE_DEBUG("Send buffer full when TCRELEASE sent");
504  } else if (ret_code == -5) {
505  TRACE_DEBUG("Node stopping when TCRELEASE sent");
506  } else {
507  ndbout << "Impossible return from sendRecSignal when TCRELEASE" << endl;
508  abort();
509  }//if
510  releaseNdbCon(a_con);
511  DBUG_VOID_RETURN;
512 }
513 
514 template<class T>
515 static
517 update(Ndb::Free_list_usage* curr,
518  Ndb_free_list_t<T> & list,
519  const char * name)
520 {
521  curr->m_name = name;
522  curr->m_created = list.m_alloc_cnt;
523  curr->m_free = list.m_free_cnt;
524  curr->m_sizeof = sizeof(T);
525  return curr;
526 }
527 
529 Ndb::get_free_list_usage(Ndb::Free_list_usage* curr)
530 {
531  if (curr == 0)
532  {
533  return 0;
534  }
535 
536  if(curr->m_name == 0)
537  {
538  update(curr, theImpl->theConIdleList, "NdbTransaction");
539  }
540  else if(!strcmp(curr->m_name, "NdbTransaction"))
541  {
542  update(curr, theImpl->theOpIdleList, "NdbOperation");
543  }
544  else if(!strcmp(curr->m_name, "NdbOperation"))
545  {
546  update(curr, theImpl->theScanOpIdleList, "NdbIndexScanOperation");
547  }
548  else if(!strcmp(curr->m_name, "NdbIndexScanOperation"))
549  {
550  update(curr, theImpl->theIndexOpIdleList, "NdbIndexOperation");
551  }
552  else if(!strcmp(curr->m_name, "NdbIndexOperation"))
553  {
554  update(curr, theImpl->theRecAttrIdleList, "NdbRecAttr");
555  }
556  else if(!strcmp(curr->m_name, "NdbRecAttr"))
557  {
558  update(curr, theImpl->theSignalIdleList, "NdbApiSignal");
559  }
560  else if(!strcmp(curr->m_name, "NdbApiSignal"))
561  {
562  update(curr, theImpl->theLabelList, "NdbLabel");
563  }
564  else if(!strcmp(curr->m_name, "NdbLabel"))
565  {
566  update(curr, theImpl->theBranchList, "NdbBranch");
567  }
568  else if(!strcmp(curr->m_name, "NdbBranch"))
569  {
570  update(curr, theImpl->theSubroutineList, "NdbSubroutine");
571  }
572  else if(!strcmp(curr->m_name, "NdbSubroutine"))
573  {
574  update(curr, theImpl->theCallList, "NdbCall");
575  }
576  else if(!strcmp(curr->m_name, "NdbCall"))
577  {
578  update(curr, theImpl->theNdbBlobIdleList, "NdbBlob");
579  }
580  else if(!strcmp(curr->m_name, "NdbBlob"))
581  {
582  update(curr, theImpl->theScanList, "NdbReceiver");
583  }
584  else if(!strcmp(curr->m_name, "NdbReceiver"))
585  {
586  update(curr, theImpl->theLockHandleList, "NdbLockHandle");
587  }
588  else if(!strcmp(curr->m_name, "NdbLockHandle"))
589  {
590  return 0;
591  }
592  else
593  {
594  update(curr, theImpl->theConIdleList, "NdbTransaction");
595  }
596 
597  return curr;
598 }
599 
600 #define TI(T) \
601  template Ndb::Free_list_usage* \
602  update(Ndb::Free_list_usage*, Ndb_free_list_t<T> &, const char * name);\
603  template struct Ndb_free_list_t<T>
604 
605 TI(NdbBlob);
606 TI(NdbCall);
607 TI(NdbLabel);
608 TI(NdbBranch);
609 TI(NdbSubroutine);
610 TI(NdbApiSignal);
611 TI(NdbRecAttr);
612 TI(NdbOperation);
613 TI(NdbReceiver);
614 TI(NdbConnection);
617 TI(NdbLockHandle);