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