summaryrefslogtreecommitdiff
path: root/ndb/src/ndbapi/NdbOperationExec.cpp
diff options
context:
space:
mode:
authorunknown <magnus@neptunus.(none)>2004-04-14 10:53:21 +0200
committerunknown <magnus@neptunus.(none)>2004-04-14 10:53:21 +0200
commit6386c55cee50bad6a9979d1fab28e03bb8612ca7 (patch)
tree3fbbacf704304b69228474b9f03549ccd585a017 /ndb/src/ndbapi/NdbOperationExec.cpp
parent0ba6cb48d84f1ff951d09871a96be6cdef3f2c3c (diff)
downloadmariadb-git-6386c55cee50bad6a9979d1fab28e03bb8612ca7.tar.gz
Initial revision of NDB Cluster files
BitKeeper/etc/logging_ok: Logging to logging@openlogging.org accepted
Diffstat (limited to 'ndb/src/ndbapi/NdbOperationExec.cpp')
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp967
1 files changed, 967 insertions, 0 deletions
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
new file mode 100644
index 00000000000..1b0ad68b1eb
--- /dev/null
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -0,0 +1,967 @@
+/* Copyright (C) 2003 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+/***************************************************************************
+Name: NdbOperationExec.C
+Include:
+Link:
+Author: UABRONM Mikael Ronström UAB/M/MT Jonas Kamf UAB/M/MT
+Date: 2001-10-16
+Version: 1.2
+Description:
+Documentation:
+***************************************************************************/
+#include "NdbOperation.hpp"
+#include "NdbConnection.hpp"
+#include "NdbApiSignal.hpp"
+#include "Ndb.hpp"
+#include "NdbRecAttr.hpp"
+#include "NdbUtil.hpp"
+
+#include "Interpreter.hpp"
+#include <AttributeHeader.hpp>
+#include <signaldata/TcKeyReq.hpp>
+#include <signaldata/KeyInfo.hpp>
+#include <signaldata/AttrInfo.hpp>
+#include <signaldata/ScanTab.hpp>
+
+#include <ndb_version.h>
+
+#include "API.hpp"
+#include <NdbOut.hpp>
+
+
+/******************************************************************************
+int doSend()
+
+Return Value: Return >0 : send was succesful, returns number of signals sent
+ Return -1: In all other case.
+Parameters: aProcessorId: Receiving processor node
+Remark: Sends the ATTRINFO signal(s)
+******************************************************************************/
+int
+NdbOperation::doSendScan(int aProcessorId)
+{
+ Uint32 tSignalCount = 0;
+ NdbApiSignal* tSignal;
+
+ if (theInterpretIndicator != 1 ||
+ (theOperationType != OpenScanRequest &&
+ theOperationType != OpenRangeScanRequest)) {
+ setErrorCodeAbort(4005);
+ return -1;
+ }
+
+ assert(theSCAN_TABREQ != NULL);
+ tSignal = theSCAN_TABREQ;
+ if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
+ setErrorCode(4001);
+ return -1;
+ }
+ // Update the "attribute info length in words" in SCAN_TABREQ before
+ // sending it. This could not be done in openScan because
+ // we created the ATTRINFO signals after the SCAN_TABREQ signal.
+ ScanTabReq * const scanTabReq = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
+ scanTabReq->attrLen = theTotalCurrAI_Len;
+ if (theOperationType == OpenRangeScanRequest)
+ scanTabReq->attrLen += theTotalBoundAI_Len;
+ TransporterFacade *tp = TransporterFacade::instance();
+ if (tp->sendSignal(tSignal, aProcessorId) == -1) {
+ setErrorCode(4002);
+ return -1;
+ }
+ tSignalCount++;
+
+ tSignal = theFirstSCAN_TABINFO_Send;
+ while (tSignal != NULL){
+ if (tp->sendSignal(tSignal, aProcessorId)) {
+ setErrorCode(4002);
+ return -1;
+ }
+ tSignalCount++;
+ tSignal = tSignal->next();
+ }
+
+ if (theOperationType == OpenRangeScanRequest) {
+ // must have at least one signal since it contains attrLen for bounds
+ assert(theBoundATTRINFO != NULL);
+ tSignal = theBoundATTRINFO;
+ while (tSignal != NULL) {
+ if (tp->sendSignal(tSignal,aProcessorId) == -1){
+ setErrorCode(4002);
+ return -1;
+ }
+ tSignalCount++;
+ tSignal = tSignal->next();
+ }
+ }
+
+ tSignal = theFirstATTRINFO;
+ while (tSignal != NULL) {
+ if (tp->sendSignal(tSignal,aProcessorId) == -1){
+ setErrorCode(4002);
+ return -1;
+ }
+ tSignalCount++;
+ tSignal = tSignal->next();
+ }
+ theStatus = WaitResponse;
+ return tSignalCount;
+}//NdbOperation::doSendScan()
+
+void
+NdbOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
+{
+ TcKeyReq * const req = CAST_PTR(TcKeyReq, signal->getDataPtrSend());
+ TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
+}
+
+/******************************************************************************
+int doSend()
+
+Return Value: Return >0 : send was succesful, returns number of signals sent
+ Return -1: In all other case.
+Parameters: aProcessorId: Receiving processor node
+Remark: Sends the TCKEYREQ signal and optional KEYINFO and ATTRINFO
+ signals.
+******************************************************************************/
+int
+NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
+{
+ int tReturnCode;
+ int tSignalCount = 0;
+ assert(theTCREQ != NULL);
+ setLastFlag(theTCREQ, lastFlag);
+ TransporterFacade *tp = TransporterFacade::instance();
+ tReturnCode = tp->sendSignal(theTCREQ, aNodeId);
+ tSignalCount++;
+ if (tReturnCode == -1) {
+ return -1;
+ }
+ NdbApiSignal *tSignal = theFirstKEYINFO;
+ while (tSignal != NULL) {
+ NdbApiSignal* tnextSignal = tSignal->next();
+ tReturnCode = tp->sendSignal(tSignal, aNodeId);
+ tSignal = tnextSignal;
+ if (tReturnCode == -1) {
+ return -1;
+ }
+ tSignalCount++;
+ }//while
+ tSignal = theFirstATTRINFO;
+ while (tSignal != NULL) {
+ NdbApiSignal* tnextSignal = tSignal->next();
+ tReturnCode = tp->sendSignal(tSignal, aNodeId);
+ tSignal = tnextSignal;
+ if (tReturnCode == -1) {
+ return -1;
+ }
+ tSignalCount++;
+ }//while
+ theNdbCon->OpSent();
+ return tSignalCount;
+}//NdbOperation::doSend()
+
+/***************************************************************************
+int prepareSendScan(Uint32 aTC_ConnectPtr,
+ Uint64 aTransactionId)
+
+Return Value: Return 0 : preparation of send was succesful.
+ Return -1: In all other case.
+Parameters: aTC_ConnectPtr: the Connect pointer to TC.
+ aTransactionId: the Transaction identity of the transaction.
+Remark: Puts the the final data into ATTRINFO signal(s) after this
+ we know the how many signal to send and their sizes
+***************************************************************************/
+int NdbOperation::prepareSendScan(Uint32 aTC_ConnectPtr,
+ Uint64 aTransactionId){
+
+ if (theInterpretIndicator != 1 ||
+ (theOperationType != OpenScanRequest &&
+ theOperationType != OpenRangeScanRequest)) {
+ setErrorCodeAbort(4005);
+ return -1;
+ }
+
+ if (theStatus == SetBound) {
+ saveBoundATTRINFO();
+ theStatus = GetValue;
+ }
+
+ theErrorLine = 0;
+
+ // In preapareSendInterpreted we set the sizes (word 4-8) in the
+ // first ATTRINFO signal.
+ if (prepareSendInterpreted() == -1)
+ return -1;
+
+ const Uint32 transId1 = (Uint32) (aTransactionId & 0xFFFFFFFF);
+ const Uint32 transId2 = (Uint32) (aTransactionId >> 32);
+
+ if (theOperationType == OpenRangeScanRequest) {
+ NdbApiSignal* tSignal = theBoundATTRINFO;
+ do{
+ tSignal->setData(aTC_ConnectPtr, 1);
+ tSignal->setData(transId1, 2);
+ tSignal->setData(transId2, 3);
+ tSignal = tSignal->next();
+ } while (tSignal != NULL);
+ }
+ theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
+ NdbApiSignal* tSignal = theFirstATTRINFO;
+ do{
+ tSignal->setData(aTC_ConnectPtr, 1);
+ tSignal->setData(transId1, 2);
+ tSignal->setData(transId2, 3);
+ tSignal = tSignal->next();
+ } while (tSignal != NULL);
+ return 0;
+}
+
+/***************************************************************************
+int prepareSend(Uint32 aTC_ConnectPtr,
+ Uint64 aTransactionId)
+
+Return Value: Return 0 : preparation of send was succesful.
+ Return -1: In all other case.
+Parameters: aTC_ConnectPtr: the Connect pointer to TC.
+ aTransactionId: the Transaction identity of the transaction.
+Remark: Puts the the data into TCKEYREQ signal and optional KEYINFO and ATTRINFO signals.
+***************************************************************************/
+int
+NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
+{
+ Uint32 tTransId1, tTransId2;
+ Uint32 tReqInfo;
+ Uint32 tInterpretInd = theInterpretIndicator;
+
+ theErrorLine = 0;
+
+ if (tInterpretInd != 1) {
+ OperationType tOpType = theOperationType;
+ OperationStatus tStatus = theStatus;
+ if ((tOpType == UpdateRequest) ||
+ (tOpType == InsertRequest) ||
+ (tOpType == WriteRequest)) {
+ if (tStatus != SetValue) {
+ setErrorCodeAbort(4116);
+ return -1;
+ }//if
+ } else if ((tOpType == ReadRequest) || (tOpType == ReadExclusive) ||
+ (tOpType == DeleteRequest)) {
+ if (tStatus != GetValue) {
+ setErrorCodeAbort(4116);
+ return -1;
+ }//if
+ } else {
+ setErrorCodeAbort(4005);
+ return -1;
+ }//if
+ } else {
+ if (prepareSendInterpreted() == -1) {
+ return -1;
+ }//if
+ }//if
+
+//-------------------------------------------------------------
+// We start by filling in the first 9 unconditional words of the
+// TCKEYREQ signal.
+//-------------------------------------------------------------
+ TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
+
+ Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
+ Uint32 tTableId = m_currentTable->m_tableId;
+ Uint32 tSchemaVersion = m_currentTable->m_version;
+
+ tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
+ tcKeyReq->apiOperationPtr = ptr2int();
+ // Check if too much attrinfo have been defined
+ if (tTotalCurrAI_Len > TcKeyReq::MaxTotalAttrInfo){
+ setErrorCodeAbort(4257);
+ return -1;
+ }
+ Uint32 TattrLen = 0;
+ tcKeyReq->setAttrinfoLen(TattrLen, tTotalCurrAI_Len);
+ tcKeyReq->setAPIVersion(TattrLen, NDB_VERSION);
+ tcKeyReq->attrLen = TattrLen;
+
+ tcKeyReq->tableId = tTableId;
+ tcKeyReq->tableSchemaVersion = tSchemaVersion;
+ tTransId1 = (Uint32) aTransId;
+ tTransId2 = (Uint32) (aTransId >> 32);
+
+//-------------------------------------------------------------
+// Simple is simple if simple or both start and commit is set.
+//-------------------------------------------------------------
+// Temporarily disable simple stuff
+ Uint8 tSimpleIndicator = 0;
+// Uint8 tSimpleIndicator = theSimpleIndicator;
+ Uint8 tCommitIndicator = theCommitIndicator;
+ Uint8 tStartIndicator = theStartIndicator;
+// if ((theNdbCon->theLastOpInList == this) && (theCommitIndicator == 0))
+// abort();
+// Temporarily disable simple stuff
+ Uint8 tSimpleAlt = 0;
+// Uint8 tSimpleAlt = tStartIndicator & tCommitIndicator;
+ tSimpleIndicator = tSimpleIndicator | tSimpleAlt;
+
+//-------------------------------------------------------------
+// Simple state is set if start and commit is set and it is
+// a read request. Otherwise it is set to zero.
+//-------------------------------------------------------------
+ Uint8 tReadInd = (theOperationType == ReadRequest);
+ Uint8 tSimpleState = tReadInd & tSimpleAlt;
+ theNdbCon->theSimpleState = tSimpleState;
+
+ tcKeyReq->transId1 = tTransId1;
+ tcKeyReq->transId2 = tTransId2;
+
+ tReqInfo = 0;
+ if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
+ } else {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
+ }//if
+
+ tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
+ tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
+ tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
+ const Uint8 tInterpretIndicator = theInterpretIndicator;
+ tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+
+ Uint8 tDirtyIndicator = theDirtyIndicator;
+ OperationType tOperationType = theOperationType;
+ Uint32 tTupKeyLen = theTupKeyLen;
+ Uint8 abortOption = theNdbCon->m_abortOption;
+
+ tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
+ tcKeyReq->setOperationType(tReqInfo, tOperationType);
+ tcKeyReq->setKeyLength(tReqInfo, tTupKeyLen);
+ tcKeyReq->setAbortOption(tReqInfo, abortOption);
+
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
+ Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
+ Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tScanIndicator = theScanInfo & 1;
+
+ tcKeyReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
+ tcKeyReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
+ tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
+ tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
+
+ tcKeyReq->requestInfo = tReqInfo;
+
+//-------------------------------------------------------------
+// The next step is to fill in the upto three conditional words.
+//-------------------------------------------------------------
+ Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
+ Uint32 tDistrGHIndex = tScanIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+
+ Uint32 tScanInfo = theScanInfo;
+ Uint32 tDistributionGroup = theDistributionGroup;
+ Uint32 tDistrKeySize = theDistrKeySize;
+
+ tOptionalDataPtr[0] = tScanInfo;
+ tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+
+//-------------------------------------------------------------
+// The next is step is to compress the key data part of the
+// TCKEYREQ signal.
+//-------------------------------------------------------------
+ Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
+ Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
+ Uint32 Tdata1 = tcKeyReq->keyInfo[0];
+ Uint32 Tdata2 = tcKeyReq->keyInfo[1];
+ Uint32 Tdata3 = tcKeyReq->keyInfo[2];
+ Uint32 Tdata4 = tcKeyReq->keyInfo[3];
+ Uint32 Tdata5;
+
+ tKeyDataPtr[0] = Tdata1;
+ tKeyDataPtr[1] = Tdata2;
+ tKeyDataPtr[2] = Tdata3;
+ tKeyDataPtr[3] = Tdata4;
+ if (tTupKeyLen > 4) {
+ Tdata1 = tcKeyReq->keyInfo[4];
+ Tdata2 = tcKeyReq->keyInfo[5];
+ Tdata3 = tcKeyReq->keyInfo[6];
+ Tdata4 = tcKeyReq->keyInfo[7];
+
+ tKeyDataPtr[4] = Tdata1;
+ tKeyDataPtr[5] = Tdata2;
+ tKeyDataPtr[6] = Tdata3;
+ tKeyDataPtr[7] = Tdata4;
+ }//if
+//-------------------------------------------------------------
+// Finally we also compress the ATTRINFO part of the signal.
+// We optimise by using the if-statement for sending KEYINFO
+// signals to calculating the new Attrinfo Index.
+//-------------------------------------------------------------
+ Uint32 tAttrInfoIndex;
+
+ if (tTupKeyLen > TcKeyReq::MaxKeyInfo) {
+ /**
+ * Set transid, TC connect ptr and length in the KEYINFO signals
+ */
+ NdbApiSignal* tSignal = theFirstKEYINFO;
+ Uint32 remainingKey = tTupKeyLen - TcKeyReq::MaxKeyInfo;
+ do {
+ Uint32* tSigDataPtr = tSignal->getDataPtrSend();
+ NdbApiSignal* tnextSignal = tSignal->next();
+ tSigDataPtr[0] = aTC_ConnectPtr;
+ tSigDataPtr[1] = tTransId1;
+ tSigDataPtr[2] = tTransId2;
+ if (remainingKey > KeyInfo::DataLength) {
+ // The signal is full
+ tSignal->setLength(KeyInfo::MaxSignalLength);
+ remainingKey -= KeyInfo::DataLength;
+ }
+ else {
+ // Last signal
+ tSignal->setLength(KeyInfo::HeaderLength + remainingKey);
+ remainingKey = 0;
+ }
+ tSignal = tnextSignal;
+ } while (tSignal != NULL);
+ tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
+ } else {
+ tAttrInfoIndex = tKeyIndex + tTupKeyLen;
+ }//if
+
+//-------------------------------------------------------------
+// Perform the Attrinfo packing in the TCKEYREQ signal started
+// above.
+//-------------------------------------------------------------
+ Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
+ Tdata1 = tcKeyReq->attrInfo[0];
+ Tdata2 = tcKeyReq->attrInfo[1];
+ Tdata3 = tcKeyReq->attrInfo[2];
+ Tdata4 = tcKeyReq->attrInfo[3];
+ Tdata5 = tcKeyReq->attrInfo[4];
+
+ theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
+ tAttrInfoIndex + TcKeyReq::StaticLength);
+ tAIDataPtr[0] = Tdata1;
+ tAIDataPtr[1] = Tdata2;
+ tAIDataPtr[2] = Tdata3;
+ tAIDataPtr[3] = Tdata4;
+ tAIDataPtr[4] = Tdata5;
+
+/***************************************************
+* Send the ATTRINFO signals.
+***************************************************/
+ if (tTotalCurrAI_Len > 5) {
+ // Set the last signal's length.
+ NdbApiSignal* tSignal = theFirstATTRINFO;
+ theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
+ do {
+ Uint32* tSigDataPtr = tSignal->getDataPtrSend();
+ NdbApiSignal* tnextSignal = tSignal->next();
+ tSigDataPtr[0] = aTC_ConnectPtr;
+ tSigDataPtr[1] = tTransId1;
+ tSigDataPtr[2] = tTransId2;
+ tSignal = tnextSignal;
+ } while (tSignal != NULL);
+ }//if
+ NdbRecAttr* tRecAttrObject = theFirstRecAttr;
+ theStatus = WaitResponse;
+ theCurrentRecAttr = tRecAttrObject;
+ return 0;
+}//NdbOperation::prepareSend()
+
+/***************************************************************************
+int prepareSendInterpreted()
+
+Make preparations to send an interpreted operation.
+Return Value: Return 0 : succesful.
+ Return -1: In all other case.
+***************************************************************************/
+int
+NdbOperation::prepareSendInterpreted()
+{
+ Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
+ Uint32 tInitReadSize = theInitialReadSize;
+ if (theStatus == ExecInterpretedValue) {
+ if (insertATTRINFO(Interpreter::EXIT_OK_LAST) != -1) {
+//-------------------------------------------------------------------------
+// Since we read the total length before inserting the last entry in the
+// signals we need to add one to the total length.
+//-------------------------------------------------------------------------
+
+ theInterpretedSize = (tTotalCurrAI_Len + 1) -
+ (tInitReadSize + 5);
+
+ } else {
+ return -1;
+ }//if
+ } else if (theStatus == FinalGetValue) {
+
+ theFinalReadSize = tTotalCurrAI_Len -
+ (tInitReadSize + theInterpretedSize + theFinalUpdateSize + 5);
+
+ } else if (theStatus == SetValueInterpreted) {
+
+ theFinalUpdateSize = tTotalCurrAI_Len -
+ (tInitReadSize + theInterpretedSize + 5);
+
+ } else if (theStatus == SubroutineEnd) {
+
+ theSubroutineSize = tTotalCurrAI_Len -
+ (tInitReadSize + theInterpretedSize +
+ theFinalUpdateSize + theFinalReadSize + 5);
+
+ } else if (theStatus == GetValue) {
+ theInitialReadSize = tTotalCurrAI_Len - 5;
+ } else {
+ setErrorCodeAbort(4116);
+ return -1;
+ }
+
+ while (theFirstBranch != NULL) {
+ Uint32 tRelAddress;
+ Uint32 tLabelAddress = 0;
+ int tAddress = -1;
+ NdbBranch* tNdbBranch = theFirstBranch;
+ Uint32 tBranchLabel = tNdbBranch->theBranchLabel;
+ NdbLabel* tNdbLabel = theFirstLabel;
+ if (tBranchLabel >= theNoOfLabels) {
+ setErrorCodeAbort(4221);
+ return -1;
+ }//if
+
+ // Find the label address
+ while (tNdbLabel != NULL) {
+ for(tLabelAddress = 0; tLabelAddress<16; tLabelAddress++){
+ const Uint32 labelNo = tNdbLabel->theLabelNo[tLabelAddress];
+ if(tBranchLabel == labelNo){
+ tAddress = tNdbLabel->theLabelAddress[tLabelAddress];
+ break;
+ }
+ }
+
+ if(tAddress != -1)
+ break;
+ tNdbLabel = tNdbLabel->theNext;
+ }//while
+ if (tAddress == -1) {
+//-------------------------------------------------------------------------
+// We were unable to find any label which the branch refers to. This means
+// that the application have not programmed the interpreter program correctly.
+//-------------------------------------------------------------------------
+ setErrorCodeAbort(4222);
+ return -1;
+ }//if
+ if (tNdbLabel->theSubroutine[tLabelAddress] != tNdbBranch->theSubroutine) {
+ setErrorCodeAbort(4224);
+ return -1;
+ }//if
+ // Now it is time to update the signal data with the relative branch jump.
+ if (tAddress < int(tNdbBranch->theBranchAddress)) {
+ tRelAddress = (tNdbBranch->theBranchAddress - tAddress) << 16;
+
+ // Indicate backward jump direction
+ tRelAddress = tRelAddress + (1 << 31);
+
+ } else if (tAddress > int(tNdbBranch->theBranchAddress)) {
+ tRelAddress = (tAddress - tNdbBranch->theBranchAddress) << 16;
+ } else {
+ setErrorCodeAbort(4223);
+ return -1;
+ }//if
+ NdbApiSignal* tSignal = tNdbBranch->theSignal;
+ Uint32 tReadData = tSignal->readData(tNdbBranch->theSignalAddress);
+ tSignal->setData((tRelAddress + tReadData), tNdbBranch->theSignalAddress);
+
+ theFirstBranch = theFirstBranch->theNext;
+ theNdb->releaseNdbBranch(tNdbBranch);
+ }//while
+
+ while (theFirstCall != NULL) {
+ Uint32 tSubroutineCount = 0;
+ int tAddress = -1;
+ NdbSubroutine* tNdbSubroutine;
+ NdbCall* tNdbCall = theFirstCall;
+ if (tNdbCall->theSubroutine >= theNoOfSubroutines) {
+ setErrorCodeAbort(4221);
+ return -1;
+ }//if
+// Find the subroutine address
+ tNdbSubroutine = theFirstSubroutine;
+ while (tNdbSubroutine != NULL) {
+ tSubroutineCount += 16;
+ if (tNdbCall->theSubroutine < tSubroutineCount) {
+// Subroutine Found
+ Uint32 tSubroutineAddress = tNdbCall->theSubroutine - (tSubroutineCount - 16);
+ tAddress = tNdbSubroutine->theSubroutineAddress[tSubroutineAddress];
+ break;
+ }//if
+ tNdbSubroutine = tNdbSubroutine->theNext;
+ }//while
+ if (tAddress == -1) {
+ setErrorCodeAbort(4222);
+ return -1;
+ }//if
+// Now it is time to update the signal data with the relative branch jump.
+ NdbApiSignal* tSignal = tNdbCall->theSignal;
+ Uint32 tReadData = tSignal->readData(tNdbCall->theSignalAddress);
+ tSignal->setData(((tAddress << 16) + tReadData), tNdbCall->theSignalAddress);
+
+ theFirstCall = theFirstCall->theNext;
+ theNdb->releaseNdbCall(tNdbCall);
+ }//while
+
+ Uint32 tInitialReadSize = theInitialReadSize;
+ Uint32 tInterpretedSize = theInterpretedSize;
+ Uint32 tFinalUpdateSize = theFinalUpdateSize;
+ Uint32 tFinalReadSize = theFinalReadSize;
+ Uint32 tSubroutineSize = theSubroutineSize;
+ if (theOperationType != OpenScanRequest &&
+ theOperationType != OpenRangeScanRequest) {
+ TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
+
+ tcKeyReq->attrInfo[0] = tInitialReadSize;
+ tcKeyReq->attrInfo[1] = tInterpretedSize;
+ tcKeyReq->attrInfo[2] = tFinalUpdateSize;
+ tcKeyReq->attrInfo[3] = tFinalReadSize;
+ tcKeyReq->attrInfo[4] = tSubroutineSize;
+ } else {
+ // If a scan is defined we use the first ATTRINFO instead of TCKEYREQ.
+ theFirstATTRINFO->setData(tInitialReadSize, 4);
+ theFirstATTRINFO->setData(tInterpretedSize, 5);
+ theFirstATTRINFO->setData(tFinalUpdateSize, 6);
+ theFirstATTRINFO->setData(tFinalReadSize, 7);
+ theFirstATTRINFO->setData(tSubroutineSize, 8);
+ }//if
+ return 0;
+}//NdbOperation::prepareSendInterpreted()
+
+/***************************************************************************
+int TCOPCONF(int anAttrInfoLen)
+
+Return Value: Return 0 : send was succesful.
+ Return -1: In all other case.
+Parameters: anAttrInfoLen: The length of the attribute information from TC.
+Remark: Handles the reception of the TC[KEY/INDX]CONF signal.
+***************************************************************************/
+void
+NdbOperation::TCOPCONF(Uint32 anAttrInfoLen)
+{
+ Uint32 tCurrRecLen = theCurrRecAI_Len;
+ if (theStatus == WaitResponse) {
+ theTotalRecAI_Len = anAttrInfoLen;
+ if (anAttrInfoLen == tCurrRecLen) {
+ Uint32 tAI_ElemLen = theAI_ElementLen;
+ NdbRecAttr* tCurrRecAttr = theCurrentRecAttr;
+ theStatus = Finished;
+
+ if ((tAI_ElemLen == 0) &&
+ (tCurrRecAttr == NULL)) {
+ NdbRecAttr* tRecAttr = theFirstRecAttr;
+ while (tRecAttr != NULL) {
+ if (tRecAttr->copyoutRequired()) // copy to application buffer
+ tRecAttr->copyout();
+ tRecAttr = tRecAttr->next();
+ }
+ theNdbCon->OpCompleteSuccess();
+ return;
+ } else if (tAI_ElemLen != 0) {
+ setErrorCode(4213);
+ theNdbCon->OpCompleteFailure();
+ return;
+ } else {
+ setErrorCode(4214);
+ theNdbCon->OpCompleteFailure();
+ return;
+ }//if
+ } else if (anAttrInfoLen > tCurrRecLen) {
+ return;
+ } else {
+ theStatus = Finished;
+
+ if (theAI_ElementLen != 0) {
+ setErrorCode(4213);
+ theNdbCon->OpCompleteFailure();
+ return;
+ }//if
+ if (theCurrentRecAttr != NULL) {
+ setErrorCode(4214);
+ theNdbCon->OpCompleteFailure();
+ return;
+ }//if
+ theNdbCon->OpCompleteFailure();
+ return;
+ }//if
+ } else {
+ setErrorCode(4004);
+ }//if
+ return;
+}//NdbOperation::TCKEYOPCONF()
+
+int
+NdbOperation::checkState_TransId(NdbApiSignal* aSignal)
+{
+ Uint64 tRecTransId, tCurrTransId;
+ Uint32 tTmp1, tTmp2;
+
+ if (theStatus != WaitResponse) {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ return -1;
+ }//if
+
+ tTmp1 = aSignal->readData(2);
+ tTmp2 = aSignal->readData(3);
+
+ tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
+ tCurrTransId = theNdbCon->getTransactionId();
+ if (tCurrTransId != tRecTransId) {
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ return -1;
+ }//if
+ return 0;
+}//NdbOperation::checkState_TransId()
+
+/***************************************************************************
+int receiveTCKEYREF( NdbApiSignal* aSignal)
+
+Return Value: Return 0 : send was succesful.
+ Return -1: In all other case.
+Parameters: aSignal: the signal object that contains the TCKEYREF signal from TC.
+Remark: Handles the reception of the TCKEYREF signal.
+***************************************************************************/
+int
+NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
+{
+ if (checkState_TransId(aSignal) == -1) {
+ return -1;
+ }//if
+
+ theStatus = Finished;
+
+ theNdbCon->theReturnStatus = ReturnFailure;
+ //-------------------------------------------------------------------------//
+ // If the transaction this operation belongs to consists only of simple reads
+ // we set the error code on the transaction object.
+ // If the transaction consists of other types of operations we set
+ // the error code only on the operation since the simple read is not really
+ // part of this transaction and we can not decide the status of the whole
+ // transaction based on this operation.
+ //-------------------------------------------------------------------------//
+ if (theNdbCon->theSimpleState == 0) {
+ theError.code = aSignal->readData(4);
+ theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4));
+ return theNdbCon->OpCompleteFailure();
+ } else {
+ theError.code = aSignal->readData(4);
+ return theNdbCon->OpCompleteSuccess();
+ }
+
+}//NdbOperation::receiveTCKEYREF()
+
+/***************************************************************************
+int receiveREAD_CONF( NdbApiSignal* aSignal)
+
+Return Value: Return 0 : send was succesful.
+ Return -1: In all other case.
+Parameters: aSignal: the signal object that contains the READCONF signal from TUP.
+Remark: Handles the reception of the READCONF signal.
+***************************************************************************/
+int
+NdbOperation::receiveREAD_CONF(const Uint32* aDataPtr, Uint32 aDataLength)
+{
+ Uint64 tRecTransId, tCurrTransId;
+ Uint32 tCondFlag = (Uint32)(theStatus - WaitResponse);
+ Uint32 tTotLen = aDataPtr[3];
+
+ tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32);
+ tCurrTransId = theNdbCon->getTransactionId();
+ tCondFlag |= (Uint32)((tRecTransId - tCurrTransId) != (Uint64)0);
+ tCondFlag |= (Uint32)(aDataLength < 4);
+
+ if (tCondFlag == 0) {
+ theTotalRecAI_Len = tTotLen;
+ int tRetValue = receiveREAD_AI((Uint32*)&aDataPtr[4], (aDataLength - 4));
+ if (theStatus == Finished) {
+ return tRetValue;
+ } else {
+ theStatus = Finished;
+ return theNdbCon->OpCompleteFailure();
+ }//if
+ }//if
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ return -1;
+}//NdbOperation::receiveREAD_CONF()
+
+/***************************************************************************
+int receiveTRANSID_AI( NdbApiSignal* aSignal)
+
+Return Value: Return 0 : send was succesful.
+ Return -1: In all other case.
+Parameters: aSignal: the signal object that contains the TRANSID_AI signal.
+Remark: Handles the reception of the TRANSID_AI signal.
+***************************************************************************/
+int
+NdbOperation::receiveTRANSID_AI(const Uint32* aDataPtr, Uint32 aDataLength)
+{
+ Uint64 tRecTransId, tCurrTransId;
+ Uint32 tCondFlag = (Uint32)(theStatus - WaitResponse);
+
+ tRecTransId = (Uint64)aDataPtr[1] + ((Uint64)aDataPtr[2] << 32);
+ tCurrTransId = theNdbCon->getTransactionId();
+ tCondFlag |= (Uint32)((tRecTransId - tCurrTransId) != (Uint64)0);
+ tCondFlag |= (Uint32)(aDataLength < 3);
+
+ if (tCondFlag == 0) {
+ return receiveREAD_AI((Uint32*)&aDataPtr[3], (aDataLength - 3));
+ }//if
+#ifdef NDB_NO_DROPPED_SIGNAL
+ abort();
+#endif
+ return -1;
+}//NdbOperation::receiveTRANSID_AI()
+
+/***************************************************************************
+int receiveREAD_AI( NdbApiSignal* aSignal, int aLength, int aStartPos)
+
+Return Value: Return 0 : send was succesoccurredful.
+ Return -1: In all other case.
+Parameters: aSignal: the signal object that contains the LEN_ATTRINFO11 signal.
+ aLength:
+ aStartPos:
+Remark: Handles the reception of the LEN_ATTRINFO11 signal.
+***************************************************************************/
+int
+NdbOperation::receiveREAD_AI(Uint32* aDataPtr, Uint32 aLength)
+{
+
+ register Uint32 tAI_ElementLen = theAI_ElementLen;
+ register Uint32* tCurrElemPtr = theCurrElemPtr;
+ if (theError.code == 0) {
+ // If inconsistency error occurred we will still continue
+ // receiving signals since we need to know whether commit
+ // has occurred.
+
+ register Uint32 tData;
+ for (register Uint32 i = 0; i < aLength ; i++, aDataPtr++)
+ {
+ // Code to receive Attribute Information
+ tData = *aDataPtr;
+ if (tAI_ElementLen != 0) {
+ tAI_ElementLen--;
+ *tCurrElemPtr = tData;
+ tCurrElemPtr++;
+ continue;
+ } else {
+ // Waiting for a new attribute element
+ NdbRecAttr* tWorkingRecAttr;
+
+ tWorkingRecAttr = theCurrentRecAttr;
+ AttributeHeader ah(tData);
+ const Uint32 tAttrId = ah.getAttributeId();
+ const Uint32 tAttrSize = ah.getDataSize();
+ if ((tWorkingRecAttr != NULL) &&
+ (tWorkingRecAttr->attrId() == tAttrId)) {
+ ;
+ } else {
+ setErrorCode(4211);
+ break;
+ }//if
+ theCurrentRecAttr = tWorkingRecAttr->next();
+ NdbColumnImpl * col = m_currentTable->getColumn(tAttrId);
+ if (ah.isNULL()) {
+ // Return a Null value from the NDB to the attribute.
+ if(col != 0 && col->m_nullable) {
+ tWorkingRecAttr->setNULL();
+ tAI_ElementLen = 0;
+ } else {
+ setErrorCode(4212);
+ break;
+ }//if
+ } else {
+ // Return a value from the NDB to the attribute.
+ tWorkingRecAttr->setNotNULL();
+ const Uint32 sizeInBytes = col->m_attrSize * col->m_arraySize;
+ const Uint32 sizeInWords = (sizeInBytes + 3) / 4;
+ tAI_ElementLen = tAttrSize;
+ tCurrElemPtr = (Uint32*)tWorkingRecAttr->aRef();
+ if (sizeInWords == tAttrSize){
+ continue;
+ } else {
+ setErrorCode(4201);
+ break;
+ }//if
+ }//if
+ }//if
+ }//for
+ }//if
+ Uint32 tCurrRecLen = theCurrRecAI_Len;
+ Uint32 tTotRecLen = theTotalRecAI_Len;
+ theAI_ElementLen = tAI_ElementLen;
+ theCurrElemPtr = tCurrElemPtr;
+ tCurrRecLen = tCurrRecLen + aLength;
+ theCurrRecAI_Len = tCurrRecLen; // Update Current Received AI Length
+ if (tTotRecLen == tCurrRecLen){ // Operation completed
+ NdbRecAttr* tCurrRecAttr = theCurrentRecAttr;
+ theStatus = Finished;
+
+ NdbConnection* tNdbCon = theNdbCon;
+ if ((tAI_ElementLen == 0) &&
+ (tCurrRecAttr == NULL)) {
+ NdbRecAttr* tRecAttr = theFirstRecAttr;
+ while (tRecAttr != NULL) {
+ if (tRecAttr->copyoutRequired()) // copy to application buffer
+ tRecAttr->copyout();
+ tRecAttr = tRecAttr->next();
+ }
+ return tNdbCon->OpCompleteSuccess();
+ } else if (tAI_ElementLen != 0) {
+ setErrorCode(4213);
+ return tNdbCon->OpCompleteFailure();
+ } else {
+ setErrorCode(4214);
+ return tNdbCon->OpCompleteFailure();
+ }//if
+ }
+ else if ((tCurrRecLen > tTotRecLen) &&
+ (tTotRecLen > 0)) { /* == 0 if TCKEYCONF not yet received */
+ setErrorCode(4215);
+ theStatus = Finished;
+
+ return theNdbCon->OpCompleteFailure();
+ }//if
+ return -1; // Continue waiting for more signals of this operation
+}//NdbOperation::receiveREAD_AI()
+
+void
+NdbOperation::handleFailedAI_ElemLen()
+{
+ NdbRecAttr* tRecAttr = theFirstRecAttr;
+ while (tRecAttr != NULL) {
+ tRecAttr->setUNDEFINED();
+ tRecAttr = tRecAttr->next();
+ }//while
+}//NdbOperation::handleFailedAI_ElemLen()
+
+
+
+