1 /*
2    Copyright (c) 2003, 2015, 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 #ifndef DBUG_OFF
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 DBUG_OFF
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 DBUG_OFF
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 DBUG_OFF
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 DBUG_OFF
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