1 /*
2 Copyright (c) 2003, 2021, Oracle and/or its affiliates.
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 #ifndef NDEBUG
49 #include <NdbSleep.h>
50 #endif
51 #include <EventLogger.hpp>
52
53 /******************************************************************************
54 * int init( int aNrOfCon, int aNrOfOp );
55 *
56 * Return Value: Return 0 : init was successful.
57 * Return -1: In all other case.
58 * Parameters: aNrOfCon : Number of connections offered to the application.
59 * aNrOfOp : Number of operations offered to the application.
60 * Remark: Create pointers and idle list Synchronous.
61 ****************************************************************************/
62 int
init(int aMaxNoOfTransactions)63 Ndb::init(int aMaxNoOfTransactions)
64 {
65 DBUG_ENTER("Ndb::init");
66
67 int i;
68 int aNrOfCon;
69 int aNrOfOp;
70 int tMaxNoOfTransactions;
71 NdbApiSignal* tSignal[16]; // Initiate free list of 16 signal objects
72 if (theInitState != NotInitialised) {
73 switch(theInitState){
74 case InitConfigError:
75 theError.code = 4117;
76 break;
77 default:
78 theError.code = 4104;
79 break;
80 }
81 DBUG_RETURN(-1);
82 }//if
83 theInitState = StartingInit;
84 TransporterFacade * theFacade = theImpl->m_transporter_facade;
85 theEventBuffer->m_mutex = theImpl->m_mutex;
86
87 const Uint32 tRef = theImpl->open(theFacade);
88
89 #ifndef NDEBUG
90 if(DBUG_EVALUATE_IF("sleep_in_ndbinit", true, false))
91 {
92 fprintf(stderr, "Ndb::init() (%p) taking a break\n", this);
93 NdbSleep_MilliSleep(20000);
94 fprintf(stderr, "Ndb::init() resuming\n");
95 }
96 #endif
97
98 if (tRef == 0)
99 {
100 theError.code = 4105;
101 DBUG_RETURN(-1); // no more free blocknumbers
102 }//if
103
104 Uint32 nodeId = refToNode(tRef);
105 theNdbBlockNumber = refToBlock(tRef);
106
107 if (nodeId > 0)
108 {
109 connected(Uint32(tRef));
110 }
111
112 /* Init cached min node version */
113 theFacade->lock_poll_mutex();
114 theCachedMinDbNodeVersion = theFacade->getMinDbNodeVersion();
115 theFacade->unlock_poll_mutex();
116
117 theDictionary->setTransporter(this, theFacade);
118
119 aNrOfCon = theImpl->theNoOfDBnodes;
120 aNrOfOp = 2*theImpl->theNoOfDBnodes;
121
122 // Create connection object in a linked list
123 if((createConIdleList(aNrOfCon)) == -1){
124 theError.code = 4000;
125 goto error_handler;
126 }
127
128 // Create operations in a linked list
129 if((createOpIdleList(aNrOfOp)) == -1){
130 theError.code = 4000;
131 goto error_handler;
132 }
133
134
135 tMaxNoOfTransactions = aMaxNoOfTransactions;
136 theMaxNoOfTransactions = tMaxNoOfTransactions;
137 theRemainingStartTransactions= tMaxNoOfTransactions;
138 thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
139 theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
140 theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
141
142 if ((thePreparedTransactionsArray == NULL) ||
143 (theSentTransactionsArray == NULL) ||
144 (theCompletedTransactionsArray == NULL)) {
145 goto error_handler;
146 }//if
147
148 for (i = 0; i < tMaxNoOfTransactions; i++) {
149 thePreparedTransactionsArray[i] = NULL;
150 theSentTransactionsArray[i] = NULL;
151 theCompletedTransactionsArray[i] = NULL;
152 }//for
153 for (i = 0; i < 16; i++){
154 tSignal[i] = getSignal();
155 if(tSignal[i] == NULL) {
156 theError.code = 4000;
157 goto error_handler;
158 }
159 }
160 for (i = 0; i < 16; i++)
161 releaseSignal(tSignal[i]);
162
163 /* Force visibility of Ndb object initialisation work before marking it initialised */
164 theFacade->lock_poll_mutex();
165 theFacade->unlock_poll_mutex();
166 theInitState = Initialised;
167
168 DBUG_RETURN(0);
169
170 error_handler:
171 ndbout << "error_handler" << endl;
172 releaseTransactionArrays();
173 delete theDictionary;
174 theImpl->close();
175 DBUG_RETURN(-1);
176 }
177
178 void
releaseTransactionArrays()179 Ndb::releaseTransactionArrays()
180 {
181 DBUG_ENTER("Ndb::releaseTransactionArrays");
182 if (thePreparedTransactionsArray != NULL) {
183 delete [] thePreparedTransactionsArray;
184 }//if
185 if (theSentTransactionsArray != NULL) {
186 delete [] theSentTransactionsArray;
187 }//if
188 if (theCompletedTransactionsArray != NULL) {
189 delete [] theCompletedTransactionsArray;
190 }//if
191 DBUG_VOID_RETURN;
192 }//Ndb::releaseTransactionArrays()
193
connected(Uint32 ref)194 void Ndb::connected(Uint32 ref)
195 {
196 // cluster connect, a_node == own reference
197 theMyRef= ref;
198 Uint32 tmpTheNode= refToNode(ref);
199 Uint64 tBlockNo= refToBlock(ref);
200 if (theNdbBlockNumber >= 0){
201 assert(theMyRef == numberToRef(theNdbBlockNumber, tmpTheNode));
202 }
203
204 Uint32 cnt =
205 theImpl->m_ndb_cluster_connection.get_db_nodes(theImpl->theDBnodes);
206 theImpl->theNoOfDBnodes = cnt;
207
208 theFirstTransId += ((Uint64)tBlockNo << 52)+
209 ((Uint64)tmpTheNode << 40);
210 // assert(0);
211 DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id: 0x%lx",
212 theMyRef,
213 tmpTheNode,
214 theImpl->theNoOfDBnodes,
215 (long) theFirstTransId));
216 theCommitAckSignal = new NdbApiSignal(theMyRef);
217
218 theDictionary->m_receiver.m_reference= theMyRef;
219 theNode= tmpTheNode; // flag that Ndb object is initialized
220 }
221
222 void
report_node_failure(Uint32 node_id)223 Ndb::report_node_failure(Uint32 node_id)
224 {
225 /**
226 * We can only set the state here since this object can execute
227 * simultaneously.
228 *
229 * This method is only called by ClusterMgr (via lots of methods)
230 */
231 assert(node_id < NDB_ARRAY_SIZE(theImpl->the_release_ind));
232 if (node_id < NDB_ARRAY_SIZE(theImpl->the_release_ind))
233 {
234 theImpl->the_release_ind[node_id] = 1;
235 // must come after
236 theImpl->the_release_ind[0] = 1;
237 theImpl->theWaiter.nodeFail(node_id);
238 }
239 return;
240 }//Ndb::report_node_failure()
241
242
243 void
report_node_failure_completed(Uint32 node_id)244 Ndb::report_node_failure_completed(Uint32 node_id)
245 {
246 if (theEventBuffer)
247 {
248 // node failed
249 // eventOperations in the ndb object should be notified
250 theEventBuffer->report_node_failure_completed(node_id);
251 }
252
253 abortTransactionsAfterNodeFailure(node_id);
254
255 }//Ndb::report_node_failure_completed()
256
257 /***************************************************************************
258 void abortTransactionsAfterNodeFailure();
259
260 Remark: Abort all transactions in theSentTransactionsArray after connection
261 to one node has failed
262 ****************************************************************************/
263 void
abortTransactionsAfterNodeFailure(Uint16 aNodeId)264 Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
265 {
266 Uint32 tNoSentTransactions = theNoOfSentTransactions;
267 for (int i = tNoSentTransactions - 1; i >= 0; i--) {
268 NdbTransaction* localCon = theSentTransactionsArray[i];
269 if (localCon->getConnectedNodeId() == aNodeId) {
270 const NdbTransaction::SendStatusType sendStatus = localCon->theSendStatus;
271 if (sendStatus == NdbTransaction::sendTC_OP ||
272 sendStatus == NdbTransaction::sendTC_COMMIT) {
273 /*
274 A transaction was interrupted in the prepare phase by a node
275 failure. Since the transaction was not found in the phase
276 after the node failure it cannot have been committed and
277 we report a normal node failure abort.
278 */
279 localCon->setOperationErrorCodeAbort(4010);
280 localCon->theCompletionStatus = NdbTransaction::CompletedFailure;
281 } else if (sendStatus == NdbTransaction::sendTC_ROLLBACK) {
282 /*
283 We aimed for abort and abort we got even if it was by a node
284 failure. We will thus report it as a success.
285 */
286 localCon->theCompletionStatus = NdbTransaction::CompletedSuccess;
287 } else {
288 #ifdef VM_TRACE
289 printState("abortTransactionsAfterNodeFailure %lx", (long)this);
290 abort();
291 #endif
292 }
293 /*
294 All transactions arriving here have no connection to the kernel
295 intact since the node was failing and they were aborted. Thus we
296 set commit state to Aborted and set state to release on close.
297 */
298 localCon->theReturnStatus = NdbTransaction::ReturnFailure;
299 localCon->theCommitStatus = NdbTransaction::Aborted;
300 localCon->theReleaseOnClose = true;
301 completedTransaction(localCon);
302 }
303 else if(localCon->report_node_failure(aNodeId))
304 {
305 completedTransaction(localCon);
306 }
307 }//for
308 return;
309 }//Ndb::abortTransactionsAfterNodeFailure()
310
311 NdbTransaction*
lookupTransactionFromOperation(const TcKeyConf * conf)312 NdbImpl::lookupTransactionFromOperation(const TcKeyConf * conf)
313 {
314 assert(TcKeyConf::getNoOfOperations(conf->confInfo) > 0);
315 Uint32 opPtr = conf->operations[0].apiOperationPtr;
316 void * voidptr = int2void(opPtr);
317 if (voidptr)
318 {
319 NdbReceiver* rec = void2rec(voidptr);
320 if (rec)
321 {
322 return rec->getTransaction(rec->getType());
323 }
324 }
325 return 0;
326 }
327
328 /****************************************************************************
329 void trp_deliver_signal(NdbApiSignal* aSignal);
330
331 Parameters: aSignal: The signal object.
332 Remark: Send all operations belonging to this connection.
333 *****************************************************************************/
334 void
trp_deliver_signal(const NdbApiSignal * aSignal,const LinearSectionPtr ptr[3])335 NdbImpl::trp_deliver_signal(const NdbApiSignal * aSignal,
336 const LinearSectionPtr ptr[3])
337 {
338 Ndb *myNdb = &m_ndb;
339 int tReturnCode = -1;
340 const Uint32* tDataPtr = aSignal->getDataPtr();
341 const Uint32 tSignalNumber = aSignal->readSignalNumber();
342 Ndb::InitType tInitState = myNdb->theInitState;
343 const Uint32 tFirstData = *tDataPtr;
344 const Uint32 tLen = aSignal->getLength();
345 Uint32 secs = aSignal->m_noOfSections;
346 Uint32 bytesReceived = ((aSignal->getLength() << 2) +
347 ((secs > 2)? ptr[2].sz << 2: 0) +
348 ((secs > 1)? ptr[1].sz << 2: 0) +
349 ((secs > 0)? ptr[0].sz << 2: 0));
350
351 NdbOperation* tOp;
352 NdbIndexOperation* tIndexOp;
353 NdbTransaction* tCon;
354
355 /* Check that Ndb object is properly setup to handle the signal */
356 if (tInitState != Ndb::Initialised)
357 return;
358
359 void *tFirstDataPtr = int2void(tFirstData);
360 const Uint32 tWaitState = theWaiter.get_state();
361 Uint32 tNewState = tWaitState;
362
363 /* Update cached Min Db node version */
364 myNdb->theCachedMinDbNodeVersion = m_transporter_facade->getMinDbNodeVersion();
365
366 if (likely(recordGSN(tSignalNumber)))
367 {
368 incClientStat(Ndb::BytesRecvdCount, bytesReceived);
369 }
370
371 /*
372 In order to support 64 bit processes in the application we need to use
373 id's rather than a direct pointer to the object used. It is also a good
374 idea that one cannot corrupt the application code by sending a corrupt
375 memory pointer.
376
377 All traffic signals received by the API requires the first data word to be
378 such an id to the receiving object.
379 */
380
381 switch (tSignalNumber)
382 {
383 case GSN_TCKEYCONF:
384 case GSN_TCINDXCONF:
385 {
386 const TcKeyConf * const keyConf = (TcKeyConf *)tDataPtr;
387 if (tFirstData != RNIL)
388 {
389 tCon = void2con(tFirstDataPtr);
390 }
391 else
392 {
393 tCon = lookupTransactionFromOperation(keyConf);
394 }
395 if (likely(tCon != NULL))
396 {
397 const Uint32 magicNumber = tCon->getMagicNumberFromObject();
398 NdbTransaction::SendStatusType tSendStatus = tCon->theSendStatus;
399 const BlockReference aTCRef = aSignal->theSendersBlockRef;
400 const bool marker = TcKeyConf::getMarkerFlag(keyConf->confInfo);
401
402 if (likely((magicNumber == tCon->getMagicNumber()) &&
403 (tSendStatus == NdbTransaction::sendTC_OP)))
404 {
405 tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
406 /**
407 * BUG#19643174
408 * ------------
409 * Ensure that we always send TC_COMMIT_ACK before we report
410 * transaction as completed, this avoids races where the API
411 * user starts another activity before we've completed the
412 * sending of TC_COMMIT_ACK. This is mostly a problem for
413 * test applications that e.g. want to check for memory
414 * leaks after a transaction has completed. We only do this
415 * action if requested by the API user (should only be
416 * requested by test application).
417 */
418 if (unlikely(marker && send_TC_COMMIT_ACK_immediate_flag))
419 {
420 NdbTransaction::sendTC_COMMIT_ACK(this,
421 myNdb->theCommitAckSignal,
422 keyConf->transId1,
423 keyConf->transId2,
424 aTCRef,
425 send_TC_COMMIT_ACK_immediate_flag);
426 if (tReturnCode != -1)
427 {
428 myNdb->completedTransaction(tCon);
429 }
430 return;
431 }
432 if (tReturnCode != -1)
433 {
434 myNdb->completedTransaction(tCon);
435 }
436 if (marker)
437 {
438 NdbTransaction::sendTC_COMMIT_ACK(this,
439 myNdb->theCommitAckSignal,
440 keyConf->transId1,
441 keyConf->transId2,
442 aTCRef,
443 false);
444 }
445 return;
446 }
447 }
448 const bool marker = TcKeyConf::getMarkerFlag(keyConf->confInfo);
449 const BlockReference aTCRef = aSignal->theSendersBlockRef;
450 if (marker)
451 {
452 /**
453 * We must send the TC_COMMIT_ACK even if we "reject" signal!
454 */
455 NdbTransaction::sendTC_COMMIT_ACK(this,
456 myNdb->theCommitAckSignal,
457 keyConf->transId1,
458 keyConf->transId2,
459 aTCRef,
460 send_TC_COMMIT_ACK_immediate_flag);
461 }
462 goto InvalidSignal;
463 return;
464 }
465 case GSN_TRANSID_AI:
466 {
467 if (likely(tFirstDataPtr != NULL))
468 {
469 NdbReceiver* const tRec = void2rec(tFirstDataPtr);
470 Uint32 magicNumber = tRec->getMagicNumberFromObject();
471 Uint32 num_sections = aSignal->m_noOfSections;
472 NdbReceiver::ReceiverType type = tRec->getType();
473
474 if (unlikely(magicNumber != tRec->getMagicNumber()))
475 {
476 #ifdef NDB_NO_DROPPED_SIGNAL
477 abort();
478 #endif
479 return;
480 }
481 tCon = tRec->getTransaction(type);
482 if (likely(((tCon != NULL) &&
483 tCon->checkState_TransId(
484 ((const TransIdAI*)tDataPtr)->transId))))
485 {
486 void *owner = (void*)tRec->getOwner();
487 Uint32 com;
488 if (num_sections > 0)
489 {
490 if (type == NdbReceiver::NDB_QUERY_OPERATION)
491 {
492 NdbQueryOperationImpl* impl_owner = (NdbQueryOperationImpl*)owner;
493 com = impl_owner->execTRANSID_AI(ptr[0].p, ptr[0].sz);
494 }
495 else
496 {
497 com = tRec->execTRANSID_AI(ptr[0].p, ptr[0].sz);
498 }
499 }
500 else
501 {
502 assert(type != NdbReceiver::NDB_QUERY_OPERATION);
503 DBUG_EXECUTE_IF("ndb_delay_transid_ai",
504 {
505 fprintf(stderr,
506 "NdbImpl::trp_deliver_signal() (%p)"
507 " taking a break before TRANSID_AI\n",
508 this);
509 NdbSleep_MilliSleep(1000);
510 fprintf(stderr, "NdbImpl::trp_deliver_signal() resuming\n");
511 });
512
513 com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength,
514 tLen - TransIdAI::HeaderLength);
515 }
516 {
517 BlockReference ref = aSignal->theSendersBlockRef;
518 NodeId dbNode = tCon->theDBnode;
519 NodeId senderNode = refToNode(ref);
520 incClientStat(Ndb::ReadRowCount, 1);
521 if (senderNode == dbNode)
522 {
523 incClientStat(Ndb::TransLocalReadRowCount,1);
524 }
525 }
526 if (com == 0)
527 {
528 return;
529 }
530 switch (type)
531 {
532 case NdbReceiver::NDB_OPERATION:
533 case NdbReceiver::NDB_INDEX_OPERATION:
534 {
535 if (tCon->OpCompleteSuccess() != -1)
536 { //More completions pending?
537 myNdb->completedTransaction(tCon);
538 }
539 return;
540 }
541 case NdbReceiver::NDB_SCANRECEIVER:
542 {
543 tCon->theScanningOp->receiver_delivered(tRec);
544 tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
545 (Uint32) NO_WAIT : tWaitState);
546 break;
547 }
548 case NdbReceiver::NDB_QUERY_OPERATION:
549 {
550 // Handled differently whether it is a scan or lookup
551 NdbQueryOperationImpl* impl_owner = (NdbQueryOperationImpl*)owner;
552 if (impl_owner->getQueryDef().isScanQuery())
553 {
554 tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
555 (Uint32) NO_WAIT : tWaitState);
556 break;
557 }
558 else
559 {
560 if (tCon->OpCompleteSuccess() != -1)
561 { //More completions pending?
562 myNdb->completedTransaction(tCon);
563 }
564 return;
565 }
566 }
567 default:
568 {
569 goto InvalidSignal;
570 }
571 }
572 break;
573 }
574 else
575 {
576 /**
577 * This is ok as transaction can have been aborted before TRANSID_AI
578 * arrives (if TUP on other node than TC)
579 */
580 return;
581 }
582 }
583 else
584 {
585 return;
586 }
587 }
588 case GSN_SCAN_TABCONF:
589 {
590 tCon = void2con(tFirstDataPtr);
591 if (unlikely(tFirstDataPtr == NULL))
592 {
593 goto InvalidSignal;
594 }
595 Uint32 magicNumber = tCon->getMagicNumberFromObject();
596 Uint32 num_sections = aSignal->m_noOfSections;
597 Uint32 sz;
598 Uint32 *sig_ptr;
599
600 if (unlikely(magicNumber != tCon->getMagicNumber()))
601 {
602 goto InvalidSignal;
603 }
604 if (num_sections > 0)
605 {
606 sig_ptr = ptr[0].p;
607 sz = ptr[0].sz;
608 }
609 else
610 {
611 sig_ptr = (Uint32*)tDataPtr + ScanTabConf::SignalLength,
612 sz = tLen - ScanTabConf::SignalLength;
613 }
614 tReturnCode = tCon->receiveSCAN_TABCONF(aSignal, sig_ptr, sz);
615 if (tReturnCode != -1 && tWaitState == WAIT_SCAN)
616 {
617 tNewState = NO_WAIT;
618 }
619 break;
620 }
621 case GSN_TC_COMMITCONF:
622 {
623 const TcCommitConf * const commitConf = (TcCommitConf *)tDataPtr;
624 const BlockReference aTCRef = aSignal->theSendersBlockRef;
625
626 if (tFirstDataPtr == 0)
627 {
628 goto invalid0;
629 }
630 tCon = void2con(tFirstDataPtr);
631 if ((tCon->checkMagicNumber() == 0) &&
632 (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT))
633 {
634 tReturnCode = tCon->receiveTC_COMMITCONF(commitConf, tLen);
635 if (unlikely((tFirstData & 1) && send_TC_COMMIT_ACK_immediate_flag))
636 {
637 NdbTransaction::sendTC_COMMIT_ACK(this,
638 myNdb->theCommitAckSignal,
639 commitConf->transId1,
640 commitConf->transId2,
641 aTCRef,
642 true);
643 if (tReturnCode != -1)
644 {
645 myNdb->completedTransaction(tCon);
646 }
647 return;
648 }
649 if (tReturnCode != -1)
650 {
651 myNdb->completedTransaction(tCon);
652 }
653 if (tFirstData & 1)
654 {
655 NdbTransaction::sendTC_COMMIT_ACK(this,
656 myNdb->theCommitAckSignal,
657 commitConf->transId1,
658 commitConf->transId2,
659 aTCRef,
660 false);
661 }
662 return;
663 }
664 invalid0:
665 if(tFirstData & 1)
666 {
667 /**
668 * We must send TC_COMMIT_ACK regardless if we "reject" signal!
669 */
670 NdbTransaction::sendTC_COMMIT_ACK(this,
671 myNdb->theCommitAckSignal,
672 commitConf->transId1,
673 commitConf->transId2,
674 aTCRef,
675 send_TC_COMMIT_ACK_immediate_flag);
676 }
677 goto InvalidSignal;
678 return;
679 }
680 case GSN_TCROLLBACKCONF:
681 {
682 if (tFirstDataPtr == 0)
683 {
684 goto InvalidSignal;
685 }
686 tCon = void2con(tFirstDataPtr);
687 if ((tCon->checkMagicNumber() == 0) &&
688 (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK))
689 {
690 tReturnCode = tCon->receiveTCROLLBACKCONF(aSignal);
691 if (tReturnCode != -1)
692 {
693 myNdb->completedTransaction(tCon);
694 }
695 }
696 return;
697 }
698 case GSN_KEYINFO20:
699 {
700 NdbReceiver* tRec;
701 if (tFirstDataPtr &&
702 (tRec = void2rec(tFirstDataPtr)) &&
703 tRec->checkMagicNumber() &&
704 (tCon = tRec->getTransaction(tRec->getType())) &&
705 tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1))
706 {
707 Uint32 len = ((const KeyInfo20*)tDataPtr)->keyLen;
708 Uint32 info = ((const KeyInfo20*)tDataPtr)->scanInfo_Node;
709 int com = -1;
710 if (aSignal->m_noOfSections > 0 && len == ptr[0].sz)
711 {
712 com = tRec->execKEYINFO20(info, ptr[0].p, len);
713 }
714 else if (len == tLen - KeyInfo20::HeaderLength)
715 {
716 com = tRec->execKEYINFO20(info, tDataPtr+KeyInfo20::HeaderLength, len);
717 }
718
719 switch(com)
720 {
721 case 1:
722 tCon->theScanningOp->receiver_delivered(tRec);
723 tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
724 (Uint32) NO_WAIT : tWaitState);
725 break;
726 case 0:
727 break;
728 case -1:
729 goto InvalidSignal;
730 }
731 break;
732 }
733 else
734 {
735 /**
736 * This is ok as transaction can have been aborted before KEYINFO20
737 * arrives (if TUP on other node than TC)
738 */
739 return;
740 }
741 }
742 case GSN_TCKEYREF:
743 {
744 if (tFirstDataPtr == 0)
745 {
746 goto InvalidSignal;
747 }
748 const NdbReceiver* const receiver = void2rec(tFirstDataPtr);
749 if (!receiver->checkMagicNumber())
750 {
751 goto InvalidSignal;
752 }
753 tCon = receiver->getTransaction(receiver->getType());
754 if (tCon != NULL)
755 {
756 if (tCon->theSendStatus == NdbTransaction::sendTC_OP)
757 {
758 if (receiver->getType()==NdbReceiver::NDB_QUERY_OPERATION)
759 {
760 NdbQueryOperationImpl* tmp =
761 (NdbQueryOperationImpl*)(receiver->m_owner);
762 if (tmp->execTCKEYREF(aSignal) &&
763 tCon->OpCompleteFailure() != -1)
764 {
765 myNdb->completedTransaction(tCon);
766 return;
767 }
768 }
769 else
770 {
771 tOp = void2rec_op(tFirstDataPtr);
772 /* NB! NdbOperation::checkMagicNumber() returns 0 if it *is*
773 * an NdbOperation.*/
774 assert(tOp->checkMagicNumber()==0);
775 tReturnCode = tOp->receiveTCKEYREF(aSignal);
776 if (tReturnCode != -1)
777 {
778 myNdb->completedTransaction(tCon);
779 return;
780 }//if
781 }//if
782 break;
783 }
784 }
785 goto InvalidSignal;
786 return;
787 }
788 case GSN_TCINDXREF:
789 {
790 if (tFirstDataPtr == 0)
791 {
792 goto InvalidSignal;
793 }
794 tIndexOp = void2rec_iop(tFirstDataPtr);
795 if (tIndexOp->checkMagicNumber() == 0)
796 {
797 tCon = tIndexOp->theNdbCon;
798 if (tCon != NULL)
799 {
800 if (tCon->theSendStatus == NdbTransaction::sendTC_OP)
801 {
802 tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
803 if (tReturnCode != -1)
804 {
805 myNdb->completedTransaction(tCon);
806 }
807 return;
808 }
809 }
810 }
811 goto InvalidSignal;
812 return;
813 }
814 case GSN_TC_COMMITREF:
815 {
816 if (tFirstDataPtr == 0)
817 {
818 goto InvalidSignal;
819 }
820 tCon = void2con(tFirstDataPtr);
821 if ((tCon->checkMagicNumber() == 0) &&
822 (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT))
823 {
824 tReturnCode = tCon->receiveTC_COMMITREF(aSignal);
825 if (tReturnCode != -1)
826 {
827 myNdb->completedTransaction(tCon);
828 }
829 }
830 return;
831 }
832 case GSN_TCROLLBACKREF:
833 {
834 if (tFirstDataPtr == 0)
835 {
836 goto InvalidSignal;
837 }
838 tCon = void2con(tFirstDataPtr);
839 if ((tCon->checkMagicNumber() == 0) &&
840 (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK))
841 {
842 tReturnCode = tCon->receiveTCROLLBACKREF(aSignal);
843 if (tReturnCode != -1)
844 {
845 myNdb->completedTransaction(tCon);
846 }
847 }
848 return;
849 }
850 case GSN_TCROLLBACKREP:
851 {
852 if (tFirstDataPtr == 0)
853 {
854 goto InvalidSignal;
855 }
856 tCon = void2con(tFirstDataPtr);
857 if (tCon->checkMagicNumber() == 0)
858 {
859 tReturnCode = tCon->receiveTCROLLBACKREP(aSignal);
860 if (tReturnCode != -1)
861 {
862 myNdb->completedTransaction(tCon);
863 }
864 }
865 return;
866 }
867 case GSN_SCAN_TABREF:
868 {
869 if (tFirstDataPtr == 0)
870 {
871 goto InvalidSignal;
872 }
873 tCon = void2con(tFirstDataPtr);
874 assert(tFirstDataPtr != 0 &&
875 void2con(tFirstDataPtr)->checkMagicNumber() == 0);
876 if (tCon->checkMagicNumber() == 0)
877 {
878 tReturnCode = tCon->receiveSCAN_TABREF(aSignal);
879 if (tReturnCode != -1 && tWaitState == WAIT_SCAN)
880 {
881 tNewState = NO_WAIT;
882 }
883 break;
884 }
885 goto InvalidSignal;
886 }
887 case GSN_TCSEIZECONF:
888 {
889 if (tFirstDataPtr == 0)
890 {
891 goto InvalidSignal;
892 }
893 if (tWaitState != WAIT_TC_SEIZE)
894 {
895 goto InvalidSignal;
896 }
897 tCon = void2con(tFirstDataPtr);
898 if (tCon->checkMagicNumber() != 0)
899 {
900 goto InvalidSignal;
901 }
902 tReturnCode = tCon->receiveTCSEIZECONF(aSignal);
903 if (tReturnCode != -1)
904 {
905 tNewState = NO_WAIT;
906 }
907 else
908 {
909 goto InvalidSignal;
910 }
911 break;
912 }
913 case GSN_TCSEIZEREF:
914 {
915 if (tFirstDataPtr == 0)
916 {
917 goto InvalidSignal;
918 }
919 if (tWaitState != WAIT_TC_SEIZE)
920 {
921 return;
922 }
923 tCon = void2con(tFirstDataPtr);
924 if (tCon->checkMagicNumber() != 0)
925 {
926 return;
927 }
928 tReturnCode = tCon->receiveTCSEIZEREF(aSignal);
929 if (tReturnCode != -1)
930 {
931 tNewState = NO_WAIT;
932 }
933 else
934 {
935 return;
936 }
937 break;
938 }
939 case GSN_TCRELEASECONF:
940 {
941 if (tFirstDataPtr == 0)
942 {
943 goto InvalidSignal;
944 }
945 if (tWaitState != WAIT_TC_RELEASE)
946 {
947 goto InvalidSignal;
948 }
949 tCon = void2con(tFirstDataPtr);
950 if (tCon->checkMagicNumber() != 0)
951 {
952 goto InvalidSignal;
953 }
954 tReturnCode = tCon->receiveTCRELEASECONF(aSignal);
955 if (tReturnCode != -1)
956 {
957 tNewState = NO_WAIT;
958 }
959 break;
960 }
961 case GSN_TCRELEASEREF:
962 {
963 if (tFirstDataPtr == 0)
964 {
965 goto InvalidSignal;
966 }
967 if (tWaitState != WAIT_TC_RELEASE)
968 {
969 goto InvalidSignal;
970 }
971 tCon = void2con(tFirstDataPtr);
972 if (tCon->checkMagicNumber() != 0)
973 {
974 goto InvalidSignal;
975 }
976 tReturnCode = tCon->receiveTCRELEASEREF(aSignal);
977 if (tReturnCode != -1)
978 {
979 tNewState = NO_WAIT;
980 }
981 break;
982 }
983 case GSN_TCKEY_FAILCONF:
984 {
985 const TcKeyFailConf * failConf = (TcKeyFailConf *)tDataPtr;
986 const BlockReference aTCRef = aSignal->theSendersBlockRef;
987 if (tFirstDataPtr != 0)
988 {
989 tOp = void2rec_op(tFirstDataPtr);
990 if (tOp->checkMagicNumber(false) == 0)
991 {
992 tCon = tOp->theNdbCon;
993 if (tCon != NULL)
994 {
995 if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
996 (tCon->theSendStatus == NdbTransaction::sendTC_COMMIT))
997 {
998 tReturnCode = tCon->receiveTCKEY_FAILCONF(failConf);
999 if(tFirstData & 1)
1000 {
1001 NdbTransaction::sendTC_COMMIT_ACK(this,
1002 myNdb->theCommitAckSignal,
1003 failConf->transId1,
1004 failConf->transId2,
1005 aTCRef,
1006 send_TC_COMMIT_ACK_immediate_flag);
1007 }
1008 if (tReturnCode != -1)
1009 {
1010 myNdb->completedTransaction(tCon);
1011 }
1012 return;
1013 }
1014 }
1015 }
1016 }
1017 else
1018 {
1019 #ifdef VM_TRACE
1020 ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
1021 #endif
1022 }
1023 if(tFirstData & 1)
1024 {
1025 NdbTransaction::sendTC_COMMIT_ACK(this,
1026 myNdb->theCommitAckSignal,
1027 failConf->transId1,
1028 failConf->transId2,
1029 aTCRef,
1030 send_TC_COMMIT_ACK_immediate_flag);
1031 }
1032 return;
1033 }
1034 case GSN_TCKEY_FAILREF:
1035 {
1036 if (tFirstDataPtr != 0)
1037 {
1038 tOp = void2rec_op(tFirstDataPtr);
1039 if (tOp->checkMagicNumber(false) == 0)
1040 {
1041 tCon = tOp->theNdbCon;
1042 if (tCon != NULL)
1043 {
1044 if ((tCon->theSendStatus == NdbTransaction::sendTC_OP) ||
1045 (tCon->theSendStatus == NdbTransaction::sendTC_ROLLBACK))
1046 {
1047 tReturnCode = tCon->receiveTCKEY_FAILREF(aSignal);
1048 if (tReturnCode != -1)
1049 {
1050 myNdb->completedTransaction(tCon);
1051 return;
1052 }
1053 }
1054 }
1055 }
1056 }
1057 #ifdef VM_TRACE
1058 ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
1059 #endif
1060 return;
1061 }
1062 case GSN_CLOSE_COMREQ:
1063 {
1064 m_transporter_facade->perform_close_clnt(this);
1065 break;
1066 }
1067 case GSN_GET_TABINFOREF:
1068 case GSN_GET_TABINFO_CONF:
1069 case GSN_CREATE_TABLE_REF:
1070 case GSN_CREATE_TABLE_CONF:
1071 case GSN_DROP_TABLE_CONF:
1072 case GSN_DROP_TABLE_REF:
1073 case GSN_ALTER_TABLE_CONF:
1074 case GSN_ALTER_TABLE_REF:
1075 case GSN_CREATE_INDX_CONF:
1076 case GSN_CREATE_INDX_REF:
1077 case GSN_DROP_INDX_CONF:
1078 case GSN_DROP_INDX_REF:
1079 case GSN_INDEX_STAT_CONF:
1080 case GSN_INDEX_STAT_REF:
1081 case GSN_CREATE_EVNT_CONF:
1082 case GSN_CREATE_EVNT_REF:
1083 case GSN_DROP_EVNT_CONF:
1084 case GSN_DROP_EVNT_REF:
1085 case GSN_LIST_TABLES_CONF:
1086 case GSN_CREATE_FILE_REF:
1087 case GSN_CREATE_FILE_CONF:
1088 case GSN_CREATE_FILEGROUP_REF:
1089 case GSN_CREATE_FILEGROUP_CONF:
1090 case GSN_DROP_FILE_REF:
1091 case GSN_DROP_FILE_CONF:
1092 case GSN_DROP_FILEGROUP_REF:
1093 case GSN_DROP_FILEGROUP_CONF:
1094 case GSN_SCHEMA_TRANS_BEGIN_CONF:
1095 case GSN_SCHEMA_TRANS_BEGIN_REF:
1096 case GSN_SCHEMA_TRANS_END_CONF:
1097 case GSN_SCHEMA_TRANS_END_REF:
1098 case GSN_SCHEMA_TRANS_END_REP:
1099 case GSN_WAIT_GCP_CONF:
1100 case GSN_WAIT_GCP_REF:
1101 case GSN_CREATE_HASH_MAP_REF:
1102 case GSN_CREATE_HASH_MAP_CONF:
1103 case GSN_CREATE_FK_REF:
1104 case GSN_CREATE_FK_CONF:
1105 case GSN_DROP_FK_REF:
1106 case GSN_DROP_FK_CONF:
1107 {
1108 NdbDictInterface::execSignal(&myNdb->theDictionary->m_receiver,
1109 aSignal,
1110 ptr);
1111 return;
1112 }
1113 case GSN_SUB_REMOVE_CONF:
1114 case GSN_SUB_REMOVE_REF:
1115 {
1116 return; // ignore these signals
1117 }
1118 case GSN_SUB_START_CONF:
1119 case GSN_SUB_START_REF:
1120 case GSN_SUB_STOP_CONF:
1121 case GSN_SUB_STOP_REF:
1122 {
1123 NdbDictInterface::execSignal(&myNdb->theDictionary->m_receiver,
1124 aSignal,
1125 ptr);
1126 return;
1127 }
1128 case GSN_SUB_GCP_COMPLETE_REP:
1129 {
1130 const SubGcpCompleteRep * const rep=
1131 CAST_CONSTPTR(SubGcpCompleteRep, aSignal->getDataPtr());
1132 myNdb->theEventBuffer->execSUB_GCP_COMPLETE_REP(rep, tLen);
1133 return;
1134 }
1135 case GSN_SUB_TABLE_DATA:
1136 {
1137 const SubTableData * const sdata=
1138 CAST_CONSTPTR(SubTableData, aSignal->getDataPtr());
1139 const Uint32 oid = sdata->senderData;
1140 NdbEventOperationImpl *op= (NdbEventOperationImpl*)int2void(oid);
1141
1142 if (unlikely(op == 0 || op->m_magic_number != NDB_EVENT_OP_MAGIC_NUMBER))
1143 {
1144 g_eventLogger->error("dropped GSN_SUB_TABLE_DATA due to wrong magic "
1145 "number");
1146 return ;
1147 }
1148
1149 // Accumulate DIC_TAB_INFO for TE_ALTER events
1150 if (SubTableData::getOperation(sdata->requestInfo) ==
1151 NdbDictionary::Event::_TE_ALTER &&
1152 !op->execSUB_TABLE_DATA(aSignal, ptr))
1153 {
1154 return;
1155 }
1156
1157 LinearSectionPtr copy[3];
1158 for (int i = 0; i<aSignal->m_noOfSections; i++)
1159 {
1160 copy[i] = ptr[i];
1161 }
1162 for (int i = aSignal->m_noOfSections; i < 3; i++)
1163 {
1164 copy[i].p = NULL;
1165 copy[i].sz = 0;
1166 }
1167 DBUG_PRINT("info",("oid=senderData: %d, gci{hi/lo}: %d/%d, operation: %d, "
1168 "tableId: %d",
1169 sdata->senderData, sdata->gci_hi, sdata->gci_lo,
1170 SubTableData::getOperation(sdata->requestInfo),
1171 sdata->tableId));
1172
1173 myNdb->theEventBuffer->insertDataL(op, sdata, tLen, copy);
1174 return;
1175 }
1176 case GSN_API_REGCONF:
1177 case GSN_CONNECT_REP:
1178 {
1179 return; // Ignore
1180 }
1181 case GSN_NODE_FAILREP:
1182 {
1183 const NodeFailRep *rep = CAST_CONSTPTR(NodeFailRep,
1184 aSignal->getDataPtr());
1185 Uint32 len = NodeFailRep::getNodeMaskLength(aSignal->getLength());
1186 assert(len == NodeBitmask::Size); // only full length in ndbapi
1187 for (Uint32 i = BitmaskImpl::find_first(len, rep->theAllNodes);
1188 i != BitmaskImpl::NotFound;
1189 i = BitmaskImpl::find_next(len, rep->theAllNodes, i + 1))
1190 {
1191 if (i <= MAX_DATA_NODE_ID)
1192 {
1193 // Ndbif only cares about data-nodes (so far??)
1194 myNdb->report_node_failure(i);
1195 }
1196 }
1197
1198 NdbDictInterface::execSignal(&myNdb->theDictionary->m_receiver,
1199 aSignal,
1200 ptr);
1201 break;
1202 }
1203 case GSN_NF_COMPLETEREP:
1204 {
1205 const NFCompleteRep *rep = CAST_CONSTPTR(NFCompleteRep,
1206 aSignal->getDataPtr());
1207 myNdb->report_node_failure_completed(rep->failedNodeId);
1208 break;
1209 }
1210 case GSN_TAKE_OVERTCCONF:
1211 {
1212 myNdb->abortTransactionsAfterNodeFailure(tFirstData); // theData[0]
1213 break;
1214 }
1215 case GSN_ALLOC_NODEID_CONF:
1216 {
1217 const AllocNodeIdConf *rep = CAST_CONSTPTR(AllocNodeIdConf,
1218 aSignal->getDataPtr());
1219 Uint32 nodeId = rep->nodeId;
1220 myNdb->connected(numberToRef(myNdb->theNdbBlockNumber, nodeId));
1221 break;
1222 }
1223 default:
1224 {
1225 tFirstDataPtr = NULL;
1226 goto InvalidSignal;
1227 }
1228 }//swich
1229
1230 if (tNewState != tWaitState)
1231 {
1232 /*
1233 If our waiter object is the owner of the "poll rights", then we
1234 can simply return, we will return from this routine to the
1235 place where external_poll was called. From there it will move
1236 the "poll ownership" to a new thread if available.
1237
1238 If our waiter object doesn't own the "poll rights", then we must
1239 signal the thread from where this waiter object called
1240 its conditional wait. This will wake up this thread so that it
1241 can continue its work.
1242 */
1243 theWaiter.signal(tNewState);
1244 }
1245 return;
1246
1247 InvalidSignal:
1248 #ifdef VM_TRACE
1249 ndbout_c("Ndbif: Error NdbImpl::trp_deliver_signal "
1250 "(tFirstDataPtr=%p, GSN=%d, theWaiter.m_state=%d)"
1251 " sender = (Block: %d Node: %d)",
1252 tFirstDataPtr,
1253 tSignalNumber,
1254 tWaitState,
1255 refToBlock(aSignal->theSendersBlockRef),
1256 refToNode(aSignal->theSendersBlockRef));
1257 #endif
1258 #ifdef NDB_NO_DROPPED_SIGNAL
1259 abort();
1260 #endif
1261
1262 return;
1263 }
1264
1265 /*****************************************************************************
1266 void completedTransaction(NdbTransaction* aCon);
1267
1268 Remark: One transaction has been completed.
1269 Remove it from send array and put it into the completed
1270 transaction array. Finally check if it is time to wake
1271 up a poller.
1272 ******************************************************************************/
1273 void
completedTransaction(NdbTransaction * aCon)1274 Ndb::completedTransaction(NdbTransaction* aCon)
1275 {
1276 Uint32 tTransArrayIndex = aCon->theTransArrayIndex;
1277 Uint32 tNoSentTransactions = theNoOfSentTransactions;
1278 Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
1279 if ((tNoSentTransactions > 0) && (aCon->theListState == NdbTransaction::InSendList) &&
1280 (tTransArrayIndex < tNoSentTransactions)) {
1281 NdbTransaction* tMoveCon = theSentTransactionsArray[tNoSentTransactions - 1];
1282
1283 theCompletedTransactionsArray[tNoCompletedTransactions] = aCon;
1284 aCon->theTransArrayIndex = tNoCompletedTransactions;
1285 if (tMoveCon != aCon) {
1286 tMoveCon->theTransArrayIndex = tTransArrayIndex;
1287 theSentTransactionsArray[tTransArrayIndex] = tMoveCon;
1288 }//if
1289 theSentTransactionsArray[tNoSentTransactions - 1] = NULL;
1290 theNoOfCompletedTransactions = tNoCompletedTransactions + 1;
1291
1292 theNoOfSentTransactions = tNoSentTransactions - 1;
1293 aCon->theListState = NdbTransaction::InCompletedList;
1294 aCon->handleExecuteCompletion();
1295
1296 if (theImpl->wakeHandler == 0)
1297 {
1298 if ((theMinNoOfEventsToWakeUp != 0) &&
1299 (theNoOfCompletedTransactions >= theMinNoOfEventsToWakeUp))
1300 {
1301 theMinNoOfEventsToWakeUp = 0;
1302 theImpl->theWaiter.signal(NO_WAIT);
1303 return;
1304 }
1305 }
1306 else
1307 {
1308 /**
1309 * This is for multi-wait handling
1310 */
1311 theImpl->wakeHandler->notifyTransactionCompleted(this);
1312 }
1313 } else {
1314 ndbout << "theNoOfSentTransactions = " << (int) theNoOfSentTransactions;
1315 ndbout << " theListState = " << (int) aCon->theListState;
1316 ndbout << " theTransArrayIndex = " << aCon->theTransArrayIndex;
1317 ndbout << endl << flush;
1318 #ifdef VM_TRACE
1319 printState("completedTransaction abort");
1320 //abort();
1321 #endif
1322 }//if
1323 }//Ndb::completedTransaction()
1324
1325 /*****************************************************************************
1326 void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans);
1327
1328 Remark: Call the callback methods of the completed transactions.
1329 ******************************************************************************/
1330 void
reportCallback(NdbTransaction ** aCopyArray,Uint32 aNoOfCompletedTrans)1331 Ndb::reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans)
1332 {
1333 Uint32 i;
1334 if (aNoOfCompletedTrans > 0) {
1335 for (i = 0; i < aNoOfCompletedTrans; i++) {
1336 void* anyObject = aCopyArray[i]->theCallbackObject;
1337 NdbAsynchCallback aCallback = aCopyArray[i]->theCallbackFunction;
1338 int tResult = 0;
1339 if (aCallback != NULL) {
1340 if (aCopyArray[i]->theReturnStatus == NdbTransaction::ReturnFailure) {
1341 tResult = -1;
1342 }//if
1343 (*aCallback)(tResult, aCopyArray[i], anyObject);
1344 }//if
1345 }//for
1346 }//if
1347 }//Ndb::reportCallback()
1348
1349 /*****************************************************************************
1350 Uint32 pollCompleted(NdbTransaction** aCopyArray);
1351
1352 Remark: Transfer the data from the completed transaction to a local array.
1353 This support is used by a number of the poll-methods.
1354 ******************************************************************************/
1355 Uint32
pollCompleted(NdbTransaction ** aCopyArray)1356 Ndb::pollCompleted(NdbTransaction** aCopyArray)
1357 {
1358 check_send_timeout();
1359 Uint32 i;
1360 Uint32 tNoCompletedTransactions = theNoOfCompletedTransactions;
1361 if (tNoCompletedTransactions > 0) {
1362 for (i = 0; i < tNoCompletedTransactions; i++) {
1363 aCopyArray[i] = theCompletedTransactionsArray[i];
1364 if (aCopyArray[i]->theListState != NdbTransaction::InCompletedList) {
1365 ndbout << "pollCompleted error ";
1366 ndbout << (int) aCopyArray[i]->theListState << endl;
1367 abort();
1368 }//if
1369 theCompletedTransactionsArray[i] = NULL;
1370 aCopyArray[i]->theListState = NdbTransaction::NotInList;
1371 }//for
1372 }//if
1373 theNoOfCompletedTransactions = 0;
1374 return tNoCompletedTransactions;
1375 }//Ndb::pollCompleted()
1376
1377 void
check_send_timeout()1378 Ndb::check_send_timeout()
1379 {
1380 const Uint32 timeout = theImpl->get_ndbapi_config_parameters().m_waitfor_timeout;
1381 const Uint64 current_time = NdbTick_CurrentMillisecond();
1382 assert(current_time >= the_last_check_time);
1383 #ifndef NDEBUG
1384 if(DBUG_EVALUATE_IF("early_trans_timeout", true, false))
1385 {
1386 fprintf(stderr, "Forcing immediate timeout check in Ndb::check_send_timeout()\n");
1387 the_last_check_time = current_time - 1000 - 1;
1388 }
1389 #endif
1390 if (current_time - the_last_check_time > 1000) {
1391 the_last_check_time = current_time;
1392 Uint32 no_of_sent = theNoOfSentTransactions;
1393 for (Uint32 i = 0; i < no_of_sent; i++) {
1394 NdbTransaction* a_con = theSentTransactionsArray[i];
1395 #ifndef NDEBUG
1396 if(DBUG_EVALUATE_IF("early_trans_timeout", true, false))
1397 {
1398 fprintf(stderr, "Inducing early timeout in Ndb::check_send_timeout()\n");
1399 a_con->theStartTransTime = current_time - timeout - 1;
1400 }
1401 #endif
1402 if ((current_time - a_con->theStartTransTime) > timeout)
1403 {
1404 #ifdef VM_TRACE
1405 a_con->printState();
1406 Uint32 t1 = (Uint32) a_con->theTransactionId;
1407 Uint32 t2 = a_con->theTransactionId >> 32;
1408 ndbout_c("4012 [%.8x %.8x]", t1, t2);
1409 //abort();
1410 #endif
1411 a_con->theReleaseOnClose = true;
1412 a_con->theError.code = 4012;
1413 a_con->setOperationErrorCodeAbort(4012);
1414 a_con->theCommitStatus = NdbTransaction::NeedAbort;
1415 a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
1416 a_con->theReturnStatus = NdbTransaction::ReturnFailure;
1417 a_con->handleExecuteCompletion();
1418 remove_sent_list(i);
1419 insert_completed_list(a_con);
1420 no_of_sent--;
1421 i--;
1422 }//if
1423 }//for
1424 }//if
1425 }
1426
1427 void
remove_sent_list(Uint32 list_index)1428 Ndb::remove_sent_list(Uint32 list_index)
1429 {
1430 Uint32 last_index = theNoOfSentTransactions - 1;
1431 if (list_index < last_index) {
1432 NdbTransaction* t_con = theSentTransactionsArray[last_index];
1433 theSentTransactionsArray[list_index] = t_con;
1434 }//if
1435 theNoOfSentTransactions = last_index;
1436 theSentTransactionsArray[last_index] = 0;
1437 }
1438
1439 Uint32
insert_completed_list(NdbTransaction * a_con)1440 Ndb::insert_completed_list(NdbTransaction* a_con)
1441 {
1442 Uint32 no_of_comp = theNoOfCompletedTransactions;
1443 theCompletedTransactionsArray[no_of_comp] = a_con;
1444 theNoOfCompletedTransactions = no_of_comp + 1;
1445 a_con->theListState = NdbTransaction::InCompletedList;
1446 a_con->theTransArrayIndex = no_of_comp;
1447 return no_of_comp;
1448 }
1449
1450 Uint32
insert_sent_list(NdbTransaction * a_con)1451 Ndb::insert_sent_list(NdbTransaction* a_con)
1452 {
1453 Uint32 no_of_sent = theNoOfSentTransactions;
1454 theSentTransactionsArray[no_of_sent] = a_con;
1455 theNoOfSentTransactions = no_of_sent + 1;
1456 a_con->theListState = NdbTransaction::InSendList;
1457 a_con->theTransArrayIndex = no_of_sent;
1458 return no_of_sent;
1459 }
1460
1461 /*****************************************************************************
1462 void sendPrepTrans(int forceSend);
1463
1464 Remark: Send a batch of transactions prepared for sending to the NDB kernel.
1465 ******************************************************************************/
1466 void
sendPrepTrans(int forceSend)1467 Ndb::sendPrepTrans(int forceSend)
1468 {
1469 // Always called when holding mutex on TransporterFacade
1470 /*
1471 We will send a list of transactions to the NDB kernel. Before
1472 sending we check the following.
1473 1) Node connected to is still alive
1474 Checked by both checking node status and node sequence
1475 2) Send buffer can handle the size of messages we are planning to send
1476 So far this is just a fake check but will soon be a real check
1477 When the connected node has failed we abort the transaction without
1478 responding anymore to the node since the kernel will clean up
1479 automatically.
1480 When sendBuffer cannot handle anymore messages then we will also abort
1481 transaction but by communicating to the kernel since it is still alive
1482 and we keep a small space for messages like that.
1483 */
1484 Uint32 i;
1485 theCachedMinDbNodeVersion = theImpl->m_transporter_facade->getMinDbNodeVersion();
1486 Uint32 no_of_prep_trans = theNoOfPreparedTransactions;
1487 for (i = 0; i < no_of_prep_trans; i++) {
1488 NdbTransaction * a_con = thePreparedTransactionsArray[i];
1489 thePreparedTransactionsArray[i] = NULL;
1490 Uint32 node_id = a_con->getConnectedNodeId();
1491 if ((theImpl->getNodeSequence(node_id) == a_con->theNodeSequence) &&
1492 (theImpl->get_node_alive(node_id) || theImpl->get_node_stopping(node_id)))
1493 {
1494 /*
1495 We will send if
1496 1) Node is alive and sequences are correct OR
1497 2) Node is stopping and we only want to commit or abort
1498 In a graceful stop situation we want to ensure quick aborts
1499 of all transactions and commits and thus we allow aborts and
1500 commits to continue but not normal operations.
1501 */
1502 if (theImpl->check_send_size(node_id, a_con->get_send_size())) {
1503 if (a_con->doSend() == 0) {
1504 const Uint64 current_time = NdbTick_CurrentMillisecond();
1505 a_con->theStartTransTime = current_time;
1506 continue;
1507 } else {
1508 /*
1509 Although all precautions we did not manage to send the operations
1510 Must have been a dropped connection on the transporter side.
1511 We don't expect to be able to continue using this connection so
1512 we will treat it as a node failure.
1513 */
1514 TRACE_DEBUG("Send problem even after checking node status");
1515 }//if
1516 } else {
1517 /*
1518 The send buffer is currently full or at least close to. We will
1519 not allow a send to continue. We will set the connection so that
1520 it is indicated that we need to abort the transaction. If we were
1521 trying to commit or abort and got a send buffer we will not try
1522 again and will thus set the state to Aborted to avoid a more or
1523 less eternal loop of tries.
1524 */
1525 if (a_con->theSendStatus == NdbTransaction::sendOperations) {
1526 a_con->setOperationErrorCodeAbort(4021);
1527 a_con->theCommitStatus = NdbTransaction::NeedAbort;
1528 TRACE_DEBUG("Send buffer full and sendOperations");
1529 } else {
1530 a_con->setOperationErrorCodeAbort(4026);
1531 a_con->theCommitStatus = NdbTransaction::Aborted;
1532 TRACE_DEBUG("Send buffer full, set state to Aborted");
1533 }//if
1534 }//if
1535 } else {
1536 #ifdef VM_TRACE
1537 a_con->printState();
1538 #endif
1539 /*
1540 The node is hard dead and we cannot continue. We will also release
1541 the connection to the free pool.
1542 */
1543 TRACE_DEBUG("The node was stone dead, inform about abort");
1544 a_con->setOperationErrorCodeAbort(4025);
1545 a_con->theReleaseOnClose = true;
1546 a_con->theTransactionIsStarted = false;
1547 a_con->theCommitStatus = NdbTransaction::Aborted;
1548 }//if
1549 a_con->theReturnStatus = NdbTransaction::ReturnFailure;
1550 a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
1551 a_con->handleExecuteCompletion();
1552 insert_completed_list(a_con);
1553 }//for
1554 theNoOfPreparedTransactions = 0;
1555 int did_send = theImpl->do_forceSend(forceSend);
1556 if(forceSend) {
1557 theImpl->incClientStat(Ndb::ForcedSendsCount, 1);
1558 }
1559 else {
1560 theImpl->incClientStat(did_send ? Ndb::UnforcedSendsCount : Ndb::DeferredSendsCount, 1);
1561 }
1562 return;
1563 }//Ndb::sendPrepTrans()
1564
1565 /*****************************************************************************
1566 void waitCompletedTransactions(int aMilliSecondsToWait, int noOfEventsToWaitFor);
1567
1568 Remark: First send all prepared operations and then check if there are any
1569 transactions already completed. Do not wait for not completed
1570 transactions.
1571 ******************************************************************************/
1572 void
waitCompletedTransactions(int aMilliSecondsToWait,int noOfEventsToWaitFor,PollGuard * poll_guard)1573 Ndb::waitCompletedTransactions(int aMilliSecondsToWait,
1574 int noOfEventsToWaitFor,
1575 PollGuard *poll_guard)
1576 {
1577 theImpl->theWaiter.set_node(0);
1578 theImpl->theWaiter.set_state(WAIT_TRANS);
1579
1580 /**
1581 * theImpl->theWaiter.set_node(0)
1582 * To ensure no messup with synchronous node fail handling
1583 * (see ReportFailure)
1584 */
1585 int waitTime = aMilliSecondsToWait;
1586 const NDB_TICKS start = NdbTick_getCurrentTicks();
1587 theMinNoOfEventsToWakeUp = noOfEventsToWaitFor;
1588 theImpl->incClientStat(Ndb::WaitExecCompleteCount, 1);
1589 do {
1590 const int maxsleep = waitTime > 10 ? 10 : waitTime;
1591 poll_guard->wait_for_input(maxsleep);
1592 if (theNoOfCompletedTransactions >= (Uint32)noOfEventsToWaitFor) {
1593 break;
1594 }//if
1595 theMinNoOfEventsToWakeUp = noOfEventsToWaitFor;
1596 const NDB_TICKS now = NdbTick_getCurrentTicks();
1597 waitTime = aMilliSecondsToWait -
1598 (int)NdbTick_Elapsed(start,now).milliSec();
1599 #ifndef NDEBUG
1600 if(DBUG_EVALUATE_IF("early_trans_timeout", true, false))
1601 {
1602 fprintf(stderr, "Inducing early timeout in Ndb::waitCompletedTransactions()\n");
1603 break;
1604 }
1605 #endif
1606 } while (waitTime > 0);
1607 }//Ndb::waitCompletedTransactions()
1608
1609 /*****************************************************************************
1610 void sendPreparedTransactions(int forceSend = 0);
1611
1612 Remark: First send all prepared operations and then check if there are any
1613 transactions already completed. Do not wait for not completed
1614 transactions.
1615 ******************************************************************************/
1616 void
sendPreparedTransactions(int forceSend)1617 Ndb::sendPreparedTransactions(int forceSend)
1618 {
1619 theImpl->lock();
1620 sendPrepTrans(forceSend);
1621 theImpl->unlock();
1622 return;
1623 }//Ndb::sendPreparedTransactions()
1624
1625 /*****************************************************************************
1626 int sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup = 1, int forceSend = 0);
1627
1628 Remark: First send all prepared operations and then check if there are any
1629 transactions already completed. Wait for not completed
1630 transactions until the specified number have completed or until the
1631 timeout has occured. Timeout zero means no waiting time.
1632 ******************************************************************************/
1633 int
sendPollNdb(int aMillisecondNumber,int minNoOfEventsToWakeup,int forceSend)1634 Ndb::sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup, int forceSend)
1635 {
1636 /*
1637 The PollGuard has an implicit call of unlock_and_signal through the
1638 ~PollGuard method. This method is called implicitly by the compiler
1639 in all places where the object is out of context due to a return,
1640 break, continue or simply end of statement block
1641 */
1642 PollGuard pg(* theImpl);
1643 sendPrepTrans(forceSend);
1644 return poll_trans(aMillisecondNumber, minNoOfEventsToWakeup, &pg);
1645 }
1646
1647 int
poll_trans(int aMillisecondNumber,int minNoOfEventsToWakeup,PollGuard * pg)1648 Ndb::poll_trans(int aMillisecondNumber, int minNoOfEventsToWakeup,
1649 PollGuard *pg)
1650 {
1651 NdbTransaction* tConArray[1024];
1652 Uint32 tNoCompletedTransactions;
1653 if ((minNoOfEventsToWakeup <= 0) ||
1654 ((Uint32)minNoOfEventsToWakeup > theNoOfSentTransactions)) {
1655 minNoOfEventsToWakeup = theNoOfSentTransactions;
1656 }//if
1657 if ((theNoOfCompletedTransactions < (Uint32)minNoOfEventsToWakeup) &&
1658 (aMillisecondNumber > 0)) {
1659 waitCompletedTransactions(aMillisecondNumber, minNoOfEventsToWakeup, pg);
1660 tNoCompletedTransactions = pollCompleted(tConArray);
1661 } else {
1662 tNoCompletedTransactions = pollCompleted(tConArray);
1663 }//if
1664 theMinNoOfEventsToWakeUp = 0; // no more wakup
1665 pg->unlock_and_signal();
1666 reportCallback(tConArray, tNoCompletedTransactions);
1667 return tNoCompletedTransactions;
1668 }
1669
1670 /*****************************************************************************
1671 int pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup);
1672
1673 Remark: Check if there are any transactions already completed. Wait for not
1674 completed transactions until the specified number have completed or
1675 until the timeout has occured. Timeout zero means no waiting time.
1676 ******************************************************************************/
1677 int
pollNdb(int aMillisecondNumber,int minNoOfEventsToWakeup)1678 Ndb::pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup)
1679 {
1680 /*
1681 The PollGuard has an implicit call of unlock_and_signal through the
1682 ~PollGuard method. This method is called implicitly by the compiler
1683 in all places where the object is out of context due to a return,
1684 break, continue or simply end of statement block
1685 */
1686 PollGuard pg(* theImpl);
1687 return poll_trans(aMillisecondNumber, minNoOfEventsToWakeup, &pg);
1688 }
1689
1690 int
sendRecSignal(Uint16 node_id,Uint32 aWaitState,NdbApiSignal * aSignal,Uint32 conn_seq,Uint32 * ret_conn_seq)1691 Ndb::sendRecSignal(Uint16 node_id,
1692 Uint32 aWaitState,
1693 NdbApiSignal* aSignal,
1694 Uint32 conn_seq,
1695 Uint32 *ret_conn_seq)
1696 {
1697 /*
1698 In most situations 0 is returned.
1699 In error cases we have 5 different cases
1700 -1: Send ok, time out in waiting for reply
1701 -2: Node has failed
1702 -3: Send buffer not full, send failed yet
1703 -4: Send buffer full
1704 -5: Node is currently stopping
1705 */
1706
1707 int return_code;
1708 Uint32 read_conn_seq;
1709 Uint32 send_size = 1; // Always sends one signal only
1710 // Protected area
1711 /*
1712 The PollGuard has an implicit call of unlock_and_signal through the
1713 ~PollGuard method. This method is called implicitly by the compiler
1714 in all places where the object is out of context due to a return,
1715 break, continue or simply end of statement block
1716 */
1717 theImpl->incClientStat(WaitMetaRequestCount, 1);
1718 PollGuard poll_guard(* theImpl);
1719
1720 /**
1721 * Either we supply the correct conn_seq and ret_conn_seq == 0
1722 * or we supply conn_seq == 0 and ret_conn_seq != 0
1723 */
1724 read_conn_seq= theImpl->getNodeSequence(node_id);
1725 bool ok =
1726 (conn_seq == read_conn_seq && ret_conn_seq == 0) ||
1727 (conn_seq == 0 && ret_conn_seq != 0);
1728
1729 if (ret_conn_seq)
1730 *ret_conn_seq= read_conn_seq;
1731 if ((theImpl->get_node_alive(node_id)) && ok)
1732 {
1733 if (theImpl->check_send_size(node_id, send_size)) {
1734 return_code = theImpl->sendSignal(aSignal, node_id);
1735 if (return_code != -1) {
1736 return poll_guard.wait_n_unlock(WAITFOR_RESPONSE_TIMEOUT,node_id,
1737 aWaitState, false);
1738 } else {
1739 return_code = -3;
1740 }
1741 } else {
1742 return_code = -4;
1743 }//if
1744 } else {
1745 if ((theImpl->get_node_stopping(node_id)) && ok)
1746 {
1747 return_code = -5;
1748 } else {
1749 return_code = -2;
1750 }//if
1751 }//if
1752 return return_code;
1753 // End of protected area
1754 }//Ndb::sendRecSignal()
1755
1756 void
sendTC_COMMIT_ACK(NdbImpl * impl,NdbApiSignal * aSignal,Uint32 transId1,Uint32 transId2,Uint32 aTCRef,bool send_immediate)1757 NdbTransaction::sendTC_COMMIT_ACK(NdbImpl * impl,
1758 NdbApiSignal * aSignal,
1759 Uint32 transId1, Uint32 transId2,
1760 Uint32 aTCRef,
1761 bool send_immediate)
1762 {
1763 #ifdef MARKER_TRACE
1764 ndbout_c("Sending TC_COMMIT_ACK(0x%.8x, 0x%.8x) to -> %d",
1765 transId1,
1766 transId2,
1767 refToNode(aTCRef));
1768 #endif
1769 aSignal->theTrace = TestOrd::TraceAPI;
1770 aSignal->theReceiversBlockNumber = refToBlock(aTCRef);
1771 aSignal->theVerId_signalNumber = GSN_TC_COMMIT_ACK;
1772 aSignal->theLength = 2;
1773
1774 Uint32 * dataPtr = aSignal->getDataPtrSend();
1775 dataPtr[0] = transId1;
1776 dataPtr[1] = transId2;
1777 if (likely(!send_immediate))
1778 {
1779 impl->safe_noflush_sendSignal(aSignal, refToNode(aTCRef));
1780 }
1781 else
1782 {
1783 /**
1784 * To protect against TC_COMMIT_ACK being raced by DUMP_STATE_ORD
1785 * we route TC_COMMIT_ACK through the same path as DUMP_STATE_ORD.
1786 */
1787 dataPtr[2] = aTCRef;
1788 aSignal->theLength = 3;
1789 aSignal->theReceiversBlockNumber = CMVMI;
1790 impl->safe_sendSignal(aSignal, refToNode(aTCRef));
1791 }
1792 }
1793
set_TC_COMMIT_ACK_immediate(bool flag)1794 void NdbImpl::set_TC_COMMIT_ACK_immediate(bool flag)
1795 {
1796 send_TC_COMMIT_ACK_immediate_flag = flag;
1797 }
1798
1799 int
send_dump_state_all(Uint32 * dumpStateCodeArray,Uint32 len)1800 NdbImpl::send_dump_state_all(Uint32 *dumpStateCodeArray,
1801 Uint32 len)
1802 {
1803 NdbApiSignal aSignal(m_ndb.theMyRef);
1804 init_dump_state_signal(&aSignal, dumpStateCodeArray, len);
1805 return send_to_nodes(&aSignal, false, true);
1806 }
1807
1808 void
init_dump_state_signal(NdbApiSignal * aSignal,Uint32 * dumpStateCodeArray,Uint32 len)1809 NdbImpl::init_dump_state_signal(NdbApiSignal *aSignal,
1810 Uint32 *dumpStateCodeArray,
1811 Uint32 len)
1812 {
1813 Uint32 *theData = aSignal->getDataPtrSend();
1814 aSignal->theTrace = TestOrd::TraceAPI;
1815 aSignal->theReceiversBlockNumber = CMVMI;
1816 aSignal->theVerId_signalNumber = GSN_DUMP_STATE_ORD;
1817 aSignal->theLength = len;
1818 for (Uint32 i = 0; i < 25; i++)
1819 {
1820 if (i < len)
1821 {
1822 theData[i] = dumpStateCodeArray[i];
1823 }
1824 else
1825 {
1826 theData[i] = 0;
1827 }
1828 }
1829 }
1830
1831 int
send_event_report(bool is_poll_owner,Uint32 * data,Uint32 length)1832 NdbImpl::send_event_report(bool is_poll_owner,
1833 Uint32 *data, Uint32 length)
1834 {
1835 NdbApiSignal aSignal(m_ndb.theMyRef);
1836 aSignal.theTrace = TestOrd::TraceAPI;
1837 aSignal.theReceiversBlockNumber = CMVMI;
1838 aSignal.theVerId_signalNumber = GSN_EVENT_REP;
1839 aSignal.theLength = length;
1840 memcpy((char *)aSignal.getDataPtrSend(), (char *)data, length*4);
1841
1842 return send_to_nodes(&aSignal, is_poll_owner, false);
1843 }
1844
1845 /**
1846 * Return 0 to indicate success, 1 means no successful send.
1847 * If send_to_all is true success means successfully sent to
1848 * all nodes.
1849 */
1850 int
send_to_nodes(NdbApiSignal * aSignal,bool is_poll_owner,bool send_to_all)1851 NdbImpl::send_to_nodes(NdbApiSignal *aSignal,
1852 bool is_poll_owner,
1853 bool send_to_all)
1854 {
1855 int ret;
1856 Uint32 tNode;
1857
1858 if (!is_poll_owner)
1859 {
1860 /**
1861 * NdbImpl inherits from trp_client and this object needs to be locked
1862 * before we can send to a node. If we call this when we are poll owner
1863 * we need not lock anything more.
1864 */
1865 lock();
1866 }
1867 Ndb_cluster_connection_node_iter node_iter;
1868 m_ndb_cluster_connection.init_get_next_node(node_iter);
1869 while ((tNode= m_ndb_cluster_connection.get_next_node(node_iter)))
1870 {
1871 if (send_to_node(aSignal, tNode, is_poll_owner) == 0)
1872 {
1873 /* Successful send */
1874 if (!send_to_all)
1875 {
1876 ret = 0;
1877 goto done;
1878 }
1879 }
1880 else if (send_to_all)
1881 {
1882 ret = 1;
1883 goto done;
1884 }
1885 }
1886 if (send_to_all)
1887 {
1888 ret = 0;
1889 }
1890 else
1891 {
1892 ret = 1;
1893 }
1894 done:
1895 if (!is_poll_owner)
1896 {
1897 flush_send_buffers();
1898 unlock();
1899 }
1900 return ret;
1901 }
1902
1903 /**
1904 * Return 0 to indicate success, nonzero means no success.
1905 */
1906 int
send_to_node(NdbApiSignal * aSignal,Uint32 tNode,bool is_poll_owner)1907 NdbImpl::send_to_node(NdbApiSignal *aSignal,
1908 Uint32 tNode,
1909 bool is_poll_owner)
1910 {
1911 int ret_code = 1;
1912 if (get_node_alive(tNode))
1913 {
1914 if (is_poll_owner)
1915 {
1916 ret_code = safe_sendSignal(aSignal, tNode);
1917 }
1918 else
1919 {
1920 ret_code = raw_sendSignal(aSignal, tNode);
1921 }
1922 }
1923 return ret_code;
1924 }
1925