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