~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

Viewing changes to storage/ndb/src/ndbapi/Ndbif.cpp

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
173
NdbImpl::trp_deliver_signal(const NdbApiSignal * aSignal,
 
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
{
 
210
  /**
 
211
   * We can only set the state here since this object can execute 
 
212
   * simultaneously. 
 
213
   * 
 
214
   * This method is only called by ClusterMgr (via lots of methods)
 
215
   */
 
216
 
 
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 {
 
442
        /**
 
443
         * This is ok as transaction can have been aborted before TRANSID_AI
 
444
         * arrives (if TUP on  other node than TC)
 
445
         */
 
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 {
 
882
      /**
 
883
       * This is ok as transaction can have been aborted before KEYINFO20
 
884
       * arrives (if TUP on  other node than TC)
 
885
       */
 
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
 
 
1269
  /**
 
1270
   * theImpl->theWaiter.set_node(0)
 
1271
   * To ensure no messup with synchronous node fail handling
 
1272
   * (see ReportFailure)
 
1273
   */
 
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    
 
1298
Ndb::sendPreparedTransactions(int forceSend)
 
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;
 
1469
  Ndb_cluster_connection_node_iter node_iter;
 
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
 
 
1492
NdbTransaction*
 
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
}