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