2
Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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.
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.
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
19
#include <ndb_global.h>
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>
38
#include <ndb_limits.h>
42
#include <EventLogger.hpp>
44
/******************************************************************************
45
* int init( int aNrOfCon, int aNrOfOp );
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
****************************************************************************/
54
Ndb::init(int aMaxNoOfTransactions)
56
DBUG_ENTER("Ndb::init");
61
int tMaxNoOfTransactions;
62
NdbApiSignal* tSignal[16]; // Initiate free list of 16 signal objects
63
if (theInitState != NotInitialised) {
74
theInitState = StartingInit;
75
TransporterFacade * theFacade = theImpl->m_transporter_facade;
76
theEventBuffer->m_mutex = theFacade->theMutexPtr;
78
const Uint32 tRef = theImpl->open(theFacade);
83
DBUG_RETURN(-1); // no more free blocknumbers
86
Uint32 nodeId = refToNode(tRef);
87
theNdbBlockNumber = refToBlock(tRef);
91
connected(Uint32(tRef));
94
/* Init cached min node version */
95
theFacade->lock_mutex();
96
theCachedMinDbNodeVersion = theFacade->getMinDbNodeVersion();
97
theFacade->unlock_mutex();
99
theDictionary->setTransporter(this, theFacade);
101
aNrOfCon = theImpl->theNoOfDBnodes;
102
aNrOfOp = 2*theImpl->theNoOfDBnodes;
104
// Create connection object in a linked list
105
if((createConIdleList(aNrOfCon)) == -1){
106
theError.code = 4000;
110
// Create operations in a linked list
111
if((createOpIdleList(aNrOfOp)) == -1){
112
theError.code = 4000;
117
tMaxNoOfTransactions = aMaxNoOfTransactions;
118
theMaxNoOfTransactions = tMaxNoOfTransactions;
119
theRemainingStartTransactions= tMaxNoOfTransactions;
120
thePreparedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
121
theSentTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
122
theCompletedTransactionsArray = new NdbTransaction* [tMaxNoOfTransactions];
124
if ((thePreparedTransactionsArray == NULL) ||
125
(theSentTransactionsArray == NULL) ||
126
(theCompletedTransactionsArray == NULL)) {
130
for (i = 0; i < tMaxNoOfTransactions; i++) {
131
thePreparedTransactionsArray[i] = NULL;
132
theSentTransactionsArray[i] = NULL;
133
theCompletedTransactionsArray[i] = NULL;
135
for (i = 0; i < 16; i++){
136
tSignal[i] = getSignal();
137
if(tSignal[i] == NULL) {
138
theError.code = 4000;
142
for (i = 0; i < 16; i++)
143
releaseSignal(tSignal[i]);
144
theInitState = Initialised;
149
ndbout << "error_handler" << endl;
150
releaseTransactionArrays();
151
delete theDictionary;
157
Ndb::releaseTransactionArrays()
159
DBUG_ENTER("Ndb::releaseTransactionArrays");
160
if (thePreparedTransactionsArray != NULL) {
161
delete [] thePreparedTransactionsArray;
163
if (theSentTransactionsArray != NULL) {
164
delete [] theSentTransactionsArray;
166
if (theCompletedTransactionsArray != NULL) {
167
delete [] theCompletedTransactionsArray;
170
}//Ndb::releaseTransactionArrays()
173
NdbImpl::trp_deliver_signal(const NdbApiSignal * aSignal,
174
const LinearSectionPtr ptr[3])
176
m_ndb.handleReceivedSignal(aSignal, ptr);
179
void Ndb::connected(Uint32 ref)
181
// cluster connect, a_node == own reference
183
Uint32 tmpTheNode= refToNode(ref);
184
Uint64 tBlockNo= refToBlock(ref);
185
if (theNdbBlockNumber >= 0){
186
assert(theMyRef == numberToRef(theNdbBlockNumber, tmpTheNode));
190
theImpl->m_ndb_cluster_connection.get_db_nodes(theImpl->theDBnodes);
191
theImpl->theNoOfDBnodes = cnt;
193
theFirstTransId += ((Uint64)tBlockNo << 52)+
194
((Uint64)tmpTheNode << 40);
196
DBUG_PRINT("info",("connected with ref=%x, id=%d, no_db_nodes=%d, first_trans_id: 0x%lx",
199
theImpl->theNoOfDBnodes,
200
(long) theFirstTransId));
201
theCommitAckSignal = new NdbApiSignal(theMyRef);
203
theDictionary->m_receiver.m_reference= theMyRef;
204
theNode= tmpTheNode; // flag that Ndb object is initialized
208
Ndb::report_node_failure(Uint32 node_id)
211
* We can only set the state here since this object can execute
214
* This method is only called by ClusterMgr (via lots of methods)
217
theImpl->the_release_ind[node_id] = 1;
219
theImpl->the_release_ind[0] = 1;
220
theImpl->theWaiter.nodeFail(node_id);
222
}//Ndb::report_node_failure()
226
Ndb::report_node_failure_completed(Uint32 node_id)
231
// eventOperations in the ndb object should be notified
232
theEventBuffer->report_node_failure_completed(node_id);
235
abortTransactionsAfterNodeFailure(node_id);
237
}//Ndb::report_node_failure_completed()
239
/***************************************************************************
240
void abortTransactionsAfterNodeFailure();
242
Remark: Abort all transactions in theSentTransactionsArray after connection
243
to one node has failed
244
****************************************************************************/
246
Ndb::abortTransactionsAfterNodeFailure(Uint16 aNodeId)
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) {
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.
261
localCon->setOperationErrorCodeAbort(4010);
262
localCon->theCompletionStatus = NdbTransaction::CompletedFailure;
263
} else if (sendStatus == NdbTransaction::sendTC_ROLLBACK) {
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.
268
localCon->theCompletionStatus = NdbTransaction::CompletedSuccess;
271
printState("abortTransactionsAfterNodeFailure %lx", (long)this);
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.
280
localCon->theReturnStatus = NdbTransaction::ReturnFailure;
281
localCon->theCommitStatus = NdbTransaction::Aborted;
282
localCon->theReleaseOnClose = true;
283
completedTransaction(localCon);
285
else if(localCon->report_node_failure(aNodeId))
287
completedTransaction(localCon);
291
}//Ndb::abortTransactionsAfterNodeFailure()
293
/****************************************************************************
294
void handleReceivedSignal(NdbApiSignal* aSignal);
296
Parameters: aSignal: The signal object.
297
Remark: Send all operations belonging to this connection.
298
*****************************************************************************/
300
Ndb::handleReceivedSignal(const NdbApiSignal* aSignal,
301
const LinearSectionPtr ptr[3])
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;
316
/* Update cached Min Db node version */
317
theCachedMinDbNodeVersion = theImpl->m_transporter_facade->getMinDbNodeVersion();
319
if (likely(NdbImpl::recordGSN(tSignalNumber)))
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)));
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
335
All signals received by the API requires the first data word to be such
336
an id to the receiving object.
339
switch (tSignalNumber){
343
const TcKeyConf * const keyConf = (TcKeyConf *)tDataPtr;
344
if (tFirstData != RNIL)
346
tFirstDataPtr = int2void(tFirstData);
347
if (tFirstDataPtr == 0) goto InvalidSignal;
348
tCon = void2con(tFirstDataPtr);
352
tCon = lookupTransactionFromOperation(keyConf);
354
const BlockReference aTCRef = aSignal->theSendersBlockRef;
356
if ((tCon->checkMagicNumber() == 0) &&
357
(tCon->theSendStatus == NdbTransaction::sendTC_OP)) {
358
tReturnCode = tCon->receiveTCKEYCONF(keyConf, tLen);
359
if (tReturnCode != -1) {
360
completedTransaction(tCon);
363
if(TcKeyConf::getMarkerFlag(keyConf->confInfo)){
364
NdbTransaction::sendTC_COMMIT_ACK(theImpl,
377
case GSN_TRANSID_AI:{
378
tFirstDataPtr = int2void(tFirstData);
380
NdbReceiver* const tRec = void2rec(tFirstDataPtr);
381
if(!tRec->checkMagicNumber()){
384
tCon = tRec->getTransaction();
386
tCon->checkState_TransId(((const TransIdAI*)tDataPtr)->transId)){
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);
393
com = tRec->execTRANSID_AI(ptr[0].p, ptr[0].sz);
396
assert(tRec->getType()!=NdbReceiver::NDB_QUERY_OPERATION);
397
com = tRec->execTRANSID_AI(tDataPtr + TransIdAI::HeaderLength,
398
tLen - TransIdAI::HeaderLength);
402
tCon->theNdb->theImpl->incClientStat(Ndb::ReadRowCount, 1);
403
if (refToNode(aSignal->theSendersBlockRef) == tCon->theDBnode)
404
tCon->theNdb->theImpl->incClientStat(Ndb::TransLocalReadRowCount,1);
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);
417
case NdbReceiver::NDB_SCANRECEIVER:
418
tCon->theScanningOp->receiver_delivered(tRec);
419
tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
420
(Uint32) NO_WAIT : tWaitState);
422
case NdbReceiver::NDB_QUERY_OPERATION:
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);
431
if (tCon->OpCompleteSuccess() != -1) { //More completions pending?
432
completedTransaction(tCon);
443
* This is ok as transaction can have been aborted before TRANSID_AI
444
* arrives (if TUP on other node than TC)
448
} else{ // if((tFirstDataPtr)
452
case GSN_TCKEY_FAILCONF:
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);
460
if (tOp->checkMagicNumber(false) == 0) {
461
tCon = tOp->theNdbCon;
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);
474
ndbout_c("Recevied TCKEY_FAILCONF wo/ operation");
478
NdbTransaction::sendTC_COMMIT_ACK(theImpl,
486
case GSN_TCKEY_FAILREF:
488
tFirstDataPtr = int2void(tFirstData);
489
if(tFirstDataPtr != 0){
490
tOp = void2rec_op(tFirstDataPtr);
491
if (tOp->checkMagicNumber(false) == 0) {
492
tCon = tOp->theNdbCon;
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);
506
ndbout_c("Recevied TCKEY_FAILREF wo/ operation");
513
tFirstDataPtr = int2void(tFirstData);
514
if (tFirstDataPtr == 0) goto InvalidSignal;
516
const NdbReceiver* const receiver = void2rec(tFirstDataPtr);
517
if(!receiver->checkMagicNumber()){
520
tCon = receiver->getTransaction();
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);
532
tOp = void2rec_op(tFirstDataPtr);
533
/* NB! NdbOperation::checkMagicNumber() returns 0 if it *is*
535
assert(tOp->checkMagicNumber()==0);
536
tReturnCode = tOp->receiveTCKEYREF(aSignal);
537
if (tReturnCode != -1) {
538
completedTransaction(tCon);
548
case GSN_TC_COMMITCONF:
550
tFirstDataPtr = int2void(tFirstData);
551
if (tFirstDataPtr == 0) goto InvalidSignal;
553
const TcCommitConf * const commitConf = (TcCommitConf *)tDataPtr;
554
const BlockReference aTCRef = aSignal->theSendersBlockRef;
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);
565
NdbTransaction::sendTC_COMMIT_ACK(theImpl,
567
commitConf->transId1,
568
commitConf->transId2,
577
case GSN_TC_COMMITREF:
579
tFirstDataPtr = int2void(tFirstData);
580
if (tFirstDataPtr == 0) goto InvalidSignal;
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);
592
case GSN_TCROLLBACKCONF:
594
tFirstDataPtr = int2void(tFirstData);
595
if (tFirstDataPtr == 0) goto InvalidSignal;
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);
607
case GSN_TCROLLBACKREF:
609
tFirstDataPtr = int2void(tFirstData);
610
if (tFirstDataPtr == 0) goto InvalidSignal;
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);
622
case GSN_TCROLLBACKREP:
624
tFirstDataPtr = int2void(tFirstData);
625
if (tFirstDataPtr == 0) goto InvalidSignal;
627
tCon = void2con(tFirstDataPtr);
628
if (tCon->checkMagicNumber() == 0) {
629
tReturnCode = tCon->receiveTCROLLBACKREP(aSignal);
630
if (tReturnCode != -1) {
631
completedTransaction(tCon);
636
case GSN_TCSEIZECONF:
638
tFirstDataPtr = int2void(tFirstData);
639
if (tFirstDataPtr == 0) goto InvalidSignal;
641
if (tWaitState != WAIT_TC_SEIZE) {
644
tCon = void2con(tFirstDataPtr);
645
if (tCon->checkMagicNumber() != 0) {
648
tReturnCode = tCon->receiveTCSEIZECONF(aSignal);
649
if (tReturnCode != -1) {
658
tFirstDataPtr = int2void(tFirstData);
659
if (tFirstDataPtr == 0) goto InvalidSignal;
661
if (tWaitState != WAIT_TC_SEIZE) {
664
tCon = void2con(tFirstDataPtr);
665
if (tCon->checkMagicNumber() != 0) {
668
tReturnCode = tCon->receiveTCSEIZEREF(aSignal);
669
if (tReturnCode != -1) {
676
case GSN_TCRELEASECONF:
678
tFirstDataPtr = int2void(tFirstData);
679
if (tFirstDataPtr == 0) goto InvalidSignal;
681
if (tWaitState != WAIT_TC_RELEASE) {
684
tCon = void2con(tFirstDataPtr);
685
if (tCon->checkMagicNumber() != 0) {
688
tReturnCode = tCon->receiveTCRELEASECONF(aSignal);
689
if (tReturnCode != -1) {
694
case GSN_TCRELEASEREF:
696
tFirstDataPtr = int2void(tFirstData);
697
if (tFirstDataPtr == 0) goto InvalidSignal;
699
if (tWaitState != WAIT_TC_RELEASE) {
702
tCon = void2con(tFirstDataPtr);
703
if (tCon->checkMagicNumber() != 0) {
706
tReturnCode = tCon->receiveTCRELEASEREF(aSignal);
707
if (tReturnCode != -1) {
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,
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,
763
case GSN_SUB_GCP_COMPLETE_REP:
765
const SubGcpCompleteRep * const rep=
766
CAST_CONSTPTR(SubGcpCompleteRep, aSignal->getDataPtr());
767
theEventBuffer->execSUB_GCP_COMPLETE_REP(rep, tLen);
770
case GSN_SUB_TABLE_DATA:
772
const SubTableData * const sdata=
773
CAST_CONSTPTR(SubTableData, aSignal->getDataPtr());
774
const Uint32 oid = sdata->senderData;
775
NdbEventOperationImpl *op= (NdbEventOperationImpl*)int2void(oid);
777
if (unlikely(op == 0 || op->m_magic_number != NDB_EVENT_OP_MAGIC_NUMBER))
779
g_eventLogger->error("dropped GSN_SUB_TABLE_DATA due to wrong magic "
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))
790
LinearSectionPtr copy[3];
791
for (int i = 0; i<aSignal->m_noOfSections; i++)
795
for (int i = aSignal->m_noOfSections; i < 3; i++)
800
DBUG_PRINT("info",("oid=senderData: %d, gci{hi/lo}: %d/%d, operation: %d, "
802
sdata->senderData, sdata->gci_hi, sdata->gci_lo,
803
SubTableData::getOperation(sdata->requestInfo),
806
theEventBuffer->insertDataL(op, sdata, tLen, copy);
809
case GSN_SCAN_TABCONF:
811
tFirstDataPtr = int2void(tFirstData);
812
assert(tFirstDataPtr);
813
assert(void2con(tFirstDataPtr));
814
assert(void2con(tFirstDataPtr)->checkMagicNumber() == 0);
816
(tCon = void2con(tFirstDataPtr)) && (tCon->checkMagicNumber() == 0)){
818
if(aSignal->m_noOfSections > 0){
819
tReturnCode = tCon->receiveSCAN_TABCONF(aSignal,
820
ptr[0].p, ptr[0].sz);
823
tCon->receiveSCAN_TABCONF(aSignal,
824
tDataPtr + ScanTabConf::SignalLength,
825
tLen - ScanTabConf::SignalLength);
827
if (tReturnCode != -1 && tWaitState == WAIT_SCAN)
834
case GSN_SCAN_TABREF:
836
tFirstDataPtr = int2void(tFirstData);
837
if (tFirstDataPtr == 0) goto InvalidSignal;
839
tCon = void2con(tFirstDataPtr);
841
assert(tFirstDataPtr != 0 &&
842
void2con(tFirstDataPtr)->checkMagicNumber() == 0);
844
if (tCon->checkMagicNumber() == 0){
845
tReturnCode = tCon->receiveSCAN_TABREF(aSignal);
846
if (tReturnCode != -1 && tWaitState == WAIT_SCAN){
853
case GSN_KEYINFO20: {
854
tFirstDataPtr = int2void(tFirstData);
856
if (tFirstDataPtr && (tRec = void2rec(tFirstDataPtr)) &&
857
tRec->checkMagicNumber() && (tCon = tRec->getTransaction()) &&
858
tCon->checkState_TransId(&((const KeyInfo20*)tDataPtr)->transId1)){
860
Uint32 len = ((const KeyInfo20*)tDataPtr)->keyLen;
861
Uint32 info = ((const KeyInfo20*)tDataPtr)->scanInfo_Node;
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);
871
tCon->theScanningOp->receiver_delivered(tRec);
872
tNewState = (((WaitSignalType) tWaitState) == WAIT_SCAN ?
873
(Uint32) NO_WAIT : tWaitState);
883
* This is ok as transaction can have been aborted before KEYINFO20
884
* arrives (if TUP on other node than TC)
890
tFirstDataPtr = int2void(tFirstData);
891
if (tFirstDataPtr == 0) goto InvalidSignal;
893
tIndexOp = void2rec_iop(tFirstDataPtr);
894
if (tIndexOp->checkMagicNumber() == 0) {
895
tCon = tIndexOp->theNdbCon;
897
if (tCon->theSendStatus == NdbTransaction::sendTC_OP) {
898
tReturnCode = tIndexOp->receiveTCINDXREF(aSignal);
899
if (tReturnCode != -1) {
900
completedTransaction(tCon);
909
case GSN_API_REGCONF:
910
case GSN_CONNECT_REP:
912
case GSN_NODE_FAILREP:
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))
920
report_node_failure(i);
923
NdbDictInterface::execSignal(&theDictionary->m_receiver, aSignal, ptr);
926
case GSN_NF_COMPLETEREP:
928
const NFCompleteRep *rep = CAST_CONSTPTR(NFCompleteRep,
929
aSignal->getDataPtr());
930
report_node_failure_completed(rep->failedNodeId);
933
case GSN_TAKE_OVERTCCONF:
934
abortTransactionsAfterNodeFailure(tFirstData); // theData[0]
936
case GSN_ALLOC_NODEID_CONF:
938
const AllocNodeIdConf *rep = CAST_CONSTPTR(AllocNodeIdConf,
939
aSignal->getDataPtr());
940
Uint32 nodeId = rep->nodeId;
941
connected(numberToRef(theNdbBlockNumber, nodeId));
945
tFirstDataPtr = NULL;
949
if (tNewState != tWaitState)
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.
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.
962
t_waiter->signal(tNewState);
970
ndbout_c("Ndbif: Error Ndb::handleReceivedSignal "
971
"(tFirstDataPtr=%p, GSN=%d, theImpl->theWaiter.m_state=%d)"
972
" sender = (Block: %d Node: %d)",
976
refToBlock(aSignal->theSendersBlockRef),
977
refToNode(aSignal->theSendersBlockRef));
979
#ifdef NDB_NO_DROPPED_SIGNAL
984
}//Ndb::handleReceivedSignal()
987
/*****************************************************************************
988
void completedTransaction(NdbTransaction* aCon);
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
994
******************************************************************************/
996
Ndb::completedTransaction(NdbTransaction* aCon)
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];
1005
theCompletedTransactionsArray[tNoCompletedTransactions] = aCon;
1006
aCon->theTransArrayIndex = tNoCompletedTransactions;
1007
if (tMoveCon != aCon) {
1008
tMoveCon->theTransArrayIndex = tTransArrayIndex;
1009
theSentTransactionsArray[tTransArrayIndex] = tMoveCon;
1011
theSentTransactionsArray[tNoSentTransactions - 1] = NULL;
1012
theNoOfCompletedTransactions = tNoCompletedTransactions + 1;
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);
1024
ndbout << "theNoOfSentTransactions = " << (int) theNoOfSentTransactions;
1025
ndbout << " theListState = " << (int) aCon->theListState;
1026
ndbout << " theTransArrayIndex = " << aCon->theTransArrayIndex;
1027
ndbout << endl << flush;
1029
printState("completedTransaction abort");
1033
}//Ndb::completedTransaction()
1035
/*****************************************************************************
1036
void reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans);
1038
Remark: Call the callback methods of the completed transactions.
1039
******************************************************************************/
1041
Ndb::reportCallback(NdbTransaction** aCopyArray, Uint32 aNoOfCompletedTrans)
1044
if (aNoOfCompletedTrans > 0) {
1045
for (i = 0; i < aNoOfCompletedTrans; i++) {
1046
void* anyObject = aCopyArray[i]->theCallbackObject;
1047
NdbAsynchCallback aCallback = aCopyArray[i]->theCallbackFunction;
1049
if (aCallback != NULL) {
1050
if (aCopyArray[i]->theReturnStatus == NdbTransaction::ReturnFailure) {
1053
(*aCallback)(tResult, aCopyArray[i], anyObject);
1057
}//Ndb::reportCallback()
1059
/*****************************************************************************
1060
Uint32 pollCompleted(NdbTransaction** aCopyArray);
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
******************************************************************************/
1066
Ndb::pollCompleted(NdbTransaction** aCopyArray)
1068
check_send_timeout();
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;
1079
theCompletedTransactionsArray[i] = NULL;
1080
aCopyArray[i]->theListState = NdbTransaction::NotInList;
1083
theNoOfCompletedTransactions = 0;
1084
return tNoCompletedTransactions;
1085
}//Ndb::pollCompleted()
1088
Ndb::check_send_timeout()
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)
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);
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);
1123
Ndb::remove_sent_list(Uint32 list_index)
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;
1130
theNoOfSentTransactions = last_index;
1131
theSentTransactionsArray[last_index] = 0;
1135
Ndb::insert_completed_list(NdbTransaction* a_con)
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;
1146
Ndb::insert_sent_list(NdbTransaction* a_con)
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;
1156
/*****************************************************************************
1157
void sendPrepTrans(int forceSend);
1159
Remark: Send a batch of transactions prepared for sending to the NDB kernel.
1160
******************************************************************************/
1162
Ndb::sendPrepTrans(int forceSend)
1164
// Always called when holding mutex on TransporterFacade
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
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.
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)))
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.
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;
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.
1209
TRACE_DEBUG("Send problem even after checking node status");
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.
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");
1225
a_con->setOperationErrorCodeAbort(4026);
1226
a_con->theCommitStatus = NdbTransaction::Aborted;
1227
TRACE_DEBUG("Send buffer full, set state to Aborted");
1232
a_con->printState();
1235
The node is hard dead and we cannot continue. We will also release
1236
the connection to the free pool.
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;
1244
a_con->theReturnStatus = NdbTransaction::ReturnFailure;
1245
a_con->theCompletionStatus = NdbTransaction::CompletedFailure;
1246
a_con->handleExecuteCompletion();
1247
insert_completed_list(a_con);
1249
theNoOfPreparedTransactions = 0;
1250
theImpl->do_forceSend(forceSend);
1252
}//Ndb::sendPrepTrans()
1254
/*****************************************************************************
1255
void waitCompletedTransactions(int aMilliSecondsToWait, int noOfEventsToWaitFor);
1257
Remark: First send all prepared operations and then check if there are any
1258
transactions already completed. Do not wait for not completed
1260
******************************************************************************/
1262
Ndb::waitCompletedTransactions(int aMilliSecondsToWait,
1263
int noOfEventsToWaitFor,
1264
PollGuard *poll_guard)
1266
theImpl->theWaiter.set_node(0);
1267
theImpl->theWaiter.set_state(WAIT_TRANS);
1270
* theImpl->theWaiter.set_node(0)
1271
* To ensure no messup with synchronous node fail handling
1272
* (see ReportFailure)
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);
1281
poll_guard->wait_for_input(maxsleep);
1282
if (theNoOfCompletedTransactions >= (Uint32)noOfEventsToWaitFor) {
1285
theMinNoOfEventsToWakeUp = noOfEventsToWaitFor;
1286
waitTime = (int)(maxTime - NdbTick_CurrentMillisecond());
1287
} while (waitTime > 0);
1288
}//Ndb::waitCompletedTransactions()
1290
/*****************************************************************************
1291
void sendPreparedTransactions(int forceSend = 0);
1293
Remark: First send all prepared operations and then check if there are any
1294
transactions already completed. Do not wait for not completed
1296
******************************************************************************/
1298
Ndb::sendPreparedTransactions(int forceSend)
1301
sendPrepTrans(forceSend);
1304
}//Ndb::sendPreparedTransactions()
1306
/*****************************************************************************
1307
int sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup = 1, int forceSend = 0);
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
******************************************************************************/
1315
Ndb::sendPollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup, int forceSend)
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
1323
PollGuard pg(* theImpl);
1324
sendPrepTrans(forceSend);
1325
return poll_trans(aMillisecondNumber, minNoOfEventsToWakeup, &pg);
1329
Ndb::poll_trans(int aMillisecondNumber, int minNoOfEventsToWakeup,
1332
NdbTransaction* tConArray[1024];
1333
Uint32 tNoCompletedTransactions;
1334
if ((minNoOfEventsToWakeup <= 0) ||
1335
((Uint32)minNoOfEventsToWakeup > theNoOfSentTransactions)) {
1336
minNoOfEventsToWakeup = theNoOfSentTransactions;
1338
if ((theNoOfCompletedTransactions < (Uint32)minNoOfEventsToWakeup) &&
1339
(aMillisecondNumber > 0)) {
1340
waitCompletedTransactions(aMillisecondNumber, minNoOfEventsToWakeup, pg);
1341
tNoCompletedTransactions = pollCompleted(tConArray);
1343
tNoCompletedTransactions = pollCompleted(tConArray);
1345
theMinNoOfEventsToWakeUp = 0; // no more wakup
1346
pg->unlock_and_signal();
1347
reportCallback(tConArray, tNoCompletedTransactions);
1348
return tNoCompletedTransactions;
1351
/*****************************************************************************
1352
int pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup);
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
******************************************************************************/
1359
Ndb::pollNdb(int aMillisecondNumber, int minNoOfEventsToWakeup)
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
1367
PollGuard pg(* theImpl);
1368
return poll_trans(aMillisecondNumber, minNoOfEventsToWakeup, &pg);
1372
Ndb::sendRecSignal(Uint16 node_id,
1374
NdbApiSignal* aSignal,
1376
Uint32 *ret_conn_seq)
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
1383
-3: Send buffer not full, send failed yet
1384
-4: Send buffer full
1385
-5: Node is currently stopping
1389
Uint32 read_conn_seq;
1390
Uint32 send_size = 1; // Always sends one signal only
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
1398
theImpl->incClientStat(WaitMetaRequestCount, 1);
1399
PollGuard poll_guard(* theImpl);
1400
read_conn_seq= theImpl->getNodeSequence(node_id);
1402
*ret_conn_seq= read_conn_seq;
1403
if ((theImpl->get_node_alive(node_id)) &&
1404
((read_conn_seq == conn_seq) ||
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,
1418
if ((theImpl->get_node_stopping(node_id)) &&
1419
((read_conn_seq == conn_seq) ||
1427
// End of protected area
1428
}//Ndb::sendRecSignal()
1431
NdbTransaction::sendTC_COMMIT_ACK(NdbImpl * impl,
1432
NdbApiSignal * aSignal,
1433
Uint32 transId1, Uint32 transId2,
1436
ndbout_c("Sending TC_COMMIT_ACK(0x%.8x, 0x%.8x) to -> %d",
1441
aSignal->theTrace = TestOrd::TraceAPI;
1442
aSignal->theReceiversBlockNumber = refToBlock(aTCRef);
1443
aSignal->theVerId_signalNumber = GSN_TC_COMMIT_ACK;
1444
aSignal->theLength = 2;
1446
Uint32 * dataPtr = aSignal->getDataPtrSend();
1447
dataPtr[0] = transId1;
1448
dataPtr[1] = transId2;
1449
impl->safe_sendSignal(aSignal, refToNode(aTCRef));
1453
NdbImpl::send_event_report(bool has_lock,
1454
Uint32 *data, Uint32 length)
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);
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)))
1473
if(get_node_alive(tNode))
1476
safe_sendSignal(&aSignal, tNode);
1478
raw_sendSignal(&aSignal, tNode);
1493
Ndb::lookupTransactionFromOperation(const TcKeyConf * conf)
1495
assert(TcKeyConf::getNoOfOperations(conf->confInfo) > 0);
1496
Uint32 opPtr = conf->operations[0].apiOperationPtr;
1497
void * voidptr = int2void(opPtr);
1500
NdbReceiver* rec = void2rec(voidptr);
1503
return rec->getTransaction();