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, 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
26 #include <ndb_global.h>
27
28 #include "API.hpp"
29
30 #include <signaldata/TcCommit.hpp>
31 #include <signaldata/TcKeyFailConf.hpp>
32 #include <signaldata/TcKeyConf.hpp>
33 #include <signaldata/TestOrd.hpp>
34 #include <signaldata/CreateIndx.hpp>
35 #include <signaldata/DropIndx.hpp>
36 #include <signaldata/TcIndx.hpp>
37 #include <signaldata/TransIdAI.hpp>
38 #include <signaldata/ScanFrag.hpp>
39 #include <signaldata/ScanTab.hpp>
40 #include <signaldata/SumaImpl.hpp>
41 #include <signaldata/NodeFailRep.hpp>
42 #include <signaldata/NFCompleteRep.hpp>
43 #include <signaldata/AllocNodeId.hpp>
44
45 #include <ndb_limits.h>
46 #include <NdbOut.hpp>
47 #include <NdbTick.h>
48
49 #include <EventLogger.hpp>
50
51 /******************************************************************************
52 * int init( int aNrOfCon, int aNrOfOp );
53 *
54 * Return Value: Return 0 : init was successful.
55 * Return -1: In all other case.
56 * Parameters: aNrOfCon : Number of connections offered to the application.
57 * aNrOfOp : Number of operations offered to the application.
58 * Remark: Create pointers and idle list Synchronous.
59 ****************************************************************************/
60 int
init(int aMaxNoOfTransactions)61 Ndb::init(int aMaxNoOfTransactions)
62 {
63 DBUG_ENTER("Ndb::init");
64
65 int i;
66 int aNrOfCon;
67 int aNrOfOp;
68 int tMaxNoOfTransactions;
69 NdbApiSignal* tSignal[16]; // Initiate free list of 16 signal objects
70 if (theInitState != NotInitialised) {
71 switch(theInitState){
72 case InitConfigError:
73 theError.code = 4117;
74 break;
75 default:
76 theError.code = 4104;
77 break;
78 }
79 DBUG_RETURN(-1);
80 }//if
81 theInitState = StartingInit;
82 TransporterFacade * theFacade = theImpl->m_transporter_facade;
83 theEventBuffer->m_mutex = theFacade->theMutexPtr;
84
85 const Uint32 tRef = theImpl->open(theFacade);
86
87 if (tRef == 0)
88 {
89 theError.code = 4105;
90 DBUG_RETURN(-1); // no more free blocknumbers
91 }//if
92
93 Uint32 nodeId = refToNode(tRef);
94 theNdbBlockNumber = refToBlock(tRef);
95
96 if (nodeId > 0)
97 {
98 connected(Uint32(tRef));
99 }
100
101 /* Init cached min node version */
102 theFacade->lock_mutex();
103 theCachedMinDbNodeVersion = theFacade->getMinDbNodeVersion();
104 theFacade->unlock_mutex();
105
106 theDictionary->setTransporter(this, theFacade);
107
108 aNrOfCon = theImpl->theNoOfDBnodes;
109 aNrOfOp = 2*theImpl->theNoOfDBnodes;
110
111 // Create connection object in a linked list
112 if((createConIdleList(aNrOfCon)) == -1){
113 theError.code = 4000;
114 goto error_handler;
115 }
116
117 // Create operations in a linked list
118 if((createOpIdleList(aNrOfOp)) == -1){
119 theError.code = 4000;
120 goto error_handler;
121 }
122
123
124 tMaxNoOfTransactions = aMaxNoOfTransactions;
125 theMaxNoOfTransactions = tMaxNoOfTransactions;
126 theRemainingStartTransactions= tMaxNoOfTransactions;
127 thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
128 theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
129 theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
130
131 if ((thePreparedTransactionsArray == NULL) ||
132 (theSentTransactionsArray == NULL) ||
133 (theCompletedTransactionsArray == NULL)) {
134 goto error_handler;
135 }//if
136
137 for (i = 0; i < tMaxNoOfTransactions; i++) {
138 thePreparedTransactionsArray[i] = NULL;
139 theSentTransactionsArray[i] = NULL;
140 theCompletedTransactionsArray[i] = NULL;
141 }//for
142 for (i = 0; i < 16; i++){
143 tSignal[i] = getSignal();
144 if(tSignal[i] == NULL) {
145 theError.code = 4000;
146 goto error_handler;
147 }
148 }
149 for (i = 0; i < 16; i++)
150 releaseSignal(tSignal[i]);
151 theInitState = Initialised;
152
153 DBUG_RETURN(0);
154
155 error_handler:
156 ndbout << "error_handler" << endl;
157 releaseTransactionArrays();
158 delete theDictionary;
159 theImpl->close();
160 DBUG_RETURN(-1);
161 }
162
163 void
releaseTransactionArrays()164 Ndb::releaseTransactionArrays()
165 {
166 DBUG_ENTER("Ndb::releaseTransactionArrays");
167 if (thePreparedTransactionsArray != NULL) {
168 delete [] thePreparedTransactionsArray;
169 }//if
170 if (theSentTransactionsArray != NULL) {
171 delete [] theSentTransactionsArray;
172 }//if
173 if (theCompletedTransactionsArray != NULL) {
174 delete [] theCompletedTransactionsArray;
175 }//if
176 DBUG_VOID_RETURN;
177 }//Ndb::releaseTransactionArrays()
178
179 void
trp_deliver_signal(const NdbApiSignal * aSignal,const LinearSectionPtr ptr[3])180 NdbImpl::trp_deliver_signal(const NdbApiSignal * aSignal,
181 const LinearSectionPtr ptr[3])
182 {
183 m_ndb.handleReceivedSignal(aSignal, ptr);
184 }
185
connected(Uint32 ref)186 void Ndb::connected(Uint32 ref)
187 {
188 // cluster connect, a_node == own reference
189 theMyRef= ref;
190 Uint32 tmpTheNode= refToNode(ref);
191 Uint64 tBlockNo= refToBlock(ref);
192 if (theNdbBlockNumber >= 0){
193 assert(theMyRef == numberToRef(theNdbBlockNumber, tmpTheNode));
194 }
195
196 Uint32 cnt =
197 theImpl->m_ndb_cluster_connection.get_db_nodes(theImpl->theDBnodes);
198 theImpl->theNoOfDBnodes = cnt;
199
200 theFirstTransId += ((Uint64)tBlockNo << 52)+
201 ((Uint64)tmpTheNode << 40);
202 // assert(0);
203 DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id: 0x%lx",
204 theMyRef,
205 tmpTheNode,
206 theImpl->theNoOfDBnodes,
207 (long) theFirstTransId));
208 theCommitAckSignal = new NdbApiSignal(theMyRef);
209
210 theDictionary->m_receiver.m_reference= theMyRef;
211 theNode= tmpTheNode; // flag that Ndb object is initialized
212 }
213
214 void
report_node_failure(Uint32 node_id)215 Ndb::report_node_failure(Uint32 node_id)
216 {
217 /**
218 * We can only set the state here since this object can execute
219 * simultaneously.
220 *
221 * This method is only called by ClusterMgr (via lots of methods)
222 */
223
224 theImpl->the_release_ind[node_id] = 1;
225 // must come after
226 theImpl->the_release_ind[0] = 1;
227 theImpl->theWaiter.nodeFail(node_id);
228 return;
229 }//Ndb::report_node_failure()
230
231
232 void
report_node_failure_completed(Uint32 node_id)233 Ndb::report_node_failure_completed(Uint32 node_id)
234 {
235 if (theEventBuffer)
236 {
237 // node failed
238 // eventOperations in the ndb object should be notified
239 theEventBuffer->report_node_failure_completed(node_id);
240 }
241
242 abortTransactionsAfterNodeFailure(node_id);
243
244 }//Ndb::report_node_failure_completed()
245
246 /***************************************************************************
247 void abortTransactionsAfterNodeFailure();
248
249 Remark: Abort all transactions in theSentTransactionsArray after connection
250 to one node has failed
251 ****************************************************************************/
252 void
abortTransactionsAfterNodeFailure(Uint16 aNodeId)253 Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
254 {
255 Uint32 tNoSentTransactions = theNoOfSentTransactions;
256 for (int i = tNoSentTransactions - 1; i >= 0; i--) {
257 NdbTransaction* localCon = theSentTransactionsArray[i];
258 if (localCon->getConnectedNodeId() == aNodeId) {
259 const NdbTransaction::SendStatusType sendStatus = localCon->theSendStatus;
260 if (sendStatus == NdbTransaction::sendTC_OP ||
261 sendStatus == NdbTransaction::sendTC_COMMIT) {
262 /*
263 A transaction was interrupted in the prepare phase by a node
264 failure. Since the transaction was not found in the phase
265 after the node failure it cannot have been committed and
266 we report a normal node failure abort.
267 */
268 localCon->setOperationErrorCodeAbort(4010);
269 localCon->theCompletionStatus = NdbTransaction::CompletedFailure;
270 } else if (sendStatus == NdbTransaction::sendTC_ROLLBACK) {
271 /*
272 We aimed for abort and abort we got even if it was by a node
273 failure. We will thus report it as a success.
274 */
275 localCon->theCompletionStatus = NdbTransaction::CompletedSuccess;
276 } else {
277 #ifdef VM_TRACE
278 printState("abortTransactionsAfterNodeFailure %lx", (long)this);
279 abort();
280 #endif
281 }
282 /*
283 All transactions arriving here have no connection to the kernel
284 intact since the node was failing and they were aborted. Thus we
285 set commit state to Aborted and set state to release on close.
286 */
287 localCon->theReturnStatus = NdbTransaction::ReturnFailure;
288 localCon->theCommitStatus = NdbTransaction::Aborted;
289 localCon->theReleaseOnClose = true;
290 completedTransaction(localCon);
291 }
292 else if(localCon->report_node_failure(aNodeId))
293 {
294 completedTransaction(localCon);
295 }
296 }//for
297 return;
298 }//Ndb::abortTransactionsAfterNodeFailure()
299
300 /****************************************************************************
301 void handleReceivedSignal(NdbApiSignal* aSignal);
302
303 Parameters: aSignal: The signal object.
304 Remark: Send all operations belonging to this connection.
305 *****************************************************************************/
306 void
handleReceivedSignal(const NdbApiSignal * aSignal,const LinearSectionPtr ptr[3])307 Ndb::handleReceivedSignal(const NdbApiSignal* aSignal,
308 const LinearSectionPtr ptr[3])
309 {
310 NdbOperation* tOp;
311 NdbIndexOperation* tIndexOp;
312 NdbTransaction* tCon;
313 int tReturnCode = -1;
314 const Uint32* tDataPtr = aSignal->getDataPtr();
315 const Uint32 tWaitState = theImpl->theWaiter.get_state();
316 const Uint32 tSignalNumber = aSignal->readSignalNumber();
317 const Uint32 tFirstData = *tDataPtr;
318 const Uint32 tLen = aSignal->getLength();
319 Uint32 tNewState = tWaitState;
320 void * tFirstDataPtr;
321 NdbWaiter *t_waiter = &theImpl->theWaiter;
322
323 /* Update cached Min Db node version */
324 theCachedMinDbNodeVersion = theImpl->m_transporter_facade->getMinDbNodeVersion();
325
326 if (likely(NdbImpl::recordGSN(tSignalNumber)))
327 {
328 Uint32 secs = aSignal->m_noOfSections;
329 theImpl->incClientStat(BytesRecvdCount,
330 ((aSignal->getLength() << 2) +
331 ((secs > 2)? ptr[2].sz << 2: 0) +
332 ((secs > 1)? ptr[1].sz << 2: 0) +
333 ((secs > 0)? ptr[0].sz << 2: 0)));
334 }
335
336 /*
337 In order to support 64 bit processes in the application we need to use
338 id's rather than a direct pointer to the object used. It is also a good
339 idea that one cannot corrupt the application code by sending a corrupt
340 memory pointer.
341
342 All signals received by the API requires the first data word to be such
343 an id to the receiving object.
344 */
345
346 switch (tSignalNumber){
347 case GSN_TCKEYCONF:
348 case GSN_TCINDXCONF:
349 {
350 const TcKeyConf * const keyConf = (TcKeyConf *)tDataPtr;
351 if (tFirstData != RNIL)
352 {
353 tFirstDataPtr = int2void(tFirstData);
354 if (tFirstDataPtr == 0) goto InvalidSignal;
355 tCon = void2con(tFirstDataPtr);
356 }
357 else
358 {
359 tCon = lookupTransactionFromOperation(keyConf);
360 }
361 const BlockReference aTCRef = aSignal->theSendersBlockRef;
362
363 if ((tCon->checkMagicNumber() == 0) &&
364 (tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
365 tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
366 if (tReturnCode != -1) {
367 completedTransaction(tCon);
368 }//if
369
370 if(TcKeyConf::getMarkerFlag(keyConf->confInfo)){
371 NdbTransaction::sendTC_COMMIT_ACK(theImpl,
372 theCommitAckSignal,
373 keyConf->transId1,
374 keyConf->transId2,
375 aTCRef);
376 }
377
378 return;
379 }//if
380 goto InvalidSignal;
381
382 return;
383 }
384 case GSN_TRANSID_AI:{
385 tFirstDataPtr = int2void(tFirstData);
386 if (tFirstDataPtr){
387 NdbReceiver* const tRec = void2rec(tFirstDataPtr);
388 if(!tRec->checkMagicNumber()){
389 return;
390 }
391 tCon = tRec->getTransaction();
392 if((tCon!=NULL) &&
393 tCon->checkState_TransId(((const TransIdAI*)tDataPtr)->transId)){
394 Uint32 com;
395 if(aSignal->m_noOfSections > 0){
396 if(tRec->getType()==NdbReceiver::NDB_QUERY_OPERATION){
397 com = ((NdbQueryOperationImpl*)(tRec->m_owner))
398 ->execTRANSID_AI(ptr[0].p, ptr[0].sz);
399 }else{
400 com = tRec->execTRANSID_AI(ptr[0].p, ptr[0].sz);
401 }
402 } else {
403 assert(tRec->getType()!=NdbReceiver::NDB_QUERY_OPERATION);
404 com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength,
405 tLen - TransIdAI::HeaderLength);
406 }
407
408 {
409 tCon->theNdb->theImpl->incClientStat(Ndb::ReadRowCount, 1);
410 if (refToNode(aSignal->theSendersBlockRef) == tCon->theDBnode)
411 tCon->theNdb->theImpl->incClientStat(Ndb::TransLocalReadRowCount,1);
412 }
413
414 if(com == 0)
415 return;
416
417 switch(tRec->getType()){
418 case NdbReceiver::NDB_OPERATION:
419 case NdbReceiver::NDB_INDEX_OPERATION:
420 if(tCon->OpCompleteSuccess() != -1){ //More completions pending?
421 completedTransaction(tCon);
422 }
423 return;
424 case NdbReceiver::NDB_SCANRECEIVER:
425 tCon->theScanningOp->receiver_delivered(tRec);
426 tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
427 (Uint32) NO_WAIT : tWaitState);
428 break;
429 case NdbReceiver::NDB_QUERY_OPERATION:
430 {
431 // Handled differently whether it is a scan or lookup
432 NdbQueryOperationImpl* tmp = (NdbQueryOperationImpl*)(tRec->m_owner);
433 if (tmp->getQueryDef().isScanQuery()) {
434 tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
435 (Uint32) NO_WAIT : tWaitState);
436 break;
437 } else {
438 if (tCon->OpCompleteSuccess() != -1) { //More completions pending?
439 completedTransaction(tCon);
440 }
441 return;
442 }
443 }
444 default:
445 goto InvalidSignal;
446 }
447 break;
448 } else {
449 /**
450 * This is ok as transaction can have been aborted before TRANSID_AI
451 * arrives (if TUP on other node than TC)
452 */
453 return;
454 }
455 } else{ // if((tFirstDataPtr)
456 return;
457 }
458 }
459 case GSN_TCKEY_FAILCONF:
460 {
461 tFirstDataPtr = int2void(tFirstData);
462 const TcKeyFailConf * failConf = (TcKeyFailConf *)tDataPtr;
463 const BlockReference aTCRef = aSignal->theSendersBlockRef;
464 if (tFirstDataPtr != 0){
465 tOp = void2rec_op(tFirstDataPtr);
466
467 if (tOp->checkMagicNumber(false) == 0) {
468 tCon = tOp->theNdbCon;
469 if (tCon != NULL) {
470 if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
471 (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
472 tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
473 if (tReturnCode != -1) {
474 completedTransaction(tCon);
475 }//if
476 }//if
477 }
478 }
479 } else {
480 #ifdef VM_TRACE
481 ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
482 #endif
483 }
484 if(tFirstData & 1){
485 NdbTransaction::sendTC_COMMIT_ACK(theImpl,
486 theCommitAckSignal,
487 failConf->transId1,
488 failConf->transId2,
489 aTCRef);
490 }
491 return;
492 }
493 case GSN_TCKEY_FAILREF:
494 {
495 tFirstDataPtr = int2void(tFirstData);
496 if(tFirstDataPtr != 0){
497 tOp = void2rec_op(tFirstDataPtr);
498 if (tOp->checkMagicNumber(false) == 0) {
499 tCon = tOp->theNdbCon;
500 if (tCon != NULL) {
501 if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
502 (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
503 tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
504 if (tReturnCode != -1) {
505 completedTransaction(tCon);
506 return;
507 }//if
508 }//if
509 }//if
510 }//if
511 }
512 #ifdef VM_TRACE
513 ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
514 #endif
515 return;
516 return;
517 }
518 case GSN_TCKEYREF:
519 {
520 tFirstDataPtr = int2void(tFirstData);
521 if (tFirstDataPtr == 0) goto InvalidSignal;
522
523 const NdbReceiver* const receiver = void2rec(tFirstDataPtr);
524 if(!receiver->checkMagicNumber()){
525 goto InvalidSignal;
526 }
527 tCon = receiver->getTransaction();
528 if (tCon != NULL) {
529 if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
530 if (receiver->getType()==NdbReceiver::NDB_QUERY_OPERATION) {
531 NdbQueryOperationImpl* tmp =
532 (NdbQueryOperationImpl*)(receiver->m_owner);
533 if (tmp->execTCKEYREF(aSignal) &&
534 tCon->OpCompleteFailure() != -1) {
535 completedTransaction(tCon);
536 return;
537 }
538 } else {
539 tOp = void2rec_op(tFirstDataPtr);
540 /* NB! NdbOperation::checkMagicNumber() returns 0 if it *is*
541 * an NdbOperation.*/
542 assert(tOp->checkMagicNumber()==0);
543 tReturnCode = tOp->receiveTCKEYREF(aSignal);
544 if (tReturnCode != -1) {
545 completedTransaction(tCon);
546 return;
547 }//if
548 }//if
549 break;
550 }//if
551 }//if (tCon != NULL)
552 goto InvalidSignal;
553 return;
554 }
555 case GSN_TC_COMMITCONF:
556 {
557 tFirstDataPtr = int2void(tFirstData);
558 if (tFirstDataPtr == 0) goto InvalidSignal;
559
560 const TcCommitConf * const commitConf = (TcCommitConf *)tDataPtr;
561 const BlockReference aTCRef = aSignal->theSendersBlockRef;
562
563 tCon = void2con(tFirstDataPtr);
564 if ((tCon->checkMagicNumber() == 0) &&
565 (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
566 tReturnCode = tCon->receiveTC_COMMITCONF(commitConf, tLen);
567 if (tReturnCode != -1) {
568 completedTransaction(tCon);
569 }//if
570
571 if(tFirstData & 1){
572 NdbTransaction::sendTC_COMMIT_ACK(theImpl,
573 theCommitAckSignal,
574 commitConf->transId1,
575 commitConf->transId2,
576 aTCRef);
577 }
578 return;
579 }
580 goto InvalidSignal;
581 return;
582 }
583
584 case GSN_TC_COMMITREF:
585 {
586 tFirstDataPtr = int2void(tFirstData);
587 if (tFirstDataPtr == 0) goto InvalidSignal;
588
589 tCon = void2con(tFirstDataPtr);
590 if ((tCon->checkMagicNumber() == 0) &&
591 (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT)) {
592 tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
593 if (tReturnCode != -1) {
594 completedTransaction(tCon);
595 }//if
596 }//if
597 return;
598 }
599 case GSN_TCROLLBACKCONF:
600 {
601 tFirstDataPtr = int2void(tFirstData);
602 if (tFirstDataPtr == 0) goto InvalidSignal;
603
604 tCon = void2con(tFirstDataPtr);
605 if ((tCon->checkMagicNumber() == 0) &&
606 (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
607 tReturnCode = tCon->receiveTCROLLBACKCONF(aSignal);
608 if (tReturnCode != -1) {
609 completedTransaction(tCon);
610 }//if
611 }//if
612 return;
613 }
614 case GSN_TCROLLBACKREF:
615 {
616 tFirstDataPtr = int2void(tFirstData);
617 if (tFirstDataPtr == 0) goto InvalidSignal;
618
619 tCon = void2con(tFirstDataPtr);
620 if ((tCon->checkMagicNumber() == 0) &&
621 (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK)) {
622 tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
623 if (tReturnCode != -1) {
624 completedTransaction(tCon);
625 }//if
626 }//if
627 return;
628 }
629 case GSN_TCROLLBACKREP:
630 {
631 tFirstDataPtr = int2void(tFirstData);
632 if (tFirstDataPtr == 0) goto InvalidSignal;
633
634 tCon = void2con(tFirstDataPtr);
635 if (tCon->checkMagicNumber() == 0) {
636 tReturnCode = tCon->receiveTCROLLBACKREP(aSignal);
637 if (tReturnCode != -1) {
638 completedTransaction(tCon);
639 }//if
640 }//if
641 return;
642 }
643 case GSN_TCSEIZECONF:
644 {
645 tFirstDataPtr = int2void(tFirstData);
646 if (tFirstDataPtr == 0) goto InvalidSignal;
647
648 if (tWaitState != WAIT_TC_SEIZE) {
649 goto InvalidSignal;
650 }//if
651 tCon = void2con(tFirstDataPtr);
652 if (tCon->checkMagicNumber() != 0) {
653 goto InvalidSignal;
654 }//if
655 tReturnCode = tCon->receiveTCSEIZECONF(aSignal);
656 if (tReturnCode != -1) {
657 tNewState = NO_WAIT;
658 } else {
659 goto InvalidSignal;
660 }//if
661 break;
662 }
663 case GSN_TCSEIZEREF:
664 {
665 tFirstDataPtr = int2void(tFirstData);
666 if (tFirstDataPtr == 0) goto InvalidSignal;
667
668 if (tWaitState != WAIT_TC_SEIZE) {
669 return;
670 }//if
671 tCon = void2con(tFirstDataPtr);
672 if (tCon->checkMagicNumber() != 0) {
673 return;
674 }//if
675 tReturnCode = tCon->receiveTCSEIZEREF(aSignal);
676 if (tReturnCode != -1) {
677 tNewState = NO_WAIT;
678 } else {
679 return;
680 }//if
681 break;
682 }
683 case GSN_TCRELEASECONF:
684 {
685 tFirstDataPtr = int2void(tFirstData);
686 if (tFirstDataPtr == 0) goto InvalidSignal;
687
688 if (tWaitState != WAIT_TC_RELEASE) {
689 goto InvalidSignal;
690 }//if
691 tCon = void2con(tFirstDataPtr);
692 if (tCon->checkMagicNumber() != 0) {
693 goto InvalidSignal;
694 }//if
695 tReturnCode = tCon->receiveTCRELEASECONF(aSignal);
696 if (tReturnCode != -1) {
697 tNewState = NO_WAIT;
698 }//if
699 break;
700 }
701 case GSN_TCRELEASEREF:
702 {
703 tFirstDataPtr = int2void(tFirstData);
704 if (tFirstDataPtr == 0) goto InvalidSignal;
705
706 if (tWaitState != WAIT_TC_RELEASE) {
707 goto InvalidSignal;
708 }//if
709 tCon = void2con(tFirstDataPtr);
710 if (tCon->checkMagicNumber() != 0) {
711 goto InvalidSignal;
712 }//if
713 tReturnCode = tCon->receiveTCRELEASEREF(aSignal);
714 if (tReturnCode != -1) {
715 tNewState = NO_WAIT;
716 }//if
717 break;
718 }
719
720 case GSN_GET_TABINFOREF:
721 case GSN_GET_TABINFO_CONF:
722 case GSN_CREATE_TABLE_REF:
723 case GSN_CREATE_TABLE_CONF:
724 case GSN_DROP_TABLE_CONF:
725 case GSN_DROP_TABLE_REF:
726 case GSN_ALTER_TABLE_CONF:
727 case GSN_ALTER_TABLE_REF:
728 case GSN_CREATE_INDX_CONF:
729 case GSN_CREATE_INDX_REF:
730 case GSN_DROP_INDX_CONF:
731 case GSN_DROP_INDX_REF:
732 case GSN_INDEX_STAT_CONF:
733 case GSN_INDEX_STAT_REF:
734 case GSN_CREATE_EVNT_CONF:
735 case GSN_CREATE_EVNT_REF:
736 case GSN_DROP_EVNT_CONF:
737 case GSN_DROP_EVNT_REF:
738 case GSN_LIST_TABLES_CONF:
739 case GSN_CREATE_FILE_REF:
740 case GSN_CREATE_FILE_CONF:
741 case GSN_CREATE_FILEGROUP_REF:
742 case GSN_CREATE_FILEGROUP_CONF:
743 case GSN_DROP_FILE_REF:
744 case GSN_DROP_FILE_CONF:
745 case GSN_DROP_FILEGROUP_REF:
746 case GSN_DROP_FILEGROUP_CONF:
747 case GSN_SCHEMA_TRANS_BEGIN_CONF:
748 case GSN_SCHEMA_TRANS_BEGIN_REF:
749 case GSN_SCHEMA_TRANS_END_CONF:
750 case GSN_SCHEMA_TRANS_END_REF:
751 case GSN_SCHEMA_TRANS_END_REP:
752 case GSN_WAIT_GCP_CONF:
753 case GSN_WAIT_GCP_REF:
754 case GSN_CREATE_HASH_MAP_REF:
755 case GSN_CREATE_HASH_MAP_CONF:
756 NdbDictInterface::execSignal(&theDictionary->m_receiver,
757 aSignal, ptr);
758 return;
759
760 case GSN_SUB_REMOVE_CONF:
761 case GSN_SUB_REMOVE_REF:
762 return; // ignore these signals
763 case GSN_SUB_START_CONF:
764 case GSN_SUB_START_REF:
765 case GSN_SUB_STOP_CONF:
766 case GSN_SUB_STOP_REF:
767 NdbDictInterface::execSignal(&theDictionary->m_receiver,
768 aSignal, ptr);
769 return;
770 case GSN_SUB_GCP_COMPLETE_REP:
771 {
772 const SubGcpCompleteRep * const rep=
773 CAST_CONSTPTR(SubGcpCompleteRep, aSignal->getDataPtr());
774 theEventBuffer->execSUB_GCP_COMPLETE_REP(rep, tLen);
775 return;
776 }
777 case GSN_SUB_TABLE_DATA:
778 {
779 const SubTableData * const sdata=
780 CAST_CONSTPTR(SubTableData, aSignal->getDataPtr());
781 const Uint32 oid = sdata->senderData;
782 NdbEventOperationImpl *op= (NdbEventOperationImpl*)int2void(oid);
783
784 if (unlikely(op == 0 || op->m_magic_number != NDB_EVENT_OP_MAGIC_NUMBER))
785 {
786 g_eventLogger->error("dropped GSN_SUB_TABLE_DATA due to wrong magic "
787 "number");
788 return ;
789 }
790
791 // Accumulate DIC_TAB_INFO for TE_ALTER events
792 if (SubTableData::getOperation(sdata->requestInfo) ==
793 NdbDictionary::Event::_TE_ALTER &&
794 !op->execSUB_TABLE_DATA(aSignal, ptr))
795 return;
796
797 LinearSectionPtr copy[3];
798 for (int i = 0; i<aSignal->m_noOfSections; i++)
799 {
800 copy[i] = ptr[i];
801 }
802 for (int i = aSignal->m_noOfSections; i < 3; i++)
803 {
804 copy[i].p = NULL;
805 copy[i].sz = 0;
806 }
807 DBUG_PRINT("info",("oid=senderData: %d, gci{hi/lo}: %d/%d, operation: %d, "
808 "tableId: %d",
809 sdata->senderData, sdata->gci_hi, sdata->gci_lo,
810 SubTableData::getOperation(sdata->requestInfo),
811 sdata->tableId));
812
813 theEventBuffer->insertDataL(op, sdata, tLen, copy);
814 return;
815 }
816 case GSN_SCAN_TABCONF:
817 {
818 tFirstDataPtr = int2void(tFirstData);
819 assert(tFirstDataPtr);
820 assert(void2con(tFirstDataPtr));
821 assert(void2con(tFirstDataPtr)->checkMagicNumber() == 0);
822 if(tFirstDataPtr &&
823 (tCon = void2con(tFirstDataPtr)) && (tCon->checkMagicNumber() == 0)){
824
825 if(aSignal->m_noOfSections > 0){
826 tReturnCode = tCon->receiveSCAN_TABCONF(aSignal,
827 ptr[0].p, ptr[0].sz);
828 } else {
829 tReturnCode =
830 tCon->receiveSCAN_TABCONF(aSignal,
831 tDataPtr + ScanTabConf::SignalLength,
832 tLen - ScanTabConf::SignalLength);
833 }
834 if (tReturnCode != -1 && tWaitState == WAIT_SCAN)
835 tNewState = NO_WAIT;
836 break;
837 } else {
838 goto InvalidSignal;
839 }
840 }
841 case GSN_SCAN_TABREF:
842 {
843 tFirstDataPtr = int2void(tFirstData);
844 if (tFirstDataPtr == 0) goto InvalidSignal;
845
846 tCon = void2con(tFirstDataPtr);
847
848 assert(tFirstDataPtr != 0 &&
849 void2con(tFirstDataPtr)->checkMagicNumber() == 0);
850
851 if (tCon->checkMagicNumber() == 0){
852 tReturnCode = tCon->receiveSCAN_TABREF(aSignal);
853 if (tReturnCode != -1 && tWaitState == WAIT_SCAN){
854 tNewState = NO_WAIT;
855 }
856 break;
857 }
858 goto InvalidSignal;
859 }
860 case GSN_KEYINFO20: {
861 tFirstDataPtr = int2void(tFirstData);
862 NdbReceiver* tRec;
863 if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) &&
864 tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) &&
865 tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1)){
866
867 Uint32 len = ((const KeyInfo20*)tDataPtr)->keyLen;
868 Uint32 info = ((const KeyInfo20*)tDataPtr)->scanInfo_Node;
869 int com = -1;
870 if(aSignal->m_noOfSections > 0 && len == ptr[0].sz){
871 com = tRec->execKEYINFO20(info, ptr[0].p, len);
872 } else if(len == tLen - KeyInfo20::HeaderLength){
873 com = tRec->execKEYINFO20(info, tDataPtr+KeyInfo20::HeaderLength, len);
874 }
875
876 switch(com){
877 case 1:
878 tCon->theScanningOp->receiver_delivered(tRec);
879 tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
880 (Uint32) NO_WAIT : tWaitState);
881 break;
882 case 0:
883 break;
884 case -1:
885 goto InvalidSignal;
886 }
887 break;
888 } else {
889 /**
890 * This is ok as transaction can have been aborted before KEYINFO20
891 * arrives (if TUP on other node than TC)
892 */
893 return;
894 }
895 }
896 case GSN_TCINDXREF:{
897 tFirstDataPtr = int2void(tFirstData);
898 if (tFirstDataPtr == 0) goto InvalidSignal;
899
900 tIndexOp = void2rec_iop(tFirstDataPtr);
901 if (tIndexOp->checkMagicNumber() == 0) {
902 tCon = tIndexOp->theNdbCon;
903 if (tCon != NULL) {
904 if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
905 tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
906 if (tReturnCode != -1) {
907 completedTransaction(tCon);
908 }//if
909 return;
910 }//if
911 }//if
912 }//if
913 goto InvalidSignal;
914 return;
915 }
916 case GSN_API_REGCONF:
917 case GSN_CONNECT_REP:
918 return; // Ignore
919 case GSN_NODE_FAILREP:
920 {
921 const NodeFailRep *rep = CAST_CONSTPTR(NodeFailRep,
922 aSignal->getDataPtr());
923 for (Uint32 i = NdbNodeBitmask::find_first(rep->theNodes);
924 i != NdbNodeBitmask::NotFound;
925 i = NdbNodeBitmask::find_next(rep->theNodes, i + 1))
926 {
927 report_node_failure(i);
928 }
929
930 NdbDictInterface::execSignal(&theDictionary->m_receiver, aSignal, ptr);
931 break;
932 }
933 case GSN_NF_COMPLETEREP:
934 {
935 const NFCompleteRep *rep = CAST_CONSTPTR(NFCompleteRep,
936 aSignal->getDataPtr());
937 report_node_failure_completed(rep->failedNodeId);
938 break;
939 }
940 case GSN_TAKE_OVERTCCONF:
941 abortTransactionsAfterNodeFailure(tFirstData); // theData[0]
942 break;
943 case GSN_ALLOC_NODEID_CONF:
944 {
945 const AllocNodeIdConf *rep = CAST_CONSTPTR(AllocNodeIdConf,
946 aSignal->getDataPtr());
947 Uint32 nodeId = rep->nodeId;
948 connected(numberToRef(theNdbBlockNumber, nodeId));
949 break;
950 }
951 default:
952 tFirstDataPtr = NULL;
953 goto InvalidSignal;
954 }//swich
955
956 if (tNewState != tWaitState)
957 {
958 /*
959 If our waiter object is the owner of the "poll rights", then we
960 can simply return, we will return from this routine to the
961 place where external_poll was called. From there it will move
962 the "poll ownership" to a new thread if available.
963
964 If our waiter object doesn't own the "poll rights", then we must
965 signal the thread from where this waiter object called
966 its conditional wait. This will wake up this thread so that it
967 can continue its work.
968 */
969 t_waiter->signal(tNewState);
970 }
971
972 return;
973
974
975 InvalidSignal:
976 #ifdef VM_TRACE
977 ndbout_c("Ndbif: Error Ndb::handleReceivedSignal "
978 "(tFirstDataPtr=%p, GSN=%d, theImpl->theWaiter.m_state=%d)"
979 " sender = (Block: %d Node: %d)",
980 tFirstDataPtr,
981 tSignalNumber,
982 tWaitState,
983 refToBlock(aSignal->theSendersBlockRef),
984 refToNode(aSignal->theSendersBlockRef));
985 #endif
986 #ifdef NDB_NO_DROPPED_SIGNAL
987 abort();
988 #endif
989
990 return;
991 }//Ndb::handleReceivedSignal()
992
993
994 /*****************************************************************************
995 void completedTransaction(NdbTransaction* aCon);
996
997 Remark: One transaction has been completed.
998 Remove it from send array and put it into the completed
999 transaction array. Finally check if it is time to wake
1000 up a poller.
1001 ******************************************************************************/
1002 void
completedTransaction(NdbTransaction * aCon)1003 Ndb::completedTransaction(NdbTransaction* aCon)
1004 {
1005 Uint32 tTransArrayIndex = aCon->theTransArrayIndex;
1006 Uint32 tNoSentTransactions = theNoOfSentTransactions;
1007 Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
1008 if ((tNoSentTransactions > 0) && (aCon->theListState == NdbTransaction::InSendList) &&
1009 (tTransArrayIndex < tNoSentTransactions)) {
1010 NdbTransaction* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
1011
1012 theCompletedTransactionsArray[tNoCompletedTransactions] = aCon;
1013 aCon->theTransArrayIndex = tNoCompletedTransactions;
1014 if (tMoveCon != aCon) {
1015 tMoveCon->theTransArrayIndex = tTransArrayIndex;
1016 theSentTransactionsArray[tTransArrayIndex] = tMoveCon;
1017 }//if
1018 theSentTransactionsArray[tNoSentTransactions - 1] = NULL;
1019 theNoOfCompletedTransactions = tNoCompletedTransactions + 1;
1020
1021 theNoOfSentTransactions = tNoSentTransactions - 1;
1022 aCon->theListState = NdbTransaction::InCompletedList;
1023 aCon->handleExecuteCompletion();
1024 if ((theMinNoOfEventsToWakeUp != 0) &&
1025 (theNoOfCompletedTransactions >= theMinNoOfEventsToWakeUp)) {
1026 theMinNoOfEventsToWakeUp = 0;
1027 theImpl->theWaiter.signal(NO_WAIT);
1028 return;
1029 }//if
1030 } else {
1031 ndbout << "theNoOfSentTransactions = " << (int) theNoOfSentTransactions;
1032 ndbout << " theListState = " << (int) aCon->theListState;
1033 ndbout << " theTransArrayIndex = " << aCon->theTransArrayIndex;
1034 ndbout << endl << flush;
1035 #ifdef VM_TRACE
1036 printState("completedTransaction abort");
1037 abort();
1038 #endif
1039 }//if
1040 }//Ndb::completedTransaction()
1041
1042 /*****************************************************************************
1043 void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans);
1044
1045 Remark: Call the callback methods of the completed transactions.
1046 ******************************************************************************/
1047 void
reportCallback(NdbTransaction ** aCopyArray,Uint32 aNoOfCompletedTrans)1048 Ndb::reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans)
1049 {
1050 Uint32 i;
1051 if (aNoOfCompletedTrans > 0) {
1052 for (i = 0; i < aNoOfCompletedTrans; i++) {
1053 void* anyObject = aCopyArray[i]->theCallbackObject;
1054 NdbAsynchCallback aCallback = aCopyArray[i]->theCallbackFunction;
1055 int tResult = 0;
1056 if (aCallback != NULL) {
1057 if (aCopyArray[i]->theReturnStatus == NdbTransaction::ReturnFailure) {
1058 tResult = -1;
1059 }//if
1060 (*aCallback)(tResult, aCopyArray[i], anyObject);
1061 }//if
1062 }//for
1063 }//if
1064 }//Ndb::reportCallback()
1065
1066 /*****************************************************************************
1067 Uint32 pollCompleted(NdbTransaction** aCopyArray);
1068
1069 Remark: Transfer the data from the completed transaction to a local array.
1070 This support is used by a number of the poll-methods.
1071 ******************************************************************************/
1072 Uint32
pollCompleted(NdbTransaction ** aCopyArray)1073 Ndb::pollCompleted(NdbTransaction** aCopyArray)
1074 {
1075 check_send_timeout();
1076 Uint32 i;
1077 Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
1078 if (tNoCompletedTransactions > 0) {
1079 for (i = 0; i < tNoCompletedTransactions; i++) {
1080 aCopyArray[i] = theCompletedTransactionsArray[i];
1081 if (aCopyArray[i]->theListState != NdbTransaction::InCompletedList) {
1082 ndbout << "pollCompleted error ";
1083 ndbout << (int) aCopyArray[i]->theListState << endl;
1084 abort();
1085 }//if
1086 theCompletedTransactionsArray[i] = NULL;
1087 aCopyArray[i]->theListState = NdbTransaction::NotInList;
1088 }//for
1089 }//if
1090 theNoOfCompletedTransactions = 0;
1091 return tNoCompletedTransactions;
1092 }//Ndb::pollCompleted()
1093
1094 void
check_send_timeout()1095 Ndb::check_send_timeout()
1096 {
1097 Uint32 timeout = theImpl->get_ndbapi_config_parameters().m_waitfor_timeout;
1098 NDB_TICKS current_time = NdbTick_CurrentMillisecond();
1099 assert(current_time >= the_last_check_time);
1100 if (current_time - the_last_check_time > 1000) {
1101 the_last_check_time = current_time;
1102 Uint32 no_of_sent = theNoOfSentTransactions;
1103 for (Uint32 i = 0; i < no_of_sent; i++) {
1104 NdbTransaction* a_con = theSentTransactionsArray[i];
1105 if ((current_time - a_con->theStartTransTime) > timeout)
1106 {
1107 #ifdef VM_TRACE
1108 a_con->printState();
1109 Uint32 t1 = (Uint32) a_con->theTransactionId;
1110 Uint32 t2 = a_con->theTransactionId >> 32;
1111 ndbout_c("4012 [%.8x %.8x]", t1, t2);
1112 //abort();
1113 #endif
1114 a_con->theReleaseOnClose = true;
1115 a_con->theError.code = 4012;
1116 a_con->setOperationErrorCodeAbort(4012);
1117 a_con->theCommitStatus = NdbTransaction::NeedAbort;
1118 a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
1119 a_con->handleExecuteCompletion();
1120 remove_sent_list(i);
1121 insert_completed_list(a_con);
1122 no_of_sent--;
1123 i--;
1124 }//if
1125 }//for
1126 }//if
1127 }
1128
1129 void
remove_sent_list(Uint32 list_index)1130 Ndb::remove_sent_list(Uint32 list_index)
1131 {
1132 Uint32 last_index = theNoOfSentTransactions - 1;
1133 if (list_index < last_index) {
1134 NdbTransaction* t_con = theSentTransactionsArray[last_index];
1135 theSentTransactionsArray[list_index] = t_con;
1136 }//if
1137 theNoOfSentTransactions = last_index;
1138 theSentTransactionsArray[last_index] = 0;
1139 }
1140
1141 Uint32
insert_completed_list(NdbTransaction * a_con)1142 Ndb::insert_completed_list(NdbTransaction* a_con)
1143 {
1144 Uint32 no_of_comp = theNoOfCompletedTransactions;
1145 theCompletedTransactionsArray[no_of_comp] = a_con;
1146 theNoOfCompletedTransactions = no_of_comp + 1;
1147 a_con->theListState = NdbTransaction::InCompletedList;
1148 a_con->theTransArrayIndex = no_of_comp;
1149 return no_of_comp;
1150 }
1151
1152 Uint32
insert_sent_list(NdbTransaction * a_con)1153 Ndb::insert_sent_list(NdbTransaction* a_con)
1154 {
1155 Uint32 no_of_sent = theNoOfSentTransactions;
1156 theSentTransactionsArray[no_of_sent] = a_con;
1157 theNoOfSentTransactions = no_of_sent + 1;
1158 a_con->theListState = NdbTransaction::InSendList;
1159 a_con->theTransArrayIndex = no_of_sent;
1160 return no_of_sent;
1161 }
1162
1163 /*****************************************************************************
1164 void sendPrepTrans(int forceSend);
1165
1166 Remark: Send a batch of transactions prepared for sending to the NDB kernel.
1167 ******************************************************************************/
1168 void
sendPrepTrans(int forceSend)1169 Ndb::sendPrepTrans(int forceSend)
1170 {
1171 // Always called when holding mutex on TransporterFacade
1172 /*
1173 We will send a list of transactions to the NDB kernel. Before
1174 sending we check the following.
1175 1) Node connected to is still alive
1176 Checked by both checking node status and node sequence
1177 2) Send buffer can handle the size of messages we are planning to send
1178 So far this is just a fake check but will soon be a real check
1179 When the connected node has failed we abort the transaction without
1180 responding anymore to the node since the kernel will clean up
1181 automatically.
1182 When sendBuffer cannot handle anymore messages then we will also abort
1183 transaction but by communicating to the kernel since it is still alive
1184 and we keep a small space for messages like that.
1185 */
1186 Uint32 i;
1187 theCachedMinDbNodeVersion = theImpl->m_transporter_facade->getMinDbNodeVersion();
1188 Uint32 no_of_prep_trans = theNoOfPreparedTransactions;
1189 for (i = 0; i < no_of_prep_trans; i++) {
1190 NdbTransaction * a_con = thePreparedTransactionsArray[i];
1191 thePreparedTransactionsArray[i] = NULL;
1192 Uint32 node_id = a_con->getConnectedNodeId();
1193 if ((theImpl->getNodeSequence(node_id) == a_con->theNodeSequence) &&
1194 (theImpl->get_node_alive(node_id) || theImpl->get_node_stopping(node_id)))
1195 {
1196 /*
1197 We will send if
1198 1) Node is alive and sequences are correct OR
1199 2) Node is stopping and we only want to commit or abort
1200 In a graceful stop situation we want to ensure quick aborts
1201 of all transactions and commits and thus we allow aborts and
1202 commits to continue but not normal operations.
1203 */
1204 if (theImpl->check_send_size(node_id, a_con->get_send_size())) {
1205 if (a_con->doSend() == 0) {
1206 NDB_TICKS current_time = NdbTick_CurrentMillisecond();
1207 a_con->theStartTransTime = current_time;
1208 continue;
1209 } else {
1210 /*
1211 Although all precautions we did not manage to send the operations
1212 Must have been a dropped connection on the transporter side.
1213 We don't expect to be able to continue using this connection so
1214 we will treat it as a node failure.
1215 */
1216 TRACE_DEBUG("Send problem even after checking node status");
1217 }//if
1218 } else {
1219 /*
1220 The send buffer is currently full or at least close to. We will
1221 not allow a send to continue. We will set the connection so that
1222 it is indicated that we need to abort the transaction. If we were
1223 trying to commit or abort and got a send buffer we will not try
1224 again and will thus set the state to Aborted to avoid a more or
1225 less eternal loop of tries.
1226 */
1227 if (a_con->theSendStatus == NdbTransaction::sendOperations) {
1228 a_con->setOperationErrorCodeAbort(4021);
1229 a_con->theCommitStatus = NdbTransaction::NeedAbort;
1230 TRACE_DEBUG("Send buffer full and sendOperations");
1231 } else {
1232 a_con->setOperationErrorCodeAbort(4026);
1233 a_con->theCommitStatus = NdbTransaction::Aborted;
1234 TRACE_DEBUG("Send buffer full, set state to Aborted");
1235 }//if
1236 }//if
1237 } else {
1238 #ifdef VM_TRACE
1239 a_con->printState();
1240 #endif
1241 /*
1242 The node is hard dead and we cannot continue. We will also release
1243 the connection to the free pool.
1244 */
1245 TRACE_DEBUG("The node was stone dead, inform about abort");
1246 a_con->setOperationErrorCodeAbort(4025);
1247 a_con->theReleaseOnClose = true;
1248 a_con->theTransactionIsStarted = false;
1249 a_con->theCommitStatus = NdbTransaction::Aborted;
1250 }//if
1251 a_con->theReturnStatus = NdbTransaction::ReturnFailure;
1252 a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
1253 a_con->handleExecuteCompletion();
1254 insert_completed_list(a_con);
1255 }//for
1256 theNoOfPreparedTransactions = 0;
1257 theImpl->do_forceSend(forceSend);
1258 return;
1259 }//Ndb::sendPrepTrans()
1260
1261 /*****************************************************************************
1262 void waitCompletedTransactions(int aMilliSecondsToWait, int noOfEventsToWaitFor);
1263
1264 Remark: First send all prepared operations and then check if there are any
1265 transactions already completed. Do not wait for not completed
1266 transactions.
1267 ******************************************************************************/
1268 void
waitCompletedTransactions(int aMilliSecondsToWait,int noOfEventsToWaitFor,PollGuard * poll_guard)1269 Ndb::waitCompletedTransactions(int aMilliSecondsToWait,
1270 int noOfEventsToWaitFor,
1271 PollGuard *poll_guard)
1272 {
1273 theImpl->theWaiter.set_node(0);
1274 theImpl->theWaiter.set_state(WAIT_TRANS);
1275
1276 /**
1277 * theImpl->theWaiter.set_node(0)
1278 * To ensure no messup with synchronous node fail handling
1279 * (see ReportFailure)
1280 */
1281 int waitTime = aMilliSecondsToWait;
1282 NDB_TICKS currTime = NdbTick_CurrentMillisecond();
1283 NDB_TICKS maxTime = currTime + (NDB_TICKS)waitTime;
1284 theMinNoOfEventsToWakeUp = noOfEventsToWaitFor;
1285 const int maxsleep = aMilliSecondsToWait > 10 ? 10 : aMilliSecondsToWait;
1286 theImpl->incClientStat(Ndb::WaitExecCompleteCount, 1);
1287 do {
1288 poll_guard->wait_for_input(maxsleep);
1289 if (theNoOfCompletedTransactions >= (Uint32)noOfEventsToWaitFor) {
1290 break;
1291 }//if
1292 theMinNoOfEventsToWakeUp = noOfEventsToWaitFor;
1293 waitTime = (int)(maxTime - NdbTick_CurrentMillisecond());
1294 } while (waitTime > 0);
1295 }//Ndb::waitCompletedTransactions()
1296
1297 /*****************************************************************************
1298 void sendPreparedTransactions(int forceSend = 0);
1299
1300 Remark: First send all prepared operations and then check if there are any
1301 transactions already completed. Do not wait for not completed
1302 transactions.
1303 ******************************************************************************/
1304 void
sendPreparedTransactions(int forceSend)1305 Ndb::sendPreparedTransactions(int forceSend)
1306 {
1307 theImpl->lock();
1308 sendPrepTrans(forceSend);
1309 theImpl->unlock();
1310 return;
1311 }//Ndb::sendPreparedTransactions()
1312
1313 /*****************************************************************************
1314 int sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup = 1, int forceSend = 0);
1315
1316 Remark: First send all prepared operations and then check if there are any
1317 transactions already completed. Wait for not completed
1318 transactions until the specified number have completed or until the
1319 timeout has occured. Timeout zero means no waiting time.
1320 ******************************************************************************/
1321 int
sendPollNdb(int aMillisecondNumber,int minNoOfEventsToWakeup,int forceSend)1322 Ndb::sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup, int forceSend)
1323 {
1324 /*
1325 The PollGuard has an implicit call of unlock_and_signal through the
1326 ~PollGuard method. This method is called implicitly by the compiler
1327 in all places where the object is out of context due to a return,
1328 break, continue or simply end of statement block
1329 */
1330 PollGuard pg(* theImpl);
1331 sendPrepTrans(forceSend);
1332 return poll_trans(aMillisecondNumber, minNoOfEventsToWakeup, &pg);
1333 }
1334
1335 int
poll_trans(int aMillisecondNumber,int minNoOfEventsToWakeup,PollGuard * pg)1336 Ndb::poll_trans(int aMillisecondNumber, int minNoOfEventsToWakeup,
1337 PollGuard *pg)
1338 {
1339 NdbTransaction* tConArray[1024];
1340 Uint32 tNoCompletedTransactions;
1341 if ((minNoOfEventsToWakeup <= 0) ||
1342 ((Uint32)minNoOfEventsToWakeup > theNoOfSentTransactions)) {
1343 minNoOfEventsToWakeup = theNoOfSentTransactions;
1344 }//if
1345 if ((theNoOfCompletedTransactions < (Uint32)minNoOfEventsToWakeup) &&
1346 (aMillisecondNumber > 0)) {
1347 waitCompletedTransactions(aMillisecondNumber, minNoOfEventsToWakeup, pg);
1348 tNoCompletedTransactions = pollCompleted(tConArray);
1349 } else {
1350 tNoCompletedTransactions = pollCompleted(tConArray);
1351 }//if
1352 theMinNoOfEventsToWakeUp = 0; // no more wakup
1353 pg->unlock_and_signal();
1354 reportCallback(tConArray, tNoCompletedTransactions);
1355 return tNoCompletedTransactions;
1356 }
1357
1358 /*****************************************************************************
1359 int pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup);
1360
1361 Remark: Check if there are any transactions already completed. Wait for not
1362 completed transactions until the specified number have completed or
1363 until the timeout has occured. Timeout zero means no waiting time.
1364 ******************************************************************************/
1365 int
pollNdb(int aMillisecondNumber,int minNoOfEventsToWakeup)1366 Ndb::pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup)
1367 {
1368 /*
1369 The PollGuard has an implicit call of unlock_and_signal through the
1370 ~PollGuard method. This method is called implicitly by the compiler
1371 in all places where the object is out of context due to a return,
1372 break, continue or simply end of statement block
1373 */
1374 PollGuard pg(* theImpl);
1375 return poll_trans(aMillisecondNumber, minNoOfEventsToWakeup, &pg);
1376 }
1377
1378 int
sendRecSignal(Uint16 node_id,Uint32 aWaitState,NdbApiSignal * aSignal,Uint32 conn_seq,Uint32 * ret_conn_seq)1379 Ndb::sendRecSignal(Uint16 node_id,
1380 Uint32 aWaitState,
1381 NdbApiSignal* aSignal,
1382 Uint32 conn_seq,
1383 Uint32 *ret_conn_seq)
1384 {
1385 /*
1386 In most situations 0 is returned.
1387 In error cases we have 5 different cases
1388 -1: Send ok, time out in waiting for reply
1389 -2: Node has failed
1390 -3: Send buffer not full, send failed yet
1391 -4: Send buffer full
1392 -5: Node is currently stopping
1393 */
1394
1395 int return_code;
1396 Uint32 read_conn_seq;
1397 Uint32 send_size = 1; // Always sends one signal only
1398 // Protected area
1399 /*
1400 The PollGuard has an implicit call of unlock_and_signal through the
1401 ~PollGuard method. This method is called implicitly by the compiler
1402 in all places where the object is out of context due to a return,
1403 break, continue or simply end of statement block
1404 */
1405 theImpl->incClientStat(WaitMetaRequestCount, 1);
1406 PollGuard poll_guard(* theImpl);
1407 read_conn_seq= theImpl->getNodeSequence(node_id);
1408 if (ret_conn_seq)
1409 *ret_conn_seq= read_conn_seq;
1410 if ((theImpl->get_node_alive(node_id)) &&
1411 ((read_conn_seq == conn_seq) ||
1412 (conn_seq == 0))) {
1413 if (theImpl->check_send_size(node_id, send_size)) {
1414 return_code = theImpl->sendSignal(aSignal, node_id);
1415 if (return_code != -1) {
1416 return poll_guard.wait_n_unlock(WAITFOR_RESPONSE_TIMEOUT,node_id,
1417 aWaitState, false);
1418 } else {
1419 return_code = -3;
1420 }
1421 } else {
1422 return_code = -4;
1423 }//if
1424 } else {
1425 if ((theImpl->get_node_stopping(node_id)) &&
1426 ((read_conn_seq == conn_seq) ||
1427 (conn_seq == 0))) {
1428 return_code = -5;
1429 } else {
1430 return_code = -2;
1431 }//if
1432 }//if
1433 return return_code;
1434 // End of protected area
1435 }//Ndb::sendRecSignal()
1436
1437 void
sendTC_COMMIT_ACK(NdbImpl * impl,NdbApiSignal * aSignal,Uint32 transId1,Uint32 transId2,Uint32 aTCRef)1438 NdbTransaction::sendTC_COMMIT_ACK(NdbImpl * impl,
1439 NdbApiSignal * aSignal,
1440 Uint32 transId1, Uint32 transId2,
1441 Uint32 aTCRef){
1442 #ifdef MARKER_TRACE
1443 ndbout_c("Sending TC_COMMIT_ACK(0x%.8x, 0x%.8x) to -> %d",
1444 transId1,
1445 transId2,
1446 refToNode(aTCRef));
1447 #endif
1448 aSignal->theTrace = TestOrd::TraceAPI;
1449 aSignal->theReceiversBlockNumber = refToBlock(aTCRef);
1450 aSignal->theVerId_signalNumber = GSN_TC_COMMIT_ACK;
1451 aSignal->theLength = 2;
1452
1453 Uint32 * dataPtr = aSignal->getDataPtrSend();
1454 dataPtr[0] = transId1;
1455 dataPtr[1] = transId2;
1456 impl->safe_sendSignal(aSignal, refToNode(aTCRef));
1457 }
1458
1459 int
send_event_report(bool has_lock,Uint32 * data,Uint32 length)1460 NdbImpl::send_event_report(bool has_lock,
1461 Uint32 *data, Uint32 length)
1462 {
1463 NdbApiSignal aSignal(m_ndb.theMyRef);
1464 aSignal.theTrace = TestOrd::TraceAPI;
1465 aSignal.theReceiversBlockNumber = CMVMI;
1466 aSignal.theVerId_signalNumber = GSN_EVENT_REP;
1467 aSignal.theLength = length;
1468 memcpy((char *)aSignal.getDataPtrSend(), (char *)data, length*4);
1469
1470 int ret = 0;
1471 if (!has_lock)
1472 {
1473 lock();
1474 }
1475 Uint32 tNode;
1476 Ndb_cluster_connection_node_iter node_iter;
1477 m_ndb_cluster_connection.init_get_next_node(node_iter);
1478 while ((tNode= m_ndb_cluster_connection.get_next_node(node_iter)))
1479 {
1480 if(get_node_alive(tNode))
1481 {
1482 if (has_lock)
1483 safe_sendSignal(&aSignal, tNode);
1484 else
1485 raw_sendSignal(&aSignal, tNode);
1486 goto done;
1487 }
1488 }
1489
1490 ret = 1;
1491 done:
1492 if (!has_lock)
1493 {
1494 unlock();
1495 }
1496 return ret;
1497 }
1498
1499 NdbTransaction*
lookupTransactionFromOperation(const TcKeyConf * conf)1500 Ndb::lookupTransactionFromOperation(const TcKeyConf * conf)
1501 {
1502 assert(TcKeyConf::getNoOfOperations(conf->confInfo) > 0);
1503 Uint32 opPtr = conf->operations[0].apiOperationPtr;
1504 void * voidptr = int2void(opPtr);
1505 if (voidptr)
1506 {
1507 NdbReceiver* rec = void2rec(voidptr);
1508 if (rec)
1509 {
1510 return rec->getTransaction();
1511 }
1512 }
1513 return 0;
1514 }
1515