mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / storage / ndb / src / ndbapi / NdbOperationExec.cpp
blob2b13d8001f482bb9bb5a8b7052b8fd16d92ff348
1 /* Copyright (c) 2003-2007 MySQL AB
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 of the License.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with this program; if not, write to the Free Software
14 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16 #include <ndb_global.h>
17 #include <NdbOperation.hpp>
18 #include <NdbTransaction.hpp>
19 #include "NdbApiSignal.hpp"
20 #include <Ndb.hpp>
21 #include <NdbRecAttr.hpp>
22 #include "NdbUtil.hpp"
24 #include "Interpreter.hpp"
25 #include <AttributeHeader.hpp>
26 #include <signaldata/TcKeyReq.hpp>
27 #include <signaldata/TcKeyRef.hpp>
28 #include <signaldata/KeyInfo.hpp>
29 #include <signaldata/AttrInfo.hpp>
30 #include <signaldata/ScanTab.hpp>
32 #include <ndb_version.h>
34 #include "API.hpp"
35 #include <NdbOut.hpp>
39 void
40 NdbOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
42 TcKeyReq * const req = CAST_PTR(TcKeyReq, signal->getDataPtrSend());
43 TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
46 /******************************************************************************
47 int doSend()
49 Return Value: Return >0 : send was succesful, returns number of signals sent
50 Return -1: In all other case.
51 Parameters: aProcessorId: Receiving processor node
52 Remark: Sends the TCKEYREQ signal and optional KEYINFO and ATTRINFO
53 signals.
54 ******************************************************************************/
55 int
56 NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
58 int tReturnCode;
59 int tSignalCount = 0;
60 assert(theTCREQ != NULL);
61 setLastFlag(theTCREQ, lastFlag);
62 TransporterFacade *tp = theNdb->theImpl->m_transporter_facade;
63 tReturnCode = tp->sendSignal(theTCREQ, aNodeId);
64 tSignalCount++;
65 if (tReturnCode == -1) {
66 return -1;
68 NdbApiSignal *tSignal = theTCREQ->next();
69 while (tSignal != NULL) {
70 NdbApiSignal* tnextSignal = tSignal->next();
71 tReturnCode = tp->sendSignal(tSignal, aNodeId);
72 tSignal = tnextSignal;
73 if (tReturnCode == -1) {
74 return -1;
76 tSignalCount++;
77 }//while
78 tSignal = theFirstATTRINFO;
79 while (tSignal != NULL) {
80 NdbApiSignal* tnextSignal = tSignal->next();
81 tReturnCode = tp->sendSignal(tSignal, aNodeId);
82 tSignal = tnextSignal;
83 if (tReturnCode == -1) {
84 return -1;
86 tSignalCount++;
87 }//while
88 theNdbCon->OpSent();
89 return tSignalCount;
90 }//NdbOperation::doSend()
92 /***************************************************************************
93 int prepareSend(Uint32 aTC_ConnectPtr,
94 Uint64 aTransactionId)
96 Return Value: Return 0 : preparation of send was succesful.
97 Return -1: In all other case.
98 Parameters: aTC_ConnectPtr: the Connect pointer to TC.
99 aTransactionId: the Transaction identity of the transaction.
100 Remark: Puts the the data into TCKEYREQ signal and optional KEYINFO and ATTRINFO signals.
101 ***************************************************************************/
103 NdbOperation::prepareSend(Uint32 aTC_ConnectPtr,
104 Uint64 aTransId,
105 AbortOption ao)
107 Uint32 tTransId1, tTransId2;
108 Uint32 tReqInfo;
109 Uint8 tInterpretInd = theInterpretIndicator;
110 Uint8 tDirtyIndicator = theDirtyIndicator;
111 Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
112 theErrorLine = 0;
114 if (tInterpretInd != 1) {
115 OperationType tOpType = theOperationType;
116 OperationStatus tStatus = theStatus;
117 if ((tOpType == UpdateRequest) ||
118 (tOpType == InsertRequest) ||
119 (tOpType == WriteRequest)) {
120 if (tStatus != SetValue) {
121 setErrorCodeAbort(4116);
122 return -1;
123 }//if
124 } else if ((tOpType == ReadRequest) || (tOpType == ReadExclusive) ||
125 (tOpType == DeleteRequest)) {
126 if (tStatus != GetValue) {
127 setErrorCodeAbort(4116);
128 return -1;
130 else if(unlikely(tDirtyIndicator && tTotalCurrAI_Len == 0))
132 getValue(NdbDictionary::Column::FRAGMENT);
133 tTotalCurrAI_Len = theTotalCurrAI_Len;
134 assert(theTotalCurrAI_Len);
136 } else {
137 setErrorCodeAbort(4005);
138 return -1;
139 }//if
140 } else {
141 if (prepareSendInterpreted() == -1) {
142 return -1;
143 }//if
144 tTotalCurrAI_Len = theTotalCurrAI_Len;
145 }//if
147 //-------------------------------------------------------------
148 // We start by filling in the first 9 unconditional words of the
149 // TCKEYREQ signal.
150 //-------------------------------------------------------------
151 TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
153 Uint32 tTableId = m_accessTable->m_id;
154 Uint32 tSchemaVersion = m_accessTable->m_version;
156 tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
157 tcKeyReq->apiOperationPtr = ptr2int();
158 // Check if too much attrinfo have been defined
159 if (tTotalCurrAI_Len > TcKeyReq::MaxTotalAttrInfo){
160 setErrorCodeAbort(4257);
161 return -1;
163 Uint32 TattrLen = 0;
164 tcKeyReq->setAttrinfoLen(TattrLen, tTotalCurrAI_Len);
165 tcKeyReq->setAPIVersion(TattrLen, NDB_VERSION);
166 tcKeyReq->attrLen = TattrLen;
168 tcKeyReq->tableId = tTableId;
169 tcKeyReq->tableSchemaVersion = tSchemaVersion;
170 tTransId1 = (Uint32) aTransId;
171 tTransId2 = (Uint32) (aTransId >> 32);
173 Uint8 tSimpleIndicator = theSimpleIndicator;
174 Uint8 tCommitIndicator = theCommitIndicator;
175 Uint8 tStartIndicator = theStartIndicator;
176 Uint8 tInterpretIndicator = theInterpretIndicator;
177 Uint8 tNoDisk = m_no_disk_flag;
180 * A dirty read, can not abort the transaction
182 Uint8 tReadInd = (theOperationType == ReadRequest);
183 Uint8 tDirtyState = tReadInd & tDirtyIndicator;
185 tcKeyReq->transId1 = tTransId1;
186 tcKeyReq->transId2 = tTransId2;
188 tReqInfo = 0;
189 if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
190 tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
191 } else {
192 tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
193 }//if
195 tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
196 tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
197 tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
198 tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
199 tcKeyReq->setNoDiskFlag(tReqInfo, tNoDisk);
201 OperationType tOperationType = theOperationType;
202 Uint32 tTupKeyLen = theTupKeyLen;
203 Uint8 abortOption = (ao == DefaultAbortOption) ? (Uint8) m_abortOption : (Uint8) ao;
205 tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
206 tcKeyReq->setOperationType(tReqInfo, tOperationType);
207 tcKeyReq->setKeyLength(tReqInfo, tTupKeyLen);
209 // A dirty read is always ignore error
210 abortOption = tDirtyState ? (Uint8) AO_IgnoreError : (Uint8) abortOption;
211 tcKeyReq->setAbortOption(tReqInfo, abortOption);
212 m_abortOption = abortOption;
214 Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
215 Uint8 tScanIndicator = theScanInfo & 1;
217 tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
218 tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
220 tcKeyReq->requestInfo = tReqInfo;
222 //-------------------------------------------------------------
223 // The next step is to fill in the upto three conditional words.
224 //-------------------------------------------------------------
225 Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
226 Uint32 tDistrGHIndex = tScanIndicator;
227 Uint32 tDistrKeyIndex = tDistrGHIndex;
229 Uint32 tScanInfo = theScanInfo;
230 Uint32 tDistrKey = theDistributionKey;
232 tOptionalDataPtr[0] = tScanInfo;
233 tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
235 //-------------------------------------------------------------
236 // The next is step is to compress the key data part of the
237 // TCKEYREQ signal.
238 //-------------------------------------------------------------
239 Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
240 Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
241 Uint32 Tdata1 = tcKeyReq->keyInfo[0];
242 Uint32 Tdata2 = tcKeyReq->keyInfo[1];
243 Uint32 Tdata3 = tcKeyReq->keyInfo[2];
244 Uint32 Tdata4 = tcKeyReq->keyInfo[3];
245 Uint32 Tdata5;
247 tKeyDataPtr[0] = Tdata1;
248 tKeyDataPtr[1] = Tdata2;
249 tKeyDataPtr[2] = Tdata3;
250 tKeyDataPtr[3] = Tdata4;
251 if (tTupKeyLen > 4) {
252 Tdata1 = tcKeyReq->keyInfo[4];
253 Tdata2 = tcKeyReq->keyInfo[5];
254 Tdata3 = tcKeyReq->keyInfo[6];
255 Tdata4 = tcKeyReq->keyInfo[7];
257 tKeyDataPtr[4] = Tdata1;
258 tKeyDataPtr[5] = Tdata2;
259 tKeyDataPtr[6] = Tdata3;
260 tKeyDataPtr[7] = Tdata4;
261 }//if
262 //-------------------------------------------------------------
263 // Finally we also compress the ATTRINFO part of the signal.
264 // We optimise by using the if-statement for sending KEYINFO
265 // signals to calculating the new Attrinfo Index.
266 //-------------------------------------------------------------
267 Uint32 tAttrInfoIndex;
269 if (tTupKeyLen > TcKeyReq::MaxKeyInfo) {
271 * Set transid, TC connect ptr and length in the KEYINFO signals
273 NdbApiSignal* tSignal = theTCREQ->next();
274 Uint32 remainingKey = tTupKeyLen - TcKeyReq::MaxKeyInfo;
275 do {
276 Uint32* tSigDataPtr = tSignal->getDataPtrSend();
277 NdbApiSignal* tnextSignal = tSignal->next();
278 tSigDataPtr[0] = aTC_ConnectPtr;
279 tSigDataPtr[1] = tTransId1;
280 tSigDataPtr[2] = tTransId2;
281 if (remainingKey > KeyInfo::DataLength) {
282 // The signal is full
283 tSignal->setLength(KeyInfo::MaxSignalLength);
284 remainingKey -= KeyInfo::DataLength;
286 else {
287 // Last signal
288 tSignal->setLength(KeyInfo::HeaderLength + remainingKey);
289 remainingKey = 0;
291 tSignal = tnextSignal;
292 } while (tSignal != NULL);
293 tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
294 } else {
295 tAttrInfoIndex = tKeyIndex + tTupKeyLen;
296 }//if
298 //-------------------------------------------------------------
299 // Perform the Attrinfo packing in the TCKEYREQ signal started
300 // above.
301 //-------------------------------------------------------------
302 Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
303 Tdata1 = tcKeyReq->attrInfo[0];
304 Tdata2 = tcKeyReq->attrInfo[1];
305 Tdata3 = tcKeyReq->attrInfo[2];
306 Tdata4 = tcKeyReq->attrInfo[3];
307 Tdata5 = tcKeyReq->attrInfo[4];
309 theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
310 tAttrInfoIndex + TcKeyReq::StaticLength);
312 tAIDataPtr[0] = Tdata1;
313 tAIDataPtr[1] = Tdata2;
314 tAIDataPtr[2] = Tdata3;
315 tAIDataPtr[3] = Tdata4;
316 tAIDataPtr[4] = Tdata5;
318 /***************************************************
319 * Send the ATTRINFO signals.
320 ***************************************************/
321 if (tTotalCurrAI_Len > 5) {
322 // Set the last signal's length.
323 NdbApiSignal* tSignal = theFirstATTRINFO;
324 theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
325 do {
326 Uint32* tSigDataPtr = tSignal->getDataPtrSend();
327 NdbApiSignal* tnextSignal = tSignal->next();
328 tSigDataPtr[0] = aTC_ConnectPtr;
329 tSigDataPtr[1] = tTransId1;
330 tSigDataPtr[2] = tTransId2;
331 tSignal = tnextSignal;
332 } while (tSignal != NULL);
333 }//if
334 theStatus = WaitResponse;
335 theReceiver.prepareSend();
336 return 0;
337 }//NdbOperation::prepareSend()
339 /***************************************************************************
340 int prepareSendInterpreted()
342 Make preparations to send an interpreted operation.
343 Return Value: Return 0 : succesful.
344 Return -1: In all other case.
345 ***************************************************************************/
347 NdbOperation::prepareSendInterpreted()
349 Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
350 Uint32 tInitReadSize = theInitialReadSize;
351 if (theStatus == ExecInterpretedValue) {
352 if (insertATTRINFO(Interpreter::EXIT_OK) != -1) {
353 //-------------------------------------------------------------------------
354 // Since we read the total length before inserting the last entry in the
355 // signals we need to add one to the total length.
356 //-------------------------------------------------------------------------
358 theInterpretedSize = (tTotalCurrAI_Len + 1) -
359 (tInitReadSize + 5);
361 } else {
362 return -1;
363 }//if
364 } else if (theStatus == FinalGetValue) {
366 theFinalReadSize = tTotalCurrAI_Len -
367 (tInitReadSize + theInterpretedSize + theFinalUpdateSize + 5);
369 } else if (theStatus == SetValueInterpreted) {
371 theFinalUpdateSize = tTotalCurrAI_Len -
372 (tInitReadSize + theInterpretedSize + 5);
374 } else if (theStatus == SubroutineEnd) {
376 theSubroutineSize = tTotalCurrAI_Len -
377 (tInitReadSize + theInterpretedSize +
378 theFinalUpdateSize + theFinalReadSize + 5);
380 } else if (theStatus == GetValue) {
381 theInitialReadSize = tTotalCurrAI_Len - 5;
382 } else {
383 setErrorCodeAbort(4116);
384 return -1;
387 while (theFirstBranch != NULL) {
388 Uint32 tRelAddress;
389 Uint32 tLabelAddress = 0;
390 int tAddress = -1;
391 NdbBranch* tNdbBranch = theFirstBranch;
392 Uint32 tBranchLabel = tNdbBranch->theBranchLabel;
393 NdbLabel* tNdbLabel = theFirstLabel;
394 if (tBranchLabel >= theNoOfLabels) {
395 setErrorCodeAbort(4221);
396 return -1;
397 }//if
399 // Find the label address
400 while (tNdbLabel != NULL) {
401 for(tLabelAddress = 0; tLabelAddress<16; tLabelAddress++){
402 const Uint32 labelNo = tNdbLabel->theLabelNo[tLabelAddress];
403 if(tBranchLabel == labelNo){
404 tAddress = tNdbLabel->theLabelAddress[tLabelAddress];
405 break;
409 if(tAddress != -1)
410 break;
411 tNdbLabel = tNdbLabel->theNext;
412 }//while
413 if (tAddress == -1) {
414 //-------------------------------------------------------------------------
415 // We were unable to find any label which the branch refers to. This means
416 // that the application have not programmed the interpreter program correctly.
417 //-------------------------------------------------------------------------
418 setErrorCodeAbort(4222);
419 return -1;
420 }//if
421 if (tNdbLabel->theSubroutine[tLabelAddress] != tNdbBranch->theSubroutine) {
422 setErrorCodeAbort(4224);
423 return -1;
424 }//if
425 // Now it is time to update the signal data with the relative branch jump.
426 if (tAddress < int(tNdbBranch->theBranchAddress)) {
427 tRelAddress = (tNdbBranch->theBranchAddress - tAddress) << 16;
429 // Indicate backward jump direction
430 tRelAddress = tRelAddress + (1 << 31);
432 } else if (tAddress > int(tNdbBranch->theBranchAddress)) {
433 tRelAddress = (tAddress - tNdbBranch->theBranchAddress) << 16;
434 } else {
435 setErrorCodeAbort(4223);
436 return -1;
437 }//if
438 NdbApiSignal* tSignal = tNdbBranch->theSignal;
439 Uint32 tReadData = tSignal->readData(tNdbBranch->theSignalAddress);
440 tSignal->setData((tRelAddress + tReadData), tNdbBranch->theSignalAddress);
442 theFirstBranch = theFirstBranch->theNext;
443 theNdb->releaseNdbBranch(tNdbBranch);
444 }//while
446 while (theFirstCall != NULL) {
447 Uint32 tSubroutineCount = 0;
448 int tAddress = -1;
449 NdbSubroutine* tNdbSubroutine;
450 NdbCall* tNdbCall = theFirstCall;
451 if (tNdbCall->theSubroutine >= theNoOfSubroutines) {
452 setErrorCodeAbort(4221);
453 return -1;
454 }//if
455 // Find the subroutine address
456 tNdbSubroutine = theFirstSubroutine;
457 while (tNdbSubroutine != NULL) {
458 tSubroutineCount += 16;
459 if (tNdbCall->theSubroutine < tSubroutineCount) {
460 // Subroutine Found
461 Uint32 tSubroutineAddress = tNdbCall->theSubroutine - (tSubroutineCount - 16);
462 tAddress = tNdbSubroutine->theSubroutineAddress[tSubroutineAddress];
463 break;
464 }//if
465 tNdbSubroutine = tNdbSubroutine->theNext;
466 }//while
467 if (tAddress == -1) {
468 setErrorCodeAbort(4222);
469 return -1;
470 }//if
471 // Now it is time to update the signal data with the relative branch jump.
472 NdbApiSignal* tSignal = tNdbCall->theSignal;
473 Uint32 tReadData = tSignal->readData(tNdbCall->theSignalAddress);
474 tSignal->setData(((tAddress << 16) + tReadData), tNdbCall->theSignalAddress);
476 theFirstCall = theFirstCall->theNext;
477 theNdb->releaseNdbCall(tNdbCall);
478 }//while
480 Uint32 tInitialReadSize = theInitialReadSize;
481 Uint32 tInterpretedSize = theInterpretedSize;
482 Uint32 tFinalUpdateSize = theFinalUpdateSize;
483 Uint32 tFinalReadSize = theFinalReadSize;
484 Uint32 tSubroutineSize = theSubroutineSize;
485 if (theOperationType != OpenScanRequest &&
486 theOperationType != OpenRangeScanRequest) {
487 TcKeyReq * const tcKeyReq = CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
489 tcKeyReq->attrInfo[0] = tInitialReadSize;
490 tcKeyReq->attrInfo[1] = tInterpretedSize;
491 tcKeyReq->attrInfo[2] = tFinalUpdateSize;
492 tcKeyReq->attrInfo[3] = tFinalReadSize;
493 tcKeyReq->attrInfo[4] = tSubroutineSize;
494 } else {
495 // If a scan is defined we use the first ATTRINFO instead of TCKEYREQ.
496 theFirstATTRINFO->setData(tInitialReadSize, 4);
497 theFirstATTRINFO->setData(tInterpretedSize, 5);
498 theFirstATTRINFO->setData(tFinalUpdateSize, 6);
499 theFirstATTRINFO->setData(tFinalReadSize, 7);
500 theFirstATTRINFO->setData(tSubroutineSize, 8);
501 }//if
502 theReceiver.prepareSend();
503 return 0;
504 }//NdbOperation::prepareSendInterpreted()
507 NdbOperation::checkState_TransId(NdbApiSignal* aSignal)
509 Uint64 tRecTransId, tCurrTransId;
510 Uint32 tTmp1, tTmp2;
512 if (theStatus != WaitResponse) {
513 #ifdef NDB_NO_DROPPED_SIGNAL
514 abort();
515 #endif
516 return -1;
517 }//if
519 tTmp1 = aSignal->readData(2);
520 tTmp2 = aSignal->readData(3);
522 tRecTransId = (Uint64)tTmp1 + ((Uint64)tTmp2 << 32);
523 tCurrTransId = theNdbCon->getTransactionId();
524 if (tCurrTransId != tRecTransId) {
525 #ifdef NDB_NO_DROPPED_SIGNAL
526 abort();
527 #endif
528 return -1;
529 }//if
530 return 0;
531 }//NdbOperation::checkState_TransId()
533 /***************************************************************************
534 int receiveTCKEYREF( NdbApiSignal* aSignal)
536 Return Value: Return 0 : send was succesful.
537 Return -1: In all other case.
538 Parameters: aSignal: the signal object that contains the TCKEYREF signal from TC.
539 Remark: Handles the reception of the TCKEYREF signal.
540 ***************************************************************************/
542 NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
544 if (checkState_TransId(aSignal) == -1) {
545 return -1;
546 }//if
548 setErrorCode(aSignal->readData(4));
549 if (aSignal->getLength() == TcKeyRef::SignalLength)
551 // Signal may contain additional error data
552 theError.details = (char *) aSignal->readData(5);
555 theStatus = Finished;
556 theReceiver.m_received_result_length = ~0;
558 // not dirty read
559 if(! (theOperationType == ReadRequest && theDirtyIndicator))
561 theNdbCon->OpCompleteFailure(this);
562 return -1;
566 * If TCKEYCONF has arrived
567 * op has completed (maybe trans has completed)
569 if(theReceiver.m_expected_result_length)
571 return theNdbCon->OpCompleteFailure(this);
574 return -1;