18 #include <ndb_global.h>
22 #include <AttributeHeader.hpp>
23 #include <signaldata/TcKeyConf.hpp>
24 #include <signaldata/TcIndx.hpp>
25 #include <signaldata/TcCommit.hpp>
26 #include <signaldata/TcKeyFailConf.hpp>
27 #include <signaldata/TcHbRep.hpp>
28 #include <signaldata/TcRollbackRep.hpp>
37 NdbTransaction::NdbTransaction(
Ndb* aNdb ) :
38 theSendStatus(NotInit),
39 theCallbackFunction(NULL),
40 theCallbackObject(NULL),
41 theTransArrayIndex(0),
44 theErrorOperation(NULL),
47 theFirstOpInList(NULL),
48 theLastOpInList(NULL),
49 theFirstExecOpInList(NULL),
50 theLastExecOpInList(NULL),
51 theCompletedFirstOp(NULL),
52 theCompletedLastOp(NULL),
54 theNoOfOpCompleted(0),
58 theGlobalCheckpointId(0),
59 p_latest_trans_gci(0),
60 theStatus(NotConnected),
61 theCompletionStatus(NotCompleted),
62 theCommitStatus(NotStarted),
63 theMagicNumber(0xFE11DC),
64 theTransactionIsStarted(false),
66 theReleaseOnClose(false),
69 m_firstExecQuery(NULL),
70 m_firstActiveQuery(NULL),
73 m_theFirstScanOperation(NULL),
74 m_theLastScanOperation(NULL),
75 m_firstExecutedScanOp(NULL),
78 m_scanningQuery(NULL),
79 theBuddyConPtr(0xFFFFFFFF),
82 maxPendingBlobReadBytes(~Uint32(0)),
83 maxPendingBlobWriteBytes(~Uint32(0)),
84 pendingBlobReadBytes(0),
85 pendingBlobWriteBytes(0),
86 m_theFirstLockHandle(NULL),
87 m_theLastLockHandle(NULL),
88 m_tcRef(numberToRef(DBTC, 0))
90 theListState = NotInList;
93 theId = theNdb->theImpl->theNdbObjectIdMap.map(
this);
95 #define CHECK_SZ(mask, sz) assert((sizeof(mask)/sizeof(mask[0])) == sz)
97 CHECK_SZ(m_db_nodes, NdbNodeBitmask::Size);
98 CHECK_SZ(m_failed_db_nodes, NdbNodeBitmask::Size);
106 NdbTransaction::~NdbTransaction()
108 DBUG_ENTER(
"NdbTransaction::~NdbTransaction");
109 theNdb->theImpl->theNdbObjectIdMap.unmap(theId,
this);
119 NdbTransaction::init()
121 theListState = NotInList;
122 theInUseState =
true;
123 theTransactionIsStarted =
false;
126 theFirstOpInList = NULL;
127 theLastOpInList = NULL;
129 theScanningOp = NULL;
130 m_scanningQuery = NULL;
132 theFirstExecOpInList = NULL;
133 theLastExecOpInList = NULL;
135 theCompletedFirstOp = NULL;
136 theCompletedLastOp = NULL;
138 theGlobalCheckpointId = 0;
140 theNdb->theImpl->m_ndb_cluster_connection.get_latest_trans_gci();
142 theCompletionStatus = NotCompleted;
146 theErrorOperation = NULL;
148 theReleaseOnClose =
false;
149 theSimpleState =
true;
150 theSendStatus = InitState;
151 theMagicNumber = 0x37412619;
155 m_firstExecQuery = NULL;
156 m_firstActiveQuery = NULL;
159 m_waitForReply =
true;
160 m_theFirstScanOperation = NULL;
161 m_theLastScanOperation = NULL;
162 m_firstExecutedScanOp = 0;
163 theBuddyConPtr = 0xFFFFFFFF;
166 thePendingBlobOps = 0;
167 m_theFirstLockHandle = NULL;
168 m_theLastLockHandle = NULL;
169 pendingBlobReadBytes = 0;
170 pendingBlobWriteBytes = 0;
171 if (theId == NdbObjectIdMap::InvalidId)
173 theId = theNdb->theImpl->theNdbObjectIdMap.map(
this);
174 if (theId == NdbObjectIdMap::InvalidId)
176 theError.
code = 4000;
191 NdbTransaction::setOperationErrorCode(
int error)
193 DBUG_ENTER(
"NdbTransaction::setOperationErrorCode");
205 NdbTransaction::setOperationErrorCodeAbort(
int error,
int abortOption)
207 DBUG_ENTER(
"NdbTransaction::setOperationErrorCodeAbort");
208 if (theTransactionIsStarted ==
false) {
210 }
else if ((theCommitStatus !=
Committed) &&
211 (theCommitStatus !=
Aborted)) {
224 NdbTransaction::setErrorCode(
int error)
226 DBUG_ENTER(
"NdbTransaction::setErrorCode");
227 DBUG_PRINT(
"enter", (
"error: %d, theError.code: %d", error, theError.
code));
229 if (theError.
code == 0)
230 theError.
code = error;
237 DBUG_ENTER(
"NdbTransaction::restart");
238 if(theCompletionStatus == CompletedSuccess){
239 releaseCompletedOperations();
240 releaseCompletedQueries();
242 theTransactionId = theNdb->allocate_transaction_id();
245 theCompletionStatus = NotCompleted;
246 theTransactionIsStarted =
false;
249 DBUG_PRINT(
"error",(
"theCompletionStatus != CompletedSuccess"));
259 NdbTransaction::handleExecuteCompletion()
267 if (tLastExecOp != NULL) {
268 tLastExecOp->next(theCompletedFirstOp);
269 theCompletedFirstOp = tFirstExecOp;
270 if (theCompletedLastOp == NULL)
271 theCompletedLastOp = tLastExecOp;
272 theFirstExecOpInList = NULL;
273 theLastExecOpInList = NULL;
276 theSendStatus = InitState;
293 NdbError existingTransError = theError;
295 DBUG_ENTER(
"NdbTransaction::execute");
296 DBUG_PRINT(
"enter", (
"aTypeOfExec: %d, abortOption: %d",
297 aTypeOfExec, abortOption));
300 DBUG_RETURN(executeNoBlobs(aTypeOfExec, abortOption, forceSend));
329 DBUG_PRINT(
"info", (
"Forcing operations to take execute() abortOption %d",
337 tPrepOp= theFirstOpInList;
338 while(tPrepOp != NULL)
340 DBUG_PRINT(
"info", (
"Changing abortOption from %d",
341 tPrepOp->m_abortOption));
342 tPrepOp->m_abortOption= abortOption;
343 tPrepOp= tPrepOp->next();
357 tExecType = aTypeOfExec;
358 tPrepOp = theFirstOpInList;
359 while (tPrepOp != NULL) {
360 if (tPrepOp->theError.
code == 0) {
362 NdbBlob* tBlob = tPrepOp->theBlobList;
367 firstSavedOp = tPrepOp->next();
368 lastSavedOp = theLastOpInList;
369 DBUG_PRINT(
"info", (
"Splitting ops list between %p and %p",
370 firstSavedOp, lastSavedOp));
372 theLastOpInList= tPrepOp;
374 while (tBlob != NULL) {
375 if (tBlob->preExecute(tExecType, batch) == -1)
378 if (firstTransError.
code==0)
379 firstTransError= theError;
381 tBlob = tBlob->theNext;
392 DBUG_PRINT(
"info", (
"Rejoining ops list after preExecute between %p and %p",
395 if (firstSavedOp != NULL && lastSavedOp != NULL) {
396 if (theFirstOpInList == NULL)
397 theFirstOpInList = firstSavedOp;
399 theLastOpInList->next(firstSavedOp);
400 theLastOpInList = lastSavedOp;
402 firstSavedOp= lastSavedOp= NULL;
405 tPrepOp = tPrepOp->next();
408 if (tExecType ==
Commit) {
410 while (tOp != NULL) {
411 if (tOp->theError.
code == 0) {
412 NdbBlob* tBlob = tOp->theBlobList;
413 while (tBlob != NULL) {
414 if (tBlob->preCommit() == -1)
417 if (firstTransError.
code==0)
418 firstTransError= theError;
420 tBlob = tBlob->theNext;
428 if (theCompletedFirstOp != NULL) {
429 if (tCompletedFirstOp == NULL) {
430 tCompletedFirstOp = theCompletedFirstOp;
431 tCompletedLastOp = theCompletedLastOp;
433 tCompletedLastOp->next(theCompletedFirstOp);
434 tCompletedLastOp = theCompletedLastOp;
436 theCompletedFirstOp = NULL;
437 theCompletedLastOp = NULL;
440 if (executeNoBlobs(tExecType,
449 if (firstSavedOp != NULL && lastSavedOp != NULL) {
450 DBUG_PRINT(
"info", (
"Rejoining ops list after postExecute between "
451 "%p and %p", theLastOpInList, firstSavedOp));
452 if (theFirstOpInList == NULL)
453 theFirstOpInList = firstSavedOp;
455 theLastOpInList->next(firstSavedOp);
456 theLastOpInList = lastSavedOp;
458 if (tCompletedFirstOp != NULL) {
459 tCompletedLastOp->next(theCompletedFirstOp);
460 theCompletedFirstOp = tCompletedFirstOp;
461 if (theCompletedLastOp == NULL)
462 theCompletedLastOp = tCompletedLastOp;
470 if (firstTransError.
code==0)
471 firstTransError= theError;
473 #ifdef ndb_api_crash_on_complex_blob_abort
474 assert(theFirstOpInList == NULL && theLastOpInList == NULL);
476 theFirstOpInList = theLastOpInList = NULL;
481 while (tOp != NULL) {
482 if (tOp->theError.
code == 0) {
483 NdbBlob* tBlob = tOp->theBlobList;
484 while (tBlob != NULL) {
486 if (tBlob->postExecute(tExecType) == -1)
489 if (firstTransError.
code==0)
490 firstTransError= theError;
492 tBlob = tBlob->theNext;
500 if (firstSavedOp != NULL && lastSavedOp != NULL) {
501 DBUG_PRINT(
"info", (
"Rejoining ops list after postExecute between %p and %p",
504 if (theFirstOpInList == NULL)
505 theFirstOpInList = firstSavedOp;
507 theLastOpInList->next(firstSavedOp);
508 theLastOpInList = lastSavedOp;
510 assert(theFirstOpInList == NULL || tExecType ==
NoCommit);
511 }
while (theFirstOpInList != NULL || tExecType != aTypeOfExec);
513 if (tCompletedFirstOp != NULL) {
514 tCompletedLastOp->next(theCompletedFirstOp);
515 theCompletedFirstOp = tCompletedFirstOp;
516 if (theCompletedLastOp == NULL)
517 theCompletedLastOp = tCompletedLastOp;
519 #if ndb_api_count_completed_ops_after_blob_execute
521 for (tOp = theCompletedFirstOp; tOp != NULL; tOp = tOp->next()) n++;
522 ndbout <<
"completed ops: " << n << endl;
529 if (theError.
code == 4350)
531 DBUG_PRINT(
"info", (
"Trans already aborted, existingTransError.code %u, "
532 "firstTransError.code %u",
533 existingTransError.
code,
534 firstTransError.
code));
535 if (existingTransError.
code != 0)
537 theError = existingTransError;
539 else if (firstTransError.
code != 0)
541 theError = firstTransError;
549 if (firstTransError.
code != 0)
551 DBUG_PRINT(
"info", (
"Setting error to first error. firstTransError.code = %u, "
552 "theError.code = %u",
553 firstTransError.
code,
555 theError = firstTransError;
566 DBUG_ENTER(
"NdbTransaction::executeNoBlobs");
567 DBUG_PRINT(
"enter", (
"aTypeOfExec: %d, abortOption: %d",
568 aTypeOfExec, abortOption));
580 Uint32 timeout = theNdb->theImpl->get_waitfor_timeout();
581 m_waitForReply =
false;
585 int noOfComp = tNdb->
sendPollNdb(3 * timeout, 1, forceSend);
586 if (unlikely(noOfComp == 0)) {
595 g_eventLogger->
error(
"WARNING: Timeout in executeNoBlobs() waiting for "
596 "response from NDB data nodes. This should NEVER "
597 "occur. You have likely hit a NDB Bug. Please "
599 DBUG_PRINT(
"error",(
"This timeout should never occure, execute()"));
600 g_eventLogger->
error(
"Forcibly trying to rollback txn (%p"
601 ") to try to clean up data node resources.",
604 theError.
code = 4012;
607 setOperationErrorCodeAbort(4012);
616 if (theListState != NotInList)
620 for (
unsigned i = 0;
i < theNdb->theNoOfPreparedTransactions;
i++)
621 anyway += theNdb->thePreparedTransactionsArray[
i] ==
this;
622 for (
unsigned i = 0;
i < theNdb->theNoOfSentTransactions;
i++)
623 anyway += theNdb->theSentTransactionsArray[
i] ==
this;
624 for (
unsigned i = 0;
i < theNdb->theNoOfCompletedTransactions;
i++)
625 anyway += theNdb->theCompletedTransactionsArray[
i] ==
this;
627 theNdb->printState(
"execute %lx", (
long)
this);
631 if (theReturnStatus == ReturnFailure) {
637 thePendingBlobOps = 0;
638 pendingBlobReadBytes = 0;
639 pendingBlobWriteBytes = 0;
650 while (current != NULL && current->
getQueryDef().isScanQuery()) {
664 while (current != NULL) {
690 NdbAsynchCallback aCallback,
694 DBUG_ENTER(
"NdbTransaction::executeAsynchPrepare");
695 DBUG_PRINT(
"enter", (
"aTypeOfExec: %d, aCallback: 0x%lx, anyObject: Ox%lx",
696 aTypeOfExec, (
long) aCallback, (
long) anyObject));
702 if (theError.
code != 0)
703 DBUG_PRINT(
"enter", (
"Resetting error %d on execute", theError.
code));
709 theNdb->theImpl->incClientStat(Ndb::TransCommitCount, 1);
712 theNdb->theImpl->incClientStat(Ndb::TransAbortCount, 1);
722 if (theError.
code != 4012)
731 releaseCompletedQueries();
737 while (tcOp != NULL) {
740 if (tReturnCode == -1) {
743 tcOp->postExecuteRelease();
747 m_theLastScanOperation->next(m_firstExecutedScanOp);
748 m_firstExecutedScanOp = m_theFirstScanOperation;
752 m_theFirstScanOperation = m_theLastScanOperation = NULL;
755 bool tTransactionIsStarted = theTransactionIsStarted;
759 Uint32 tnoOfPreparedTransactions = tNdb->theNoOfPreparedTransactions;
761 theReturnStatus = ReturnSuccess;
762 theCallbackFunction = aCallback;
763 theCallbackObject = anyObject;
764 m_waitForReply =
true;
765 tNdb->thePreparedTransactionsArray[tnoOfPreparedTransactions] =
this;
766 theTransArrayIndex = tnoOfPreparedTransactions;
767 theListState = InPreparedList;
768 tNdb->theNoOfPreparedTransactions = tnoOfPreparedTransactions + 1;
771 theNoOfOpCompleted = 0;
772 NdbNodeBitmask::clear(m_db_nodes);
773 NdbNodeBitmask::clear(m_failed_db_nodes);
775 if ((tCommitStatus !=
Started) ||
783 if (theTransactionIsStarted ==
false || theSimpleState) {
785 theSendStatus = sendCompleted;
787 theSendStatus = sendABORT;
790 theSendStatus = sendABORTfail;
792 if (theCommitStatus ==
Aborted){
793 DBUG_PRINT(
"exit", (
"theCommitStatus: Aborted"));
799 NdbQueryImpl*
const lastLookupQuery = getLastLookupQuery(m_firstQuery);
801 if (tTransactionIsStarted ==
true) {
802 if (tLastOp != NULL) {
803 if (aTypeOfExec ==
Commit) {
808 tLastOp->theCommitIndicator = 1;
810 }
else if (lastLookupQuery != NULL) {
811 if (aTypeOfExec ==
Commit) {
814 }
else if (m_firstQuery == NULL) {
815 if (aTypeOfExec ==
Commit && !theSimpleState) {
820 theSendStatus = sendCOMMITstate;
832 theSendStatus = sendCompleted;
836 }
else if (tTransactionIsStarted ==
false) {
845 if (lastLookupQuery != NULL) {
847 }
else if (tFirstOp != NULL) {
848 tFirstOp->setStartIndicator();
851 if (tFirstOp != NULL) {
852 if (aTypeOfExec ==
Commit) {
853 tLastOp->theCommitIndicator = 1;
855 }
else if (lastLookupQuery != NULL) {
856 if (aTypeOfExec ==
Commit) {
859 }
else if (m_firstQuery == NULL) {
864 if (aTypeOfExec ==
Commit) {
876 theSendStatus = sendCompleted;
881 theCompletionStatus = NotCompleted;
887 while (query!=NULL) {
889 if (unlikely(tReturnCode != 0)) {
890 theSendStatus = sendABORTfail;
896 assert (m_firstExecQuery==NULL);
897 last->setNext(m_firstExecQuery);
898 m_firstExecQuery = m_firstQuery;
904 Uint32 pkOpCount = 0;
905 Uint32 ukOpCount = 0;
911 if (tOp->theTCREQ->theVerId_signalNumber == GSN_TCINDXREQ)
916 if (tOp->Status() == NdbOperation::UseNdbRecord)
917 tReturnCode = tOp->prepareSendNdbRecord(abortOption);
919 tReturnCode= tOp->
prepareSend(theTCConPtr, theTransactionId, abortOption);
921 if (tReturnCode == -1) {
922 theSendStatus = sendABORTfail;
934 theNdb->theImpl->incClientStat(Ndb::PkOpCount, pkOpCount);
935 theNdb->theImpl->incClientStat(Ndb::UkOpCount, ukOpCount);
940 theFirstOpInList = NULL;
941 theLastOpInList = NULL;
942 theFirstExecOpInList = tFirstOpInList;
943 theLastExecOpInList = tLastOpInList;
945 theCompletionStatus = CompletedSuccess;
946 theSendStatus = sendOperations;
952 NdbAsynchCallback aCallback,
974 scan_trans->sendTC_HBREP();
977 return sendTC_HBREP();
988 NdbTransaction::sendTC_HBREP()
992 Uint32 tTransId1, tTransId2;
994 tSignal = tNdb->getSignal();
995 if (tSignal == NULL) {
999 if (tSignal->setSignal(GSN_TC_HBREP, refToBlock(m_tcRef)) == -1) {
1003 TcHbRep *
const tcHbRep = CAST_PTR(
TcHbRep, tSignal->getDataPtrSend());
1005 tcHbRep->apiConnectPtr = theTCConPtr;
1007 tTransId1 = (Uint32) theTransactionId;
1008 tTransId2 = (Uint32) (theTransactionId >> 32);
1009 tcHbRep->transId1 = tTransId1;
1010 tcHbRep->transId2 = tTransId2;
1012 tNdb->theImpl->lock();
1013 const int res = tNdb->theImpl->sendSignal(tSignal,theDBnode);
1014 tNdb->theImpl->unlock();
1015 tNdb->releaseSignal(tSignal);
1034 NdbTransaction::doSend()
1036 DBUG_ENTER(
"NdbTransaction::doSend");
1042 switch(theSendStatus){
1043 case sendOperations: {
1044 assert (m_firstExecQuery!=NULL || theFirstExecOpInList!=NULL);
1047 = getLastLookupQuery(m_firstExecQuery);
1048 if (m_firstExecQuery!=NULL) {
1051 while (query!=NULL) {
1052 const bool lastFlag =
1053 query == lastLookupQuery && theFirstExecOpInList == NULL;
1054 const int tReturnCode = query->
doSend(theDBnode, lastFlag);
1055 if (tReturnCode == -1) {
1063 last->setNext(m_firstActiveQuery);
1064 m_firstActiveQuery = m_firstExecQuery;
1065 m_firstExecQuery = NULL;
1069 while (tOp != NULL) {
1071 const Uint32 lastFlag = ((tNext == NULL) ? 1 : 0);
1072 const int tReturnCode = tOp->doSend(theDBnode, lastFlag);
1073 if (tReturnCode == -1) {
1079 if (theFirstExecOpInList || lastLookupQuery != NULL) {
1080 theSendStatus = sendTC_OP;
1081 theTransactionIsStarted =
true;
1082 theNdb->insert_sent_list(
this);
1084 theSendStatus = sendCompleted;
1085 theNdb->insert_completed_list(
this);
1090 case sendABORTfail:{
1095 if (theSendStatus == sendABORTfail) {
1096 theReturnStatus = ReturnFailure;
1098 if (sendROLLBACK() == 0) {
1103 case sendCOMMITstate:
1104 if (sendCOMMIT() == 0) {
1109 theNdb->insert_completed_list(
this);
1112 ndbout <<
"Inconsistent theSendStatus = "
1113 << (Uint32) theSendStatus << endl;
1118 theReleaseOnClose =
true;
1119 theTransactionIsStarted =
false;
1122 setOperationErrorCodeAbort(4002);
1134 NdbTransaction::sendROLLBACK()
1137 if ((theTransactionIsStarted ==
true) &&
1139 (theCommitStatus !=
Aborted)) {
1145 Uint32 tTransId1, tTransId2;
1146 NdbImpl * impl = theNdb->theImpl;
1149 tTransId1 = (Uint32) theTransactionId;
1150 tTransId2 = (Uint32) (theTransactionId >> 32);
1151 tSignal.setSignal(GSN_TCROLLBACKREQ, refToBlock(m_tcRef));
1152 tSignal.setData(theTCConPtr, 1);
1153 tSignal.setData(tTransId1, 2);
1154 tSignal.setData(tTransId2, 3);
1155 if(theError.
code == 4012)
1157 g_eventLogger->
error(
"Sending TCROLLBACKREQ with Bad flag");
1158 tSignal.setLength(tSignal.getLength() + 1);
1159 tSignal.setData(0x1, 4);
1161 tReturnCode = impl->sendSignal(&tSignal,theDBnode);
1162 if (tReturnCode != -1) {
1163 theSendStatus = sendTC_ROLLBACK;
1164 tNdb->insert_sent_list(
this);
1179 theSendStatus = sendCompleted;
1180 tNdb->insert_completed_list(
this);
1195 NdbTransaction::sendCOMMIT()
1198 Uint32 tTransId1, tTransId2;
1199 NdbImpl * impl = theNdb->theImpl;
1202 tTransId1 = (Uint32) theTransactionId;
1203 tTransId2 = (Uint32) (theTransactionId >> 32);
1204 tSignal.setSignal(GSN_TC_COMMITREQ, refToBlock(m_tcRef));
1205 tSignal.setData(theTCConPtr, 1);
1206 tSignal.setData(tTransId1, 2);
1207 tSignal.setData(tTransId2, 3);
1209 tReturnCode = impl->sendSignal(&tSignal,theDBnode);
1210 if (tReturnCode != -1) {
1211 theSendStatus = sendTC_COMMIT;
1212 theNdb->insert_sent_list(
this);
1225 NdbTransaction::release(){
1226 releaseOperations();
1227 releaseLockHandles();
1228 if ( (theTransactionIsStarted ==
true) &&
1230 (theCommitStatus !=
Aborted))) {
1235 if (!theSimpleState)
1240 theMagicNumber = 0xFE11DC;
1241 theInUseState =
false;
1243 if (theListState != NotInList) {
1244 theNdb->printState(
"release %lx", (
long)
this);
1252 while (tOp != NULL) {
1256 theNdb->releaseOperation(tmp);
1266 NdbTransaction::releaseOperations()
1269 releaseScanOperations(m_theFirstScanOperation);
1270 releaseScanOperations(m_firstExecutedScanOp);
1272 releaseQueries(m_firstQuery);
1273 releaseQueries(m_firstExecQuery);
1274 releaseQueries(m_firstActiveQuery);
1275 releaseOps(theCompletedFirstOp);
1276 releaseOps(theFirstOpInList);
1277 releaseOps(theFirstExecOpInList);
1279 theCompletedFirstOp = NULL;
1280 theCompletedLastOp = NULL;
1281 theFirstOpInList = NULL;
1282 theFirstExecOpInList = NULL;
1283 theLastOpInList = NULL;
1284 theLastExecOpInList = NULL;
1285 theScanningOp = NULL;
1286 m_scanningQuery = NULL;
1287 m_theFirstScanOperation = NULL;
1288 m_theLastScanOperation = NULL;
1289 m_firstExecutedScanOp = NULL;
1290 m_firstQuery = NULL;
1291 m_firstExecQuery = NULL;
1292 m_firstActiveQuery = NULL;
1297 NdbTransaction::releaseCompletedOperations()
1299 releaseOps(theCompletedFirstOp);
1300 theCompletedFirstOp = NULL;
1301 theCompletedLastOp = NULL;
1306 NdbTransaction::releaseCompletedQueries()
1313 while (query != NULL) {
1319 prev->setNext(next);
1321 m_firstActiveQuery = next;
1340 while (query != NULL) {
1356 while(cursorOp != 0){
1358 cursorOp->release();
1359 theNdb->releaseScanOperation(cursorOp);
1369 if (* listhead == op)
1372 if (listtail && *listtail == op)
1374 assert(* listhead == 0);
1384 if (tmp->theNext == op)
1387 if (listtail && *listtail == op)
1389 assert(op->theNext == 0);
1403 theNdb->releaseScanOperation(op);
1411 NdbTransaction::releaseLockHandles()
1420 theNdb->releaseLockHandle(lh);
1424 m_theFirstLockHandle = NULL;
1425 m_theLastLockHandle = NULL;
1444 if (theCommitStatus ==
Started){
1454 setOperationErrorCodeAbort(4114);
1480 if (theScanningOp != NULL || m_scanningQuery != NULL){
1485 tOp = theNdb->getOperation();
1487 goto getNdbOp_error1;
1488 if (aNextOp == NULL) {
1489 if (theLastOpInList != NULL) {
1490 theLastOpInList->next(tOp);
1491 theLastOpInList = tOp;
1493 theLastOpInList = tOp;
1494 theFirstOpInList = tOp;
1499 if (theFirstOpInList == aNextOp) {
1500 theFirstOpInList = tOp;
1503 while (aLoopOp != NULL && aLoopOp->next() != aNextOp)
1504 aLoopOp = aLoopOp->next();
1505 assert(aLoopOp != NULL);
1510 if (tOp->init(tab,
this, useRec) != -1) {
1513 theNdb->releaseOperation(tOp);
1518 setOperationErrorCodeAbort(4000);
1545 if (theCommitStatus ==
Started){
1546 NdbTableImpl* tab = theNdb->theDictionary->getTable(aTableName);
1550 setOperationErrorCodeAbort(theNdb->theDictionary->m_error.
code);
1555 setOperationErrorCodeAbort(4114);
1572 const char* aTableName)
1575 theNdb->theDictionary->getIndex(anIndexName, aTableName);
1578 setOperationErrorCodeAbort(theNdb->theDictionary->
getNdbError().
code);
1584 setOperationErrorCodeAbort(theNdb->theDictionary->
getNdbError().
code);
1595 if (theCommitStatus ==
Started){
1596 const NdbTableImpl * indexTable = index->getIndexTable();
1597 if (indexTable != 0){
1601 tOp->m_currentTable =
table;
1607 setOperationErrorCodeAbort(4271);
1612 setOperationErrorCodeAbort(4114);
1623 theNdb->theDictionary->getTable(index->
getTable());
1628 setOperationErrorCodeAbort(theNdb->theDictionary->
getNdbError().
code);
1631 setOperationErrorCodeAbort(4271);
1641 & NdbTableImpl::getImpl(*table));
1642 setOperationErrorCodeAbort(4271);
1661 tOp = theNdb->getScanOperation();
1663 goto getNdbOp_error1;
1665 if (tOp->init(tab,
this) != -1) {
1666 define_scan_op(tOp);
1671 theNdb->releaseScanOperation(tOp);
1676 setOperationErrorCodeAbort(4000);
1686 while(tmp && tmp->next() != op) tmp = tmp->next();
1688 tmp->next(op->next());
1696 if (m_theLastScanOperation == NULL)
1697 m_theFirstScanOperation = m_theLastScanOperation = tOp;
1699 m_theLastScanOperation->next(tOp);
1700 m_theLastScanOperation = tOp;
1730 const char* aTableName)
1732 if (theCommitStatus ==
Started) {
1733 NdbTableImpl * table = theNdb->theDictionary->getTable(aTableName);
1738 setOperationErrorCodeAbort(theNdb->theDictionary->
getNdbError().
code);
1742 if (table->m_frm.get_data())
1745 static const char* uniqueSuffix=
"$unique";
1747 uniqueIndexName.
append(uniqueSuffix);
1748 index = theNdb->theDictionary->getIndex(uniqueIndexName.
c_str(),
1752 index = theNdb->theDictionary->getIndex(anIndexName,
1754 if(table != 0 && index != 0){
1759 setOperationErrorCodeAbort(4243);
1763 setOperationErrorCodeAbort(4243);
1767 setOperationErrorCodeAbort(4114);
1789 tOp = theNdb->getIndexOperation();
1791 goto getNdbOp_error1;
1792 if (aNextOp == NULL) {
1793 if (theLastOpInList != NULL) {
1794 theLastOpInList->next(tOp);
1795 theLastOpInList = tOp;
1797 theLastOpInList = tOp;
1798 theFirstOpInList = tOp;
1803 if (theFirstOpInList == aNextOp) {
1804 theFirstOpInList = tOp;
1807 while (aLoopOp != NULL && aLoopOp->next() != aNextOp)
1808 aLoopOp = aLoopOp->next();
1809 assert(aLoopOp != NULL);
1814 if (tOp->indxInit(anIndex, aTable,
this, useRec)!= -1) {
1817 theNdb->releaseOperation(tOp);
1822 setOperationErrorCodeAbort(4000);
1832 theNdb->theDictionary->getTable(index->
getTable());
1837 setOperationErrorCodeAbort(theNdb->theDictionary->
getNdbError().
code);
1840 setOperationErrorCodeAbort(4271);
1850 & NdbTableImpl::getImpl(*table));
1852 setOperationErrorCodeAbort(4271);
1866 NdbTransaction::receiveTCSEIZECONF(
const NdbApiSignal* aSignal)
1868 if (theStatus != Connecting)
1873 theTCConPtr = (Uint32)aSignal->readData(2);
1874 if (aSignal->getLength() >= 3)
1876 m_tcRef = aSignal->readData(3);
1880 m_tcRef = numberToRef(DBTC, theDBnode);
1883 assert(m_tcRef == aSignal->theSendersBlockRef);
1885 theStatus = Connected;
1899 NdbTransaction::receiveTCSEIZEREF(
const NdbApiSignal* aSignal)
1901 DBUG_ENTER(
"NdbTransaction::receiveTCSEIZEREF");
1902 if (theStatus != Connecting)
1907 theStatus = ConnectFailure;
1908 theNdb->theError.
code = aSignal->readData(2);
1909 DBUG_PRINT(
"info",(
"error code %d, %s",
1925 NdbTransaction::receiveTCRELEASECONF(
const NdbApiSignal* aSignal)
1927 if (theStatus != DisConnecting)
1932 theStatus = NotConnected;
1946 NdbTransaction::receiveTCRELEASEREF(
const NdbApiSignal* aSignal)
1948 if (theStatus != DisConnecting) {
1951 theStatus = ConnectFailure;
1952 theNdb->theError.
code = aSignal->readData(2);
1966 NdbTransaction::receiveTC_COMMITCONF(
const TcCommitConf * commitConf,
1969 if(checkState_TransId(&commitConf->transId1)){
1971 theCompletionStatus = CompletedSuccess;
1972 Uint32 tGCI_hi = commitConf->gci_hi;
1973 Uint32 tGCI_lo = commitConf->gci_lo;
1974 if (unlikely(len < TcCommitConf::SignalLength))
1978 Uint64 tGCI = Uint64(tGCI_lo) | (Uint64(tGCI_hi) << 32);
1979 theGlobalCheckpointId = tGCI;
1982 *p_latest_trans_gci = tGCI;
1985 #ifdef NDB_NO_DROPPED_SIGNAL
2001 NdbTransaction::receiveTC_COMMITREF(
const NdbApiSignal* aSignal)
2004 if(checkState_TransId(&ref->transId1)){
2005 setOperationErrorCodeAbort(ref->errorCode);
2007 theCompletionStatus = CompletedFailure;
2008 theReturnStatus = ReturnFailure;
2011 #ifdef NDB_NO_DROPPED_SIGNAL
2028 NdbTransaction::receiveTCROLLBACKCONF(
const NdbApiSignal* aSignal)
2030 if(checkState_TransId(aSignal->
getDataPtr() + 1)){
2032 theCompletionStatus = CompletedSuccess;
2035 #ifdef NDB_NO_DROPPED_SIGNAL
2052 NdbTransaction::receiveTCROLLBACKREF(
const NdbApiSignal* aSignal)
2054 if(checkState_TransId(aSignal->
getDataPtr() + 1)){
2055 setOperationErrorCodeAbort(aSignal->readData(4));
2057 theCompletionStatus = CompletedFailure;
2058 theReturnStatus = ReturnFailure;
2061 #ifdef NDB_NO_DROPPED_SIGNAL
2079 NdbTransaction::receiveTCROLLBACKREP(
const NdbApiSignal* aSignal)
2081 DBUG_ENTER(
"NdbTransaction::receiveTCROLLBACKREP");
2088 if(checkState_TransId(aSignal->
getDataPtr() + 1)){
2089 theError.
code = aSignal->readData(4);
2090 if (aSignal->getLength() == TcRollbackRep::SignalLength)
2093 theError.
details = (
char *) aSignal->readData(5);
2103 theCompletionStatus = CompletedFailure;
2105 theReturnStatus = ReturnFailure;
2108 #ifdef NDB_NO_DROPPED_SIGNAL
2125 NdbTransaction::receiveTCKEYCONF(
const TcKeyConf * keyConf, Uint32 aDataLength)
2127 const Uint32 tTemp = keyConf->confInfo;
2133 if(checkState_TransId(&keyConf->transId1)){
2135 const Uint32 tNoOfOperations = TcKeyConf::getNoOfOperations(tTemp);
2136 const Uint32 tCommitFlag = TcKeyConf::getCommitFlag(tTemp);
2138 const Uint32* tPtr = (Uint32 *)&keyConf->operations[0];
2139 Uint32 tNoComp = theNoOfOpCompleted;
2140 for (Uint32
i = 0;
i < tNoOfOperations ;
i++) {
2142 theNdb->void2rec(theNdb->int2void(*tPtr++));
2143 const Uint32 tAttrInfoLen = *tPtr++;
2144 if(tReceiver && tReceiver->checkMagicNumber()){
2146 if(tReceiver->getType()==NdbReceiver::NDB_QUERY_OPERATION){
2149 ->getQuery().execTCKEYCONF();
2151 done = tReceiver->execTCOPCONF(tAttrInfoLen);
2153 if(tAttrInfoLen > TcKeyConf::DirtyReadBit){
2154 Uint32 node = tAttrInfoLen & (~
TcKeyConf::DirtyReadBit);
2155 NdbNodeBitmask::set(m_db_nodes, node);
2160 tReceiver->setErrorCode(4119);
2161 theCompletionStatus = CompletedFailure;
2162 theReturnStatus = NdbTransaction::ReturnFailure;
2170 theNoOfOpCompleted = tNoComp;
2171 const Uint32 tNoSent = theNoOfOpSent;
2172 const Uint32 tGCI_hi = keyConf->gci_hi;
2173 Uint32 tGCI_lo = * tPtr;
2174 if (unlikely(aDataLength < TcKeyConf::StaticLength+1 + 2*tNoOfOperations))
2178 const Uint64 tGCI = Uint64(tGCI_lo) | (Uint64(tGCI_hi) << 32);
2179 if (tCommitFlag == 1)
2182 theGlobalCheckpointId = tGCI;
2185 *p_latest_trans_gci = tGCI;
2188 else if (theLastExecOpInList &&
2189 theLastExecOpInList->theCommitIndicator == 1)
2196 if (tNoComp >= tNoSent)
2202 #ifdef NDB_NO_DROPPED_SIGNAL
2220 NdbTransaction::receiveTCKEY_FAILCONF(
const TcKeyFailConf * failConf)
2228 if(checkState_TransId(&failConf->transId1)){
2234 tOp = theFirstExecOpInList;
2235 while (tOp != NULL) {
2241 switch(tOp->theOperationType){
2247 case NdbOperation::RefreshRequest:
2254 theCompletionStatus = CompletedFailure;
2255 theReturnStatus = NdbTransaction::ReturnFailure;
2256 setOperationErrorCodeAbort(4115);
2265 theReleaseOnClose =
true;
2269 ndbout_c(
"Recevied TCKEY_FAILCONF wo/ operation");
2285 NdbTransaction::receiveTCKEY_FAILREF(
const NdbApiSignal* aSignal)
2292 if(checkState_TransId(aSignal->
getDataPtr()+1)){
2297 if (theSendStatus == NdbTransaction::sendTC_ROLLBACK) {
2302 theCompletionStatus = NdbTransaction::CompletedSuccess;
2304 theReturnStatus = NdbTransaction::ReturnFailure;
2305 theCompletionStatus = NdbTransaction::CompletedFailure;
2306 theError.
code = 4031;
2308 theReleaseOnClose =
true;
2313 ndbout_c(
"Recevied TCKEY_FAILREF wo/ operation");
2327 NdbTransaction::OpCompleteFailure()
2329 Uint32 tNoComp = theNoOfOpCompleted;
2330 Uint32 tNoSent = theNoOfOpSent;
2333 theNoOfOpCompleted = tNoComp;
2335 return (tNoComp == tNoSent) ? 0 : -1;
2346 NdbTransaction::OpCompleteSuccess()
2348 Uint32 tNoComp = theNoOfOpCompleted;
2349 Uint32 tNoSent = theNoOfOpSent;
2351 theNoOfOpCompleted = tNoComp;
2353 ndbout <<
"NdbTransaction::OpCompleteSuccess() tNoComp=" << tNoComp
2354 <<
" tNoSent=" << tNoSent << endl;
2356 if (tNoComp == tNoSent) {
2358 }
else if (tNoComp < tNoSent) {
2361 setOperationErrorCodeAbort(4113);
2363 theCompletionStatus = NdbTransaction::CompletedFailure;
2364 theReturnStatus = NdbTransaction::ReturnFailure;
2380 return (
int)(val >> 32);
2392 * val = theGlobalCheckpointId;
2407 return theTransactionId;
2413 return theCommitStatus;
2419 return theErrorLine;
2425 return theErrorOperation;
2432 return theErrorOperation;
2439 return theCompletedFirstOp;
2440 return current->theNext;
2448 const char *key_row,
2450 const char *attribute_row,
2451 const unsigned char *mask,
2453 Uint32 sizeOfOptions,
2459 if (attribute_record->flags & NdbRecord::RecIsIndex)
2463 setOperationErrorCodeAbort(4340);
2473 if (key_record->flags & NdbRecord::RecIsIndex)
2476 attribute_record->table, NULL,
true);
2480 if (key_record->tableId != attribute_record->tableId)
2482 setOperationErrorCodeAbort(4287);
2490 op->theStatus= NdbOperation::UseNdbRecord;
2491 op->theOperationType=
type;
2493 op->theLockMode= lock_mode;
2494 op->m_key_record= key_record;
2495 op->m_key_row= key_row;
2496 op->m_attribute_record= attribute_record;
2497 op->m_attribute_row= attribute_row;
2498 op->m_abortOption=default_ao;
2502 attribute_record->copyMask(readMask.rep.data, mask);
2510 Uint32 result = NdbOperation::handleOperationOptions (type,
2516 setOperationErrorCodeAbort(result);
2523 (attribute_record->flags & NdbRecord::RecTableHasBlob))
2529 if (op->getBlobHandlesNdbRecordDelete(
this,
2530 (attribute_row != NULL),
2531 readMask.rep.data) == -1)
2534 else if (unlikely((attribute_record->flags & NdbRecord::RecHasBlob) &&
2538 if (op->getBlobHandlesNdbRecord(
this, readMask.rep.data) == -1)
2546 int returnCode=op->buildSignalsNdbRecord(theTCConPtr, theTransactionId,
2562 NdbTransaction::readTuple(
const NdbRecord *key_rec,
const char *key_row,
2563 const NdbRecord *result_rec,
char *result_row,
2565 const unsigned char *result_mask,
2567 Uint32 sizeOfOptions)
2570 if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
2572 setOperationErrorCodeAbort(4292);
2577 if (key_rec->flags & NdbRecord::RecIsIndex &&
2587 result_rec, result_row, result_mask,
2595 op->theDirtyIndicator= 1;
2596 op->theSimpleIndicator= 1;
2602 op->theSimpleIndicator = 1;
2610 op->theReceiver.getValues(result_rec, result_row);
2616 NdbTransaction::insertTuple(
const NdbRecord *key_rec,
const char *key_row,
2617 const NdbRecord *attr_rec,
const char *attr_row,
2618 const unsigned char *mask,
2620 Uint32 sizeOfOptions)
2623 if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
2625 setOperationErrorCodeAbort(4292);
2633 attr_rec, attr_row, mask,
2645 NdbTransaction::insertTuple(
const NdbRecord *combined_rec,
const char *combined_row,
2646 const unsigned char *mask,
2648 Uint32 sizeOfOptions)
2650 return insertTuple(combined_rec, combined_row,
2651 combined_rec, combined_row,
2658 NdbTransaction::updateTuple(
const NdbRecord *key_rec,
const char *key_row,
2659 const NdbRecord *attr_rec,
const char *attr_row,
2660 const unsigned char *mask,
2662 Uint32 sizeOfOptions)
2665 if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
2667 setOperationErrorCodeAbort(4292);
2675 attr_rec, attr_row, mask,
2687 NdbTransaction::deleteTuple(
const NdbRecord *key_rec,
2688 const char *key_row,
2691 const unsigned char *result_mask,
2693 Uint32 sizeOfOptions)
2696 if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
2698 setOperationErrorCodeAbort(4292);
2706 result_rec, result_row, result_mask,
2714 if (result_row != NULL)
2717 op->theReceiver.getValues(result_rec, result_row);
2724 NdbTransaction::writeTuple(
const NdbRecord *key_rec,
const char *key_row,
2725 const NdbRecord *attr_rec,
const char *attr_row,
2726 const unsigned char *mask,
2728 Uint32 sizeOfOptions)
2731 if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
2733 setOperationErrorCodeAbort(4292);
2741 attr_rec, attr_row, mask,
2753 NdbTransaction::refreshTuple(
const NdbRecord *key_rec,
const char *key_row,
2755 Uint32 sizeOfOptions)
2759 Uint32 tcVer = theNdb->theImpl->getNodeInfo(theDBnode).m_info.
m_version;
2760 if (unlikely(! ndb_refresh_tuple(tcVer)))
2763 setOperationErrorCodeAbort(4003);
2769 if (!(key_rec->flags & NdbRecord::RecHasAllKeys))
2771 setOperationErrorCodeAbort(4292);
2775 Uint8 keymask[NDB_MAX_ATTRIBUTES_IN_TABLE/8];
2776 bzero(keymask,
sizeof(keymask));
2777 for (Uint32
i = 0;
i<key_rec->key_index_length;
i++)
2779 Uint32
id = key_rec->columns[key_rec->key_indexes[
i]].attrId;
2780 keymask[(
id / 8)] |= (1 << (
id & 7));
2783 NdbOperation *op= setupRecordOp(NdbOperation::RefreshRequest,
2802 const unsigned char *result_mask,
2804 Uint32 sizeOfOptions)
2806 DBUG_ENTER(
"NdbTransaction::scanTable");
2807 DBUG_PRINT(
"info", (
"Options=%p(0x%x)", options,
2808 (options ? (
unsigned)(options->optionsPresent) : 0)));
2820 setOperationErrorCodeAbort(4000);
2824 op_idx->m_scanUsingOldApi=
false;
2827 if (op_idx->scanTableImpl(result_record,
2831 sizeOfOptions) == 0)
2833 DBUG_RETURN(op_idx);
2836 releaseScanOperation(&m_theFirstScanOperation, &m_theLastScanOperation,
2847 const unsigned char *result_mask,
2850 Uint32 sizeOfOptions)
2861 setOperationErrorCodeAbort(4000);
2865 op->m_scanUsingOldApi=
false;
2868 if (op->scanIndexImpl(key_record,
2874 sizeOfOptions) != 0)
2876 releaseScanOperation(&m_theFirstScanOperation, &m_theLastScanOperation, op);
2884 NdbTransaction::getMaxPendingBlobReadBytes()
const
2887 return (maxPendingBlobReadBytes ==
2888 (~Uint32(0)) ? 0 : maxPendingBlobReadBytes);
2892 NdbTransaction::getMaxPendingBlobWriteBytes()
const
2895 return (maxPendingBlobWriteBytes ==
2896 (~Uint32(0)) ? 0 : maxPendingBlobWriteBytes);
2900 NdbTransaction::setMaxPendingBlobReadBytes(Uint32 bytes)
2903 maxPendingBlobReadBytes = (bytes?bytes : (~ Uint32(0)));
2907 NdbTransaction::setMaxPendingBlobWriteBytes(Uint32 bytes)
2910 maxPendingBlobWriteBytes = (bytes?bytes : (~ Uint32(0)));
2914 #define CASE(x) case x: ndbout << " " << #x; break
2916 NdbTransaction::printState()
2918 ndbout <<
"con=" << hex <<
this << dec;
2920 switch (theStatus) {
2924 CASE(DisConnecting);
2925 CASE(ConnectFailure);
2926 default: ndbout << (Uint32) theStatus;
2928 switch (theListState) {
2930 CASE(InPreparedList);
2932 CASE(InCompletedList);
2933 default: ndbout << (Uint32) theListState;
2935 switch (theSendStatus) {
2938 CASE(sendOperations);
2939 CASE(sendCompleted);
2940 CASE(sendCOMMITstate);
2942 CASE(sendABORTfail);
2943 CASE(sendTC_ROLLBACK);
2944 CASE(sendTC_COMMIT);
2946 default: ndbout << (Uint32) theSendStatus;
2948 switch (theCommitStatus) {
2954 default: ndbout << (Uint32) theCommitStatus;
2956 switch (theCompletionStatus) {
2958 CASE(CompletedSuccess);
2959 CASE(CompletedFailure);
2960 CASE(DefinitionFailure);
2961 default: ndbout << (Uint32) theCompletionStatus;
2969 NdbTransaction::report_node_failure(Uint32
id){
2970 NdbNodeBitmask::set(m_failed_db_nodes,
id);
2985 const Uint32 len = TcKeyConf::DirtyReadBit |
id;
2986 Uint32 tNoComp = theNoOfOpCompleted;
2987 Uint32 tNoSent = theNoOfOpSent;
2991 if(tmp->theReceiver.m_expected_result_length == len &&
2992 tmp->theReceiver.m_received_result_length == 0)
2995 tmp->theError.
code = 4119;
3015 theNoOfOpCompleted = tNoComp;
3018 theReturnStatus = NdbTransaction::ReturnFailure;
3019 if(tNoComp == tNoSent)
3021 theError.
code = 4119;
3022 theCompletionStatus = NdbTransaction::CompletedFailure;
3035 if (unlikely(query == NULL)) {
3040 if (unlikely(error)) {
3046 query->setNext(m_firstQuery);
3047 m_firstQuery = query;
3049 return &query->getInterface();
3053 NdbTransaction::getLockHandle()
3060 lh = theNdb->getLockHandle();
3064 lh->thePrev = m_theLastLockHandle;
3065 if (m_theLastLockHandle == NULL)
3067 m_theFirstLockHandle = lh;
3068 m_theLastLockHandle = lh;
3073 m_theLastLockHandle->next(lh);
3074 m_theLastLockHandle = lh;
3085 switch(lockHandle->m_state)
3087 case NdbLockHandle::FREE:
3091 case NdbLockHandle::PREPARED:
3092 if (likely(lockHandle->isLockRefValid()))
3098 case NdbLockHandle::ALLOCATED:
3107 if (m_theFirstLockHandle == NULL)
3118 while (tmp && (tmp != lockHandle))
3123 if (tmp != lockHandle)
3132 assert(theSimpleState == 0);
3140 opts.optionsPresent = NdbOperation::OperationOptions::OO_PARTITION_ID;
3141 opts.partitionId = lockHandle->getDistKey();
3146 opts.optionsPresent |= NdbOperation::OperationOptions::OO_ABORTOPTION;
3147 opts.abortOption = ao;
3166 NdbTransaction::releaseLockHandle(
const NdbLockHandle* lockHandle)
3171 switch(lockHandle->m_state)
3173 case NdbLockHandle::FREE:
3177 case NdbLockHandle::PREPARED:
3178 if (! lockHandle->isLockRefValid())
3190 case NdbLockHandle::ALLOCATED:
3203 (tmp != lockHandle))
3208 if (tmp != lockHandle)
3220 next->thePrev = prev;
3223 if (lockHandle == m_theFirstLockHandle)
3225 m_theFirstLockHandle = next;
3227 if (lockHandle == m_theLastLockHandle)
3229 m_theLastLockHandle = prev;
3238 theNdb->releaseLockHandle(lh);