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