1 /* Copyright (c) 2003-2008 MySQL AB
2 Use is subject to license terms
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
16
17 #define DBTC_C
18
19 #include "Dbtc.hpp"
20 #include "md5_hash.hpp"
21 #include <RefConvert.hpp>
22 #include <ndb_limits.h>
23 #include <my_sys.h>
24 #include <ndb_rand.h>
25
26 #include <signaldata/EventReport.hpp>
27 #include <signaldata/TcKeyReq.hpp>
28 #include <signaldata/TcKeyConf.hpp>
29 #include <signaldata/TcKeyRef.hpp>
30 #include <signaldata/KeyInfo.hpp>
31 #include <signaldata/AttrInfo.hpp>
32 #include <signaldata/TransIdAI.hpp>
33 #include <signaldata/TcRollbackRep.hpp>
34 #include <signaldata/NodeFailRep.hpp>
35 #include <signaldata/ReadNodesConf.hpp>
36 #include <signaldata/NFCompleteRep.hpp>
37 #include <signaldata/LqhKey.hpp>
38 #include <signaldata/TcCommit.hpp>
39 #include <signaldata/TcContinueB.hpp>
40 #include <signaldata/TcKeyFailConf.hpp>
41 #include <signaldata/AbortAll.hpp>
42 #include <signaldata/DihFragCount.hpp>
43 #include <signaldata/ScanFrag.hpp>
44 #include <signaldata/ScanTab.hpp>
45 #include <signaldata/PrepDropTab.hpp>
46 #include <signaldata/DropTab.hpp>
47 #include <signaldata/AlterTab.hpp>
48 #include <signaldata/CreateTrig.hpp>
49 #include <signaldata/DropTrig.hpp>
50 #include <signaldata/FireTrigOrd.hpp>
51 #include <signaldata/TrigAttrInfo.hpp>
52 #include <signaldata/CreateIndx.hpp>
53 #include <signaldata/DropIndx.hpp>
54 #include <signaldata/AlterIndx.hpp>
55 #include <signaldata/ScanTab.hpp>
56 #include <signaldata/SystemError.hpp>
57 #include <signaldata/DumpStateOrd.hpp>
58 #include <signaldata/DisconnectRep.hpp>
59 #include <signaldata/TcHbRep.hpp>
60
61 #include <signaldata/PrepDropTab.hpp>
62 #include <signaldata/DropTab.hpp>
63 #include <signaldata/TcIndx.hpp>
64 #include <signaldata/IndxKeyInfo.hpp>
65 #include <signaldata/IndxAttrInfo.hpp>
66 #include <signaldata/PackedSignal.hpp>
67 #include <AttributeHeader.hpp>
68 #include <signaldata/DictTabInfo.hpp>
69 #include <AttributeDescriptor.hpp>
70 #include <SectionReader.hpp>
71 #include <KeyDescriptor.hpp>
72
73 #include <NdbOut.hpp>
74 #include <DebuggerNames.hpp>
75
76 #include <signaldata/RouteOrd.hpp>
77
78 // Use DEBUG to print messages that should be
79 // seen only when we debug the product
80 #ifdef VM_TRACE
81 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
82 #else
83 #define DEBUG(x)
84 #endif
85
86 #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
87
88 #ifdef VM_TRACE
89 NdbOut &
operator <<(NdbOut & out,Dbtc::ConnectionState state)90 operator<<(NdbOut& out, Dbtc::ConnectionState state){
91 switch(state){
92 case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
93 case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
94 case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
95 case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
96 case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
97 case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
98 case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
99 case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
100 case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
101 case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
102 case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
103 case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
104 case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
105 case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
106 case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
107 case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
108 case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
109 case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
110 case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
111 case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
112 case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
113 case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
114 case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
115 case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
116 case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
117 case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
118 default:
119 out << "Unknown: " << (int)state; break;
120 }
121 return out;
122 }
123 NdbOut &
operator <<(NdbOut & out,Dbtc::OperationState state)124 operator<<(NdbOut& out, Dbtc::OperationState state){
125 out << (int)state;
126 return out;
127 }
128 NdbOut &
operator <<(NdbOut & out,Dbtc::AbortState state)129 operator<<(NdbOut& out, Dbtc::AbortState state){
130 out << (int)state;
131 return out;
132 }
133 NdbOut &
operator <<(NdbOut & out,Dbtc::ReturnSignal state)134 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
135 out << (int)state;
136 return out;
137 }
138 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanRecord::ScanState state)139 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
140 out << (int)state;
141 return out;
142 }
143 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanFragRec::ScanFragState state)144 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
145 out << (int)state;
146 return out;
147 }
148 #endif
149
150 void
updateBuddyTimer(ApiConnectRecordPtr apiPtr)151 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
152 {
153 if (apiPtr.p->buddyPtr != RNIL) {
154 jam();
155 ApiConnectRecordPtr buddyApiPtr;
156 buddyApiPtr.i = apiPtr.p->buddyPtr;
157 ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
158 if (getApiConTimer(buddyApiPtr.i) != 0) {
159 if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
160 (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
161 jam();
162 setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
163 } else {
164 jam();
165 // Not a buddy anymore since not the same transid
166 apiPtr.p->buddyPtr = RNIL;
167 }//if
168 }//if
169 }//if
170 }
171
execCONTINUEB(Signal * signal)172 void Dbtc::execCONTINUEB(Signal* signal)
173 {
174 UintR tcase;
175
176 jamEntry();
177 tcase = signal->theData[0];
178 UintR Tdata0 = signal->theData[1];
179 UintR Tdata1 = signal->theData[2];
180 UintR Tdata2 = signal->theData[3];
181 switch (tcase) {
182 case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
183 jam();
184 ndbrequire(false);
185 return;
186 case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
187 jam();
188 tcNodeFailptr.i = Tdata0;
189 ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
190 completeTransAtTakeOverLab(signal, Tdata1);
191 return;
192 case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
193 jam();
194 timeOutLoopStartLab(signal, Tdata0);
195 return;
196 case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
197 jam();
198 tnodeid = Tdata0;
199 tcNodeFailptr.i = 0;
200 ptrAss(tcNodeFailptr, tcFailRecord);
201 nodeTakeOverCompletedLab(signal);
202 return;
203 case TcContinueB::ZINITIALISE_RECORDS:
204 jam();
205 initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
206 return;
207 case TcContinueB::ZSEND_COMMIT_LOOP:
208 jam();
209 apiConnectptr.i = Tdata0;
210 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
211 tcConnectptr.i = Tdata1;
212 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
213 commit020Lab(signal);
214 return;
215 case TcContinueB::ZSEND_COMPLETE_LOOP:
216 jam();
217 apiConnectptr.i = Tdata0;
218 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
219 tcConnectptr.i = Tdata1;
220 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
221 complete010Lab(signal);
222 return;
223 case TcContinueB::ZHANDLE_FAILED_API_NODE:
224 jam();
225 handleFailedApiNode(signal, Tdata0, Tdata1);
226 return;
227 case TcContinueB::ZTRANS_EVENT_REP:
228 jam();
229 /* -------------------------------------------------------------------- */
230 // Report information about transaction activity once per second.
231 /* -------------------------------------------------------------------- */
232 if (c_counters.c_trans_status == TransCounters::Timer){
233 Uint32 len = c_counters.report(signal);
234 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
235
236 c_counters.reset();
237 signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
238 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
239 }
240 return;
241 case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
242 jam();
243 timeOutLoopStartFragLab(signal, Tdata0);
244 return;
245 case TcContinueB::ZABORT_BREAK:
246 jam();
247 tcConnectptr.i = Tdata0;
248 apiConnectptr.i = Tdata1;
249 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
250 apiConnectptr.p->counter--;
251 abort015Lab(signal);
252 return;
253 case TcContinueB::ZABORT_TIMEOUT_BREAK:
254 jam();
255 tcConnectptr.i = Tdata0;
256 apiConnectptr.i = Tdata1;
257 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
258 apiConnectptr.p->counter--;
259 sendAbortedAfterTimeout(signal, 1);
260 return;
261 case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
262 jam();
263 removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
264 return;
265 case TcContinueB::ZWAIT_ABORT_ALL:
266 jam();
267 checkAbortAllTimeout(signal, Tdata0);
268 return;
269 case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
270 jam();
271 checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
272 return;
273 case TcContinueB::ZNF_CHECK_TRANSACTIONS:
274 jam();
275 nodeFailCheckTransactions(signal, Tdata0, Tdata1);
276 return;
277 case TcContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH:
278 jam();
279 checkWaitDropTabFailedLqh(signal, Tdata0, Tdata1);
280 return;
281 case TcContinueB::TRIGGER_PENDING:
282 jam();
283 ApiConnectRecordPtr transPtr;
284 transPtr.i = Tdata0;
285 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
286 transPtr.p->triggerPending = false;
287 executeTriggers(signal, &transPtr);
288 return;
289 case TcContinueB::DelayTCKEYCONF:
290 jam();
291 apiConnectptr.i = Tdata0;
292 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
293 sendtckeyconf(signal, Tdata1);
294 return;
295 default:
296 ndbrequire(false);
297 }//switch
298 }
299
execDIGETNODESREF(Signal * signal)300 void Dbtc::execDIGETNODESREF(Signal* signal)
301 {
302 jamEntry();
303 terrorCode = signal->theData[1];
304 releaseAtErrorLab(signal);
305 }
306
execINCL_NODEREQ(Signal * signal)307 void Dbtc::execINCL_NODEREQ(Signal* signal)
308 {
309 jamEntry();
310 tblockref = signal->theData[0];
311 hostptr.i = signal->theData[1];
312 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
313 hostptr.p->hostStatus = HS_ALIVE;
314 c_alive_nodes.set(hostptr.i);
315
316 signal->theData[0] = hostptr.i;
317 signal->theData[1] = cownref;
318
319 if (ERROR_INSERTED(8039))
320 {
321 CLEAR_ERROR_INSERT_VALUE;
322 Uint32 save = signal->theData[0];
323 signal->theData[0] = 9999;
324 sendSignal(numberToRef(CMVMI, hostptr.i),
325 GSN_NDB_TAMPER, signal, 1, JBB);
326 signal->theData[0] = save;
327 sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
328 return;
329 }
330
331 sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
332 }
333
execREAD_NODESREF(Signal * signal)334 void Dbtc::execREAD_NODESREF(Signal* signal)
335 {
336 jamEntry();
337 ndbrequire(false);
338 }
339
execTC_SCHVERREQ(Signal * signal)340 void Dbtc::execTC_SCHVERREQ(Signal* signal)
341 {
342 jamEntry();
343 if (! assembleFragments(signal)) {
344 jam();
345 return;
346 }
347 tabptr.i = signal->theData[0];
348 ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
349 tabptr.p->currentSchemaVersion = signal->theData[1];
350 tabptr.p->m_flags = 0;
351 tabptr.p->set_storedTable((bool)signal->theData[2]);
352 BlockReference retRef = signal->theData[3];
353 tabptr.p->tableType = (Uint8)signal->theData[4];
354 BlockReference retPtr = signal->theData[5];
355 Uint32 noOfKeyAttr = signal->theData[6];
356 tabptr.p->singleUserMode = (Uint8)signal->theData[7];
357 ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
358
359 const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
360 ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
361
362 ndbrequire(tabptr.p->get_enabled() == false);
363 tabptr.p->set_enabled(true);
364 tabptr.p->set_dropping(false);
365 tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
366 tabptr.p->hasCharAttr = desc->hasCharAttr;
367 tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
368 tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
369 signal->theData[0] = tabptr.i;
370 signal->theData[1] = retPtr;
371 sendSignal(retRef, GSN_TC_SCHVERCONF, signal, 2, JBB);
372 }//Dbtc::execTC_SCHVERREQ()
373
374 void
execPREP_DROP_TAB_REQ(Signal * signal)375 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
376 {
377 jamEntry();
378
379 PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
380
381 TableRecordPtr tabPtr;
382 tabPtr.i = req->tableId;
383 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
384
385 Uint32 senderRef = req->senderRef;
386 Uint32 senderData = req->senderData;
387
388 if(!tabPtr.p->get_enabled()){
389 jam();
390 PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
391 ref->senderRef = reference();
392 ref->senderData = senderData;
393 ref->tableId = tabPtr.i;
394 ref->errorCode = PrepDropTabRef::NoSuchTable;
395 sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
396 PrepDropTabRef::SignalLength, JBB);
397 return;
398 }
399
400 if(tabPtr.p->get_dropping()){
401 jam();
402 PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
403 ref->senderRef = reference();
404 ref->senderData = senderData;
405 ref->tableId = tabPtr.i;
406 ref->errorCode = PrepDropTabRef::DropInProgress;
407 sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
408 PrepDropTabRef::SignalLength, JBB);
409 return;
410 }
411
412 tabPtr.p->set_dropping(true);
413 tabPtr.p->dropTable.senderRef = senderRef;
414 tabPtr.p->dropTable.senderData = senderData;
415
416 {
417 WaitDropTabReq * req = (WaitDropTabReq*)signal->getDataPtrSend();
418 req->tableId = tabPtr.i;
419 req->senderRef = reference();
420
421 HostRecordPtr hostPtr;
422 tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor();
423 for (hostPtr.i = 1; hostPtr.i < MAX_NDB_NODES; hostPtr.i++) {
424 jam();
425 ptrAss(hostPtr, hostRecord);
426 if (hostPtr.p->hostStatus == HS_ALIVE) {
427 jam();
428 tabPtr.p->dropTable.waitDropTabCount.setWaitingFor(hostPtr.i);
429 sendSignal(calcLqhBlockRef(hostPtr.i), GSN_WAIT_DROP_TAB_REQ,
430 signal, WaitDropTabReq::SignalLength, JBB);
431 }//for
432 }//if
433
434 ndbrequire(tabPtr.p->dropTable.waitDropTabCount.done() != true);
435 }
436 }
437
438 void
execWAIT_DROP_TAB_CONF(Signal * signal)439 Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal)
440 {
441 jamEntry();
442 WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
443
444 TableRecordPtr tabPtr;
445 tabPtr.i = conf->tableId;
446 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
447
448 ndbrequire(tabPtr.p->get_dropping() == true);
449 Uint32 nodeId = refToNode(conf->senderRef);
450 tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
451
452 if(!tabPtr.p->dropTable.waitDropTabCount.done()){
453 jam();
454 return;
455 }
456
457 {
458 PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
459 conf->tableId = tabPtr.i;
460 conf->senderRef = reference();
461 conf->senderData = tabPtr.p->dropTable.senderData;
462 sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
463 PrepDropTabConf::SignalLength, JBB);
464 tabPtr.p->dropTable.senderRef = 0;
465 }
466 }
467
468 void
execWAIT_DROP_TAB_REF(Signal * signal)469 Dbtc::execWAIT_DROP_TAB_REF(Signal* signal)
470 {
471 jamEntry();
472 WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr();
473
474 TableRecordPtr tabPtr;
475 tabPtr.i = ref->tableId;
476 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
477
478 ndbrequire(tabPtr.p->get_dropping() == true);
479 Uint32 nodeId = refToNode(ref->senderRef);
480 tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
481
482 ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable ||
483 ref->errorCode == WaitDropTabRef::NF_FakeErrorREF);
484
485 if(!tabPtr.p->dropTable.waitDropTabCount.done()){
486 jam();
487 return;
488 }
489
490 {
491 PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
492 conf->tableId = tabPtr.i;
493 conf->senderRef = reference();
494 conf->senderData = tabPtr.p->dropTable.senderData;
495 sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
496 PrepDropTabConf::SignalLength, JBB);
497 tabPtr.p->dropTable.senderRef = 0;
498 }
499 }
500
501 void
checkWaitDropTabFailedLqh(Signal * signal,Uint32 nodeId,Uint32 tableId)502 Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId)
503 {
504
505 TableRecordPtr tabPtr;
506 tabPtr.i = tableId;
507
508 WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
509 conf->tableId = tableId;
510
511 const Uint32 RT_BREAK = 16;
512 for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){
513 jam();
514 ptrAss(tabPtr, tableRecord);
515 if(tabPtr.p->get_enabled() && tabPtr.p->get_dropping()){
516 if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){
517 jam();
518 conf->senderRef = calcLqhBlockRef(nodeId);
519 execWAIT_DROP_TAB_CONF(signal);
520 tabPtr.i++;
521 break;
522 }
523 }
524 }
525
526 if(tabPtr.i == ctabrecFilesize){
527 /**
528 * Finished
529 */
530 jam();
531 checkNodeFailComplete(signal, nodeId, HostRecord::NF_CHECK_DROP_TAB);
532 return;
533 }
534
535 signal->theData[0] = TcContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH;
536 signal->theData[1] = nodeId;
537 signal->theData[2] = tabPtr.i;
538 sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
539 }
540
541 void
execDROP_TAB_REQ(Signal * signal)542 Dbtc::execDROP_TAB_REQ(Signal* signal)
543 {
544 jamEntry();
545
546 DropTabReq* req = (DropTabReq*)signal->getDataPtr();
547
548 TableRecordPtr tabPtr;
549 tabPtr.i = req->tableId;
550 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
551
552 Uint32 senderRef = req->senderRef;
553 Uint32 senderData = req->senderData;
554 DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
555
556 if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
557 jam();
558 DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
559 ref->senderRef = reference();
560 ref->senderData = senderData;
561 ref->tableId = tabPtr.i;
562 ref->errorCode = DropTabRef::NoSuchTable;
563 sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
564 DropTabRef::SignalLength, JBB);
565 return;
566 }
567
568 if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
569 jam();
570 DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
571 ref->senderRef = reference();
572 ref->senderData = senderData;
573 ref->tableId = tabPtr.i;
574 ref->errorCode = DropTabRef::DropWoPrep;
575 sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
576 DropTabRef::SignalLength, JBB);
577 return;
578 }
579
580 tabPtr.p->set_enabled(false);
581 tabPtr.p->set_dropping(false);
582
583 DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
584 conf->tableId = tabPtr.i;
585 conf->senderRef = reference();
586 conf->senderData = senderData;
587 sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
588 PrepDropTabConf::SignalLength, JBB);
589 }
590
execALTER_TAB_REQ(Signal * signal)591 void Dbtc::execALTER_TAB_REQ(Signal * signal)
592 {
593 AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
594 const Uint32 senderRef = req->senderRef;
595 const Uint32 senderData = req->senderData;
596 const Uint32 changeMask = req->changeMask;
597 const Uint32 tableId = req->tableId;
598 const Uint32 tableVersion = req->tableVersion;
599 const Uint32 gci = req->gci;
600 AlterTabReq::RequestType requestType =
601 (AlterTabReq::RequestType) req->requestType;
602
603 TableRecordPtr tabPtr;
604 tabPtr.i = req->tableId;
605 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
606 tabPtr.p->currentSchemaVersion = tableVersion;
607
608 // Request handled successfully
609 AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
610 conf->senderRef = reference();
611 conf->senderData = senderData;
612 conf->changeMask = changeMask;
613 conf->tableId = tableId;
614 conf->tableVersion = tableVersion;
615 conf->gci = gci;
616 conf->requestType = requestType;
617 sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
618 AlterTabConf::SignalLength, JBB);
619 }
620
621 /* ***************************************************************************/
622 /* START / RESTART */
623 /* ***************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)624 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
625 {
626 const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
627 Uint32 ref = req->senderRef;
628 Uint32 senderData = req->senderData;
629 ndbrequire(req->noOfParameters == 0);
630
631 jamEntry();
632
633 const ndb_mgm_configuration_iterator * p =
634 m_ctx.m_config.getOwnConfigIterator();
635 ndbrequire(p != 0);
636
637 initData();
638
639 UintR apiConnect;
640 UintR tcConnect;
641 UintR tables;
642 UintR localScan;
643 UintR tcScan;
644
645 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
646 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
647 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
648 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
649 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
650
651 ccacheFilesize = (apiConnect/3) + 1;
652 capiConnectFilesize = apiConnect;
653 ctcConnectFilesize = tcConnect;
654 ctabrecFilesize = tables;
655 cscanrecFileSize = tcScan;
656 cscanFragrecFileSize = localScan;
657
658 initRecords();
659 initialiseRecordsLab(signal, 0, ref, senderData);
660
661 Uint32 val = 3000;
662 ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
663 set_timeout_value(val);
664
665 val = 1500;
666 ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
667 cDbHbInterval = (val < 10) ? 10 : val;
668
669 val = 3000;
670 ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
671 set_appl_timeout_value(val);
672
673 val = 1;
674 //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
675 set_no_parallel_takeover(val);
676
677 ctimeOutCheckDelay = 50; // 500ms
678 }//Dbtc::execSIZEALT_REP()
679
execSTTOR(Signal * signal)680 void Dbtc::execSTTOR(Signal* signal)
681 {
682 Uint16 tphase;
683
684 jamEntry();
685 /* START CASE */
686 tphase = signal->theData[1];
687 csignalKey = signal->theData[6];
688 switch (tphase) {
689 case ZSPH1:
690 jam();
691 startphase1x010Lab(signal);
692 return;
693 default:
694 jam();
695 sttorryLab(signal); /* START PHASE 255 */
696 return;
697 }//switch
698 }//Dbtc::execSTTOR()
699
sttorryLab(Signal * signal)700 void Dbtc::sttorryLab(Signal* signal)
701 {
702 signal->theData[0] = csignalKey;
703 signal->theData[1] = 3; /* BLOCK CATEGORY */
704 signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
705 signal->theData[3] = ZSPH1;
706 signal->theData[4] = 255;
707 sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
708 }//Dbtc::sttorryLab()
709
710 /* ***************************************************************************/
711 /* INTERNAL START / RESTART */
712 /*****************************************************************************/
execNDB_STTOR(Signal * signal)713 void Dbtc::execNDB_STTOR(Signal* signal)
714 {
715 Uint16 tndbstartphase;
716 Uint16 tstarttype;
717
718 jamEntry();
719 tusersblkref = signal->theData[0];
720 tnodeid = signal->theData[1];
721 tndbstartphase = signal->theData[2]; /* START PHASE */
722 tstarttype = signal->theData[3]; /* START TYPE */
723 switch (tndbstartphase) {
724 case ZINTSPH1:
725 jam();
726 intstartphase1x010Lab(signal);
727 return;
728 case ZINTSPH2:
729 jam();
730 intstartphase2x010Lab(signal);
731 return;
732 case ZINTSPH3:
733 jam();
734 intstartphase3x010Lab(signal); /* SEIZE CONNECT RECORD IN EACH LQH*/
735 // Start transaction event reporting.
736 c_counters.c_trans_status = TransCounters::Timer;
737 c_counters.reset();
738 signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
739 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 1);
740 return;
741 case ZINTSPH6:
742 jam();
743 csystemStart = SSS_TRUE;
744 break;
745 default:
746 jam();
747 break;
748 }//switch
749 ndbsttorry010Lab(signal);
750 return;
751 }//Dbtc::execNDB_STTOR()
752
ndbsttorry010Lab(Signal * signal)753 void Dbtc::ndbsttorry010Lab(Signal* signal)
754 {
755 signal->theData[0] = cownref;
756 sendSignal(cndbcntrblockref, GSN_NDB_STTORRY, signal, 1, JBB);
757 }//Dbtc::ndbsttorry010Lab()
758
759 void
set_timeout_value(Uint32 timeOut)760 Dbtc::set_timeout_value(Uint32 timeOut)
761 {
762 timeOut = timeOut / 10;
763 if (timeOut < 2) {
764 jam();
765 timeOut = 100;
766 }//if
767 ctimeOutValue = timeOut;
768 }
769
770 void
set_appl_timeout_value(Uint32 timeOut)771 Dbtc::set_appl_timeout_value(Uint32 timeOut)
772 {
773 if (timeOut)
774 {
775 timeOut /= 10;
776 if (timeOut < ctimeOutValue) {
777 jam();
778 c_appl_timeout_value = ctimeOutValue;
779 }//if
780 }
781 c_appl_timeout_value = timeOut;
782 }
783
784 void
set_no_parallel_takeover(Uint32 noParallelTakeOver)785 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
786 {
787 if (noParallelTakeOver == 0) {
788 jam();
789 noParallelTakeOver = 1;
790 } else if (noParallelTakeOver > MAX_NDB_NODES) {
791 jam();
792 noParallelTakeOver = MAX_NDB_NODES;
793 }//if
794 cnoParallelTakeOver = noParallelTakeOver;
795 }
796
797 /* ***************************************************************************/
798 /* S T A R T P H A S E 1 X */
799 /* INITIALISE BLOCKREF AND BLOCKNUMBERS */
800 /* ***************************************************************************/
startphase1x010Lab(Signal * signal)801 void Dbtc::startphase1x010Lab(Signal* signal)
802 {
803 csystemStart = SSS_FALSE;
804 ctimeOutCheckCounter = 0;
805 ctimeOutCheckFragCounter = 0;
806 ctimeOutMissedHeartbeats = 0;
807 ctimeOutCheckHeartbeat = 0;
808 ctimeOutCheckLastHeartbeat = 0;
809 ctimeOutCheckActive = TOCS_FALSE;
810 ctimeOutCheckFragActive = TOCS_FALSE;
811 sttorryLab(signal);
812 }//Dbtc::startphase1x010Lab()
813
814 /*****************************************************************************/
815 /* I N T S T A R T P H A S E 1 X */
816 /* INITIALISE ALL RECORDS. */
817 /*****************************************************************************/
intstartphase1x010Lab(Signal * signal)818 void Dbtc::intstartphase1x010Lab(Signal* signal)
819 {
820 cownNodeid = tnodeid;
821 cownref = calcTcBlockRef(cownNodeid);
822 clqhblockref = calcLqhBlockRef(cownNodeid);
823 cdihblockref = calcDihBlockRef(cownNodeid);
824 cdictblockref = calcDictBlockRef(cownNodeid);
825 cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
826 cerrorBlockref = calcNdbCntrBlockRef(cownNodeid);
827 coperationsize = 0;
828 cfailure_nr = 0;
829 ndbsttorry010Lab(signal);
830 }//Dbtc::intstartphase1x010Lab()
831
832 /*****************************************************************************/
833 /* I N T S T A R T P H A S E 2 X */
834 /* SET-UP LOCAL CONNECTIONS. */
835 /*****************************************************************************/
intstartphase2x010Lab(Signal * signal)836 void Dbtc::intstartphase2x010Lab(Signal* signal)
837 {
838 tcConnectptr.i = cfirstfreeTcConnect;
839 intstartphase2x020Lab(signal);
840 }//Dbtc::intstartphase2x010Lab()
841
intstartphase2x020Lab(Signal * signal)842 void Dbtc::intstartphase2x020Lab(Signal* signal)
843 {
844 if (tcConnectptr.i == RNIL) {
845 jam();
846 ndbsttorry010Lab(signal);
847 return;
848 }//if
849 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
850 tcConnectptr.p->tcConnectstate = OS_CONNECTING_DICT;
851 /* ****************** */
852 /* DISEIZEREQ < */
853 /* ****************** */
854 signal->theData[0] = tcConnectptr.i;
855 signal->theData[1] = cownref;
856 sendSignal(cdihblockref, GSN_DISEIZEREQ, signal, 2, JBB);
857 }//Dbtc::intstartphase2x020Lab()
858
execDISEIZECONF(Signal * signal)859 void Dbtc::execDISEIZECONF(Signal* signal)
860 {
861 jamEntry();
862 tcConnectptr.i = signal->theData[0];
863 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
864 tcConnectptr.p->dihConnectptr = signal->theData[1];
865 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
866 intstartphase2x020Lab(signal);
867 }//Dbtc::execDISEIZECONF()
868
869 /*****************************************************************************/
870 /* I N T S T A R T P H A S E 3 X */
871 /* PREPARE DISTRIBUTED CONNECTIONS */
872 /*****************************************************************************/
intstartphase3x010Lab(Signal * signal)873 void Dbtc::intstartphase3x010Lab(Signal* signal)
874 {
875 signal->theData[0] = cownref;
876 sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
877 }//Dbtc::intstartphase3x010Lab()
878
execREAD_NODESCONF(Signal * signal)879 void Dbtc::execREAD_NODESCONF(Signal* signal)
880 {
881 UintR guard0;
882
883 jamEntry();
884
885 ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
886
887 csystemnodes = readNodes->noOfNodes;
888 cmasterNodeId = readNodes->masterNodeId;
889
890 con_lineNodes = 0;
891 arrGuard(csystemnodes, MAX_NDB_NODES);
892 guard0 = csystemnodes - 1;
893 arrGuard(guard0, MAX_NDB_NODES); // Check not zero nodes
894
895 for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
896 jam();
897 if (NodeBitmask::get(readNodes->allNodes, i)) {
898 hostptr.i = i;
899 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
900
901 if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
902 jam();
903 hostptr.p->hostStatus = HS_DEAD;
904 } else {
905 jam();
906 con_lineNodes++;
907 hostptr.p->hostStatus = HS_ALIVE;
908 c_alive_nodes.set(i);
909 }//if
910 }//if
911 }//for
912 ndbsttorry010Lab(signal);
913 }//Dbtc::execREAD_NODESCONF()
914
915 /*****************************************************************************/
916 /* A P I _ F A I L R E Q */
917 // An API node has failed for some reason. We need to disconnect all API
918 // connections to the API node. This also includes
919 /*****************************************************************************/
execAPI_FAILREQ(Signal * signal)920 void Dbtc::execAPI_FAILREQ(Signal* signal)
921 {
922 /***************************************************************************
923 * Set the block reference to return API_FAILCONF to. Set the number of api
924 * connects currently closing to one to indicate that we are still in the
925 * process of going through the api connect records. Thus checking for zero
926 * can only be true after all api connect records have been checked.
927 **************************************************************************/
928 jamEntry();
929 capiFailRef = signal->theData[1];
930 arrGuard(signal->theData[0], MAX_NODES);
931 capiConnectClosing[signal->theData[0]] = 1;
932 handleFailedApiNode(signal, signal->theData[0], (UintR)0);
933 }
934
935 void
handleFailedApiNode(Signal * signal,UintR TapiFailedNode,UintR TapiConnectPtr)936 Dbtc::handleFailedApiNode(Signal* signal,
937 UintR TapiFailedNode,
938 UintR TapiConnectPtr)
939 {
940 UintR TloopCount = 0;
941 arrGuard(TapiFailedNode, MAX_NODES);
942 apiConnectptr.i = TapiConnectPtr;
943 do {
944 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
945 const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
946 if (TapiNode == TapiFailedNode) {
947 #ifdef VM_TRACE
948 if (apiConnectptr.p->apiFailState != ZFALSE) {
949 ndbout << "Error in previous API fail handling discovered" << endl
950 << " apiConnectptr.i = " << apiConnectptr.i << endl
951 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate
952 << endl
953 << " ndbapiBlockref = " << hex
954 << apiConnectptr.p->ndbapiBlockref << endl
955 << " apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
956 << endl;
957 if (apiConnectptr.p->lastTcConnect != RNIL){
958 jam();
959 tcConnectptr.i = apiConnectptr.p->lastTcConnect;
960 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
961 ndbout << " tcConnectptr.i = " << tcConnectptr.i << endl
962 << " tcConnectstate = " << tcConnectptr.p->tcConnectstate
963 << endl;
964 }
965 }//if
966 #endif
967
968 apiConnectptr.p->returnsignal = RS_NO_RETURN;
969 /***********************************************************************/
970 // The connected node is the failed node.
971 /**********************************************************************/
972 switch(apiConnectptr.p->apiConnectstate) {
973 case CS_DISCONNECTED:
974 /*********************************************************************/
975 // These states do not need any special handling.
976 // Simply continue with the next.
977 /*********************************************************************/
978 jam();
979 break;
980 case CS_ABORTING:
981 /*********************************************************************/
982 // This could actually mean that the API connection is already
983 // ready to release if the abortState is IDLE.
984 /*********************************************************************/
985 if (apiConnectptr.p->abortState == AS_IDLE) {
986 jam();
987 releaseApiCon(signal, apiConnectptr.i);
988 } else {
989 jam();
990 capiConnectClosing[TapiFailedNode]++;
991 apiConnectptr.p->apiFailState = ZTRUE;
992 }//if
993 break;
994 case CS_WAIT_ABORT_CONF:
995 case CS_WAIT_COMMIT_CONF:
996 case CS_START_COMMITTING:
997 case CS_PREPARE_TO_COMMIT:
998 case CS_COMMITTING:
999 case CS_COMMIT_SENT:
1000 /*********************************************************************/
1001 // These states indicate that an abort process or commit process is
1002 // already ongoing. We will set a state in the api record indicating
1003 // that the API node has failed.
1004 // Also we will increase the number of outstanding api records to
1005 // wait for before we can respond with API_FAILCONF.
1006 /*********************************************************************/
1007 jam();
1008 capiConnectClosing[TapiFailedNode]++;
1009 apiConnectptr.p->apiFailState = ZTRUE;
1010 break;
1011 case CS_START_SCAN:
1012 /*********************************************************************/
1013 // The api record was performing a scan operation. We need to check
1014 // on the scan state. Since completing a scan process might involve
1015 // sending several signals we will increase the loop count by 64.
1016 /*********************************************************************/
1017 jam();
1018
1019 apiConnectptr.p->apiFailState = ZTRUE;
1020 capiConnectClosing[TapiFailedNode]++;
1021
1022 ScanRecordPtr scanPtr;
1023 scanPtr.i = apiConnectptr.p->apiScanRec;
1024 ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
1025 close_scan_req(signal, scanPtr, true);
1026
1027 TloopCount += 64;
1028 break;
1029 case CS_CONNECTED:
1030 case CS_REC_COMMITTING:
1031 case CS_RECEIVING:
1032 case CS_STARTED:
1033 /*********************************************************************/
1034 // The api record was in the process of performing a transaction but
1035 // had not yet sent all information.
1036 // We need to initiate an ABORT since the API will not provide any
1037 // more information.
1038 // Since the abort can send many signals we will insert a real-time
1039 // break after checking this record.
1040 /*********************************************************************/
1041 jam();
1042 apiConnectptr.p->apiFailState = ZTRUE;
1043 capiConnectClosing[TapiFailedNode]++;
1044 abort010Lab(signal);
1045 TloopCount = 256;
1046 break;
1047 case CS_PREPARED:
1048 jam();
1049 case CS_REC_PREPARING:
1050 jam();
1051 case CS_START_PREPARING:
1052 jam();
1053 /*********************************************************************/
1054 // Not implemented yet.
1055 /*********************************************************************/
1056 systemErrorLab(signal, __LINE__);
1057 break;
1058 case CS_RESTART:
1059 jam();
1060 case CS_COMPLETING:
1061 jam();
1062 case CS_COMPLETE_SENT:
1063 jam();
1064 case CS_WAIT_COMPLETE_CONF:
1065 jam();
1066 case CS_FAIL_ABORTING:
1067 jam();
1068 case CS_FAIL_ABORTED:
1069 jam();
1070 case CS_FAIL_PREPARED:
1071 jam();
1072 case CS_FAIL_COMMITTING:
1073 jam();
1074 case CS_FAIL_COMMITTED:
1075 /*********************************************************************/
1076 // These states are only valid on copy and fail API connections.
1077 /*********************************************************************/
1078 default:
1079 jam();
1080 systemErrorLab(signal, __LINE__);
1081 break;
1082 }//switch
1083 } else {
1084 jam();
1085 }//if
1086 apiConnectptr.i++;
1087 if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
1088 jam();
1089 /**
1090 * Finished with scanning connection record
1091 *
1092 * Now scan markers
1093 */
1094 removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1095 return;
1096 }//if
1097 } while (TloopCount++ < 256);
1098 signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1099 signal->theData[1] = TapiFailedNode;
1100 signal->theData[2] = apiConnectptr.i;
1101 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1102 }//Dbtc::handleFailedApiNode()
1103
1104 void
removeMarkerForFailedAPI(Signal * signal,Uint32 nodeId,Uint32 startBucket)1105 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1106 Uint32 nodeId,
1107 Uint32 startBucket)
1108 {
1109 TcFailRecordPtr node_fail_ptr;
1110 node_fail_ptr.i = 0;
1111 ptrAss(node_fail_ptr, tcFailRecord);
1112 if(node_fail_ptr.p->failStatus != FS_IDLE) {
1113 jam();
1114 DEBUG("Restarting removeMarkerForFailedAPI");
1115 /**
1116 * TC take-over in progress
1117 * needs to restart as this
1118 * creates new markers
1119 */
1120 signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1121 signal->theData[1] = nodeId;
1122 signal->theData[2] = 0;
1123 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1124 return;
1125 }
1126
1127 CommitAckMarkerIterator iter;
1128 m_commitAckMarkerHash.next(startBucket, iter);
1129
1130 const Uint32 RT_BREAK = 256;
1131 for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1132 jam();
1133
1134 if(iter.curr.i == RNIL){
1135 jam();
1136 /**
1137 * Done with iteration
1138 */
1139 capiConnectClosing[nodeId]--;
1140 if (capiConnectClosing[nodeId] == 0) {
1141 jam();
1142 /********************************************************************/
1143 // No outstanding ABORT or COMMIT's of this failed API node.
1144 // We can respond with API_FAILCONF
1145 /********************************************************************/
1146 signal->theData[0] = nodeId;
1147 signal->theData[1] = cownref;
1148 sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
1149 }
1150 return;
1151 }
1152
1153 if(iter.curr.p->apiNodeId == nodeId){
1154 jam();
1155
1156 /**
1157 * Check so that the record is not still in use
1158 *
1159 */
1160 ApiConnectRecordPtr apiConnectPtr;
1161 apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1162 ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
1163 if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
1164 jam();
1165 /**
1166 * The record is still active
1167 *
1168 * Don't remove it, but continueb instead
1169 */
1170 break;
1171 }
1172 sendRemoveMarkers(signal, iter.curr.p);
1173 m_commitAckMarkerHash.release(iter.curr);
1174
1175 break;
1176 }
1177 m_commitAckMarkerHash.next(iter);
1178 }
1179
1180 signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1181 signal->theData[1] = nodeId;
1182 signal->theData[2] = iter.bucket;
1183 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1184 }
1185
handleApiFailState(Signal * signal,UintR TapiConnectptr)1186 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1187 {
1188 ApiConnectRecordPtr TlocalApiConnectptr;
1189 UintR TfailedApiNode;
1190
1191 TlocalApiConnectptr.i = TapiConnectptr;
1192 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
1193 TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1194 arrGuard(TfailedApiNode, MAX_NODES);
1195 capiConnectClosing[TfailedApiNode]--;
1196 releaseApiCon(signal, TapiConnectptr);
1197 TlocalApiConnectptr.p->apiFailState = ZFALSE;
1198 if (capiConnectClosing[TfailedApiNode] == 0) {
1199 jam();
1200 signal->theData[0] = TfailedApiNode;
1201 signal->theData[1] = cownref;
1202 sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
1203 }//if
1204 }//Dbtc::handleApiFailState()
1205
1206 /****************************************************************************
1207 * T C S E I Z E R E Q
1208 * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1209 * TRANSACTION
1210 * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1211 * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1212 ****************************************************************************/
execTCSEIZEREQ(Signal * signal)1213 void Dbtc::execTCSEIZEREQ(Signal* signal)
1214 {
1215 UintR tapiPointer;
1216 BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
1217
1218 jamEntry();
1219 tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1220 tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1221
1222 const NodeState::StartLevel sl =
1223 (NodeState::StartLevel)getNodeState().startLevel;
1224
1225 const NodeId senderNodeId = refToNode(tapiBlockref);
1226 const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1227
1228 {
1229 {
1230 if (!(sl == NodeState::SL_STARTED ||
1231 (sl == NodeState::SL_STARTING && local == true))) {
1232 jam();
1233
1234 Uint32 errCode = 0;
1235 if(!local)
1236 {
1237 switch(sl){
1238 case NodeState::SL_STARTING:
1239 errCode = ZSYSTEM_NOT_STARTED_ERROR;
1240 break;
1241 case NodeState::SL_STOPPING_1:
1242 case NodeState::SL_STOPPING_2:
1243 if (getNodeState().getSingleUserMode())
1244 break;
1245 case NodeState::SL_STOPPING_3:
1246 case NodeState::SL_STOPPING_4:
1247 if(getNodeState().stopping.systemShutdown)
1248 errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1249 else
1250 errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1251 break;
1252 case NodeState::SL_SINGLEUSER:
1253 break;
1254 default:
1255 errCode = ZWRONG_STATE;
1256 break;
1257 }
1258 if (errCode)
1259 {
1260 signal->theData[0] = tapiPointer;
1261 signal->theData[1] = errCode;
1262 sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1263 return;
1264 }
1265 }//if (!(sl == SL_SINGLEUSER))
1266 } //if
1267 }
1268 }
1269
1270 seizeApiConnect(signal);
1271 if (terrorCode == ZOK) {
1272 jam();
1273 apiConnectptr.p->ndbapiConnect = tapiPointer;
1274 apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1275 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1276 signal->theData[1] = apiConnectptr.i;
1277 sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 2, JBB);
1278 return;
1279 }
1280
1281 signal->theData[0] = tapiPointer;
1282 signal->theData[1] = terrorCode;
1283 sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1284 }//Dbtc::execTCSEIZEREQ()
1285
1286 /****************************************************************************/
1287 /* T C R E L E A S E Q */
1288 /* REQUEST TO RELEASE A CONNECT RECORD */
1289 /****************************************************************************/
execTCRELEASEREQ(Signal * signal)1290 void Dbtc::execTCRELEASEREQ(Signal* signal)
1291 {
1292 UintR tapiPointer;
1293 BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
1294
1295 jamEntry();
1296 tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1297 tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1298 tuserpointer = signal->theData[2];
1299 if (tapiPointer >= capiConnectFilesize) {
1300 jam();
1301 signal->theData[0] = tuserpointer;
1302 signal->theData[1] = ZINVALID_CONNECTION;
1303 signal->theData[2] = __LINE__;
1304 sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1305 return;
1306 } else {
1307 jam();
1308 apiConnectptr.i = tapiPointer;
1309 }//if
1310 ptrAss(apiConnectptr, apiConnectRecord);
1311 if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
1312 jam();
1313 signal->theData[0] = tuserpointer;
1314 sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1315 } else {
1316 if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
1317 if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
1318 (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
1319 apiConnectptr.p->abortState == AS_IDLE) ||
1320 (apiConnectptr.p->apiConnectstate == CS_STARTED &&
1321 apiConnectptr.p->firstTcConnect == RNIL))
1322 {
1323 jam(); /* JUST REPLY OK */
1324 apiConnectptr.p->m_transaction_nodes.clear();
1325 releaseApiCon(signal, apiConnectptr.i);
1326 signal->theData[0] = tuserpointer;
1327 sendSignal(tapiBlockref,
1328 GSN_TCRELEASECONF, signal, 1, JBB);
1329 } else {
1330 jam();
1331 signal->theData[0] = tuserpointer;
1332 signal->theData[1] = ZINVALID_CONNECTION;
1333 signal->theData[2] = __LINE__;
1334 signal->theData[3] = apiConnectptr.p->apiConnectstate;
1335 sendSignal(tapiBlockref,
1336 GSN_TCRELEASEREF, signal, 4, JBB);
1337 }
1338 } else {
1339 jam();
1340 signal->theData[0] = tuserpointer;
1341 signal->theData[1] = ZINVALID_CONNECTION;
1342 signal->theData[2] = __LINE__;
1343 signal->theData[3] = tapiBlockref;
1344 signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1345 sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1346 }//if
1347 }//if
1348 }//Dbtc::execTCRELEASEREQ()
1349
1350 /****************************************************************************/
1351 // Error Handling for TCKEYREQ messages
1352 /****************************************************************************/
signalErrorRefuseLab(Signal * signal)1353 void Dbtc::signalErrorRefuseLab(Signal* signal)
1354 {
1355 ptrGuard(apiConnectptr);
1356 if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1357 jam();
1358 apiConnectptr.p->abortState = AS_IDLE;
1359 apiConnectptr.p->apiConnectstate = CS_ABORTING;
1360 }//if
1361 sendSignalErrorRefuseLab(signal);
1362 }//Dbtc::signalErrorRefuseLab()
1363
sendSignalErrorRefuseLab(Signal * signal)1364 void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
1365 {
1366 ndbassert(false);
1367 ptrGuard(apiConnectptr);
1368 if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1369 jam();
1370 ndbrequire(false);
1371 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1372 signal->theData[1] = signal->theData[ttransid_ptr];
1373 signal->theData[2] = signal->theData[ttransid_ptr + 1];
1374 signal->theData[3] = ZSIGNAL_ERROR;
1375 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1376 signal, 4, JBB);
1377 }
1378 }//Dbtc::sendSignalErrorRefuseLab()
1379
abortBeginErrorLab(Signal * signal)1380 void Dbtc::abortBeginErrorLab(Signal* signal)
1381 {
1382 apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1383 apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1384 abortErrorLab(signal);
1385 }//Dbtc::abortBeginErrorLab()
1386
printState(Signal * signal,int place)1387 void Dbtc::printState(Signal* signal, int place)
1388 {
1389 #ifdef VM_TRACE // Change to if 0 to disable these printouts
1390 ndbout << "-- Dbtc::printState -- " << endl;
1391 ndbout << "Received from place = " << place
1392 << " apiConnectptr.i = " << apiConnectptr.i
1393 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
1394 ndbout << "ctcTimer = " << ctcTimer
1395 << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
1396 << " Transid = " << apiConnectptr.p->transid[0]
1397 << " " << apiConnectptr.p->transid[1] << endl;
1398 ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
1399 << " counter = " << apiConnectptr.p->counter
1400 << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
1401 << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
1402 ndbout << "abortState = " << apiConnectptr.p->abortState
1403 << " apiScanRec = " << apiConnectptr.p->apiScanRec
1404 << " returncode = " << apiConnectptr.p->returncode << endl;
1405 ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
1406 << " returnsignal = " << apiConnectptr.p->returnsignal
1407 << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
1408 if (apiConnectptr.p->cachePtr != RNIL) {
1409 jam();
1410 CacheRecord *localCacheRecord = cacheRecord;
1411 UintR TcacheFilesize = ccacheFilesize;
1412 UintR TcachePtr = apiConnectptr.p->cachePtr;
1413 if (TcachePtr < TcacheFilesize) {
1414 jam();
1415 CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1416 ndbout << "currReclenAi = " << regCachePtr->currReclenAi
1417 << " attrlength = " << regCachePtr->attrlength
1418 << " tableref = " << regCachePtr->tableref
1419 << " keylen = " << regCachePtr->keylen << endl;
1420 } else {
1421 jam();
1422 systemErrorLab(signal, __LINE__);
1423 }//if
1424 }//if
1425 #endif
1426 return;
1427 }//Dbtc::printState()
1428
1429 void
TCKEY_abort(Signal * signal,int place)1430 Dbtc::TCKEY_abort(Signal* signal, int place)
1431 {
1432 switch (place) {
1433 case 0:
1434 jam();
1435 terrorCode = ZSTATE_ERROR;
1436 apiConnectptr.p->firstTcConnect = RNIL;
1437 printState(signal, 4);
1438 abortBeginErrorLab(signal);
1439 return;
1440 case 1:
1441 jam();
1442 printState(signal, 3);
1443 sendSignalErrorRefuseLab(signal);
1444 return;
1445 case 2:{
1446 printState(signal, 6);
1447 const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
1448 const Uint32 t1 = tcKeyReq->transId1;
1449 const Uint32 t2 = tcKeyReq->transId2;
1450 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1451 signal->theData[1] = t1;
1452 signal->theData[2] = t2;
1453 signal->theData[3] = ZABORT_ERROR;
1454 ndbrequire(false);
1455 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1456 signal, 4, JBB);
1457 return;
1458 }
1459 case 3:
1460 jam();
1461 printState(signal, 7);
1462 noFreeConnectionErrorLab(signal);
1463 return;
1464 case 4:
1465 jam();
1466 terrorCode = ZERO_KEYLEN_ERROR;
1467 releaseAtErrorLab(signal);
1468 return;
1469 case 5:
1470 jam();
1471 terrorCode = ZNO_AI_WITH_UPDATE;
1472 releaseAtErrorLab(signal);
1473 return;
1474 case 6:
1475 jam();
1476 warningHandlerLab(signal, __LINE__);
1477 return;
1478
1479 case 7:
1480 jam();
1481 tabStateErrorLab(signal);
1482 return;
1483
1484 case 8:
1485 jam();
1486 wrongSchemaVersionErrorLab(signal);
1487 return;
1488
1489 case 9:
1490 jam();
1491 terrorCode = ZSTATE_ERROR;
1492 releaseAtErrorLab(signal);
1493 return;
1494
1495 case 10:
1496 jam();
1497 systemErrorLab(signal, __LINE__);
1498 return;
1499
1500 case 11:
1501 jam();
1502 terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
1503 releaseAtErrorLab(signal);
1504 return;
1505
1506 case 12:
1507 jam();
1508 terrorCode = ZSIMPLE_READ_WITHOUT_AI;
1509 releaseAtErrorLab(signal);
1510 return;
1511
1512 case 13:
1513 jam();
1514 switch (tcConnectptr.p->tcConnectstate) {
1515 case OS_WAIT_KEYINFO:
1516 jam();
1517 printState(signal, 8);
1518 terrorCode = ZSTATE_ERROR;
1519 abortErrorLab(signal);
1520 return;
1521 default:
1522 jam();
1523 /********************************************************************/
1524 /* MISMATCH BETWEEN STATE ON API CONNECTION AND THIS */
1525 /* PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB */
1526 /* INTERNAL ERROR. */
1527 /********************************************************************/
1528 systemErrorLab(signal, __LINE__);
1529 return;
1530 }//switch
1531 return;
1532
1533 case 15:
1534 jam();
1535 terrorCode = ZSCAN_NODE_ERROR;
1536 releaseAtErrorLab(signal);
1537 return;
1538
1539 case 16:
1540 jam();
1541 systemErrorLab(signal, __LINE__);
1542 return;
1543
1544 case 17:
1545 jam();
1546 systemErrorLab(signal, __LINE__);
1547 return;
1548
1549 case 18:
1550 jam();
1551 warningHandlerLab(signal, __LINE__);
1552 return;
1553
1554 case 19:
1555 jam();
1556 return;
1557
1558 case 20:
1559 jam();
1560 warningHandlerLab(signal, __LINE__);
1561 return;
1562
1563 case 21:
1564 jam();
1565 systemErrorLab(signal, __LINE__);
1566 return;
1567
1568 case 22:
1569 jam();
1570 systemErrorLab(signal, __LINE__);
1571 return;
1572
1573 case 23:
1574 jam();
1575 systemErrorLab(signal, __LINE__);
1576 return;
1577
1578 case 24:
1579 jam();
1580 seizeAttrbuferrorLab(signal);
1581 return;
1582
1583 case 25:
1584 jam();
1585 warningHandlerLab(signal, __LINE__);
1586 return;
1587
1588 case 26:
1589 jam();
1590 return;
1591
1592 case 27:
1593 systemErrorLab(signal, __LINE__);
1594 jam();
1595 return;
1596
1597 case 28:
1598 jam();
1599 // NOT USED
1600 return;
1601
1602 case 29:
1603 jam();
1604 systemErrorLab(signal, __LINE__);
1605 return;
1606
1607 case 30:
1608 jam();
1609 systemErrorLab(signal, __LINE__);
1610 return;
1611
1612 case 31:
1613 jam();
1614 systemErrorLab(signal, __LINE__);
1615 return;
1616
1617 case 32:
1618 jam();
1619 systemErrorLab(signal, __LINE__);
1620 return;
1621
1622 case 33:
1623 jam();
1624 systemErrorLab(signal, __LINE__);
1625 return;
1626
1627 case 34:
1628 jam();
1629 systemErrorLab(signal, __LINE__);
1630 return;
1631
1632 case 35:
1633 jam();
1634 systemErrorLab(signal, __LINE__);
1635 return;
1636
1637 case 36:
1638 jam();
1639 systemErrorLab(signal, __LINE__);
1640 return;
1641
1642 case 37:
1643 jam();
1644 systemErrorLab(signal, __LINE__);
1645 return;
1646
1647 case 38:
1648 jam();
1649 systemErrorLab(signal, __LINE__);
1650 return;
1651
1652 case 39:
1653 jam();
1654 systemErrorLab(signal, __LINE__);
1655 return;
1656
1657 case 40:
1658 jam();
1659 systemErrorLab(signal, __LINE__);
1660 return;
1661
1662 case 41:
1663 jam();
1664 systemErrorLab(signal, __LINE__);
1665 return;
1666
1667 case 42:
1668 jam();
1669 systemErrorLab(signal, __LINE__);
1670 return;
1671
1672 case 43:
1673 jam();
1674 systemErrorLab(signal, __LINE__);
1675 return;
1676
1677 case 44:
1678 jam();
1679 systemErrorLab(signal, __LINE__);
1680 return;
1681
1682 case 45:
1683 jam();
1684 systemErrorLab(signal, __LINE__);
1685 return;
1686
1687 case 46:
1688 jam();
1689 systemErrorLab(signal, __LINE__);
1690 return;
1691
1692 case 47:
1693 jam();
1694 terrorCode = apiConnectptr.p->returncode;
1695 releaseAtErrorLab(signal);
1696 return;
1697
1698 case 48:
1699 jam();
1700 terrorCode = ZCOMMIT_TYPE_ERROR;
1701 releaseAtErrorLab(signal);
1702 return;
1703
1704 case 49:
1705 jam();
1706 abortErrorLab(signal);
1707 return;
1708
1709 case 50:
1710 jam();
1711 systemErrorLab(signal, __LINE__);
1712 return;
1713
1714 case 51:
1715 jam();
1716 abortErrorLab(signal);
1717 return;
1718
1719 case 52:
1720 jam();
1721 abortErrorLab(signal);
1722 return;
1723
1724 case 53:
1725 jam();
1726 abortErrorLab(signal);
1727 return;
1728
1729 case 54:
1730 jam();
1731 abortErrorLab(signal);
1732 return;
1733
1734 case 55:
1735 jam();
1736 printState(signal, 5);
1737 sendSignalErrorRefuseLab(signal);
1738 return;
1739
1740 case 56:{
1741 jam();
1742 terrorCode = ZNO_FREE_TC_MARKER;
1743 abortErrorLab(signal);
1744 return;
1745 }
1746 case 57:{
1747 jam();
1748 /**
1749 * Initialize object before starting error handling
1750 */
1751 initApiConnectRec(signal, apiConnectptr.p, true);
1752 start_failure:
1753 switch(getNodeState().startLevel){
1754 case NodeState::SL_STOPPING_2:
1755 if (getNodeState().getSingleUserMode())
1756 {
1757 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1758 break;
1759 }
1760 case NodeState::SL_STOPPING_3:
1761 case NodeState::SL_STOPPING_4:
1762 if(getNodeState().stopping.systemShutdown)
1763 terrorCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1764 else
1765 terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1766 break;
1767 case NodeState::SL_SINGLEUSER:
1768 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1769 break;
1770 case NodeState::SL_STOPPING_1:
1771 if (getNodeState().getSingleUserMode())
1772 {
1773 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1774 break;
1775 }
1776 default:
1777 terrorCode = ZWRONG_STATE;
1778 break;
1779 }
1780 abortErrorLab(signal);
1781 return;
1782 }
1783
1784 case 58:{
1785 jam();
1786 releaseAtErrorLab(signal);
1787 return;
1788 }
1789
1790 case 59:{
1791 jam();
1792 terrorCode = ZABORTINPROGRESS;
1793 abortErrorLab(signal);
1794 return;
1795 }
1796
1797 case 60:
1798 {
1799 jam();
1800 initApiConnectRec(signal, apiConnectptr.p, true);
1801 apiConnectptr.p->m_exec_flag = 1;
1802 goto start_failure;
1803 }
1804 default:
1805 jam();
1806 systemErrorLab(signal, __LINE__);
1807 return;
1808 }//switch
1809 }
1810
1811 static
1812 inline
1813 bool
compare_transid(Uint32 * val0,Uint32 * val1)1814 compare_transid(Uint32* val0, Uint32* val1)
1815 {
1816 Uint32 tmp0 = val0[0] ^ val1[0];
1817 Uint32 tmp1 = val0[1] ^ val1[1];
1818 return (tmp0 | tmp1) == 0;
1819 }
1820
execKEYINFO(Signal * signal)1821 void Dbtc::execKEYINFO(Signal* signal)
1822 {
1823 jamEntry();
1824 apiConnectptr.i = signal->theData[0];
1825 tmaxData = 20;
1826 if (apiConnectptr.i >= capiConnectFilesize) {
1827 TCKEY_abort(signal, 18);
1828 return;
1829 }//if
1830 ptrAss(apiConnectptr, apiConnectRecord);
1831 ttransid_ptr = 1;
1832 if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
1833 {
1834 TCKEY_abort(signal, 19);
1835 return;
1836 }//if
1837 switch (apiConnectptr.p->apiConnectstate) {
1838 case CS_RECEIVING:
1839 case CS_REC_COMMITTING:
1840 case CS_START_SCAN:
1841 jam();
1842 /*empty*/;
1843 break;
1844 /* OK */
1845 case CS_ABORTING:
1846 jam();
1847 return; /* IGNORE */
1848 case CS_CONNECTED:
1849 jam();
1850 /****************************************************************>*/
1851 /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
1852 /* SET STATE TO ABORTING. */
1853 /****************************************************************>*/
1854 printState(signal, 11);
1855 signalErrorRefuseLab(signal);
1856 return;
1857 case CS_STARTED:
1858 jam();
1859 /****************************************************************>*/
1860 /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
1861 /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
1862 /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
1863 /****************************************************************>*/
1864 terrorCode = ZSIGNAL_ERROR;
1865 printState(signal, 2);
1866 abortErrorLab(signal);
1867 return;
1868 default:
1869 jam();
1870 warningHandlerLab(signal, __LINE__);
1871 return;
1872 }//switch
1873
1874 CacheRecord *localCacheRecord = cacheRecord;
1875 UintR TcacheFilesize = ccacheFilesize;
1876 UintR TcachePtr = apiConnectptr.p->cachePtr;
1877 UintR TtcTimer = ctcTimer;
1878 CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1879 if (TcachePtr >= TcacheFilesize) {
1880 TCKEY_abort(signal, 42);
1881 return;
1882 }//if
1883 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
1884 cachePtr.i = TcachePtr;
1885 cachePtr.p = regCachePtr;
1886
1887 tcConnectptr.i = apiConnectptr.p->lastTcConnect;
1888 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
1889 switch (tcConnectptr.p->tcConnectstate) {
1890 case OS_WAIT_KEYINFO:
1891 jam();
1892 tckeyreq020Lab(signal);
1893 return;
1894 case OS_WAIT_SCAN:
1895 break;
1896 default:
1897 jam();
1898 terrorCode = ZSTATE_ERROR;
1899 abortErrorLab(signal);
1900 return;
1901 }//switch
1902
1903 UintR TdataPos = 0;
1904 UintR TkeyLen = regCachePtr->keylen;
1905 UintR Tlen = regCachePtr->save1;
1906
1907 do {
1908 if (cfirstfreeDatabuf == RNIL) {
1909 jam();
1910 seizeDatabuferrorLab(signal);
1911 return;
1912 }//if
1913 linkKeybuf(signal);
1914 arrGuard(TdataPos, 19);
1915 databufptr.p->data[0] = signal->theData[TdataPos + 3];
1916 databufptr.p->data[1] = signal->theData[TdataPos + 4];
1917 databufptr.p->data[2] = signal->theData[TdataPos + 5];
1918 databufptr.p->data[3] = signal->theData[TdataPos + 6];
1919 Tlen = Tlen + 4;
1920 TdataPos = TdataPos + 4;
1921 if (Tlen < TkeyLen) {
1922 jam();
1923 if (TdataPos >= tmaxData) {
1924 jam();
1925 /*----------------------------------------------------*/
1926 /** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9 **/
1927 /** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP **/
1928 /** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE **/
1929 /** PROGRAM RETURNS TO LABEL TCKEYREQ020 **/
1930 /*----------------------------------------------------*/
1931 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
1932 regCachePtr->save1 = Tlen;
1933 return;
1934 }//if
1935 } else {
1936 jam();
1937 return;
1938 }//if
1939 } while (1);
1940 return;
1941 }//Dbtc::execKEYINFO()
1942
1943 /*---------------------------------------------------------------------------*/
1944 /* */
1945 /* MORE THAN FOUR WORDS OF KEY DATA. WE NEED TO PACK THIS IN KEYINFO SIGNALS.*/
1946 /* WE WILL ALWAYS PACK 4 WORDS AT A TIME. */
1947 /*---------------------------------------------------------------------------*/
packKeyData000Lab(Signal * signal,BlockReference TBRef,Uint32 totalLen)1948 void Dbtc::packKeyData000Lab(Signal* signal,
1949 BlockReference TBRef,
1950 Uint32 totalLen)
1951 {
1952 CacheRecord * const regCachePtr = cachePtr.p;
1953
1954 jam();
1955 Uint32 len = 0;
1956 databufptr.i = regCachePtr->firstKeybuf;
1957 signal->theData[0] = tcConnectptr.i;
1958 signal->theData[1] = apiConnectptr.p->transid[0];
1959 signal->theData[2] = apiConnectptr.p->transid[1];
1960 Uint32 * dst = signal->theData+3;
1961 ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
1962
1963 do {
1964 jam();
1965 databufptr.i = databufptr.p->nextDatabuf;
1966 dst[len + 0] = databufptr.p->data[0];
1967 dst[len + 1] = databufptr.p->data[1];
1968 dst[len + 2] = databufptr.p->data[2];
1969 dst[len + 3] = databufptr.p->data[3];
1970 len += 4;
1971 if (totalLen <= 4) {
1972 jam();
1973 /*---------------------------------------------------------------------*/
1974 /* LAST PACK OF KEY DATA HAVE BEEN SENT */
1975 /*---------------------------------------------------------------------*/
1976 /* THERE WERE UNSENT INFORMATION, SEND IT. */
1977 /*---------------------------------------------------------------------*/
1978 sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
1979 return;
1980 } else if(len == KeyInfo::DataLength){
1981 jam();
1982 len = 0;
1983 sendSignal(TBRef, GSN_KEYINFO, signal, 3 + KeyInfo::DataLength, JBB);
1984 }
1985 totalLen -= 4;
1986 ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
1987 } while (1);
1988 }//Dbtc::packKeyData000Lab()
1989
tckeyreq020Lab(Signal * signal)1990 void Dbtc::tckeyreq020Lab(Signal* signal)
1991 {
1992 CacheRecord * const regCachePtr = cachePtr.p;
1993 UintR TdataPos = 0;
1994 UintR TkeyLen = regCachePtr->keylen;
1995 UintR Tlen = regCachePtr->save1;
1996
1997 do {
1998 if (cfirstfreeDatabuf == RNIL) {
1999 jam();
2000 seizeDatabuferrorLab(signal);
2001 return;
2002 }//if
2003 linkKeybuf(signal);
2004 arrGuard(TdataPos, 19);
2005 databufptr.p->data[0] = signal->theData[TdataPos + 3];
2006 databufptr.p->data[1] = signal->theData[TdataPos + 4];
2007 databufptr.p->data[2] = signal->theData[TdataPos + 5];
2008 databufptr.p->data[3] = signal->theData[TdataPos + 6];
2009 Tlen = Tlen + 4;
2010 TdataPos = TdataPos + 4;
2011 if (Tlen < TkeyLen) {
2012 jam();
2013 if (TdataPos >= tmaxData) {
2014 jam();
2015 /*----------------------------------------------------*/
2016 /** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9 **/
2017 /** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP **/
2018 /** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE **/
2019 /** PROGRAM RETURNS TO LABEL TCKEYREQ020 **/
2020 /*----------------------------------------------------*/
2021 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2022 regCachePtr->save1 = Tlen;
2023 tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2024 return;
2025 }//if
2026 } else {
2027 jam();
2028 tckeyreq050Lab(signal);
2029 return;
2030 }//if
2031 } while (1);
2032 return;
2033 }//Dbtc::tckeyreq020Lab()
2034
2035 /* ------------------------------------------------------------------------- */
2036 /* ------- SAVE ATTRIBUTE INFORMATION IN OPERATION RECORD ------- */
2037 /* ------------------------------------------------------------------------- */
saveAttrbuf(Signal * signal)2038 void Dbtc::saveAttrbuf(Signal* signal)
2039 {
2040 CacheRecord * const regCachePtr = cachePtr.p;
2041 UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
2042 UintR TattrbufFilesize = cattrbufFilesize;
2043 UintR TTcfirstAttrbuf = regCachePtr->firstAttrbuf;
2044 UintR Tlen = signal->length() - 3;
2045 AttrbufRecord *localAttrbufRecord = attrbufRecord;
2046
2047 AttrbufRecord * const regAttrPtr = &localAttrbufRecord[TfirstfreeAttrbuf];
2048 if (TfirstfreeAttrbuf >= TattrbufFilesize) {
2049 TCKEY_abort(signal, 21);
2050 return;
2051 }//if
2052 UintR Tnext = regAttrPtr->attrbuf[ZINBUF_NEXT];
2053 if (TTcfirstAttrbuf == RNIL) {
2054 jam();
2055 regCachePtr->firstAttrbuf = TfirstfreeAttrbuf;
2056 } else {
2057 AttrbufRecordPtr saAttrbufptr;
2058
2059 saAttrbufptr.i = regCachePtr->lastAttrbuf;
2060 jam();
2061 if (saAttrbufptr.i >= TattrbufFilesize) {
2062 TCKEY_abort(signal, 22);
2063 return;
2064 }//if
2065 saAttrbufptr.p = &localAttrbufRecord[saAttrbufptr.i];
2066 saAttrbufptr.p->attrbuf[ZINBUF_NEXT] = TfirstfreeAttrbuf;
2067 }//if
2068
2069 cfirstfreeAttrbuf = Tnext;
2070 regAttrPtr->attrbuf[ZINBUF_NEXT] = RNIL;
2071 regCachePtr->lastAttrbuf = TfirstfreeAttrbuf;
2072 regAttrPtr->attrbuf[ZINBUF_DATA_LEN] = Tlen;
2073
2074 UintR Tdata1 = signal->theData[3];
2075 UintR Tdata2 = signal->theData[4];
2076 UintR Tdata3 = signal->theData[5];
2077 UintR Tdata4 = signal->theData[6];
2078 UintR Tdata5 = signal->theData[7];
2079 UintR Tdata6 = signal->theData[8];
2080 UintR Tdata7 = signal->theData[9];
2081 UintR Tdata8 = signal->theData[10];
2082
2083 regAttrPtr->attrbuf[0] = Tdata1;
2084 regAttrPtr->attrbuf[1] = Tdata2;
2085 regAttrPtr->attrbuf[2] = Tdata3;
2086 regAttrPtr->attrbuf[3] = Tdata4;
2087 regAttrPtr->attrbuf[4] = Tdata5;
2088 regAttrPtr->attrbuf[5] = Tdata6;
2089 regAttrPtr->attrbuf[6] = Tdata7;
2090 regAttrPtr->attrbuf[7] = Tdata8;
2091
2092 if (Tlen > 8) {
2093
2094 Tdata1 = signal->theData[11];
2095 Tdata2 = signal->theData[12];
2096 Tdata3 = signal->theData[13];
2097 Tdata4 = signal->theData[14];
2098 Tdata5 = signal->theData[15];
2099 Tdata6 = signal->theData[16];
2100 Tdata7 = signal->theData[17];
2101
2102 regAttrPtr->attrbuf[8] = Tdata1;
2103 regAttrPtr->attrbuf[9] = Tdata2;
2104 regAttrPtr->attrbuf[10] = Tdata3;
2105 regAttrPtr->attrbuf[11] = Tdata4;
2106 regAttrPtr->attrbuf[12] = Tdata5;
2107 regAttrPtr->attrbuf[13] = Tdata6;
2108 regAttrPtr->attrbuf[14] = Tdata7;
2109 jam();
2110 if (Tlen > 15) {
2111
2112 Tdata1 = signal->theData[18];
2113 Tdata2 = signal->theData[19];
2114 Tdata3 = signal->theData[20];
2115 Tdata4 = signal->theData[21];
2116 Tdata5 = signal->theData[22];
2117 Tdata6 = signal->theData[23];
2118 Tdata7 = signal->theData[24];
2119
2120 jam();
2121 regAttrPtr->attrbuf[15] = Tdata1;
2122 regAttrPtr->attrbuf[16] = Tdata2;
2123 regAttrPtr->attrbuf[17] = Tdata3;
2124 regAttrPtr->attrbuf[18] = Tdata4;
2125 regAttrPtr->attrbuf[19] = Tdata5;
2126 regAttrPtr->attrbuf[20] = Tdata6;
2127 regAttrPtr->attrbuf[21] = Tdata7;
2128 }//if
2129 }//if
2130 }//Dbtc::saveAttrbuf()
2131
execATTRINFO(Signal * signal)2132 void Dbtc::execATTRINFO(Signal* signal)
2133 {
2134 UintR Tdata1 = signal->theData[0];
2135 UintR Tlength = signal->length();
2136 UintR TapiConnectFilesize = capiConnectFilesize;
2137 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2138
2139 jamEntry();
2140 apiConnectptr.i = Tdata1;
2141 ttransid_ptr = 1;
2142 if (Tdata1 >= TapiConnectFilesize) {
2143 DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2144 TCKEY_abort(signal, 18);
2145 return;
2146 }//if
2147
2148 ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
2149 apiConnectptr.p = regApiPtr;
2150
2151 if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
2152 {
2153 DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2154 << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2155 TCKEY_abort(signal, 19);
2156 return;
2157 }//if
2158 if (Tlength < 4) {
2159 DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2160 TCKEY_abort(signal, 20);
2161 return;
2162 }
2163 Tlength -= 3;
2164 UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2165 UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2166 UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2167
2168 if (TcompBOTH) {
2169 jam();
2170 if (ERROR_INSERTED(8015)) {
2171 CLEAR_ERROR_INSERT_VALUE;
2172 return;
2173 }//if
2174 if (ERROR_INSERTED(8016)) {
2175 CLEAR_ERROR_INSERT_VALUE;
2176 return;
2177 }//if
2178 CacheRecord *localCacheRecord = cacheRecord;
2179 UintR TcacheFilesize = ccacheFilesize;
2180 UintR TcachePtr = regApiPtr->cachePtr;
2181 UintR TtcTimer = ctcTimer;
2182 CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2183 if (TcachePtr >= TcacheFilesize) {
2184 TCKEY_abort(signal, 43);
2185 return;
2186 }//if
2187 UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
2188 UintR TcurrReclenAi = regCachePtr->currReclenAi;
2189 UintR TattrLen = regCachePtr->attrlength;
2190
2191 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2192 cachePtr.i = TcachePtr;
2193 cachePtr.p = regCachePtr;
2194 TcurrReclenAi = TcurrReclenAi + Tlength;
2195 regCachePtr->currReclenAi = TcurrReclenAi;
2196 int TattrlengthRemain = TattrLen - TcurrReclenAi;
2197
2198 if (TfirstfreeAttrbuf == RNIL) {
2199 DEBUG("No more attrinfo buffers");
2200 TCKEY_abort(signal, 24);
2201 return;
2202 }//if
2203 saveAttrbuf(signal);
2204 if (TattrlengthRemain == 0) {
2205 /****************************************************************>*/
2206 /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
2207 /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2208 /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2209 /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
2210 /* OPERATIONS. */
2211 /****************************************************************>*/
2212 UintR TlastConnect = regApiPtr->lastTcConnect;
2213 if (TcompRECEIVING) {
2214 jam();
2215 regApiPtr->apiConnectstate = CS_STARTED;
2216 } else {
2217 jam();
2218 regApiPtr->apiConnectstate = CS_START_COMMITTING;
2219 }//if
2220 tcConnectptr.i = TlastConnect;
2221 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2222 attrinfoDihReceivedLab(signal);
2223 } else if (TattrlengthRemain < 0) {
2224 jam();
2225 DEBUG("ATTRINFO wrong total length="<<Tlength
2226 <<", TattrlengthRemain="<<TattrlengthRemain
2227 <<", TattrLen="<<TattrLen
2228 <<", TcurrReclenAi="<<TcurrReclenAi);
2229 tcConnectptr.i = regApiPtr->lastTcConnect;
2230 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2231 aiErrorLab(signal);
2232 }//if
2233 return;
2234 } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
2235 jam();
2236 scanAttrinfoLab(signal, Tlength);
2237 return;
2238 } else {
2239 switch (regApiPtr->apiConnectstate) {
2240 case CS_ABORTING:
2241 jam();
2242 /* JUST IGNORE THE SIGNAL*/
2243 // DEBUG("Drop ATTRINFO, CS_ABORTING");
2244 return;
2245 case CS_CONNECTED:
2246 jam();
2247 /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2248 // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2249 return;
2250 case CS_STARTED:
2251 jam();
2252 /****************************************************************>*/
2253 /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
2254 /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
2255 /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
2256 /****************************************************************>*/
2257 terrorCode = ZSIGNAL_ERROR;
2258 printState(signal, 1);
2259 abortErrorLab(signal);
2260 return;
2261 default:
2262 jam();
2263 /****************************************************************>*/
2264 /* SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2265 /* SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED. */
2266 /****************************************************************>*/
2267 DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2268 printState(signal, 9);
2269 return;
2270 }//switch
2271 }//if
2272 }//Dbtc::execATTRINFO()
2273
2274 /* *********************************************************************>> */
2275 /* */
2276 /* MODULE: HASH MODULE */
2277 /* DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION */
2278 /* *********************************************************************> */
hash(Signal * signal)2279 void Dbtc::hash(Signal* signal)
2280 {
2281 DatabufRecordPtr locDatabufptr;
2282 UintR ti;
2283 UintR Tdata0;
2284 UintR Tdata1;
2285 UintR Tdata2;
2286 UintR Tdata3;
2287 UintR* Tdata32;
2288
2289 CacheRecord * const regCachePtr = cachePtr.p;
2290 Tdata32 = signal->theData;
2291
2292 Tdata0 = regCachePtr->keydata[0];
2293 Tdata1 = regCachePtr->keydata[1];
2294 Tdata2 = regCachePtr->keydata[2];
2295 Tdata3 = regCachePtr->keydata[3];
2296 Tdata32[0] = Tdata0;
2297 Tdata32[1] = Tdata1;
2298 Tdata32[2] = Tdata2;
2299 Tdata32[3] = Tdata3;
2300 if (regCachePtr->keylen > 4) {
2301 locDatabufptr.i = regCachePtr->firstKeybuf;
2302 ti = 4;
2303 while (locDatabufptr.i != RNIL) {
2304 ptrCheckGuard(locDatabufptr, cdatabufFilesize, databufRecord);
2305 Tdata0 = locDatabufptr.p->data[0];
2306 Tdata1 = locDatabufptr.p->data[1];
2307 Tdata2 = locDatabufptr.p->data[2];
2308 Tdata3 = locDatabufptr.p->data[3];
2309 Tdata32[ti ] = Tdata0;
2310 Tdata32[ti + 1] = Tdata1;
2311 Tdata32[ti + 2] = Tdata2;
2312 Tdata32[ti + 3] = Tdata3;
2313 locDatabufptr.i = locDatabufptr.p->nextDatabuf;
2314 ti += 4;
2315 }//while
2316 }//if
2317
2318 UintR keylen = (UintR)regCachePtr->keylen;
2319 Uint32 distKey = regCachePtr->distributionKeyIndicator;
2320
2321 Uint32 tmp[4];
2322 if(!regCachePtr->m_special_hash)
2323 {
2324 md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2325 }
2326 else
2327 {
2328 handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2329 }
2330
2331 thashValue = tmp[0];
2332 if (distKey){
2333 jam();
2334 tdistrHashValue = regCachePtr->distributionKey;
2335 } else {
2336 jam();
2337 tdistrHashValue = tmp[1];
2338 }//if
2339 }//Dbtc::hash()
2340
2341 bool
handle_special_hash(Uint32 dstHash[4],Uint32 * src,Uint32 srcLen,Uint32 tabPtrI,bool distr)2342 Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
2343 Uint32 tabPtrI,
2344 bool distr)
2345 {
2346 Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
2347 const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2348 const bool hasVarKeys = tabPtrP->hasVarKeys;
2349 const bool hasCharAttr = tabPtrP->hasCharAttr;
2350 const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2351
2352 Uint32 *dst = (Uint32*)Tmp;
2353 Uint32 dstPos = 0;
2354 Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2355 Uint32 * keyPartLenPtr;
2356 if(hasCharAttr || (compute_distkey && hasVarKeys))
2357 {
2358 keyPartLenPtr = keyPartLen;
2359 dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
2360 if (unlikely(dstPos == 0))
2361 {
2362 goto error;
2363 }
2364 }
2365 else
2366 {
2367 dst = src;
2368 dstPos = srcLen;
2369 keyPartLenPtr = 0;
2370 }
2371
2372 md5_hash(dstHash, (Uint64*)dst, dstPos);
2373
2374 if(compute_distkey)
2375 {
2376 jam();
2377
2378 Uint32 tmp[4];
2379 Uint32 len = create_distr_key(tabPtrI, dst, keyPartLenPtr);
2380 md5_hash(tmp, (Uint64*)dst, len);
2381 dstHash[1] = tmp[1];
2382 }
2383 return true; // success
2384
2385 error:
2386 terrorCode = ZINVALID_KEY;
2387 return false;
2388 }
2389
2390 /*
2391 INIT_API_CONNECT_REC
2392 ---------------------------
2393 */
2394 /* ========================================================================= */
2395 /* ======= INIT_API_CONNECT_REC ======= */
2396 /* */
2397 /* ========================================================================= */
initApiConnectRec(Signal * signal,ApiConnectRecord * const regApiPtr,bool releaseIndexOperations)2398 void Dbtc::initApiConnectRec(Signal* signal,
2399 ApiConnectRecord * const regApiPtr,
2400 bool releaseIndexOperations)
2401 {
2402 const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2403 UintR TfailureNr = cfailure_nr;
2404 UintR TtransCount = c_counters.ctransCount;
2405 UintR Ttransid0 = tcKeyReq->transId1;
2406 UintR Ttransid1 = tcKeyReq->transId2;
2407
2408 regApiPtr->m_exec_flag = 0;
2409 regApiPtr->returncode = 0;
2410 regApiPtr->returnsignal = RS_TCKEYCONF;
2411 ndbassert(regApiPtr->firstTcConnect == RNIL);
2412 regApiPtr->firstTcConnect = RNIL;
2413 regApiPtr->lastTcConnect = RNIL;
2414 regApiPtr->globalcheckpointid = 0;
2415 regApiPtr->lqhkeyconfrec = 0;
2416 regApiPtr->lqhkeyreqrec = 0;
2417 regApiPtr->tckeyrec = 0;
2418 regApiPtr->tcindxrec = 0;
2419 regApiPtr->failureNr = TfailureNr;
2420 regApiPtr->transid[0] = Ttransid0;
2421 regApiPtr->transid[1] = Ttransid1;
2422 regApiPtr->commitAckMarker = RNIL;
2423 regApiPtr->buddyPtr = RNIL;
2424 regApiPtr->currSavePointId = 0;
2425 regApiPtr->m_transaction_nodes.clear();
2426 regApiPtr->singleUserMode = 0;
2427 // Trigger data
2428 releaseFiredTriggerData(®ApiPtr->theFiredTriggers),
2429 // Index data
2430 regApiPtr->indexOpReturn = false;
2431 regApiPtr->noIndexOp = 0;
2432 if(releaseIndexOperations)
2433 releaseAllSeizedIndexOperations(regApiPtr);
2434
2435 c_counters.ctransCount = TtransCount + 1;
2436 }//Dbtc::initApiConnectRec()
2437
2438 int
seizeTcRecord(Signal * signal)2439 Dbtc::seizeTcRecord(Signal* signal)
2440 {
2441 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2442 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
2443 UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
2444 UintR TtcConnectFilesize = ctcConnectFilesize;
2445 tcConnectptr.i = TfirstfreeTcConnect;
2446 if (TfirstfreeTcConnect >= TtcConnectFilesize) {
2447 int place = 3;
2448 if (TfirstfreeTcConnect != RNIL) {
2449 place = 10;
2450 }//if
2451 TCKEY_abort(signal, place);
2452 return 1;
2453 }//if
2454 //--------------------------------------------------------------------------
2455 // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
2456 //--------------------------------------------------------------------------
2457 TcConnectRecord * const regTcPtr =
2458 &localTcConnectRecord[TfirstfreeTcConnect];
2459
2460 UintR TconcurrentOp = c_counters.cconcurrentOp;
2461 UintR TlastTcConnect = regApiPtr->lastTcConnect;
2462 UintR TtcConnectptrIndex = tcConnectptr.i;
2463 TcConnectRecordPtr tmpTcConnectptr;
2464
2465 cfirstfreeTcConnect = regTcPtr->nextTcConnect;
2466 tcConnectptr.p = regTcPtr;
2467
2468 c_counters.cconcurrentOp = TconcurrentOp + 1;
2469 regTcPtr->prevTcConnect = TlastTcConnect;
2470 regTcPtr->nextTcConnect = RNIL;
2471 regTcPtr->accumulatingTriggerData.i = RNIL;
2472 regTcPtr->accumulatingTriggerData.p = NULL;
2473 regTcPtr->noFiredTriggers = 0;
2474 regTcPtr->noReceivedTriggers = 0;
2475 regTcPtr->triggerExecutionCount = 0;
2476 regTcPtr->triggeringOperation = RNIL;
2477 regTcPtr->isIndexOp = false;
2478 regTcPtr->indexOp = RNIL;
2479 regTcPtr->currentIndexId = RNIL;
2480
2481 regApiPtr->lastTcConnect = TtcConnectptrIndex;
2482
2483 if (TlastTcConnect == RNIL) {
2484 jam();
2485 regApiPtr->firstTcConnect = TtcConnectptrIndex;
2486 } else {
2487 tmpTcConnectptr.i = TlastTcConnect;
2488 jam();
2489 ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
2490 tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
2491 }//if
2492 return 0;
2493 }//Dbtc::seizeTcRecord()
2494
2495 int
seizeCacheRecord(Signal * signal)2496 Dbtc::seizeCacheRecord(Signal* signal)
2497 {
2498 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2499 UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2500 UintR TcacheFilesize = ccacheFilesize;
2501 CacheRecord *localCacheRecord = cacheRecord;
2502 if (TfirstfreeCacheRec >= TcacheFilesize) {
2503 TCKEY_abort(signal, 41);
2504 return 1;
2505 }//if
2506 CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
2507
2508 regApiPtr->cachePtr = TfirstfreeCacheRec;
2509 cfirstfreeCacheRec = regCachePtr->nextCacheRec;
2510 cachePtr.i = TfirstfreeCacheRec;
2511 cachePtr.p = regCachePtr;
2512
2513 #ifdef VM_TRACE
2514 // This is a good place to check that resources have
2515 // been properly released from CacheRecord
2516 ndbrequire(regCachePtr->firstKeybuf == RNIL);
2517 ndbrequire(regCachePtr->lastKeybuf == RNIL);
2518 #endif
2519 regCachePtr->firstKeybuf = RNIL;
2520 regCachePtr->lastKeybuf = RNIL;
2521 regCachePtr->firstAttrbuf = RNIL;
2522 regCachePtr->lastAttrbuf = RNIL;
2523 regCachePtr->currReclenAi = 0;
2524 return 0;
2525 }//Dbtc::seizeCacheRecord()
2526
2527 /*****************************************************************************/
2528 /* T C K E Y R E Q */
2529 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN */
2530 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST */
2531 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES */
2532 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA */
2533 /*****************************************************************************/
execTCKEYREQ(Signal * signal)2534 void Dbtc::execTCKEYREQ(Signal* signal)
2535 {
2536 Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
2537 UintR compare_transid1, compare_transid2;
2538 UintR titcLenAiInTckeyreq;
2539 UintR TkeyLength;
2540 const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
2541 UintR Treqinfo;
2542
2543 jamEntry();
2544 /*-------------------------------------------------------------------------
2545 * Common error routines are used for several signals, they need to know
2546 * where to find the transaction identifier in the signal.
2547 *-------------------------------------------------------------------------*/
2548 const UintR TapiIndex = tcKeyReq->apiConnectPtr;
2549 const UintR TapiMaxIndex = capiConnectFilesize;
2550 const UintR TtabIndex = tcKeyReq->tableId;
2551 const UintR TtabMaxIndex = ctabrecFilesize;
2552 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2553
2554 ttransid_ptr = 6;
2555 apiConnectptr.i = TapiIndex;
2556 if (TapiIndex >= TapiMaxIndex) {
2557 TCKEY_abort(signal, 6);
2558 return;
2559 }//if
2560 if (TtabIndex >= TtabMaxIndex) {
2561 TCKEY_abort(signal, 7);
2562 return;
2563 }//if
2564
2565 Treqinfo = tcKeyReq->requestInfo;
2566 //--------------------------------------------------------------------------
2567 // Optimised version of ptrAss(tabptr, tableRecord)
2568 // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
2569 //--------------------------------------------------------------------------
2570 ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
2571 apiConnectptr.p = regApiPtr;
2572
2573 Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
2574 Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo);
2575
2576 Uint8 isIndexOp = regApiPtr->isIndexOp;
2577 bool isIndexOpReturn = regApiPtr->indexOpReturn;
2578 regApiPtr->isIndexOp = false; // Reset marker
2579 regApiPtr->m_exec_flag |= TexecFlag;
2580 TableRecordPtr localTabptr;
2581 localTabptr.i = TtabIndex;
2582 localTabptr.p = &tableRecord[TtabIndex];
2583 switch (regApiPtr->apiConnectstate) {
2584 case CS_CONNECTED:{
2585 if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2586 //---------------------------------------------------------------------
2587 // Initialise API connect record if transaction is started.
2588 //---------------------------------------------------------------------
2589 jam();
2590 initApiConnectRec(signal, regApiPtr);
2591 regApiPtr->m_exec_flag = TexecFlag;
2592 } else {
2593 if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2594 /*------------------------------------------------------------------
2595 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
2596 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
2597 * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
2598 *-----------------------------------------------------------------*/
2599 TCKEY_abort(signal, 0);
2600 return;
2601 } else {
2602 /**
2603 * getAllowStartTransaction(sendersNodeId) == false
2604 */
2605 TCKEY_abort(signal, TexecFlag ? 60 : 57);
2606 return;
2607 }//if
2608 }
2609 }
2610 break;
2611 case CS_STARTED:
2612 if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
2613 {
2614 /**
2615 * If last operation in last transaction was a simple/dirty read
2616 * it does not have to be committed or rollbacked hence,
2617 * the state will be CS_STARTED
2618 */
2619 jam();
2620 if (unlikely(getNodeState().getSingleUserMode()) &&
2621 getNodeState().getSingleUserApi() != sendersNodeId &&
2622 !localTabptr.p->singleUserMode)
2623 {
2624 TCKEY_abort(signal, TexecFlag ? 60 : 57);
2625 return;
2626 }
2627 initApiConnectRec(signal, regApiPtr);
2628 regApiPtr->m_exec_flag = TexecFlag;
2629 } else {
2630 //----------------------------------------------------------------------
2631 // Transaction is started already.
2632 // Check that the operation is on the same transaction.
2633 //-----------------------------------------------------------------------
2634 compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
2635 compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
2636 jam();
2637 compare_transid1 = compare_transid1 | compare_transid2;
2638 if (compare_transid1 != 0) {
2639 TCKEY_abort(signal, 1);
2640 return;
2641 }//if
2642 }
2643 break;
2644 case CS_ABORTING:
2645 if (regApiPtr->abortState == AS_IDLE) {
2646 if (TstartFlag == 1) {
2647 if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
2648 TCKEY_abort(signal, TexecFlag ? 60 : 57);
2649 return;
2650 }
2651 //--------------------------------------------------------------------
2652 // Previous transaction had been aborted and the abort was completed.
2653 // It is then OK to start a new transaction again.
2654 //--------------------------------------------------------------------
2655 jam();
2656 initApiConnectRec(signal, regApiPtr);
2657 regApiPtr->m_exec_flag = TexecFlag;
2658 } else if(TexecFlag) {
2659 TCKEY_abort(signal, 59);
2660 return;
2661 } else {
2662 //--------------------------------------------------------------------
2663 // The current transaction was aborted successfully.
2664 // We will not do anything before we receive an operation
2665 // with a start indicator. We will ignore this signal.
2666 //--------------------------------------------------------------------
2667 jam();
2668 DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
2669 return;
2670 }//if
2671 } else {
2672 //----------------------------------------------------------------------
2673 // Previous transaction is still aborting
2674 //----------------------------------------------------------------------
2675 jam();
2676 if (TstartFlag == 1) {
2677 //--------------------------------------------------------------------
2678 // If a new transaction tries to start while the old is
2679 // still aborting, we will report this to the starting API.
2680 //--------------------------------------------------------------------
2681 TCKEY_abort(signal, 2);
2682 return;
2683 } else if(TexecFlag) {
2684 TCKEY_abort(signal, 59);
2685 return;
2686 }
2687 //----------------------------------------------------------------------
2688 // Ignore signals without start indicator set when aborting transaction.
2689 //----------------------------------------------------------------------
2690 DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
2691 return;
2692 }//if
2693 break;
2694 case CS_START_COMMITTING:
2695 jam();
2696 if(isIndexOpReturn || TcKeyReq::getExecutingTrigger(Treqinfo)){
2697 break;
2698 }
2699 default:
2700 jam();
2701 /*----------------------------------------------------------------------
2702 * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
2703 * WHEN IT WAS NOT EXPECTED TO.
2704 * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
2705 * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
2706 * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
2707 * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
2708 * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
2709 *---------------------------------------------------------------------*/
2710 TCKEY_abort(signal, 55);
2711 return;
2712 }//switch
2713
2714 if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
2715 ;
2716 } else {
2717 /*-----------------------------------------------------------------------*/
2718 /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT. */
2719 /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED. */
2720 /*-----------------------------------------------------------------------*/
2721 TCKEY_abort(signal, 8);
2722 return;
2723 }//if
2724
2725 //-------------------------------------------------------------------------
2726 // Error Insertion for testing purposes. Test to see what happens when no
2727 // more TC records available.
2728 //-------------------------------------------------------------------------
2729 if (ERROR_INSERTED(8032)) {
2730 TCKEY_abort(signal, 3);
2731 return;
2732 }//if
2733
2734 if (seizeTcRecord(signal) != 0) {
2735 return;
2736 }//if
2737
2738 if (seizeCacheRecord(signal) != 0) {
2739 return;
2740 }//if
2741
2742 TcConnectRecord * const regTcPtr = tcConnectptr.p;
2743 CacheRecord * const regCachePtr = cachePtr.p;
2744
2745 /*
2746 INIT_TC_CONNECT_REC
2747 -------------------------
2748 */
2749 /* ---------------------------------------------------------------------- */
2750 /* ------- INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS ------- */
2751 /* */
2752 /* ---------------------------------------------------------------------- */
2753
2754 UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen);
2755 UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
2756 regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
2757 regCachePtr->apiVersionNo = TapiVersionNo;
2758
2759 UintR TapiConnectptrIndex = apiConnectptr.i;
2760 UintR TsenderData = tcKeyReq->senderData;
2761 UintR TattrLen = TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
2762 UintR TattrinfoCount = c_counters.cattrinfoCount;
2763
2764 regTcPtr->apiConnect = TapiConnectptrIndex;
2765 regTcPtr->clientData = TsenderData;
2766 regTcPtr->commitAckMarker = RNIL;
2767 regTcPtr->isIndexOp = isIndexOp;
2768 regTcPtr->indexOp = regApiPtr->executingIndexOp;
2769 regTcPtr->savePointId = regApiPtr->currSavePointId;
2770 regApiPtr->executingIndexOp = RNIL;
2771
2772 regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
2773
2774 if (TcKeyReq::getExecutingTrigger(Treqinfo)) {
2775 // Save the TcOperationPtr for fireing operation
2776 regTcPtr->triggeringOperation = TsenderData;
2777 }
2778
2779 if (TexecFlag){
2780 Uint32 currSPId = regApiPtr->currSavePointId;
2781 regApiPtr->currSavePointId = ++currSPId;
2782 }
2783
2784 regCachePtr->attrlength = TattrLen;
2785 c_counters.cattrinfoCount = TattrinfoCount + TattrLen;
2786
2787 UintR TtabptrIndex = localTabptr.i;
2788 UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
2789 Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
2790 regCachePtr->tableref = TtabptrIndex;
2791 regCachePtr->schemaVersion = TtableSchemaVersion;
2792 regTcPtr->operation = TOperationType;
2793
2794 Uint8 TSimpleFlag = TcKeyReq::getSimpleFlag(Treqinfo);
2795 Uint8 TDirtyFlag = TcKeyReq::getDirtyFlag(Treqinfo);
2796 Uint8 TInterpretedFlag = TcKeyReq::getInterpretedFlag(Treqinfo);
2797 Uint8 TDistrKeyFlag = TcKeyReq::getDistributionKeyFlag(Treqinfo);
2798 Uint8 TNoDiskFlag = TcKeyReq::getNoDiskFlag(Treqinfo);
2799 Uint8 TexecuteFlag = TexecFlag;
2800
2801 regTcPtr->dirtyOp = TDirtyFlag;
2802 regTcPtr->opSimple = TSimpleFlag;
2803 regCachePtr->opExec = TInterpretedFlag;
2804 regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
2805 regCachePtr->m_no_disk_flag = TNoDiskFlag;
2806
2807 //-------------------------------------------------------------
2808 // The next step is to read the upto three conditional words.
2809 //-------------------------------------------------------------
2810 Uint32 TkeyIndex;
2811 Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
2812 {
2813 Uint32 TDistrGHIndex = TcKeyReq::getScanIndFlag(Treqinfo);
2814 Uint32 TDistrKeyIndex = TDistrGHIndex;
2815
2816 Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
2817
2818 regCachePtr->scanTakeOverInd = TDistrGHIndex;
2819 regCachePtr->scanInfo = TscanInfo;
2820
2821 regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
2822
2823 TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
2824 }
2825 Uint32* TkeyDataPtr = &TOptionalDataPtr[TkeyIndex];
2826
2827 UintR Tdata1 = TkeyDataPtr[0];
2828 UintR Tdata2 = TkeyDataPtr[1];
2829 UintR Tdata3 = TkeyDataPtr[2];
2830 UintR Tdata4 = TkeyDataPtr[3];
2831 UintR Tdata5;
2832
2833 regCachePtr->keydata[0] = Tdata1;
2834 regCachePtr->keydata[1] = Tdata2;
2835 regCachePtr->keydata[2] = Tdata3;
2836 regCachePtr->keydata[3] = Tdata4;
2837
2838 TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
2839 Uint32 TAIDataIndex;
2840 if (TkeyLength > 8) {
2841 TAIDataIndex = TkeyIndex + 8;
2842 } else {
2843 if (TkeyLength == 0) {
2844 TCKEY_abort(signal, 4);
2845 return;
2846 }//if
2847 TAIDataIndex = TkeyIndex + TkeyLength;
2848 }//if
2849 Uint32* TAIDataPtr = &TOptionalDataPtr[TAIDataIndex];
2850
2851 titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
2852 regCachePtr->keylen = TkeyLength;
2853 regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
2854 regCachePtr->currReclenAi = titcLenAiInTckeyreq;
2855 regCachePtr->m_special_hash =
2856 localTabptr.p->hasCharAttr | (localTabptr.p->noOfDistrKeys > 0);
2857 Tdata1 = TAIDataPtr[0];
2858 Tdata2 = TAIDataPtr[1];
2859 Tdata3 = TAIDataPtr[2];
2860 Tdata4 = TAIDataPtr[3];
2861 Tdata5 = TAIDataPtr[4];
2862
2863 regCachePtr->attrinfo0 = Tdata1;
2864 regCachePtr->attrinfo15[0] = Tdata2;
2865 regCachePtr->attrinfo15[1] = Tdata3;
2866 regCachePtr->attrinfo15[2] = Tdata4;
2867 regCachePtr->attrinfo15[3] = Tdata5;
2868
2869 if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
2870 Uint32 TreadCount = c_counters.creadCount;
2871 jam();
2872 c_counters.creadCount = TreadCount + 1;
2873 } else {
2874 if(regApiPtr->commitAckMarker == RNIL){
2875 jam();
2876 CommitAckMarkerPtr tmp;
2877 if(!m_commitAckMarkerHash.seize(tmp)){
2878 TCKEY_abort(signal, 56);
2879 return;
2880 } else {
2881 regTcPtr->commitAckMarker = tmp.i;
2882 regApiPtr->commitAckMarker = tmp.i;
2883 tmp.p->transid1 = tcKeyReq->transId1;
2884 tmp.p->transid2 = tcKeyReq->transId2;
2885 tmp.p->apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
2886 tmp.p->apiConnectPtr = TapiIndex;
2887 tmp.p->noOfLqhs = 0;
2888 #if defined VM_TRACE || defined ERROR_INSERT
2889 {
2890 CommitAckMarkerPtr check;
2891 ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
2892 }
2893 #endif
2894 m_commitAckMarkerHash.add(tmp);
2895 }
2896 }
2897
2898 UintR TwriteCount = c_counters.cwriteCount;
2899 UintR Toperationsize = coperationsize;
2900 /* --------------------------------------------------------------------
2901 * THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
2902 * THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
2903 * TEMP TABLES DON'T PARTICIPATE.
2904 * -------------------------------------------------------------------- */
2905 if (localTabptr.p->get_storedTable()) {
2906 coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
2907 }
2908 c_counters.cwriteCount = TwriteCount + 1;
2909 switch (TOperationType) {
2910 case ZUPDATE:
2911 case ZINSERT:
2912 case ZDELETE:
2913 case ZWRITE:
2914 jam();
2915 break;
2916 default:
2917 TCKEY_abort(signal, 9);
2918 return;
2919 }//switch
2920 }//if
2921
2922 Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
2923 regTcPtr->m_execAbortOption = TabortOption;
2924
2925 /*-------------------------------------------------------------------------
2926 * Check error handling per operation
2927 * If CommitFlag is set state accordingly and check for early abort
2928 *------------------------------------------------------------------------*/
2929 if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
2930 ndbrequire(TexecuteFlag);
2931 regApiPtr->apiConnectstate = CS_REC_COMMITTING;
2932 } else {
2933 /* ---------------------------------------------------------------------
2934 * PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
2935 * ---------------------------------------------------------------------
2936 * ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
2937 * IF PREPARE TRANSACTION THEN
2938 * API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
2939 * SET STATE TO PREPARING
2940 * --------------------------------------------------------------------- */
2941 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
2942 jam();
2943 // Trigger execution at commit
2944 regApiPtr->apiConnectstate = CS_REC_COMMITTING;
2945 } else {
2946 jam();
2947 regApiPtr->apiConnectstate = CS_RECEIVING;
2948 }//if
2949 }//if
2950 if (TkeyLength <= 4) {
2951 tckeyreq050Lab(signal);
2952 return;
2953 } else {
2954 if (cfirstfreeDatabuf != RNIL) {
2955 jam();
2956 linkKeybuf(signal);
2957 Tdata1 = TkeyDataPtr[4];
2958 Tdata2 = TkeyDataPtr[5];
2959 Tdata3 = TkeyDataPtr[6];
2960 Tdata4 = TkeyDataPtr[7];
2961
2962 DatabufRecord * const regDataPtr = databufptr.p;
2963 regDataPtr->data[0] = Tdata1;
2964 regDataPtr->data[1] = Tdata2;
2965 regDataPtr->data[2] = Tdata3;
2966 regDataPtr->data[3] = Tdata4;
2967 } else {
2968 jam();
2969 seizeDatabuferrorLab(signal);
2970 return;
2971 }//if
2972 if (TkeyLength <= 8) {
2973 jam();
2974 tckeyreq050Lab(signal);
2975 return;
2976 } else {
2977 jam();
2978 /* --------------------------------------------------------------------
2979 * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
2980 * SAVE STATE AND WAIT FOR KEYINFO
2981 * --------------------------------------------------------------------*/
2982 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2983 regCachePtr->save1 = 8;
2984 regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
2985 return;
2986 }//if
2987 }//if
2988 return;
2989 }//Dbtc::execTCKEYREQ()
2990
tckeyreq050Lab(Signal * signal)2991 void Dbtc::tckeyreq050Lab(Signal* signal)
2992 {
2993 UintR tnoOfBackup;
2994 UintR tnoOfStandby;
2995 UintR tnodeinfo;
2996
2997 terrorCode = 0;
2998
2999 hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
3000
3001 if (unlikely(terrorCode))
3002 {
3003 releaseAtErrorLab(signal);
3004 return;
3005 }
3006
3007 CacheRecord * const regCachePtr = cachePtr.p;
3008 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3009 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3010
3011 UintR TtcTimer = ctcTimer;
3012 UintR ThashValue = thashValue;
3013 UintR TdistrHashValue = tdistrHashValue;
3014 UintR TdihConnectptr = regTcPtr->dihConnectptr;
3015 UintR Ttableref = regCachePtr->tableref;
3016
3017 TableRecordPtr localTabptr;
3018 localTabptr.i = Ttableref;
3019 localTabptr.p = &tableRecord[localTabptr.i];
3020 Uint32 schemaVersion = regCachePtr->schemaVersion;
3021 if(localTabptr.p->checkTable(schemaVersion)){
3022 ;
3023 } else {
3024 terrorCode = localTabptr.p->getErrorCode(schemaVersion);
3025 TCKEY_abort(signal, 58);
3026 return;
3027 }
3028
3029 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3030 regCachePtr->hashValue = ThashValue;
3031
3032 signal->theData[0] = TdihConnectptr;
3033 signal->theData[1] = Ttableref;
3034 signal->theData[2] = TdistrHashValue;
3035 signal->theData[3] = 0;
3036 signal->theData[4] = 0;
3037 signal->theData[5] = 0;
3038 signal->theData[6] = 0;
3039
3040 /*-------------------------------------------------------------*/
3041 /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
3042 /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE */
3043 /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION. */
3044 /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
3045 /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
3046 /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB. */
3047 /*-------------------------------------------------------------*/
3048 EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
3049 UintR TerrorIndicator = signal->theData[0];
3050 jamEntry();
3051 if (TerrorIndicator != 0) {
3052 execDIGETNODESREF(signal);
3053 return;
3054 }
3055
3056 if(ERROR_INSERTED(8050) && signal->theData[3] != getOwnNodeId())
3057 {
3058 ndbassert(false);
3059 signal->theData[1] = 626;
3060 execDIGETNODESREF(signal);
3061 return;
3062 }
3063
3064 /****************>>*/
3065 /* DIGETNODESCONF >*/
3066 /* ***************>*/
3067
3068 UintR Tdata1 = signal->theData[1];
3069 UintR Tdata2 = signal->theData[2];
3070 UintR Tdata3 = signal->theData[3];
3071 UintR Tdata4 = signal->theData[4];
3072 UintR Tdata5 = signal->theData[5];
3073 UintR Tdata6 = signal->theData[6];
3074
3075 regCachePtr->fragmentid = Tdata1;
3076 tnodeinfo = Tdata2;
3077
3078 regTcPtr->tcNodedata[0] = Tdata3;
3079 regTcPtr->tcNodedata[1] = Tdata4;
3080 regTcPtr->tcNodedata[2] = Tdata5;
3081 regTcPtr->tcNodedata[3] = Tdata6;
3082
3083 Uint8 Toperation = regTcPtr->operation;
3084 Uint8 Tdirty = regTcPtr->dirtyOp;
3085 tnoOfBackup = tnodeinfo & 3;
3086 tnoOfStandby = (tnodeinfo >> 8) & 3;
3087
3088 regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
3089 if (Toperation == ZREAD || Toperation == ZREAD_EX) {
3090 if (Tdirty == 1) {
3091 jam();
3092 /*-------------------------------------------------------------*/
3093 /* A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND */
3094 /* BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS */
3095 /* NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION */
3096 /* WITH SIMPLE READS. */
3097 /*-------------------------------------------------------------*/
3098 arrGuard(tnoOfBackup, MAX_REPLICAS);
3099 UintR Tindex;
3100 UintR TownNode = cownNodeid;
3101 for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
3102 UintR Tnode = regTcPtr->tcNodedata[Tindex];
3103 jam();
3104 if (Tnode == TownNode) {
3105 jam();
3106 regTcPtr->tcNodedata[0] = Tnode;
3107 }//if
3108 }//for
3109 if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
3110 {
3111 for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
3112 {
3113 UintR Tnode = regTcPtr->tcNodedata[Tindex];
3114 jam();
3115 if (Tnode != TownNode) {
3116 jam();
3117 regTcPtr->tcNodedata[0] = Tnode;
3118 ndbout_c("Choosing %d", Tnode);
3119 }//if
3120 }//for
3121 }
3122 }//if
3123 jam();
3124 regTcPtr->lastReplicaNo = 0;
3125 regTcPtr->noOfNodes = 1;
3126 } else {
3127 UintR TlastReplicaNo;
3128 jam();
3129 TlastReplicaNo = tnoOfBackup + tnoOfStandby;
3130 regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
3131 regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
3132 }//if
3133 if (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength) {
3134 /****************************************************************>*/
3135 /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
3136 /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
3137 /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
3138 /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
3139 /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
3140 /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET. */
3141 /****************************************************************>*/
3142 switch (regApiPtr->apiConnectstate) {
3143 case CS_RECEIVING:
3144 jam();
3145 regApiPtr->apiConnectstate = CS_STARTED;
3146 break;
3147 case CS_REC_COMMITTING:
3148 jam();
3149 regApiPtr->apiConnectstate = CS_START_COMMITTING;
3150 break;
3151 default:
3152 jam();
3153 systemErrorLab(signal, __LINE__);
3154 return;
3155 }//switch
3156 attrinfoDihReceivedLab(signal);
3157 return;
3158 } else {
3159 if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
3160 TtcTimer = ctcTimer;
3161 jam();
3162 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3163 regTcPtr->tcConnectstate = OS_WAIT_ATTR;
3164 return;
3165 } else {
3166 TCKEY_abort(signal, 11);
3167 return;
3168 }//if
3169 }//if
3170 return;
3171 }//Dbtc::tckeyreq050Lab()
3172
attrinfoDihReceivedLab(Signal * signal)3173 void Dbtc::attrinfoDihReceivedLab(Signal* signal)
3174 {
3175 CacheRecord * const regCachePtr = cachePtr.p;
3176 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3177 Uint16 Tnode = regTcPtr->tcNodedata[0];
3178
3179 TableRecordPtr localTabptr;
3180 localTabptr.i = regCachePtr->tableref;
3181 localTabptr.p = &tableRecord[localTabptr.i];
3182
3183 if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
3184 ;
3185 } else {
3186 terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
3187 TCKEY_abort(signal, 58);
3188 return;
3189 }
3190 arrGuard(Tnode, MAX_NDB_NODES);
3191 packLqhkeyreq(signal, calcLqhBlockRef(Tnode));
3192 }//Dbtc::attrinfoDihReceivedLab()
3193
packLqhkeyreq(Signal * signal,BlockReference TBRef)3194 void Dbtc::packLqhkeyreq(Signal* signal,
3195 BlockReference TBRef)
3196 {
3197 CacheRecord * const regCachePtr = cachePtr.p;
3198 UintR Tkeylen = regCachePtr->keylen;
3199 UintR TfirstAttrbuf = regCachePtr->firstAttrbuf;
3200 sendlqhkeyreq(signal, TBRef);
3201 if (Tkeylen > 4) {
3202 packKeyData000Lab(signal, TBRef, Tkeylen - 4);
3203 releaseKeys();
3204 }//if
3205 packLqhkeyreq040Lab(signal,
3206 TfirstAttrbuf,
3207 TBRef);
3208 }//Dbtc::packLqhkeyreq()
3209
sendlqhkeyreq(Signal * signal,BlockReference TBRef)3210 void Dbtc::sendlqhkeyreq(Signal* signal,
3211 BlockReference TBRef)
3212 {
3213 UintR tslrAttrLen;
3214 UintR Tdata10;
3215 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3216 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3217 CacheRecord * const regCachePtr = cachePtr.p;
3218 Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
3219 UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
3220 #ifdef ERROR_INSERT
3221 if (ERROR_INSERTED(8002)) {
3222 systemErrorLab(signal, __LINE__);
3223 }//if
3224 if (ERROR_INSERTED(8007)) {
3225 if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3226 CLEAR_ERROR_INSERT_VALUE;
3227 return;
3228 }//if
3229 }//if
3230 if (ERROR_INSERTED(8008)) {
3231 if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3232 CLEAR_ERROR_INSERT_VALUE;
3233 return;
3234 }//if
3235 }//if
3236 if (ERROR_INSERTED(8009)) {
3237 if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3238 return;
3239 }//if
3240 }//if
3241 if (ERROR_INSERTED(8010)) {
3242 if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3243 return;
3244 }//if
3245 }//if
3246 #endif
3247
3248 tslrAttrLen = 0;
3249 LqhKeyReq::setAttrLen(tslrAttrLen, regCachePtr->attrlength);
3250 /* ---------------------------------------------------------------------- */
3251 // Bit16 == 0 since StoredProcedures are not yet supported.
3252 /* ---------------------------------------------------------------------- */
3253 LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
3254 LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
3255
3256 Tdata10 = 0;
3257 sig0 = regTcPtr->opSimple;
3258 sig1 = regTcPtr->operation;
3259 sig2 = regTcPtr->dirtyOp;
3260 bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
3261 LqhKeyReq::setKeyLen(Tdata10, regCachePtr->keylen);
3262 LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
3263 if (unlikely(version < NDBD_ROWID_VERSION))
3264 {
3265 Uint32 op = regTcPtr->operation;
3266 Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
3267 LqhKeyReq::setLockType(Tdata10, lock);
3268 }
3269 /* ---------------------------------------------------------------------- */
3270 // Indicate Application Reference is present in bit 15
3271 /* ---------------------------------------------------------------------- */
3272 LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
3273 LqhKeyReq::setDirtyFlag(Tdata10, sig2);
3274 LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
3275 LqhKeyReq::setSimpleFlag(Tdata10, sig0);
3276 LqhKeyReq::setOperation(Tdata10, sig1);
3277 LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
3278
3279 /* -----------------------------------------------------------------------
3280 * Sequential Number of first LQH = 0, bit 22-23
3281 * IF ATTRIBUTE INFORMATION IS SENT IN TCKEYREQ,
3282 * IT IS ALSO SENT IN LQHKEYREQ
3283 * ----------------------------------------------------------------------- */
3284 LqhKeyReq::setAIInLqhKeyReq(Tdata10, regCachePtr->lenAiInTckeyreq);
3285 /* -----------------------------------------------------------------------
3286 * Bit 27 == 0 since TC record is the same as the client record.
3287 * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
3288 * ----------------------------------------------------------------------- */
3289 //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
3290 Uint32 commitAckMarker = regTcPtr->commitAckMarker;
3291 const Uint32 noOfLqhs = regTcPtr->noOfNodes;
3292 if(commitAckMarker != RNIL){
3293 jam();
3294 LqhKeyReq::setMarkerFlag(Tdata10, 1);
3295
3296 CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
3297
3298 /**
3299 * Populate LQH array
3300 */
3301 tmp->noOfLqhs = noOfLqhs;
3302 for(Uint32 i = 0; i<noOfLqhs; i++){
3303 tmp->lqhNodeId[i] = regTcPtr->tcNodedata[i];
3304 }
3305 }
3306
3307 /* ************************************************************> */
3308 /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT */
3309 /* IS SENT TO A PRIMARY NODE. */
3310 /* ************************************************************> */
3311
3312 LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
3313
3314 sig0 = tcConnectptr.i;
3315 sig2 = regCachePtr->hashValue;
3316 sig4 = cownref;
3317 sig5 = regTcPtr->savePointId;
3318
3319 lqhKeyReq->clientConnectPtr = sig0;
3320 lqhKeyReq->attrLen = tslrAttrLen;
3321 lqhKeyReq->hashValue = sig2;
3322 lqhKeyReq->requestInfo = Tdata10;
3323 lqhKeyReq->tcBlockref = sig4;
3324 lqhKeyReq->savePointId = sig5;
3325
3326 sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
3327 sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
3328 sig2 = regApiPtr->transid[0];
3329 sig3 = regApiPtr->transid[1];
3330 sig4 = (regTcPtr->isIndexOp == 2) ? reference() : regApiPtr->ndbapiBlockref;
3331 sig5 = regTcPtr->clientData;
3332 sig6 = regCachePtr->scanInfo;
3333
3334 if (! dirtyRead)
3335 {
3336 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
3337 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
3338 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
3339 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
3340 }
3341
3342 lqhKeyReq->tableSchemaVersion = sig0;
3343 lqhKeyReq->fragmentData = sig1;
3344 lqhKeyReq->transId1 = sig2;
3345 lqhKeyReq->transId2 = sig3;
3346 lqhKeyReq->scanInfo = sig6;
3347
3348 lqhKeyReq->variableData[0] = sig4;
3349 lqhKeyReq->variableData[1] = sig5;
3350
3351 UintR nextPos = 2;
3352
3353 if (regTcPtr->lastReplicaNo > 1) {
3354 sig0 = (UintR)regTcPtr->tcNodedata[2] +
3355 (UintR)(regTcPtr->tcNodedata[3] << 16);
3356 lqhKeyReq->variableData[nextPos] = sig0;
3357 nextPos++;
3358 }//if
3359
3360 sig0 = regCachePtr->keydata[0];
3361 sig1 = regCachePtr->keydata[1];
3362 sig2 = regCachePtr->keydata[2];
3363 sig3 = regCachePtr->keydata[3];
3364 UintR Tkeylen = regCachePtr->keylen;
3365
3366 lqhKeyReq->variableData[nextPos + 0] = sig0;
3367 lqhKeyReq->variableData[nextPos + 1] = sig1;
3368 lqhKeyReq->variableData[nextPos + 2] = sig2;
3369 lqhKeyReq->variableData[nextPos + 3] = sig3;
3370
3371 if (Tkeylen < 4) {
3372 nextPos += Tkeylen;
3373 } else {
3374 nextPos += 4;
3375 }//if
3376
3377 sig0 = regCachePtr->attrinfo0;
3378 sig1 = regCachePtr->attrinfo15[0];
3379 sig2 = regCachePtr->attrinfo15[1];
3380 sig3 = regCachePtr->attrinfo15[2];
3381 sig4 = regCachePtr->attrinfo15[3];
3382 UintR TlenAi = regCachePtr->lenAiInTckeyreq;
3383
3384 lqhKeyReq->variableData[nextPos + 0] = sig0;
3385 lqhKeyReq->variableData[nextPos + 1] = sig1;
3386 lqhKeyReq->variableData[nextPos + 2] = sig2;
3387 lqhKeyReq->variableData[nextPos + 3] = sig3;
3388 lqhKeyReq->variableData[nextPos + 4] = sig4;
3389
3390 nextPos += TlenAi;
3391
3392 // Reset trigger count
3393 regTcPtr->accumulatingTriggerData.i = RNIL;
3394 regTcPtr->accumulatingTriggerData.p = NULL;
3395 regTcPtr->noFiredTriggers = 0;
3396 regTcPtr->triggerExecutionCount = 0;
3397
3398 sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3399 nextPos + LqhKeyReq::FixedSignalLength, JBB);
3400 }//Dbtc::sendlqhkeyreq()
3401
packLqhkeyreq040Lab(Signal * signal,UintR anAttrBufIndex,BlockReference TBRef)3402 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
3403 UintR anAttrBufIndex,
3404 BlockReference TBRef)
3405 {
3406 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3407 #ifdef ERROR_INSERT
3408 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3409 if (ERROR_INSERTED(8009)) {
3410 if (regApiPtr->apiConnectstate == CS_STARTED) {
3411 attrbufptr.i = RNIL;
3412 CLEAR_ERROR_INSERT_VALUE;
3413 return;
3414 }//if
3415 }//if
3416 if (ERROR_INSERTED(8010)) {
3417 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3418 attrbufptr.i = RNIL;
3419 CLEAR_ERROR_INSERT_VALUE;
3420 return;
3421 }//if
3422 }//if
3423 #endif
3424
3425 UintR TattrbufFilesize = cattrbufFilesize;
3426 AttrbufRecord *localAttrbufRecord = attrbufRecord;
3427 while (1) {
3428 if (anAttrBufIndex == RNIL) {
3429 UintR TtcTimer = ctcTimer;
3430 UintR Tread = (regTcPtr->operation == ZREAD);
3431 UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
3432 UintR Tboth = Tread & Tdirty;
3433 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3434 jam();
3435 /*--------------------------------------------------------------------
3436 * WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
3437 *---------------------------------------------------------------------*/
3438 releaseAttrinfo();
3439 if (Tboth) {
3440 jam();
3441 releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
3442 return;
3443 }//if
3444 regTcPtr->tcConnectstate = OS_OPERATING;
3445 return;
3446 }//if
3447 if (anAttrBufIndex < TattrbufFilesize) {
3448 AttrbufRecord * const regAttrPtr = &localAttrbufRecord[anAttrBufIndex];
3449 anAttrBufIndex = regAttrPtr->attrbuf[ZINBUF_NEXT];
3450 sendAttrinfo(signal,
3451 tcConnectptr.i,
3452 regAttrPtr,
3453 TBRef);
3454 } else {
3455 TCKEY_abort(signal, 17);
3456 return;
3457 }//if
3458 }//while
3459 }//Dbtc::packLqhkeyreq040Lab()
3460
3461 /* ========================================================================= */
3462 /* ------- RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD ------- */
3463 /* ========================================================================= */
releaseAttrinfo()3464 void Dbtc::releaseAttrinfo()
3465 {
3466 UintR Tmp;
3467 AttrbufRecordPtr Tattrbufptr;
3468 CacheRecord * const regCachePtr = cachePtr.p;
3469 UintR TattrbufFilesize = cattrbufFilesize;
3470 UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
3471 Tattrbufptr.i = regCachePtr->firstAttrbuf;
3472 AttrbufRecord *localAttrbufRecord = attrbufRecord;
3473
3474 while (Tattrbufptr.i < TattrbufFilesize) {
3475 Tattrbufptr.p = &localAttrbufRecord[Tattrbufptr.i];
3476 Tmp = Tattrbufptr.p->attrbuf[ZINBUF_NEXT];
3477 Tattrbufptr.p->attrbuf[ZINBUF_NEXT] = TfirstfreeAttrbuf;
3478 TfirstfreeAttrbuf = Tattrbufptr.i;
3479 Tattrbufptr.i = Tmp;
3480 jam();
3481 }//while
3482 if (Tattrbufptr.i == RNIL) {
3483 //---------------------------------------------------
3484 // Now we will release the cache record at the same
3485 // time as releasing the attrinfo records.
3486 //---------------------------------------------------
3487 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3488 UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
3489 UintR TCacheIndex = cachePtr.i;
3490 cfirstfreeAttrbuf = TfirstfreeAttrbuf;
3491 regCachePtr->nextCacheRec = TfirstfreeCacheRec;
3492 cfirstfreeCacheRec = TCacheIndex;
3493 regApiPtr->cachePtr = RNIL;
3494 return;
3495 }//if
3496 systemErrorLab(0, __LINE__);
3497 return;
3498 }//Dbtc::releaseAttrinfo()
3499
3500 /* ========================================================================= */
3501 /* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION ------- */
3502 /* ========================================================================= */
releaseDirtyRead(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * regTcPtr)3503 void Dbtc::releaseDirtyRead(Signal* signal,
3504 ApiConnectRecordPtr regApiPtr,
3505 TcConnectRecord* regTcPtr)
3506 {
3507 Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
3508 Uint32 TclientData = regTcPtr->clientData;
3509 Uint32 Tnode = regTcPtr->tcNodedata[0];
3510 Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3511 Uint32 TsimpleReadCount = c_counters.csimpleReadCount;
3512 ConnectionState state = regApiPtr.p->apiConnectstate;
3513
3514 regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3515 regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
3516 regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3517
3518 unlinkReadyTcCon(signal);
3519 releaseTcCon();
3520
3521 /**
3522 * No LQHKEYCONF in Simple/Dirty read
3523 * Therefore decrese no LQHKEYCONF(REF) we are waiting for
3524 */
3525 c_counters.csimpleReadCount = TsimpleReadCount + 1;
3526 regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
3527
3528 if(Tlqhkeyreqrec == 0)
3529 {
3530 /**
3531 * Special case of lqhKeyConf_checkTransactionState:
3532 * - commit with zero operations: handle only for simple read
3533 */
3534 sendtckeyconf(signal, state == CS_START_COMMITTING);
3535 regApiPtr.p->apiConnectstate =
3536 (state == CS_START_COMMITTING ? CS_CONNECTED : state);
3537 setApiConTimer(regApiPtr.i, 0, __LINE__);
3538
3539 return;
3540 }
3541
3542 /**
3543 * Emulate LQHKEYCONF
3544 */
3545 lqhKeyConf_checkTransactionState(signal, regApiPtr);
3546 }//Dbtc::releaseDirtyRead()
3547
3548 /* ------------------------------------------------------------------------- */
3549 /* ------- CHECK IF ALL TC CONNECTIONS ARE COMPLETED ------- */
3550 /* ------------------------------------------------------------------------- */
unlinkReadyTcCon(Signal * signal)3551 void Dbtc::unlinkReadyTcCon(Signal* signal)
3552 {
3553 TcConnectRecordPtr urtTcConnectptr;
3554
3555 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3556 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3557 UintR TtcConnectFilesize = ctcConnectFilesize;
3558 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3559 if (regTcPtr->prevTcConnect != RNIL) {
3560 jam();
3561 urtTcConnectptr.i = regTcPtr->prevTcConnect;
3562 ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3563 urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
3564 } else {
3565 jam();
3566 regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
3567 }//if
3568 if (regTcPtr->nextTcConnect != RNIL) {
3569 jam();
3570 urtTcConnectptr.i = regTcPtr->nextTcConnect;
3571 ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3572 urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
3573 } else {
3574 jam();
3575 regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
3576 }//if
3577 }//Dbtc::unlinkReadyTcCon()
3578
releaseTcCon()3579 void Dbtc::releaseTcCon()
3580 {
3581 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3582 UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
3583 UintR TconcurrentOp = c_counters.cconcurrentOp;
3584 UintR TtcConnectptrIndex = tcConnectptr.i;
3585
3586 regTcPtr->tcConnectstate = OS_CONNECTED;
3587 regTcPtr->nextTcConnect = TfirstfreeTcConnect;
3588 regTcPtr->apiConnect = RNIL;
3589 regTcPtr->isIndexOp = false;
3590 regTcPtr->indexOp = RNIL;
3591 cfirstfreeTcConnect = TtcConnectptrIndex;
3592 c_counters.cconcurrentOp = TconcurrentOp - 1;
3593 }//Dbtc::releaseTcCon()
3594
execPACKED_SIGNAL(Signal * signal)3595 void Dbtc::execPACKED_SIGNAL(Signal* signal)
3596 {
3597 LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
3598
3599 UintR Ti;
3600 UintR Tstep = 0;
3601 UintR Tlength;
3602 UintR TpackedData[28];
3603 UintR Tdata1, Tdata2, Tdata3, Tdata4;
3604
3605 jamEntry();
3606 Tlength = signal->length();
3607 if (Tlength > 25) {
3608 jam();
3609 systemErrorLab(signal, __LINE__);
3610 return;
3611 }//if
3612 Uint32* TpackDataPtr;
3613 for (Ti = 0; Ti < Tlength; Ti += 4) {
3614 Uint32* TsigDataPtr = &signal->theData[Ti];
3615 Tdata1 = TsigDataPtr[0];
3616 Tdata2 = TsigDataPtr[1];
3617 Tdata3 = TsigDataPtr[2];
3618 Tdata4 = TsigDataPtr[3];
3619
3620 TpackDataPtr = &TpackedData[Ti];
3621 TpackDataPtr[0] = Tdata1;
3622 TpackDataPtr[1] = Tdata2;
3623 TpackDataPtr[2] = Tdata3;
3624 TpackDataPtr[3] = Tdata4;
3625 }//for
3626 while (Tlength > Tstep) {
3627
3628 TpackDataPtr = &TpackedData[Tstep];
3629 Tdata1 = TpackDataPtr[0];
3630 Tdata2 = TpackDataPtr[1];
3631 Tdata3 = TpackDataPtr[2];
3632
3633 lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
3634 lqhKeyConf->opPtr = Tdata2;
3635 lqhKeyConf->userRef = Tdata3;
3636
3637 switch (Tdata1 >> 28) {
3638 case ZCOMMITTED:
3639 signal->header.theLength = 3;
3640 execCOMMITTED(signal);
3641 Tstep += 3;
3642 break;
3643 case ZCOMPLETED:
3644 signal->header.theLength = 3;
3645 execCOMPLETED(signal);
3646 Tstep += 3;
3647 break;
3648 case ZLQHKEYCONF:
3649 jam();
3650 Tdata1 = TpackDataPtr[3];
3651 Tdata2 = TpackDataPtr[4];
3652 Tdata3 = TpackDataPtr[5];
3653 Tdata4 = TpackDataPtr[6];
3654
3655 lqhKeyConf->readLen = Tdata1;
3656 lqhKeyConf->transId1 = Tdata2;
3657 lqhKeyConf->transId2 = Tdata3;
3658 lqhKeyConf->noFiredTriggers = Tdata4;
3659 signal->header.theLength = LqhKeyConf::SignalLength;
3660 execLQHKEYCONF(signal);
3661 Tstep += LqhKeyConf::SignalLength;
3662 break;
3663 default:
3664 systemErrorLab(signal, __LINE__);
3665 return;
3666 }//switch
3667 }//while
3668 return;
3669 }//Dbtc::execPACKED_SIGNAL()
3670
execLQHKEYCONF(Signal * signal)3671 void Dbtc::execLQHKEYCONF(Signal* signal)
3672 {
3673 const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
3674 UintR compare_transid1, compare_transid2;
3675 BlockReference tlastLqhBlockref;
3676 UintR tlastLqhConnect;
3677 UintR treadlenAi;
3678 UintR TtcConnectptrIndex;
3679 UintR TtcConnectFilesize = ctcConnectFilesize;
3680
3681 tlastLqhConnect = lqhKeyConf->connectPtr;
3682 TtcConnectptrIndex = lqhKeyConf->opPtr;
3683 tlastLqhBlockref = lqhKeyConf->userRef;
3684 treadlenAi = lqhKeyConf->readLen;
3685 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3686
3687 /*------------------------------------------------------------------------
3688 * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
3689 * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
3690 * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
3691 * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
3692 * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
3693 * OPERATIONS ON THE LQH CONNECT RECORD.
3694 *------------------------------------------------------------------------
3695 * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
3696 * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
3697 * PROBLEM WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
3698 * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
3699 * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
3700 * BEFORE ACCEPTING THIS SIGNAL.
3701 * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
3702 * this.
3703 * This is more reason to ignore the signal if not all states are correct.
3704 *------------------------------------------------------------------------*/
3705 if (TtcConnectptrIndex >= TtcConnectFilesize) {
3706 TCKEY_abort(signal, 25);
3707 return;
3708 }//if
3709 TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
3710 OperationState TtcConnectstate = regTcPtr->tcConnectstate;
3711 tcConnectptr.i = TtcConnectptrIndex;
3712 tcConnectptr.p = regTcPtr;
3713 if (TtcConnectstate != OS_OPERATING) {
3714 warningReport(signal, 23);
3715 return;
3716 }//if
3717 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
3718 UintR TapiConnectptrIndex = regTcPtr->apiConnect;
3719 UintR TapiConnectFilesize = capiConnectFilesize;
3720 UintR Ttrans1 = lqhKeyConf->transId1;
3721 UintR Ttrans2 = lqhKeyConf->transId2;
3722 Uint32 noFired = lqhKeyConf->noFiredTriggers;
3723
3724 if (TapiConnectptrIndex >= TapiConnectFilesize) {
3725 TCKEY_abort(signal, 29);
3726 return;
3727 }//if
3728 Ptr<ApiConnectRecord> regApiPtr;
3729 regApiPtr.i = TapiConnectptrIndex;
3730 regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
3731 apiConnectptr.i = TapiConnectptrIndex;
3732 apiConnectptr.p = regApiPtr.p;
3733 compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
3734 compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
3735 compare_transid1 = compare_transid1 | compare_transid2;
3736 if (compare_transid1 != 0) {
3737 warningReport(signal, 24);
3738 return;
3739 }//if
3740
3741 #ifdef ERROR_INSERT
3742 if (ERROR_INSERTED(8029)) {
3743 systemErrorLab(signal, __LINE__);
3744 }//if
3745 if (ERROR_INSERTED(8003)) {
3746 if (regApiPtr.p->apiConnectstate == CS_STARTED) {
3747 CLEAR_ERROR_INSERT_VALUE;
3748 return;
3749 }//if
3750 }//if
3751 if (ERROR_INSERTED(8004)) {
3752 if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
3753 CLEAR_ERROR_INSERT_VALUE;
3754 return;
3755 }//if
3756 }//if
3757 if (ERROR_INSERTED(8005)) {
3758 if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
3759 CLEAR_ERROR_INSERT_VALUE;
3760 return;
3761 }//if
3762 }//if
3763 if (ERROR_INSERTED(8006)) {
3764 if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
3765 CLEAR_ERROR_INSERT_VALUE;
3766 return;
3767 }//if
3768 }//if
3769 if (ERROR_INSERTED(8023)) {
3770 SET_ERROR_INSERT_VALUE(8024);
3771 return;
3772 }//if
3773 #endif
3774 UintR TtcTimer = ctcTimer;
3775 regTcPtr->lastLqhCon = tlastLqhConnect;
3776 regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
3777 regTcPtr->noFiredTriggers = noFired;
3778
3779 UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
3780 UintR TclientData = regTcPtr->clientData;
3781 UintR TdirtyOp = regTcPtr->dirtyOp;
3782 Uint32 TopSimple = regTcPtr->opSimple;
3783 Uint32 Toperation = regTcPtr->operation;
3784 ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
3785 if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
3786 TCKEY_abort(signal, 30);
3787 return;
3788 }
3789 if (TapiConnectstate == CS_ABORTING) {
3790 warningReport(signal, 27);
3791 return;
3792 }//if
3793
3794 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3795
3796 if (regTcPtr->isIndexOp) {
3797 jam();
3798 // This was an internal TCKEYREQ
3799 // will be returned unpacked
3800 regTcPtr->attrInfoLen = treadlenAi;
3801 } else {
3802 if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
3803 jam();
3804 /*
3805 * Skip counting triggering operations the first round
3806 * since they will enter execLQHKEYCONF a second time
3807 * Skip counting internally generated TcKeyReq
3808 */
3809 regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3810 regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
3811 regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3812 }//if
3813 }//if
3814 if (TdirtyOp == ZTRUE)
3815 {
3816 UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3817 jam();
3818 releaseDirtyWrite(signal);
3819 regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
3820 }
3821 else if (Toperation == ZREAD && TopSimple)
3822 {
3823 UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3824 jam();
3825 unlinkReadyTcCon(signal);
3826 releaseTcCon();
3827 regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
3828 }
3829 else
3830 {
3831 jam();
3832 if (noFired == 0) {
3833 jam();
3834 // No triggers to execute
3835 UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
3836 regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
3837 regTcPtr->tcConnectstate = OS_PREPARED;
3838 }
3839 }//if
3840
3841 /**
3842 * And now decide what to do next
3843 */
3844 if (regTcPtr->triggeringOperation != RNIL) {
3845 jam();
3846 // This operation was created by a trigger execting operation
3847 // Restart it if we have executed all it's triggers
3848 TcConnectRecordPtr opPtr;
3849
3850 opPtr.i = regTcPtr->triggeringOperation;
3851 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
3852 opPtr.p->triggerExecutionCount--;
3853 if (opPtr.p->triggerExecutionCount == 0) {
3854 /*
3855 We have completed current trigger execution
3856 Continue triggering operation
3857 */
3858 jam();
3859 continueTriggeringOp(signal, opPtr.p);
3860 }
3861 } else if (noFired == 0) {
3862 // This operation did not fire any triggers, finish operation
3863 jam();
3864 if (regTcPtr->isIndexOp) {
3865 jam();
3866 setupIndexOpReturn(regApiPtr.p, regTcPtr);
3867 }
3868 lqhKeyConf_checkTransactionState(signal, regApiPtr);
3869 } else {
3870 // We have fired triggers
3871 jam();
3872 saveTriggeringOpState(signal, regTcPtr);
3873 if (regTcPtr->noReceivedTriggers == noFired)
3874 {
3875 // We have received all data
3876 jam();
3877 executeTriggers(signal, ®ApiPtr);
3878 }
3879 // else wait for more trigger data
3880 }
3881 }//Dbtc::execLQHKEYCONF()
3882
setupIndexOpReturn(ApiConnectRecord * regApiPtr,TcConnectRecord * regTcPtr)3883 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
3884 TcConnectRecord* regTcPtr)
3885 {
3886 regApiPtr->indexOpReturn = true;
3887 regApiPtr->indexOp = regTcPtr->indexOp;
3888 regApiPtr->clientData = regTcPtr->clientData;
3889 regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
3890 }
3891
3892 /**
3893 * lqhKeyConf_checkTransactionState
3894 *
3895 * This functions checks state variables, and
3896 * decides if it should wait for more LQHKEYCONF signals
3897 * or if it should start commiting
3898 */
3899 void
lqhKeyConf_checkTransactionState(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)3900 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
3901 Ptr<ApiConnectRecord> regApiPtr)
3902 {
3903 /*---------------------------------------------------------------*/
3904 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
3905 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN */
3906 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE */
3907 /* WHOLE TRANSACTION */
3908 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF */
3909 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
3910 /* TRANSACTION */
3911 /*---------------------------------------------------------------*/
3912 ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
3913 UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
3914 UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3915 int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
3916
3917 switch (TapiConnectstate) {
3918 case CS_START_COMMITTING:
3919 if (TnoOfOutStanding == 0) {
3920 jam();
3921 diverify010Lab(signal);
3922 return;
3923 } else if (TnoOfOutStanding > 0) {
3924 if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
3925 jam();
3926 sendtckeyconf(signal, 0);
3927 return;
3928 } else if (regApiPtr.p->indexOpReturn) {
3929 jam();
3930 sendtckeyconf(signal, 0);
3931 return;
3932 }//if
3933 jam();
3934 return;
3935 } else {
3936 TCKEY_abort(signal, 44);
3937 return;
3938 }//if
3939 return;
3940 case CS_STARTED:
3941 case CS_RECEIVING:
3942 if (TnoOfOutStanding == 0) {
3943 jam();
3944 sendtckeyconf(signal, 2);
3945 return;
3946 } else {
3947 if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
3948 jam();
3949 sendtckeyconf(signal, 0);
3950 return;
3951 } else if (regApiPtr.p->indexOpReturn) {
3952 jam();
3953 sendtckeyconf(signal, 0);
3954 return;
3955 }//if
3956 jam();
3957 }//if
3958 return;
3959 case CS_REC_COMMITTING:
3960 if (TnoOfOutStanding > 0) {
3961 if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
3962 jam();
3963 sendtckeyconf(signal, 0);
3964 return;
3965 } else if (regApiPtr.p->indexOpReturn) {
3966 jam();
3967 sendtckeyconf(signal, 0);
3968 return;
3969 }//if
3970 jam();
3971 return;
3972 }//if
3973 TCKEY_abort(signal, 45);
3974 return;
3975 case CS_CONNECTED:
3976 jam();
3977 /*---------------------------------------------------------------*/
3978 /* WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY */
3979 /* CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE */
3980 /* COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS. */
3981 /*---------------------------------------------------------------*/
3982 regApiPtr.p->tckeyrec = 0;
3983 return;
3984 default:
3985 TCKEY_abort(signal, 46);
3986 return;
3987 }//switch
3988 }//Dbtc::lqhKeyConf_checkTransactionState()
3989
sendtckeyconf(Signal * signal,UintR TcommitFlag)3990 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
3991 {
3992 if(ERROR_INSERTED(8049)){
3993 CLEAR_ERROR_INSERT_VALUE;
3994 signal->theData[0] = TcContinueB::DelayTCKEYCONF;
3995 signal->theData[1] = apiConnectptr.i;
3996 signal->theData[2] = TcommitFlag;
3997 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
3998 return;
3999 }
4000
4001 HostRecordPtr localHostptr;
4002 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4003 const UintR TopWords = (UintR)regApiPtr->tckeyrec;
4004 localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
4005 const Uint32 type = getNodeInfo(localHostptr.i).m_type;
4006 const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
4007 const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
4008 const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
4009 ptrAss(localHostptr, hostRecord);
4010 UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
4011 UintR confInfo = 0;
4012 TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
4013 TcKeyConf::setMarkerFlag(confInfo, Tmarker);
4014 const UintR TpacketLen = 6 + TopWords;
4015 regApiPtr->tckeyrec = 0;
4016
4017 if (regApiPtr->indexOpReturn) {
4018 jam();
4019 // Return internally generated TCKEY
4020 TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4021 TcKeyConf::setNoOfOperations(confInfo, 1);
4022 tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
4023 tcKeyConf->gci = regApiPtr->globalcheckpointid;
4024 tcKeyConf->confInfo = confInfo;
4025 tcKeyConf->transId1 = regApiPtr->transid[0];
4026 tcKeyConf->transId2 = regApiPtr->transid[1];
4027 tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
4028 tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
4029 Uint32 sigLen = TcKeyConf::StaticLength + TcKeyConf::OperationLength;
4030 EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
4031 regApiPtr->indexOpReturn = false;
4032 if (TopWords == 0) {
4033 jam();
4034 return; // No queued TcKeyConf
4035 }//if
4036 }//if
4037 if(TcommitFlag){
4038 jam();
4039 regApiPtr->m_exec_flag = 0;
4040 }
4041 TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
4042 if ((TpacketLen > 25) || !is_api){
4043 TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4044
4045 jam();
4046 tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4047 tcKeyConf->gci = regApiPtr->globalcheckpointid;;
4048 tcKeyConf->confInfo = confInfo;
4049 tcKeyConf->transId1 = regApiPtr->transid[0];
4050 tcKeyConf->transId2 = regApiPtr->transid[1];
4051 copyFromToLen(®ApiPtr->tcSendArray[0],
4052 (UintR*)&tcKeyConf->operations,
4053 (UintR)ZTCOPCONF_SIZE);
4054 sendSignal(regApiPtr->ndbapiBlockref,
4055 GSN_TCKEYCONF, signal, (TpacketLen - 1), JBB);
4056 return;
4057 } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
4058 jam();
4059 sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
4060 TcurrLen = 0;
4061 } else {
4062 jam();
4063 updatePackedList(signal, localHostptr.p, localHostptr.i);
4064 }//if
4065 // -------------------------------------------------------------------------
4066 // The header contains the block reference of receiver plus the real signal
4067 // length - 3, since we have the real signal length plus one additional word
4068 // for the header we have to do - 4.
4069 // -------------------------------------------------------------------------
4070 UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
4071 UintR Tpack1 = regApiPtr->ndbapiConnect;
4072 UintR Tpack2 = regApiPtr->globalcheckpointid;
4073 UintR Tpack3 = confInfo;
4074 UintR Tpack4 = regApiPtr->transid[0];
4075 UintR Tpack5 = regApiPtr->transid[1];
4076
4077 localHostptr.p->noOfWordsTCKEYCONF = TcurrLen + TpacketLen;
4078
4079 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 0] = Tpack0;
4080 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 1] = Tpack1;
4081 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 2] = Tpack2;
4082 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 3] = Tpack3;
4083 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 4] = Tpack4;
4084 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 5] = Tpack5;
4085
4086 UintR Ti;
4087 for (Ti = 6; Ti < TpacketLen; Ti++) {
4088 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + Ti] =
4089 regApiPtr->tcSendArray[Ti - 6];
4090 }//for
4091 }//Dbtc::sendtckeyconf()
4092
copyFromToLen(UintR * sourceBuffer,UintR * destBuffer,UintR Tlen)4093 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
4094 {
4095 UintR Tindex = 0;
4096 UintR Ti;
4097 while (Tlen >= 4) {
4098 UintR Tdata0 = sourceBuffer[Tindex + 0];
4099 UintR Tdata1 = sourceBuffer[Tindex + 1];
4100 UintR Tdata2 = sourceBuffer[Tindex + 2];
4101 UintR Tdata3 = sourceBuffer[Tindex + 3];
4102 Tlen -= 4;
4103 destBuffer[Tindex + 0] = Tdata0;
4104 destBuffer[Tindex + 1] = Tdata1;
4105 destBuffer[Tindex + 2] = Tdata2;
4106 destBuffer[Tindex + 3] = Tdata3;
4107 Tindex += 4;
4108 }//while
4109 for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
4110 destBuffer[Tindex] = sourceBuffer[Tindex];
4111 }//for
4112 }//Dbtc::copyFromToLen()
4113
execSEND_PACKED(Signal * signal)4114 void Dbtc::execSEND_PACKED(Signal* signal)
4115 {
4116 HostRecordPtr Thostptr;
4117 HostRecord *localHostRecord = hostRecord;
4118 UintR i;
4119 UintR TpackedListIndex = cpackedListIndex;
4120 jamEntry();
4121 for (i = 0; i < TpackedListIndex; i++) {
4122 Thostptr.i = cpackedList[i];
4123 ptrAss(Thostptr, localHostRecord);
4124 arrGuard(Thostptr.i - 1, MAX_NODES - 1);
4125 UintR TnoOfPackedWordsLqh = Thostptr.p->noOfPackedWordsLqh;
4126 UintR TnoOfWordsTCKEYCONF = Thostptr.p->noOfWordsTCKEYCONF;
4127 UintR TnoOfWordsTCINDXCONF = Thostptr.p->noOfWordsTCINDXCONF;
4128 jam();
4129 if (TnoOfPackedWordsLqh > 0) {
4130 jam();
4131 sendPackedSignalLqh(signal, Thostptr.p);
4132 }//if
4133 if (TnoOfWordsTCKEYCONF > 0) {
4134 jam();
4135 sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4136 }//if
4137 if (TnoOfWordsTCINDXCONF > 0) {
4138 jam();
4139 sendPackedTCINDXCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4140 }//if
4141 Thostptr.p->inPackedList = false;
4142 }//for
4143 cpackedListIndex = 0;
4144 return;
4145 }//Dbtc::execSEND_PACKED()
4146
4147 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 ahostIndex)4148 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
4149 {
4150 if (ahostptr->inPackedList == false) {
4151 UintR TpackedListIndex = cpackedListIndex;
4152 jam();
4153 ahostptr->inPackedList = true;
4154 cpackedList[TpackedListIndex] = ahostIndex;
4155 cpackedListIndex = TpackedListIndex + 1;
4156 }//if
4157 }//Dbtc::updatePackedList()
4158
sendPackedSignalLqh(Signal * signal,HostRecord * ahostptr)4159 void Dbtc::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
4160 {
4161 UintR Tj;
4162 UintR TnoOfWords = ahostptr->noOfPackedWordsLqh;
4163 for (Tj = 0; Tj < TnoOfWords; Tj += 4) {
4164 UintR sig0 = ahostptr->packedWordsLqh[Tj + 0];
4165 UintR sig1 = ahostptr->packedWordsLqh[Tj + 1];
4166 UintR sig2 = ahostptr->packedWordsLqh[Tj + 2];
4167 UintR sig3 = ahostptr->packedWordsLqh[Tj + 3];
4168 signal->theData[Tj + 0] = sig0;
4169 signal->theData[Tj + 1] = sig1;
4170 signal->theData[Tj + 2] = sig2;
4171 signal->theData[Tj + 3] = sig3;
4172 }//for
4173 ahostptr->noOfPackedWordsLqh = 0;
4174 sendSignal(ahostptr->hostLqhBlockRef,
4175 GSN_PACKED_SIGNAL,
4176 signal,
4177 TnoOfWords,
4178 JBB);
4179 }//Dbtc::sendPackedSignalLqh()
4180
sendPackedTCKEYCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)4181 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
4182 HostRecord * ahostptr,
4183 UintR hostId)
4184 {
4185 UintR Tj;
4186 UintR TnoOfWords = ahostptr->noOfWordsTCKEYCONF;
4187 BlockReference TBref = numberToRef(API_PACKED, hostId);
4188 for (Tj = 0; Tj < ahostptr->noOfWordsTCKEYCONF; Tj += 4) {
4189 UintR sig0 = ahostptr->packedWordsTCKEYCONF[Tj + 0];
4190 UintR sig1 = ahostptr->packedWordsTCKEYCONF[Tj + 1];
4191 UintR sig2 = ahostptr->packedWordsTCKEYCONF[Tj + 2];
4192 UintR sig3 = ahostptr->packedWordsTCKEYCONF[Tj + 3];
4193 signal->theData[Tj + 0] = sig0;
4194 signal->theData[Tj + 1] = sig1;
4195 signal->theData[Tj + 2] = sig2;
4196 signal->theData[Tj + 3] = sig3;
4197 }//for
4198 ahostptr->noOfWordsTCKEYCONF = 0;
4199 sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
4200 }//Dbtc::sendPackedTCKEYCONF()
4201
sendPackedTCINDXCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)4202 void Dbtc::sendPackedTCINDXCONF(Signal* signal,
4203 HostRecord * ahostptr,
4204 UintR hostId)
4205 {
4206 UintR Tj;
4207 UintR TnoOfWords = ahostptr->noOfWordsTCINDXCONF;
4208 BlockReference TBref = numberToRef(API_PACKED, hostId);
4209 for (Tj = 0; Tj < ahostptr->noOfWordsTCINDXCONF; Tj += 4) {
4210 UintR sig0 = ahostptr->packedWordsTCINDXCONF[Tj + 0];
4211 UintR sig1 = ahostptr->packedWordsTCINDXCONF[Tj + 1];
4212 UintR sig2 = ahostptr->packedWordsTCINDXCONF[Tj + 2];
4213 UintR sig3 = ahostptr->packedWordsTCINDXCONF[Tj + 3];
4214 signal->theData[Tj + 0] = sig0;
4215 signal->theData[Tj + 1] = sig1;
4216 signal->theData[Tj + 2] = sig2;
4217 signal->theData[Tj + 3] = sig3;
4218 }//for
4219 ahostptr->noOfWordsTCINDXCONF = 0;
4220 sendSignal(TBref, GSN_TCINDXCONF, signal, TnoOfWords, JBB);
4221 }//Dbtc::sendPackedTCINDXCONF()
4222
4223 /*
4224 4.3.11 DIVERIFY
4225 ---------------
4226 */
4227 /*****************************************************************************/
4228 /* D I V E R I F Y */
4229 /* */
4230 /*****************************************************************************/
diverify010Lab(Signal * signal)4231 void Dbtc::diverify010Lab(Signal* signal)
4232 {
4233 UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
4234 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4235 signal->theData[0] = apiConnectptr.i;
4236 if (ERROR_INSERTED(8022)) {
4237 jam();
4238 systemErrorLab(signal, __LINE__);
4239 }//if
4240
4241 if (regApiPtr->lqhkeyreqrec)
4242 {
4243 if (TfirstfreeApiConnectCopy != RNIL) {
4244 seizeApiConnectCopy(signal);
4245 regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
4246 /*-----------------------------------------------------------------------
4247 * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
4248 * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
4249 * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
4250 * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
4251 *---------------------------------------------------------------------*/
4252 EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal, 1);
4253 if (signal->theData[2] == 0) {
4254 execDIVERIFYCONF(signal);
4255 }
4256 return;
4257 } else {
4258 /*-----------------------------------------------------------------------
4259 * There were no free copy connections available. We must abort the
4260 * transaction since otherwise we will have a problem with the report
4261 * to the application.
4262 * This should more or less not happen but if it happens we do
4263 * not want to crash and we do not want to create code to handle it
4264 * properly since it is difficult to test it and will be complex to
4265 * handle a problem more or less not occurring.
4266 *---------------------------------------------------------------------*/
4267 terrorCode = ZSEIZE_API_COPY_ERROR;
4268 abortErrorLab(signal);
4269 return;
4270 }
4271 }
4272 else
4273 {
4274 jam();
4275 sendtckeyconf(signal, 1);
4276 regApiPtr->apiConnectstate = CS_CONNECTED;
4277 regApiPtr->m_transaction_nodes.clear();
4278 setApiConTimer(apiConnectptr.i, 0,__LINE__);
4279 }
4280 }//Dbtc::diverify010Lab()
4281
4282 /* ------------------------------------------------------------------------- */
4283 /* ------- SEIZE_API_CONNECT ------- */
4284 /* SEIZE CONNECT RECORD FOR A REQUEST */
4285 /* ------------------------------------------------------------------------- */
seizeApiConnectCopy(Signal * signal)4286 void Dbtc::seizeApiConnectCopy(Signal* signal)
4287 {
4288 ApiConnectRecordPtr locApiConnectptr;
4289
4290 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4291 UintR TapiConnectFilesize = capiConnectFilesize;
4292 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4293
4294 locApiConnectptr.i = cfirstfreeApiConnectCopy;
4295 ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4296 cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
4297 locApiConnectptr.p->nextApiConnect = RNIL;
4298 regApiPtr->apiCopyRecord = locApiConnectptr.i;
4299 regApiPtr->triggerPending = false;
4300 regApiPtr->isIndexOp = false;
4301 }//Dbtc::seizeApiConnectCopy()
4302
execDIVERIFYCONF(Signal * signal)4303 void Dbtc::execDIVERIFYCONF(Signal* signal)
4304 {
4305 UintR TapiConnectptrIndex = signal->theData[0];
4306 UintR TapiConnectFilesize = capiConnectFilesize;
4307 UintR Tgci = signal->theData[1];
4308 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4309
4310 jamEntry();
4311 if (ERROR_INSERTED(8017)) {
4312 CLEAR_ERROR_INSERT_VALUE;
4313 return;
4314 }//if
4315 if (TapiConnectptrIndex >= TapiConnectFilesize) {
4316 TCKEY_abort(signal, 31);
4317 return;
4318 }//if
4319 ApiConnectRecord * const regApiPtr =
4320 &localApiConnectRecord[TapiConnectptrIndex];
4321 ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
4322 UintR TApifailureNr = regApiPtr->failureNr;
4323 UintR Tfailure_nr = cfailure_nr;
4324 apiConnectptr.i = TapiConnectptrIndex;
4325 apiConnectptr.p = regApiPtr;
4326 if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
4327 TCKEY_abort(signal, 32);
4328 return;
4329 }//if
4330 /*--------------------------------------------------------------------------
4331 * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
4332 * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
4333 * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
4334 * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
4335 * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
4336 *-------------------------------------------------------------------------*/
4337 if (TApifailureNr != Tfailure_nr) {
4338 DIVER_node_fail_handling(signal, Tgci);
4339 return;
4340 }//if
4341 commitGciHandling(signal, Tgci);
4342
4343 /**************************************************************************
4344 * C O M M I T
4345 * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
4346 **************************************************************************/
4347
4348 UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
4349 UintR TtcConnectFilesize = ctcConnectFilesize;
4350 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4351
4352 regApiPtr->counter = regApiPtr->lqhkeyconfrec;
4353 regApiPtr->apiConnectstate = CS_COMMITTING;
4354 if (TtcConnectptrIndex >= TtcConnectFilesize) {
4355 TCKEY_abort(signal, 33);
4356 return;
4357 }//if
4358 TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
4359 tcConnectptr.i = TtcConnectptrIndex;
4360 tcConnectptr.p = regTcPtr;
4361 commit020Lab(signal);
4362 }//Dbtc::execDIVERIFYCONF()
4363
4364 /*--------------------------------------------------------------------------*/
4365 /* COMMIT_GCI_HANDLING */
4366 /* SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT. */
4367 /*--------------------------------------------------------------------------*/
commitGciHandling(Signal * signal,UintR Tgci)4368 void Dbtc::commitGciHandling(Signal* signal, UintR Tgci)
4369 {
4370 GcpRecordPtr localGcpPointer;
4371
4372 UintR TgcpFilesize = cgcpFilesize;
4373 UintR Tfirstgcp = cfirstgcp;
4374 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4375 GcpRecord *localGcpRecord = gcpRecord;
4376
4377 regApiPtr->globalcheckpointid = Tgci;
4378 if (Tfirstgcp != RNIL) {
4379 /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
4380 localGcpPointer.i = Tfirstgcp;
4381 ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
4382 do {
4383 if (regApiPtr->globalcheckpointid == localGcpPointer.p->gcpId) {
4384 jam();
4385 gcpPtr.i = localGcpPointer.i;
4386 gcpPtr.p = localGcpPointer.p;
4387 linkApiToGcp(signal);
4388 return;
4389 } else {
4390 localGcpPointer.i = localGcpPointer.p->nextGcp;
4391 jam();
4392 if (localGcpPointer.i != RNIL) {
4393 jam();
4394 ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
4395 continue;
4396 }//if
4397 }//if
4398 seizeGcp(signal);
4399 linkApiToGcp(signal);
4400 return;
4401 } while (1);
4402 } else {
4403 jam();
4404 seizeGcp(signal);
4405 linkApiToGcp(signal);
4406 }//if
4407 }//Dbtc::commitGciHandling()
4408
4409 /* --------------------------------------------------------------------------*/
4410 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
4411 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS */
4412 /* LINKED OUT OF THE LIST. */
4413 /*---------------------------------------------------------------------------*/
linkApiToGcp(Signal * signal)4414 void Dbtc::linkApiToGcp(Signal* signal)
4415 {
4416 ApiConnectRecordPtr localApiConnectptr;
4417 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4418 GcpRecord * const regGcpPtr = gcpPtr.p;
4419 UintR TapiConnectptrIndex = apiConnectptr.i;
4420 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4421
4422 regApiPtr->nextGcpConnect = RNIL;
4423 if (regGcpPtr->firstApiConnect == RNIL) {
4424 regGcpPtr->firstApiConnect = TapiConnectptrIndex;
4425 jam();
4426 } else {
4427 UintR TapiConnectFilesize = capiConnectFilesize;
4428 localApiConnectptr.i = regGcpPtr->lastApiConnect;
4429 jam();
4430 ptrCheckGuard(localApiConnectptr,
4431 TapiConnectFilesize, localApiConnectRecord);
4432 localApiConnectptr.p->nextGcpConnect = TapiConnectptrIndex;
4433 }//if
4434 UintR TlastApiConnect = regGcpPtr->lastApiConnect;
4435 regApiPtr->gcpPointer = gcpPtr.i;
4436 regApiPtr->prevGcpConnect = TlastApiConnect;
4437 regGcpPtr->lastApiConnect = TapiConnectptrIndex;
4438 }//Dbtc::linkApiToGcp()
4439
seizeGcp(Signal * signal)4440 void Dbtc::seizeGcp(Signal* signal)
4441 {
4442 GcpRecordPtr tmpGcpPointer;
4443 GcpRecordPtr localGcpPointer;
4444
4445 UintR Tfirstgcp = cfirstgcp;
4446 UintR Tglobalcheckpointid = apiConnectptr.p->globalcheckpointid;
4447 UintR TgcpFilesize = cgcpFilesize;
4448 GcpRecord *localGcpRecord = gcpRecord;
4449
4450 localGcpPointer.i = cfirstfreeGcp;
4451 ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
4452 UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
4453 localGcpPointer.p->gcpId = Tglobalcheckpointid;
4454 localGcpPointer.p->nextGcp = RNIL;
4455 localGcpPointer.p->firstApiConnect = RNIL;
4456 localGcpPointer.p->lastApiConnect = RNIL;
4457 localGcpPointer.p->gcpNomoretransRec = ZFALSE;
4458 cfirstfreeGcp = TfirstfreeGcp;
4459
4460 if (Tfirstgcp == RNIL) {
4461 jam();
4462 cfirstgcp = localGcpPointer.i;
4463 } else {
4464 tmpGcpPointer.i = clastgcp;
4465 jam();
4466 ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
4467 tmpGcpPointer.p->nextGcp = localGcpPointer.i;
4468 }//if
4469 clastgcp = localGcpPointer.i;
4470 gcpPtr = localGcpPointer;
4471 }//Dbtc::seizeGcp()
4472
4473 /*---------------------------------------------------------------------------*/
4474 // Send COMMIT messages to all LQH operations involved in the transaction.
4475 /*---------------------------------------------------------------------------*/
commit020Lab(Signal * signal)4476 void Dbtc::commit020Lab(Signal* signal)
4477 {
4478 TcConnectRecordPtr localTcConnectptr;
4479 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4480 UintR TtcConnectFilesize = ctcConnectFilesize;
4481 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4482
4483 localTcConnectptr.p = tcConnectptr.p;
4484 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
4485 UintR Tcount = 0;
4486 do {
4487 /*-----------------------------------------------------------------------
4488 * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
4489 *-----------------------------------------------------------------------*/
4490 /* *********< */
4491 /* COMMIT < */
4492 /* *********< */
4493 localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
4494 localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
4495 sendCommitLqh(signal, localTcConnectptr.p);
4496
4497 if (localTcConnectptr.i != RNIL) {
4498 Tcount = Tcount + 1;
4499 if (Tcount < 16 && !ERROR_INSERTED(8057)) {
4500 ptrCheckGuard(localTcConnectptr,
4501 TtcConnectFilesize, localTcConnectRecord);
4502 jam();
4503 continue;
4504 } else {
4505 jam();
4506 if (ERROR_INSERTED(8014)) {
4507 CLEAR_ERROR_INSERT_VALUE;
4508 return;
4509 }//if
4510 signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
4511 signal->theData[1] = apiConnectptr.i;
4512 signal->theData[2] = localTcConnectptr.i;
4513 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
4514 return;
4515 }//if
4516 } else {
4517 jam();
4518 if (ERROR_INSERTED(8057))
4519 CLEAR_ERROR_INSERT_VALUE;
4520
4521 regApiPtr->apiConnectstate = CS_COMMIT_SENT;
4522 return;
4523 }//if
4524 } while (1);
4525 }//Dbtc::commit020Lab()
4526
sendCommitLqh(Signal * signal,TcConnectRecord * const regTcPtr)4527 void Dbtc::sendCommitLqh(Signal* signal,
4528 TcConnectRecord * const regTcPtr)
4529 {
4530 HostRecordPtr Thostptr;
4531 UintR ThostFilesize = chostFilesize;
4532 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4533 Thostptr.i = regTcPtr->lastLqhNodeId;
4534 ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
4535 if (Thostptr.p->noOfPackedWordsLqh > 21) {
4536 jam();
4537 sendPackedSignalLqh(signal, Thostptr.p);
4538 } else {
4539 jam();
4540 updatePackedList(signal, Thostptr.p, Thostptr.i);
4541 }//if
4542 UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
4543 UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
4544 UintR Tdata1 = regTcPtr->lastLqhCon;
4545 UintR Tdata2 = regApiPtr->globalcheckpointid;
4546 UintR Tdata3 = regApiPtr->transid[0];
4547 UintR Tdata4 = regApiPtr->transid[1];
4548
4549 TDataPtr[0] = Tdata1 | (ZCOMMIT << 28);
4550 TDataPtr[1] = Tdata2;
4551 TDataPtr[2] = Tdata3;
4552 TDataPtr[3] = Tdata4;
4553 Thostptr.p->noOfPackedWordsLqh = Tindex + 4;
4554 }//Dbtc::sendCommitLqh()
4555
4556 void
DIVER_node_fail_handling(Signal * signal,UintR Tgci)4557 Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci)
4558 {
4559 /*------------------------------------------------------------------------
4560 * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
4561 * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
4562 * ABORT AND THE COMMIT CASES WE NEED TO SET-UP THE DATA FOR THE
4563 * ABORT/COMMIT/COMPLETE HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
4564 *------------------------------------------------------------------------*/
4565 tabortInd = ZFALSE;
4566 setupFailData(signal);
4567 if (false && tabortInd == ZFALSE) {
4568 jam();
4569 commitGciHandling(signal, Tgci);
4570 toCommitHandlingLab(signal);
4571 } else {
4572 jam();
4573 apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
4574 apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
4575 toAbortHandlingLab(signal);
4576 }//if
4577 return;
4578 }//Dbtc::DIVER_node_fail_handling()
4579
4580
4581 /* ------------------------------------------------------------------------- */
4582 /* ------- ENTER COMMITTED ------- */
4583 /* */
4584 /* ------------------------------------------------------------------------- */
execCOMMITTED(Signal * signal)4585 void Dbtc::execCOMMITTED(Signal* signal)
4586 {
4587 TcConnectRecordPtr localTcConnectptr;
4588 ApiConnectRecordPtr localApiConnectptr;
4589
4590 UintR TtcConnectFilesize = ctcConnectFilesize;
4591 UintR TapiConnectFilesize = capiConnectFilesize;
4592 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4593 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4594
4595 #ifdef ERROR_INSERT
4596 if (ERROR_INSERTED(8018)) {
4597 CLEAR_ERROR_INSERT_VALUE;
4598 return;
4599 }//if
4600 if (ERROR_INSERTED(8030)) {
4601 systemErrorLab(signal, __LINE__);
4602 }//if
4603 if (ERROR_INSERTED(8025)) {
4604 SET_ERROR_INSERT_VALUE(8026);
4605 return;
4606 }//if
4607 if (ERROR_INSERTED(8041)) {
4608 CLEAR_ERROR_INSERT_VALUE;
4609 sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
4610 return;
4611 }//if
4612 if (ERROR_INSERTED(8042)) {
4613 SET_ERROR_INSERT_VALUE(8046);
4614 sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
4615 return;
4616 }//if
4617 #endif
4618 localTcConnectptr.i = signal->theData[0];
4619 jamEntry();
4620 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4621 localApiConnectptr.i = localTcConnectptr.p->apiConnect;
4622 if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
4623 warningReport(signal, 4);
4624 return;
4625 }//if
4626 ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
4627 localApiConnectRecord);
4628 UintR Tcounter = localApiConnectptr.p->counter - 1;
4629 ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
4630 UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
4631 UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
4632 Tdata1 = Tdata1 | Tdata2;
4633 bool TcheckCondition =
4634 (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
4635
4636 setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
4637 localApiConnectptr.p->counter = Tcounter;
4638 localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
4639 if (Tdata1 != 0) {
4640 warningReport(signal, 5);
4641 return;
4642 }//if
4643 if (TcheckCondition) {
4644 jam();
4645 /*-------------------------------------------------------*/
4646 // We have not sent all COMMIT requests yet. We could be
4647 // in the state that all sent are COMMITTED but we are
4648 // still waiting for a CONTINUEB to send the rest of the
4649 // COMMIT requests.
4650 /*-------------------------------------------------------*/
4651 return;
4652 }//if
4653 if (ERROR_INSERTED(8020)) {
4654 jam();
4655 systemErrorLab(signal, __LINE__);
4656 }//if
4657 /*-------------------------------------------------------*/
4658 /* THE ENTIRE TRANSACTION IS NOW COMMITED */
4659 /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION. */
4660 /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
4661 /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A */
4662 /* NEW API CONNECT RECORD. */
4663 /*-------------------------------------------------------*/
4664
4665 apiConnectptr = localApiConnectptr;
4666 sendApiCommit(signal);
4667
4668 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4669 localTcConnectptr.i = regApiPtr->firstTcConnect;
4670 UintR Tlqhkeyconfrec = regApiPtr->lqhkeyconfrec;
4671 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4672 regApiPtr->counter = Tlqhkeyconfrec;
4673
4674 tcConnectptr = localTcConnectptr;
4675 complete010Lab(signal);
4676 return;
4677
4678 }//Dbtc::execCOMMITTED()
4679
4680 /*-------------------------------------------------------*/
4681 /* SEND_API_COMMIT */
4682 /* SEND COMMIT DECISION TO THE API. */
4683 /*-------------------------------------------------------*/
sendApiCommit(Signal * signal)4684 void Dbtc::sendApiCommit(Signal* signal)
4685 {
4686 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4687
4688 if (regApiPtr->returnsignal == RS_TCKEYCONF) {
4689 sendtckeyconf(signal, 1);
4690 } else if (regApiPtr->returnsignal == RS_TC_COMMITCONF) {
4691 jam();
4692 TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
4693 if(regApiPtr->commitAckMarker == RNIL){
4694 jam();
4695 commitConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4696 } else {
4697 jam();
4698 commitConf->apiConnectPtr = regApiPtr->ndbapiConnect | 1;
4699 }
4700 commitConf->transId1 = regApiPtr->transid[0];
4701 commitConf->transId2 = regApiPtr->transid[1];
4702 commitConf->gci = regApiPtr->globalcheckpointid;
4703
4704 sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
4705 TcCommitConf::SignalLength, JBB);
4706 } else if (regApiPtr->returnsignal == RS_NO_RETURN) {
4707 jam();
4708 } else {
4709 TCKEY_abort(signal, 37);
4710 return;
4711 }//if
4712 UintR TapiConnectFilesize = capiConnectFilesize;
4713 UintR TcommitCount = c_counters.ccommitCount;
4714 UintR TapiIndex = apiConnectptr.i;
4715 UintR TnewApiIndex = regApiPtr->apiCopyRecord;
4716 UintR TapiFailState = regApiPtr->apiFailState;
4717 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4718
4719 tmpApiConnectptr.p = apiConnectptr.p;
4720 tmpApiConnectptr.i = TapiIndex;
4721 c_counters.ccommitCount = TcommitCount + 1;
4722 apiConnectptr.i = TnewApiIndex;
4723 ptrCheckGuard(apiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4724 copyApi(signal);
4725 if (TapiFailState != ZTRUE) {
4726 return;
4727 } else {
4728 jam();
4729 handleApiFailState(signal, tmpApiConnectptr.i);
4730 return;
4731 }//if
4732 }//Dbtc::sendApiCommit()
4733
4734 /* ========================================================================= */
4735 /* ======= COPY_API ======= */
4736 /* COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT */
4737 /* IS PREPARED TO RECEIVE A NEW TRANSACTION. */
4738 /*===========================================================================*/
copyApi(Signal * signal)4739 void Dbtc::copyApi(Signal* signal)
4740 {
4741 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4742 ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p;
4743
4744 UintR TndbapiConnect = regTmpApiPtr->ndbapiConnect;
4745 UintR TfirstTcConnect = regTmpApiPtr->firstTcConnect;
4746 UintR Ttransid1 = regTmpApiPtr->transid[0];
4747 UintR Ttransid2 = regTmpApiPtr->transid[1];
4748 UintR Tlqhkeyconfrec = regTmpApiPtr->lqhkeyconfrec;
4749 UintR TgcpPointer = regTmpApiPtr->gcpPointer;
4750 UintR TgcpFilesize = cgcpFilesize;
4751 UintR TcommitAckMarker = regTmpApiPtr->commitAckMarker;
4752 NdbNodeBitmask Tnodes = regTmpApiPtr->m_transaction_nodes;
4753 GcpRecord *localGcpRecord = gcpRecord;
4754
4755 regApiPtr->ndbapiBlockref = regTmpApiPtr->ndbapiBlockref;
4756 regApiPtr->ndbapiConnect = TndbapiConnect;
4757 regApiPtr->firstTcConnect = TfirstTcConnect;
4758 regApiPtr->apiConnectstate = CS_COMPLETING;
4759 regApiPtr->transid[0] = Ttransid1;
4760 regApiPtr->transid[1] = Ttransid2;
4761 regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec;
4762 regApiPtr->commitAckMarker = TcommitAckMarker;
4763 regApiPtr->m_transaction_nodes = Tnodes;
4764 regApiPtr->singleUserMode = 0;
4765
4766 gcpPtr.i = TgcpPointer;
4767 ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
4768 unlinkApiConnect(signal);
4769 linkApiToGcp(signal);
4770 setApiConTimer(tmpApiConnectptr.i, 0, __LINE__);
4771 regTmpApiPtr->apiConnectstate = CS_CONNECTED;
4772 regTmpApiPtr->commitAckMarker = RNIL;
4773 regTmpApiPtr->firstTcConnect = RNIL;
4774 regTmpApiPtr->lastTcConnect = RNIL;
4775 regTmpApiPtr->m_transaction_nodes.clear();
4776 regTmpApiPtr->singleUserMode = 0;
4777 releaseAllSeizedIndexOperations(regTmpApiPtr);
4778 }//Dbtc::copyApi()
4779
unlinkApiConnect(Signal * signal)4780 void Dbtc::unlinkApiConnect(Signal* signal)
4781 {
4782 ApiConnectRecordPtr localApiConnectptr;
4783 ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p;
4784 UintR TapiConnectFilesize = capiConnectFilesize;
4785 UintR TprevGcpConnect = regTmpApiPtr->prevGcpConnect;
4786 UintR TnextGcpConnect = regTmpApiPtr->nextGcpConnect;
4787 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4788
4789 if (TprevGcpConnect == RNIL) {
4790 gcpPtr.p->firstApiConnect = TnextGcpConnect;
4791 jam();
4792 } else {
4793 localApiConnectptr.i = TprevGcpConnect;
4794 jam();
4795 ptrCheckGuard(localApiConnectptr,
4796 TapiConnectFilesize, localApiConnectRecord);
4797 localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
4798 }//if
4799 if (TnextGcpConnect == RNIL) {
4800 gcpPtr.p->lastApiConnect = TprevGcpConnect;
4801 jam();
4802 } else {
4803 localApiConnectptr.i = TnextGcpConnect;
4804 jam();
4805 ptrCheckGuard(localApiConnectptr,
4806 TapiConnectFilesize, localApiConnectRecord);
4807 localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
4808 }//if
4809 }//Dbtc::unlinkApiConnect()
4810
complete010Lab(Signal * signal)4811 void Dbtc::complete010Lab(Signal* signal)
4812 {
4813 TcConnectRecordPtr localTcConnectptr;
4814 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4815 UintR TtcConnectFilesize = ctcConnectFilesize;
4816 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4817
4818 localTcConnectptr.p = tcConnectptr.p;
4819 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
4820 UintR TapiConnectptrIndex = apiConnectptr.i;
4821 UintR Tcount = 0;
4822 do {
4823 localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
4824 localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
4825
4826 /* ************ */
4827 /* COMPLETE < */
4828 /* ************ */
4829 const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
4830 sendCompleteLqh(signal, localTcConnectptr.p);
4831 localTcConnectptr.i = nextTcConnect;
4832 if (localTcConnectptr.i != RNIL) {
4833 Tcount++;
4834 if (Tcount < 16) {
4835 ptrCheckGuard(localTcConnectptr,
4836 TtcConnectFilesize, localTcConnectRecord);
4837 jam();
4838 continue;
4839 } else {
4840 jam();
4841 if (ERROR_INSERTED(8013)) {
4842 CLEAR_ERROR_INSERT_VALUE;
4843 return;
4844 }//if
4845 signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
4846 signal->theData[1] = apiConnectptr.i;
4847 signal->theData[2] = localTcConnectptr.i;
4848 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
4849 return;
4850 }//if
4851 } else {
4852 jam();
4853 regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
4854 return;
4855 }//if
4856 } while (1);
4857 }//Dbtc::complete010Lab()
4858
sendCompleteLqh(Signal * signal,TcConnectRecord * const regTcPtr)4859 void Dbtc::sendCompleteLqh(Signal* signal,
4860 TcConnectRecord * const regTcPtr)
4861 {
4862 HostRecordPtr Thostptr;
4863 UintR ThostFilesize = chostFilesize;
4864 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4865 Thostptr.i = regTcPtr->lastLqhNodeId;
4866 ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
4867 if (Thostptr.p->noOfPackedWordsLqh > 22) {
4868 jam();
4869 sendPackedSignalLqh(signal, Thostptr.p);
4870 } else {
4871 jam();
4872 updatePackedList(signal, Thostptr.p, Thostptr.i);
4873 }//if
4874
4875 UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
4876 UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
4877 UintR Tdata1 = regTcPtr->lastLqhCon | (ZCOMPLETE << 28);
4878 UintR Tdata2 = regApiPtr->transid[0];
4879 UintR Tdata3 = regApiPtr->transid[1];
4880
4881 TDataPtr[0] = Tdata1;
4882 TDataPtr[1] = Tdata2;
4883 TDataPtr[2] = Tdata3;
4884 Thostptr.p->noOfPackedWordsLqh = Tindex + 3;
4885 }//Dbtc::sendCompleteLqh()
4886
4887 void
execTC_COMMIT_ACK(Signal * signal)4888 Dbtc::execTC_COMMIT_ACK(Signal* signal){
4889 jamEntry();
4890
4891 CommitAckMarker key;
4892 key.transid1 = signal->theData[0];
4893 key.transid2 = signal->theData[1];
4894
4895 CommitAckMarkerPtr removedMarker;
4896 m_commitAckMarkerHash.remove(removedMarker, key);
4897 if (removedMarker.i == RNIL) {
4898 jam();
4899 warningHandlerLab(signal, __LINE__);
4900 return;
4901 }//if
4902 sendRemoveMarkers(signal, removedMarker.p);
4903 m_commitAckMarkerPool.release(removedMarker);
4904 }
4905
4906 void
sendRemoveMarkers(Signal * signal,const CommitAckMarker * marker)4907 Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker){
4908 jam();
4909 const Uint32 noOfLqhs = marker->noOfLqhs;
4910 const Uint32 transId1 = marker->transid1;
4911 const Uint32 transId2 = marker->transid2;
4912
4913 for(Uint32 i = 0; i<noOfLqhs; i++){
4914 jam();
4915 const NodeId nodeId = marker->lqhNodeId[i];
4916 sendRemoveMarker(signal, nodeId, transId1, transId2);
4917 }
4918 }
4919
4920 void
sendRemoveMarker(Signal * signal,NodeId nodeId,Uint32 transid1,Uint32 transid2)4921 Dbtc::sendRemoveMarker(Signal* signal,
4922 NodeId nodeId,
4923 Uint32 transid1,
4924 Uint32 transid2){
4925 /**
4926 * Seize host ptr
4927 */
4928 HostRecordPtr hostPtr;
4929 const UintR ThostFilesize = chostFilesize;
4930 hostPtr.i = nodeId;
4931 ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
4932
4933 if (hostPtr.p->noOfPackedWordsLqh > (25 - 3)){
4934 jam();
4935 sendPackedSignalLqh(signal, hostPtr.p);
4936 } else {
4937 jam();
4938 updatePackedList(signal, hostPtr.p, hostPtr.i);
4939 }//if
4940
4941 UintR numWord = hostPtr.p->noOfPackedWordsLqh;
4942 UintR* dataPtr = &hostPtr.p->packedWordsLqh[numWord];
4943
4944 dataPtr[0] = (ZREMOVE_MARKER << 28);
4945 dataPtr[1] = transid1;
4946 dataPtr[2] = transid2;
4947 hostPtr.p->noOfPackedWordsLqh = numWord + 3;
4948 }
4949
execCOMPLETED(Signal * signal)4950 void Dbtc::execCOMPLETED(Signal* signal)
4951 {
4952 TcConnectRecordPtr localTcConnectptr;
4953 ApiConnectRecordPtr localApiConnectptr;
4954
4955 UintR TtcConnectFilesize = ctcConnectFilesize;
4956 UintR TapiConnectFilesize = capiConnectFilesize;
4957 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4958 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4959
4960 #ifdef ERROR_INSERT
4961 if (ERROR_INSERTED(8031)) {
4962 systemErrorLab(signal, __LINE__);
4963 }//if
4964 if (ERROR_INSERTED(8019)) {
4965 CLEAR_ERROR_INSERT_VALUE;
4966 return;
4967 }//if
4968 if (ERROR_INSERTED(8027)) {
4969 SET_ERROR_INSERT_VALUE(8028);
4970 return;
4971 }//if
4972 if (ERROR_INSERTED(8043)) {
4973 CLEAR_ERROR_INSERT_VALUE;
4974 sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
4975 return;
4976 }//if
4977 if (ERROR_INSERTED(8044)) {
4978 SET_ERROR_INSERT_VALUE(8047);
4979 sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
4980 return;
4981 }//if
4982 #endif
4983 localTcConnectptr.i = signal->theData[0];
4984 jamEntry();
4985 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4986 bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
4987 localApiConnectptr.i = localTcConnectptr.p->apiConnect;
4988 if (Tcond1) {
4989 warningReport(signal, 6);
4990 return;
4991 }//if
4992 ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
4993 localApiConnectRecord);
4994 UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
4995 UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
4996 UintR Tcounter = localApiConnectptr.p->counter - 1;
4997 ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
4998 Tdata1 = Tdata1 | Tdata2;
4999 bool TcheckCondition =
5000 (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
5001 if (Tdata1 != 0) {
5002 warningReport(signal, 7);
5003 return;
5004 }//if
5005 setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
5006 localApiConnectptr.p->counter = Tcounter;
5007 localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
5008 localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
5009 if (TcheckCondition) {
5010 jam();
5011 /*-------------------------------------------------------*/
5012 // We have not sent all COMPLETE requests yet. We could be
5013 // in the state that all sent are COMPLETED but we are
5014 // still waiting for a CONTINUEB to send the rest of the
5015 // COMPLETE requests.
5016 /*-------------------------------------------------------*/
5017 return;
5018 }//if
5019 if (ERROR_INSERTED(8021)) {
5020 jam();
5021 systemErrorLab(signal, __LINE__);
5022 }//if
5023 apiConnectptr = localApiConnectptr;
5024 releaseTransResources(signal);
5025 }//Dbtc::execCOMPLETED()
5026
5027 /*---------------------------------------------------------------------------*/
5028 /* RELEASE_TRANS_RESOURCES */
5029 /* RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION. */
5030 /*---------------------------------------------------------------------------*/
releaseTransResources(Signal * signal)5031 void Dbtc::releaseTransResources(Signal* signal)
5032 {
5033 TcConnectRecordPtr localTcConnectptr;
5034 UintR TtcConnectFilesize = ctcConnectFilesize;
5035 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5036 apiConnectptr.p->m_transaction_nodes.clear();
5037 localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
5038 do {
5039 jam();
5040 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5041 UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
5042 tcConnectptr.i = localTcConnectptr.i;
5043 tcConnectptr.p = localTcConnectptr.p;
5044 localTcConnectptr.i = rtrTcConnectptrIndex;
5045 releaseTcCon();
5046 } while (localTcConnectptr.i != RNIL);
5047 handleGcp(signal);
5048 releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
5049 releaseAllSeizedIndexOperations(apiConnectptr.p);
5050 releaseApiConCopy(signal);
5051 }//Dbtc::releaseTransResources()
5052
5053 /* *********************************************************************>> */
5054 /* MODULE: HANDLE_GCP */
5055 /* DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
5056 /* OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC */
5057 /* SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
5058 /* GLOBAL CHECKPOINT HAVE COMPLETED. */
5059 /* *********************************************************************>> */
handleGcp(Signal * signal)5060 void Dbtc::handleGcp(Signal* signal)
5061 {
5062 GcpRecord *localGcpRecord = gcpRecord;
5063 GcpRecordPtr localGcpPtr;
5064 UintR TapiConnectptrIndex = apiConnectptr.i;
5065 UintR TgcpFilesize = cgcpFilesize;
5066 localGcpPtr.i = apiConnectptr.p->gcpPointer;
5067 tmpApiConnectptr.i = TapiConnectptrIndex;
5068 tmpApiConnectptr.p = apiConnectptr.p;
5069 ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
5070 gcpPtr.i = localGcpPtr.i;
5071 gcpPtr.p = localGcpPtr.p;
5072 unlinkApiConnect(signal);
5073 if (localGcpPtr.p->firstApiConnect == RNIL) {
5074 if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
5075 jam();
5076 tcheckGcpId = localGcpPtr.p->gcpId;
5077 gcpTcfinished(signal);
5078 unlinkGcp(signal);
5079 }//if
5080 }//if
5081 }//Dbtc::handleGcp()
5082
releaseApiConCopy(Signal * signal)5083 void Dbtc::releaseApiConCopy(Signal* signal)
5084 {
5085 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5086 UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
5087 cfirstfreeApiConnectCopy = apiConnectptr.i;
5088 regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
5089 setApiConTimer(apiConnectptr.i, 0, __LINE__);
5090 regApiPtr->apiConnectstate = CS_RESTART;
5091 }//Dbtc::releaseApiConCopy()
5092
5093 /* ========================================================================= */
5094 /* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
5095 /* ========================================================================= */
releaseDirtyWrite(Signal * signal)5096 void Dbtc::releaseDirtyWrite(Signal* signal)
5097 {
5098 unlinkReadyTcCon(signal);
5099 releaseTcCon();
5100 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5101 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
5102 if (regApiPtr->firstTcConnect == RNIL) {
5103 jam();
5104 regApiPtr->apiConnectstate = CS_CONNECTED;
5105 setApiConTimer(apiConnectptr.i, 0, __LINE__);
5106 sendtckeyconf(signal, 1);
5107 }//if
5108 }//if
5109 }//Dbtc::releaseDirtyWrite()
5110
5111 /*****************************************************************************
5112 * L Q H K E Y R E F
5113 * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
5114 * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
5115 * TCROLLBACKREP WILL BE SENT TO THE API.
5116 *
5117 * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
5118 * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
5119 * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
5120 * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
5121 * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
5122 * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
5123 * "REC_LQHREFUSE",
5124 * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
5125 * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
5126 *****************************************************************************/
execLQHKEYREF(Signal * signal)5127 void Dbtc::execLQHKEYREF(Signal* signal)
5128 {
5129 const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
5130 Uint32 indexId = 0;
5131 jamEntry();
5132
5133 UintR compare_transid1, compare_transid2;
5134 UintR TtcConnectFilesize = ctcConnectFilesize;
5135 /*-------------------------------------------------------------------------
5136 *
5137 * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
5138 * TRANSACTION PARTS ACTIVE ANYMORE.
5139 * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
5140 *-------------------------------------------------------------------------*/
5141 if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
5142 /*-----------------------------------------------------------------------
5143 * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
5144 * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
5145 * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
5146 * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
5147 * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
5148 * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
5149 * ALREADY COMPLETED (ABORTED).
5150 *-----------------------------------------------------------------------*/
5151 tcConnectptr.i = lqhKeyRef->connectPtr;
5152 Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
5153 ptrAss(tcConnectptr, tcConnectRecord);
5154 TcConnectRecord * const regTcPtr = tcConnectptr.p;
5155 if (regTcPtr->tcConnectstate == OS_OPERATING) {
5156 Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
5157 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
5158 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5159 compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
5160 compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
5161 compare_transid1 = compare_transid1 | compare_transid2;
5162 if (compare_transid1 != 0) {
5163 warningReport(signal, 25);
5164 return;
5165 }//if
5166
5167 const ConnectionState state = regApiPtr->apiConnectstate;
5168 const Uint32 triggeringOp = regTcPtr->triggeringOperation;
5169 if (triggeringOp != RNIL) {
5170 jam();
5171 // This operation was created by a trigger execting operation
5172 TcConnectRecordPtr opPtr;
5173 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5174
5175 const Uint32 currentIndexId = regTcPtr->currentIndexId;
5176 ndbassert(currentIndexId != 0); // Only index triggers so far
5177
5178 opPtr.i = triggeringOp;
5179 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
5180
5181 // The operation executed an index trigger
5182 TcIndexData* indexData = c_theIndexes.getPtr(currentIndexId);
5183 indexId = indexData->indexId;
5184 regApiPtr->errorData = indexId;
5185 const Uint32 opType = regTcPtr->operation;
5186 if (errCode == ZALREADYEXIST)
5187 errCode = terrorCode = ZNOTUNIQUE;
5188 else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
5189 jam();
5190 /**
5191 * "Normal path"
5192 */
5193 // fall-through
5194 } else {
5195 jam();
5196 /** ZDELETE && NOT_FOUND */
5197 if(indexData->indexState == IS_BUILDING && state != CS_ABORTING){
5198 jam();
5199 /**
5200 * Ignore error
5201 */
5202 regApiPtr->lqhkeyconfrec++;
5203
5204 unlinkReadyTcCon(signal);
5205 releaseTcCon();
5206
5207 opPtr.p->triggerExecutionCount--;
5208 if (opPtr.p->triggerExecutionCount == 0) {
5209 /**
5210 * We have completed current trigger execution
5211 * Continue triggering operation
5212 */
5213 jam();
5214 continueTriggeringOp(signal, opPtr.p);
5215 }
5216 return;
5217 }
5218 }
5219 }
5220
5221 Uint32 marker = regTcPtr->commitAckMarker;
5222 markOperationAborted(regApiPtr, regTcPtr);
5223
5224 if(regApiPtr->apiConnectstate == CS_ABORTING){
5225 /**
5226 * We're already aborting' so don't send an "extra" TCKEYREF
5227 */
5228 jam();
5229 return;
5230 }
5231
5232 const Uint32 abort = regTcPtr->m_execAbortOption;
5233 if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
5234 /**
5235 * No error is allowed on this operation
5236 */
5237 TCKEY_abort(signal, 49);
5238 return;
5239 }//if
5240
5241 if (marker != RNIL){
5242 /**
5243 * This was an insert/update/delete/write which failed
5244 * that contained the marker
5245 * Currently unsupported to place new marker
5246 */
5247 TCKEY_abort(signal, 49);
5248 return;
5249 }
5250
5251 /* Only ref in certain situations */
5252 {
5253 const Uint32 opType = regTcPtr->operation;
5254 if ( (opType == ZDELETE && errCode != ZNOT_FOUND)
5255 || (opType == ZINSERT && errCode != ZALREADYEXIST)
5256 || (opType == ZUPDATE && errCode != ZNOT_FOUND)
5257 || (opType == ZWRITE && errCode != 839 && errCode != 840))
5258 {
5259 TCKEY_abort(signal, 49);
5260 return;
5261 }
5262 }
5263
5264 /* *************** */
5265 /* TCKEYREF < */
5266 /* *************** */
5267 TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
5268 tcKeyRef->transId[0] = regApiPtr->transid[0];
5269 tcKeyRef->transId[1] = regApiPtr->transid[1];
5270 tcKeyRef->errorCode = terrorCode;
5271 bool isIndexOp = regTcPtr->isIndexOp;
5272 Uint32 indexOp = tcConnectptr.p->indexOp;
5273 Uint32 clientData = regTcPtr->clientData;
5274 unlinkReadyTcCon(signal); /* LINK TC CONNECT RECORD OUT OF */
5275 releaseTcCon(); /* RELEASE THE TC CONNECT RECORD */
5276 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5277 if (isIndexOp) {
5278 jam();
5279 regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
5280 tcKeyRef->connectPtr = indexOp;
5281 tcKeyRef->errorData = indexId;
5282 EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
5283 apiConnectptr.i = save;
5284 apiConnectptr.p = regApiPtr;
5285 } else {
5286 jam();
5287 tcKeyRef->connectPtr = clientData;
5288 tcKeyRef->errorData = indexId;
5289 sendSignal(regApiPtr->ndbapiBlockref,
5290 GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
5291 }//if
5292
5293 /*---------------------------------------------------------------------
5294 * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
5295 * LQHKEYREQ THAT HAVE RETURNED.
5296 * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
5297 * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
5298 *---------------------------------------------------------------------*/
5299 regApiPtr->lqhkeyreqrec--;
5300 if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
5301 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
5302 jam();
5303 diverify010Lab(signal);
5304 return;
5305 } else if (regApiPtr->tckeyrec > 0 || regApiPtr->m_exec_flag) {
5306 jam();
5307 sendtckeyconf(signal, 2);
5308 return;
5309 }
5310 }//if
5311 return;
5312
5313 } else {
5314 warningReport(signal, 26);
5315 }//if
5316 } else {
5317 errorReport(signal, 6);
5318 }//if
5319 return;
5320 }//Dbtc::execLQHKEYREF()
5321
clearCommitAckMarker(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)5322 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
5323 TcConnectRecord * const regTcPtr)
5324 {
5325 const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
5326 if (regApiPtr->commitAckMarker == RNIL)
5327 ndbassert(commitAckMarker == RNIL);
5328 if (commitAckMarker != RNIL)
5329 ndbassert(regApiPtr->commitAckMarker != RNIL);
5330 if(commitAckMarker != RNIL){
5331 jam();
5332 m_commitAckMarkerHash.release(commitAckMarker);
5333 regTcPtr->commitAckMarker = RNIL;
5334 regApiPtr->commitAckMarker = RNIL;
5335 }
5336 }
5337
markOperationAborted(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)5338 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
5339 TcConnectRecord * const regTcPtr)
5340 {
5341 /*------------------------------------------------------------------------
5342 * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
5343 * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
5344 * ALREADY COMPLETED.
5345 *------------------------------------------------------------------------*/
5346 regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
5347 regTcPtr->tcConnectstate = OS_ABORTING;
5348 clearCommitAckMarker(regApiPtr, regTcPtr);
5349 }
5350
5351 /*--------------------------------------*/
5352 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ */
5353 /* OR TCROLLBACKREQ FROM THE USER TO */
5354 /* CONTINUE THE TRANSACTION */
5355 /*--------------------------------------*/
execTC_COMMITREQ(Signal * signal)5356 void Dbtc::execTC_COMMITREQ(Signal* signal)
5357 {
5358 UintR compare_transid1, compare_transid2;
5359
5360 jamEntry();
5361 apiConnectptr.i = signal->theData[0];
5362 if (apiConnectptr.i < capiConnectFilesize) {
5363 ptrAss(apiConnectptr, apiConnectRecord);
5364 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
5365 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
5366 compare_transid1 = compare_transid1 | compare_transid2;
5367 if (compare_transid1 != 0) {
5368 jam();
5369 return;
5370 }//if
5371
5372 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5373
5374 const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
5375 const Uint32 apiBlockRef = regApiPtr->ndbapiBlockref;
5376 const Uint32 transId1 = regApiPtr->transid[0];
5377 const Uint32 transId2 = regApiPtr->transid[1];
5378 Uint32 errorCode = 0;
5379
5380 regApiPtr->m_exec_flag = 1;
5381 switch (regApiPtr->apiConnectstate) {
5382 case CS_STARTED:
5383 tcConnectptr.i = regApiPtr->firstTcConnect;
5384 if (tcConnectptr.i != RNIL) {
5385 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
5386 if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
5387 jam();
5388 /*******************************************************************/
5389 // The proper case where the application is waiting for commit or
5390 // abort order.
5391 // Start the commit order.
5392 /*******************************************************************/
5393 regApiPtr->returnsignal = RS_TC_COMMITCONF;
5394 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5395 diverify010Lab(signal);
5396 return;
5397 } else {
5398 jam();
5399 /*******************************************************************/
5400 // The transaction is started but not all operations are completed.
5401 // It is not possible to commit the transaction in this state.
5402 // We will abort it instead.
5403 /*******************************************************************/
5404 regApiPtr->returnsignal = RS_NO_RETURN;
5405 errorCode = ZTRANS_STATUS_ERROR;
5406 abort010Lab(signal);
5407 }//if
5408 } else {
5409 jam();
5410 /**
5411 * No operations, accept commit
5412 */
5413 TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
5414 commitConf->apiConnectPtr = apiConnectPtr;
5415 commitConf->transId1 = transId1;
5416 commitConf->transId2 = transId2;
5417 commitConf->gci = 0;
5418 sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
5419 TcCommitConf::SignalLength, JBB);
5420
5421 regApiPtr->returnsignal = RS_NO_RETURN;
5422 releaseAbortResources(signal);
5423 return;
5424 }//if
5425 break;
5426 case CS_RECEIVING:
5427 jam();
5428 /***********************************************************************/
5429 // A transaction is still receiving data. We cannot commit an unfinished
5430 // transaction. We will abort it instead.
5431 /***********************************************************************/
5432 regApiPtr->returnsignal = RS_NO_RETURN;
5433 errorCode = ZPREPAREINPROGRESS;
5434 abort010Lab(signal);
5435 break;
5436
5437 case CS_START_COMMITTING:
5438 case CS_COMMITTING:
5439 case CS_COMMIT_SENT:
5440 case CS_COMPLETING:
5441 case CS_COMPLETE_SENT:
5442 case CS_REC_COMMITTING:
5443 case CS_PREPARE_TO_COMMIT:
5444 jam();
5445 /***********************************************************************/
5446 // The transaction is already performing a commit but it is not concluded
5447 // yet.
5448 /***********************************************************************/
5449 errorCode = ZCOMMITINPROGRESS;
5450 break;
5451 case CS_ABORTING:
5452 jam();
5453 errorCode = regApiPtr->returncode ?
5454 regApiPtr->returncode : ZABORTINPROGRESS;
5455 break;
5456 case CS_START_SCAN:
5457 jam();
5458 /***********************************************************************/
5459 // The transaction is a scan. Scans cannot commit
5460 /***********************************************************************/
5461 errorCode = ZSCANINPROGRESS;
5462 break;
5463 case CS_PREPARED:
5464 jam();
5465 return;
5466 case CS_START_PREPARING:
5467 jam();
5468 return;
5469 case CS_REC_PREPARING:
5470 jam();
5471 return;
5472 break;
5473 default:
5474 warningHandlerLab(signal, __LINE__);
5475 return;
5476 }//switch
5477 TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
5478 commitRef->apiConnectPtr = apiConnectPtr;
5479 commitRef->transId1 = transId1;
5480 commitRef->transId2 = transId2;
5481 commitRef->errorCode = errorCode;
5482 sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
5483 TcCommitRef::SignalLength, JBB);
5484 return;
5485 } else /** apiConnectptr.i < capiConnectFilesize */ {
5486 jam();
5487 warningHandlerLab(signal, __LINE__);
5488 return;
5489 }
5490 }//Dbtc::execTC_COMMITREQ()
5491
5492 /**
5493 * TCROLLBACKREQ
5494 *
5495 * Format is:
5496 *
5497 * thedata[0] = apiconnectptr
5498 * thedata[1] = transid[0]
5499 * thedata[2] = transid[1]
5500 * OPTIONAL thedata[3] = flags
5501 *
5502 * Flags:
5503 * 0x1 = potentiallyBad data from API (try not to assert)
5504 */
execTCROLLBACKREQ(Signal * signal)5505 void Dbtc::execTCROLLBACKREQ(Signal* signal)
5506 {
5507 bool potentiallyBad= false;
5508 UintR compare_transid1, compare_transid2;
5509
5510 jamEntry();
5511
5512 if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
5513 {
5514 ndbout_c("Trying to roll back potentially bad txn\n");
5515 potentiallyBad= true;
5516 }
5517
5518 apiConnectptr.i = signal->theData[0];
5519 if (apiConnectptr.i >= capiConnectFilesize) {
5520 goto TC_ROLL_warning;
5521 }//if
5522 ptrAss(apiConnectptr, apiConnectRecord);
5523 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
5524 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
5525 compare_transid1 = compare_transid1 | compare_transid2;
5526 if (compare_transid1 != 0) {
5527 jam();
5528 return;
5529 }//if
5530
5531 apiConnectptr.p->m_exec_flag = 1;
5532 switch (apiConnectptr.p->apiConnectstate) {
5533 case CS_STARTED:
5534 case CS_RECEIVING:
5535 jam();
5536 apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
5537 abort010Lab(signal);
5538 return;
5539 case CS_CONNECTED:
5540 jam();
5541 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
5542 signal->theData[1] = apiConnectptr.p->transid[0];
5543 signal->theData[2] = apiConnectptr.p->transid[1];
5544 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
5545 signal, 3, JBB);
5546 break;
5547 case CS_START_SCAN:
5548 case CS_PREPARE_TO_COMMIT:
5549 case CS_COMMITTING:
5550 case CS_COMMIT_SENT:
5551 case CS_COMPLETING:
5552 case CS_COMPLETE_SENT:
5553 case CS_WAIT_COMMIT_CONF:
5554 case CS_WAIT_COMPLETE_CONF:
5555 case CS_RESTART:
5556 case CS_DISCONNECTED:
5557 case CS_START_COMMITTING:
5558 case CS_REC_COMMITTING:
5559 jam();
5560 /* ***************< */
5561 /* TC_ROLLBACKREF < */
5562 /* ***************< */
5563 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
5564 signal->theData[1] = apiConnectptr.p->transid[0];
5565 signal->theData[2] = apiConnectptr.p->transid[1];
5566 signal->theData[3] = ZROLLBACKNOTALLOWED;
5567 signal->theData[4] = apiConnectptr.p->apiConnectstate;
5568 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
5569 signal, 5, JBB);
5570 break;
5571 /* SEND A REFUSAL SIGNAL*/
5572 case CS_ABORTING:
5573 jam();
5574 if (apiConnectptr.p->abortState == AS_IDLE) {
5575 jam();
5576 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
5577 signal->theData[1] = apiConnectptr.p->transid[0];
5578 signal->theData[2] = apiConnectptr.p->transid[1];
5579 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
5580 signal, 3, JBB);
5581 } else {
5582 jam();
5583 apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
5584 }//if
5585 break;
5586 case CS_WAIT_ABORT_CONF:
5587 jam();
5588 apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
5589 break;
5590 case CS_START_PREPARING:
5591 jam();
5592 case CS_PREPARED:
5593 jam();
5594 case CS_REC_PREPARING:
5595 jam();
5596 default:
5597 goto TC_ROLL_system_error;
5598 break;
5599 }//switch
5600 return;
5601
5602 TC_ROLL_warning:
5603 jam();
5604 if(likely(potentiallyBad==false))
5605 warningHandlerLab(signal, __LINE__);
5606 return;
5607
5608 TC_ROLL_system_error:
5609 jam();
5610 if(likely(potentiallyBad==false))
5611 systemErrorLab(signal, __LINE__);
5612 return;
5613 }//Dbtc::execTCROLLBACKREQ()
5614
execTC_HBREP(Signal * signal)5615 void Dbtc::execTC_HBREP(Signal* signal)
5616 {
5617 const TcHbRep * const tcHbRep =
5618 (TcHbRep *)signal->getDataPtr();
5619
5620 jamEntry();
5621 apiConnectptr.i = tcHbRep->apiConnectPtr;
5622 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
5623
5624 if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
5625 apiConnectptr.p->transid[1] == tcHbRep->transId2){
5626
5627 if (getApiConTimer(apiConnectptr.i) != 0){
5628 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5629 } else {
5630 DEBUG("TCHBREP received when timer was off apiConnectptr.i="
5631 << apiConnectptr.i);
5632 }
5633 }
5634 }//Dbtc::execTCHBREP()
5635
5636 /*
5637 4.3.15 ABORT
5638 -----------
5639 */
5640 /*****************************************************************************/
5641 /* A B O R T */
5642 /* */
5643 /*****************************************************************************/
warningReport(Signal * signal,int place)5644 void Dbtc::warningReport(Signal* signal, int place)
5645 {
5646 switch (place) {
5647 case 0:
5648 jam();
5649 #ifdef ABORT_TRACE
5650 ndbout << "ABORTED to not active TC record" << endl;
5651 #endif
5652 break;
5653 case 1:
5654 jam();
5655 #ifdef ABORT_TRACE
5656 ndbout << "ABORTED to TC record active with new transaction" << endl;
5657 #endif
5658 break;
5659 case 2:
5660 jam();
5661 #ifdef ABORT_TRACE
5662 ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
5663 #endif
5664 break;
5665 case 3:
5666 jam();
5667 #ifdef ABORT_TRACE
5668 ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
5669 ndbout << "This is ok when aborting in node failure situations" << endl;
5670 #endif
5671 break;
5672 case 4:
5673 jam();
5674 #ifdef ABORT_TRACE
5675 ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
5676 #endif
5677 break;
5678 case 5:
5679 jam();
5680 #ifdef ABORT_TRACE
5681 ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
5682 #endif
5683 break;
5684 case 6:
5685 jam();
5686 #ifdef ABORT_TRACE
5687 ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
5688 #endif
5689 break;
5690 case 7:
5691 jam();
5692 #ifdef ABORT_TRACE
5693 ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
5694 #endif
5695 break;
5696 case 8:
5697 jam();
5698 #ifdef ABORT_TRACE
5699 ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
5700 #endif
5701 break;
5702 case 9:
5703 jam();
5704 #ifdef ABORT_TRACE
5705 ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
5706 #endif
5707 break;
5708 case 10:
5709 jam();
5710 #ifdef ABORT_TRACE
5711 ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
5712 #endif
5713 break;
5714 case 11:
5715 jam();
5716 #ifdef ABORT_TRACE
5717 ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
5718 #endif
5719 break;
5720 case 12:
5721 jam();
5722 #ifdef ABORT_TRACE
5723 ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
5724 #endif
5725 break;
5726 case 13:
5727 jam();
5728 #ifdef ABORT_TRACE
5729 ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
5730 #endif
5731 break;
5732 case 14:
5733 jam();
5734 #ifdef ABORT_TRACE
5735 ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
5736 #endif
5737 break;
5738 case 15:
5739 jam();
5740 #ifdef ABORT_TRACE
5741 ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
5742 #endif
5743 break;
5744 case 16:
5745 jam();
5746 #ifdef ABORT_TRACE
5747 ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
5748 #endif
5749 break;
5750 case 17:
5751 jam();
5752 #ifdef ABORT_TRACE
5753 ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
5754 #endif
5755 break;
5756 case 18:
5757 jam();
5758 #ifdef ABORT_TRACE
5759 ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
5760 #endif
5761 break;
5762 case 19:
5763 jam();
5764 #ifdef ABORT_TRACE
5765 ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
5766 #endif
5767 break;
5768 case 20:
5769 jam();
5770 #ifdef ABORT_TRACE
5771 ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
5772 #endif
5773 break;
5774 case 21:
5775 jam();
5776 #ifdef ABORT_TRACE
5777 ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
5778 #endif
5779 break;
5780 case 22:
5781 jam();
5782 #ifdef ABORT_TRACE
5783 ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
5784 #endif
5785 break;
5786 case 23:
5787 jam();
5788 #ifdef ABORT_TRACE
5789 ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
5790 #endif
5791 break;
5792 case 24:
5793 jam();
5794 #ifdef ABORT_TRACE
5795 ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
5796 #endif
5797 break;
5798 case 25:
5799 jam();
5800 #ifdef ABORT_TRACE
5801 ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
5802 #endif
5803 break;
5804 case 26:
5805 jam();
5806 #ifdef ABORT_TRACE
5807 ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
5808 #endif
5809 break;
5810 case 27:
5811 jam();
5812 // printState(signal, 27);
5813 #ifdef ABORT_TRACE
5814 ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
5815 #endif
5816 break;
5817 default:
5818 jam();
5819 break;
5820 }//switch
5821 return;
5822 }//Dbtc::warningReport()
5823
errorReport(Signal * signal,int place)5824 void Dbtc::errorReport(Signal* signal, int place)
5825 {
5826 switch (place) {
5827 case 0:
5828 jam();
5829 break;
5830 case 1:
5831 jam();
5832 break;
5833 case 2:
5834 jam();
5835 break;
5836 case 3:
5837 jam();
5838 break;
5839 case 4:
5840 jam();
5841 break;
5842 case 5:
5843 jam();
5844 break;
5845 case 6:
5846 jam();
5847 break;
5848 default:
5849 jam();
5850 break;
5851 }//switch
5852 systemErrorLab(signal, __LINE__);
5853 return;
5854 }//Dbtc::errorReport()
5855
5856 /* ------------------------------------------------------------------------- */
5857 /* ------- ENTER ABORTED ------- */
5858 /* */
5859 /*-------------------------------------------------------------------------- */
execABORTED(Signal * signal)5860 void Dbtc::execABORTED(Signal* signal)
5861 {
5862 UintR compare_transid1, compare_transid2;
5863
5864 jamEntry();
5865 tcConnectptr.i = signal->theData[0];
5866 UintR Tnodeid = signal->theData[3];
5867 UintR TlastLqhInd = signal->theData[4];
5868
5869 if (ERROR_INSERTED(8040)) {
5870 CLEAR_ERROR_INSERT_VALUE;
5871 sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
5872 return;
5873 }//if
5874 /*------------------------------------------------------------------------
5875 * ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
5876 *------------------------------------------------------------------------*/
5877 if (tcConnectptr.i >= ctcConnectFilesize) {
5878 errorReport(signal, 0);
5879 return;
5880 }//if
5881 /*-------------------------------------------------------------------------
5882 * WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
5883 * TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
5884 * IN TC WAITING FOR ABORTED.
5885 *-------------------------------------------------------------------------*/
5886 ptrAss(tcConnectptr, tcConnectRecord);
5887 if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
5888 warningReport(signal, 2);
5889 return;
5890 /*-----------------------------------------------------------------------*/
5891 // ABORTED reported on an operation not expecting ABORT.
5892 /*-----------------------------------------------------------------------*/
5893 }//if
5894 apiConnectptr.i = tcConnectptr.p->apiConnect;
5895 if (apiConnectptr.i >= capiConnectFilesize) {
5896 warningReport(signal, 0);
5897 return;
5898 }//if
5899 ptrAss(apiConnectptr, apiConnectRecord);
5900 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
5901 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
5902 compare_transid1 = compare_transid1 | compare_transid2;
5903 if (compare_transid1 != 0) {
5904 warningReport(signal, 1);
5905 return;
5906 }//if
5907 if (ERROR_INSERTED(8024)) {
5908 jam();
5909 systemErrorLab(signal, __LINE__);
5910 }//if
5911
5912 /**
5913 * Release marker
5914 */
5915 clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
5916
5917 Uint32 i;
5918 Uint32 Tfound = 0;
5919 for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
5920 jam();
5921 if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
5922 /*---------------------------------------------------------------------
5923 * We have received ABORTED from one of the participants in this
5924 * operation in this aborted transaction.
5925 * Record all nodes that have completed abort.
5926 * If last indicator is set it means that no more replica has
5927 * heard of the operation and are thus also aborted.
5928 *---------------------------------------------------------------------*/
5929 jam();
5930 Tfound = 1;
5931 clearTcNodeData(signal, TlastLqhInd, i);
5932 }//if
5933 }//for
5934 if (Tfound == 0) {
5935 warningReport(signal, 3);
5936 return;
5937 }
5938 for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
5939 if (tcConnectptr.p->tcNodedata[i] != 0) {
5940 /*--------------------------------------------------------------------
5941 * There are still outstanding ABORTED's to wait for.
5942 *--------------------------------------------------------------------*/
5943 jam();
5944 return;
5945 }//if
5946 }//for
5947 tcConnectptr.p->noOfNodes = 0;
5948 tcConnectptr.p->tcConnectstate = OS_ABORTING;
5949 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5950 apiConnectptr.p->counter--;
5951 if (apiConnectptr.p->counter > 0) {
5952 jam();
5953 /*----------------------------------------------------------------------
5954 * WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
5955 *----------------------------------------------------------------------*/
5956 return;
5957 }//if
5958 /*------------------------------------------------------------------------*/
5959 /* */
5960 /* WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED */
5961 /* FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL */
5962 /* RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
5963 /*------------------------------------------------------------------------*/
5964 releaseAbortResources(signal);
5965 }//Dbtc::execABORTED()
5966
clearTcNodeData(Signal * signal,UintR TLastLqhIndicator,UintR Tstart)5967 void Dbtc::clearTcNodeData(Signal* signal,
5968 UintR TLastLqhIndicator,
5969 UintR Tstart)
5970 {
5971 UintR Ti;
5972 if (TLastLqhIndicator == ZTRUE) {
5973 for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
5974 jam();
5975 tcConnectptr.p->tcNodedata[Ti] = 0;
5976 }//for
5977 } else {
5978 jam();
5979 tcConnectptr.p->tcNodedata[Tstart] = 0;
5980 }//for
5981 }//clearTcNodeData()
5982
abortErrorLab(Signal * signal)5983 void Dbtc::abortErrorLab(Signal* signal)
5984 {
5985 ptrGuard(apiConnectptr);
5986 ApiConnectRecord * transP = apiConnectptr.p;
5987 if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
5988 jam();
5989 return;
5990 }
5991 transP->returnsignal = RS_TCROLLBACKREP;
5992 if(transP->returncode == 0){
5993 jam();
5994 transP->returncode = terrorCode;
5995 }
5996 abort010Lab(signal);
5997 }//Dbtc::abortErrorLab()
5998
abort010Lab(Signal * signal)5999 void Dbtc::abort010Lab(Signal* signal)
6000 {
6001 ApiConnectRecord * transP = apiConnectptr.p;
6002 if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
6003 jam();
6004 return;
6005 }
6006 transP->apiConnectstate = CS_ABORTING;
6007 /*------------------------------------------------------------------------*/
6008 /* AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
6009 /* ALL PARTICIPANTS IN THE TRANSACTION. */
6010 /*------------------------------------------------------------------------*/
6011 transP->abortState = AS_ACTIVE;
6012 transP->counter = 0;
6013
6014 if (transP->firstTcConnect == RNIL) {
6015 jam();
6016 /*--------------------------------------------------------------------*/
6017 /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION. */
6018 /*--------------------------------------------------------------------*/
6019 releaseAbortResources(signal);
6020 return;
6021 }//if
6022 tcConnectptr.i = transP->firstTcConnect;
6023 abort015Lab(signal);
6024 }//Dbtc::abort010Lab()
6025
6026 /*--------------------------------------------------------------------------*/
6027 /* */
6028 /* WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP */
6029 /* ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE. */
6030 /* EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE */
6031 /* MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES */
6032 /* NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
6033 /* WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
6034 /*--------------------------------------------------------------------------*/
abort015Lab(Signal * signal)6035 void Dbtc::abort015Lab(Signal* signal)
6036 {
6037 Uint32 TloopCount = 0;
6038 ABORT020:
6039 jam();
6040 TloopCount++;
6041 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6042 switch (tcConnectptr.p->tcConnectstate) {
6043 case OS_WAIT_DIH:
6044 case OS_WAIT_KEYINFO:
6045 case OS_WAIT_ATTR:
6046 jam();
6047 /*----------------------------------------------------------------------*/
6048 /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
6049 /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING. */
6050 /*----------------------------------------------------------------------*/
6051 tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
6052 tcConnectptr.p->tcConnectstate = OS_ABORTING;
6053 break;
6054 case OS_CONNECTED:
6055 jam();
6056 /*-----------------------------------------------------------------------
6057 * WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
6058 * NEED NOT BOTHER ABOUT ANY LQH ABORTS.
6059 *-----------------------------------------------------------------------*/
6060 tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
6061 tcConnectptr.p->tcConnectstate = OS_ABORTING;
6062 break;
6063 case OS_PREPARED:
6064 jam();
6065 case OS_OPERATING:
6066 jam();
6067 /*----------------------------------------------------------------------
6068 * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
6069 * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
6070 * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
6071 *----------------------------------------------------------------------*/
6072 releaseAndAbort(signal);
6073 tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
6074 TloopCount += 127;
6075 break;
6076 case OS_ABORTING:
6077 jam();
6078 break;
6079 case OS_ABORT_SENT:
6080 jam();
6081 DEBUG("ABORT_SENT state in abort015Lab(), not expected");
6082 systemErrorLab(signal, __LINE__);
6083 return;
6084 default:
6085 jam();
6086 DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
6087 systemErrorLab(signal, __LINE__);
6088 return;
6089 }//switch
6090
6091 if (tcConnectptr.p->nextTcConnect != RNIL) {
6092 jam();
6093 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
6094 if (TloopCount < 1024) {
6095 goto ABORT020;
6096 } else {
6097 jam();
6098 /*---------------------------------------------------------------------
6099 * Reset timer to avoid time-out in real-time break.
6100 * Increase counter to ensure that we don't think that all ABORTED have
6101 * been received before all have been sent.
6102 *---------------------------------------------------------------------*/
6103 apiConnectptr.p->counter++;
6104 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6105 signal->theData[0] = TcContinueB::ZABORT_BREAK;
6106 signal->theData[1] = tcConnectptr.i;
6107 signal->theData[2] = apiConnectptr.i;
6108 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
6109 return;
6110 }//if
6111 }//if
6112 if (apiConnectptr.p->counter > 0) {
6113 jam();
6114 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6115 return;
6116 }//if
6117 /*-----------------------------------------------------------------------
6118 * WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
6119 * FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
6120 * RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
6121 *------------------------------------------------------------------------*/
6122 releaseAbortResources(signal);
6123 }//Dbtc::abort015Lab()
6124
6125 /*--------------------------------------------------------------------------*/
6126 /* RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK. */
6127 /*--------------------------------------------------------------------------*/
releaseAndAbort(Signal * signal)6128 int Dbtc::releaseAndAbort(Signal* signal)
6129 {
6130 HostRecordPtr localHostptr;
6131 UintR TnoLoops = tcConnectptr.p->noOfNodes;
6132
6133 apiConnectptr.p->counter++;
6134 bool prevAlive = false;
6135 for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
6136 localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
6137 ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
6138 if (localHostptr.p->hostStatus == HS_ALIVE) {
6139 jam();
6140 if (prevAlive) {
6141 // if previous is alive, its LQH forwards abort to this node
6142 jam();
6143 continue;
6144 }
6145 /* ************< */
6146 /* ABORT < */
6147 /* ************< */
6148 tblockref = calcLqhBlockRef(localHostptr.i);
6149 signal->theData[0] = tcConnectptr.i;
6150 signal->theData[1] = cownref;
6151 signal->theData[2] = apiConnectptr.p->transid[0];
6152 signal->theData[3] = apiConnectptr.p->transid[1];
6153 sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
6154 prevAlive = true;
6155 } else {
6156 jam();
6157 signal->theData[0] = tcConnectptr.i;
6158 signal->theData[1] = apiConnectptr.p->transid[0];
6159 signal->theData[2] = apiConnectptr.p->transid[1];
6160 signal->theData[3] = localHostptr.i;
6161 signal->theData[4] = ZFALSE;
6162 sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
6163 prevAlive = false;
6164 }//if
6165 }//for
6166 return 1;
6167 }//Dbtc::releaseAndAbort()
6168
6169 /* ------------------------------------------------------------------------- */
6170 /* ------- ENTER TIME_SIGNAL ------- */
6171 /* */
6172 /* ------------------------------------------------------------------------- */
execTIME_SIGNAL(Signal * signal)6173 void Dbtc::execTIME_SIGNAL(Signal* signal)
6174 {
6175
6176 jamEntry();
6177 ctcTimer++;
6178 if (csystemStart != SSS_TRUE) {
6179 jam();
6180 return;
6181 }//if
6182 checkStartTimeout(signal);
6183 checkStartFragTimeout(signal);
6184 }//Dbtc::execTIME_SIGNAL()
6185
6186 /*------------------------------------------------*/
6187 /* Start timeout handling if not already going on */
6188 /*------------------------------------------------*/
checkStartTimeout(Signal * signal)6189 void Dbtc::checkStartTimeout(Signal* signal)
6190 {
6191 ctimeOutCheckCounter++;
6192 if (ctimeOutCheckActive == TOCS_TRUE) {
6193 jam();
6194 // Check heartbeat of timeout loop
6195 if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
6196 jam();
6197 ctimeOutMissedHeartbeats = 0;
6198 }else{
6199 jam();
6200 ctimeOutMissedHeartbeats++;
6201 if (ctimeOutMissedHeartbeats > 100){
6202 jam();
6203 systemErrorLab(signal, __LINE__);
6204 }
6205 }
6206 ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
6207 return;
6208 }//if
6209 if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
6210 jam();
6211 /*------------------------------------------------------------------*/
6212 /* */
6213 /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
6214 /*------------------------------------------------------------------*/
6215 return;
6216 }//if
6217 ctimeOutCheckActive = TOCS_TRUE;
6218 ctimeOutCheckCounter = 0;
6219 timeOutLoopStartLab(signal, 0); // 0 is first api connect record
6220 return;
6221 }//Dbtc::execTIME_SIGNAL()
6222
6223 /*----------------------------------------------------------------*/
6224 /* Start fragment (scan) timeout handling if not already going on */
6225 /*----------------------------------------------------------------*/
checkStartFragTimeout(Signal * signal)6226 void Dbtc::checkStartFragTimeout(Signal* signal)
6227 {
6228 ctimeOutCheckFragCounter++;
6229 if (ctimeOutCheckFragActive == TOCS_TRUE) {
6230 jam();
6231 return;
6232 }//if
6233 if (ctimeOutCheckFragCounter < ctimeOutCheckDelay) {
6234 jam();
6235 /*------------------------------------------------------------------*/
6236 /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
6237 /*------------------------------------------------------------------*/
6238 return;
6239 }//if
6240
6241 // Go through the fragment records and look for timeout in a scan.
6242 ctimeOutCheckFragActive = TOCS_TRUE;
6243 ctimeOutCheckFragCounter = 0;
6244 timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
6245 }//checkStartFragTimeout()
6246
6247 /*------------------------------------------------------------------*/
6248 /* IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE */
6249 /* BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM */
6250 /* SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM */
6251 /* THE WAITING PART OF A PROTOCOL. */
6252 /*
6253 The algorithm used here is to check 1024 transactions at a time before
6254 doing a real-time break.
6255 To avoid aborting both transactions in a deadlock detected by time-out
6256 we insert a random extra time-out of upto 630 ms by using the lowest
6257 six bits of the api connect reference.
6258 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
6259 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
6260 and otherwise we spread it out 310 ms.
6261 */
6262 /*------------------------------------------------------------------*/
timeOutLoopStartLab(Signal * signal,Uint32 api_con_ptr)6263 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
6264 {
6265 Uint32 end_ptr, time_passed, time_out_value, mask_value;
6266 Uint32 old_mask_value= 0;
6267 const Uint32 api_con_sz= capiConnectFilesize;
6268 const Uint32 tc_timer= ctcTimer;
6269 const Uint32 time_out_param= ctimeOutValue;
6270 const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
6271
6272 ctimeOutCheckHeartbeat = tc_timer;
6273
6274 if (api_con_ptr + 1024 < api_con_sz) {
6275 jam();
6276 end_ptr= api_con_ptr + 1024;
6277 } else {
6278 jam();
6279 end_ptr= api_con_sz;
6280 }
6281 if (time_out_param > 300) {
6282 jam();
6283 mask_value= 63;
6284 } else if (time_out_param < 30) {
6285 jam();
6286 mask_value= 7;
6287 } else {
6288 jam();
6289 mask_value= 31;
6290 }
6291 if (time_out_param != old_time_out_param &&
6292 getNodeState().getSingleUserMode())
6293 {
6294 // abort during single user mode, use old_mask_value as flag
6295 // and calculate value to be used for connections with allowed api
6296 if (old_time_out_param > 300) {
6297 jam();
6298 old_mask_value= 63;
6299 } else if (old_time_out_param < 30) {
6300 jam();
6301 old_mask_value= 7;
6302 } else {
6303 jam();
6304 old_mask_value= 31;
6305 }
6306 }
6307 for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
6308 Uint32 api_timer= getApiConTimer(api_con_ptr);
6309 jam();
6310 if (api_timer != 0) {
6311 Uint32 error= ZTIME_OUT_ERROR;
6312 time_out_value= time_out_param + (ndb_rand() & mask_value);
6313 if (unlikely(old_mask_value)) // abort during single user mode
6314 {
6315 apiConnectptr.i = api_con_ptr;
6316 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6317 if ((getNodeState().getSingleUserApi() ==
6318 refToNode(apiConnectptr.p->ndbapiBlockref)) ||
6319 !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
6320 {
6321 // api allowed during single user, use original timeout
6322 time_out_value=
6323 old_time_out_param + (api_con_ptr & old_mask_value);
6324 }
6325 else
6326 {
6327 error= ZCLUSTER_IN_SINGLEUSER_MODE;
6328 }
6329 }
6330 time_passed= tc_timer - api_timer;
6331 if (time_passed > time_out_value)
6332 {
6333 jam();
6334 timeOutFoundLab(signal, api_con_ptr, error);
6335 api_con_ptr++;
6336 break;
6337 }
6338 }
6339 }
6340 if (api_con_ptr == api_con_sz) {
6341 jam();
6342 /*------------------------------------------------------------------*/
6343 /* */
6344 /* WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
6345 /* STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW */
6346 /* READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK. */
6347 /*------------------------------------------------------------------*/
6348 ctimeOutCheckActive = TOCS_FALSE;
6349 } else {
6350 jam();
6351 sendContinueTimeOutControl(signal, api_con_ptr);
6352 }
6353 return;
6354 }//Dbtc::timeOutLoopStartLab()
6355
timeOutFoundLab(Signal * signal,Uint32 TapiConPtr,Uint32 errCode)6356 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
6357 {
6358 apiConnectptr.i = TapiConPtr;
6359 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6360 /*------------------------------------------------------------------*/
6361 /* */
6362 /* THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
6363 /* FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
6364 /*------------------------------------------------------------------*/
6365 DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
6366 << " H'" << apiConnectptr.p->transid[1] << "] " << dec
6367 << "Time-out in state = " << apiConnectptr.p->apiConnectstate
6368 << " apiConnectptr.i = " << apiConnectptr.i
6369 << " - exec: " << apiConnectptr.p->m_exec_flag
6370 << " - place: " << c_apiConTimer_line[apiConnectptr.i]
6371 << " code: " << errCode);
6372 switch (apiConnectptr.p->apiConnectstate) {
6373 case CS_STARTED:
6374 if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
6375 errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
6376 jam();
6377 /*
6378 We are waiting for application to continue the transaction. In this
6379 particular state we will use the application timeout parameter rather
6380 than the shorter Deadlock detection timeout.
6381 */
6382 if (c_appl_timeout_value == 0 ||
6383 (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
6384 jam();
6385 return;
6386 }//if
6387 }
6388 apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
6389 apiConnectptr.p->returncode = errCode;
6390 abort010Lab(signal);
6391 return;
6392 case CS_RECEIVING:
6393 case CS_REC_COMMITTING:
6394 case CS_START_COMMITTING:
6395 jam();
6396 /*------------------------------------------------------------------*/
6397 /* WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS */
6398 /* NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO */
6399 /* START ABORTING THE TRANSACTION. ALSO START CHECKING THE */
6400 /* REMAINING TRANSACTIONS. */
6401 /*------------------------------------------------------------------*/
6402 terrorCode = errCode;
6403 abortErrorLab(signal);
6404 return;
6405 case CS_COMMITTING:
6406 jam();
6407 /*------------------------------------------------------------------*/
6408 // We are simply waiting for a signal in the job buffer. Only extreme
6409 // conditions should get us here. We ignore it.
6410 /*------------------------------------------------------------------*/
6411 case CS_COMPLETING:
6412 jam();
6413 /*------------------------------------------------------------------*/
6414 // We are simply waiting for a signal in the job buffer. Only extreme
6415 // conditions should get us here. We ignore it.
6416 /*------------------------------------------------------------------*/
6417 case CS_PREPARE_TO_COMMIT:
6418 {
6419 jam();
6420 /*------------------------------------------------------------------*/
6421 /* WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
6422 /* KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO. */
6423 /* IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE. */
6424 // To ensure against strange bugs we crash the system if we have passed
6425 // time-out period by a factor of 10 and it is also at least 5 seconds.
6426 /*------------------------------------------------------------------*/
6427 Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
6428 if (time_passed > 500 &&
6429 time_passed > (5 * cDbHbInterval) &&
6430 time_passed > (10 * ctimeOutValue))
6431 {
6432 jam();
6433 systemErrorLab(signal, __LINE__);
6434 }//if
6435 break;
6436 }
6437 case CS_COMMIT_SENT:
6438 jam();
6439 /*------------------------------------------------------------------*/
6440 /* WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
6441 /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
6442 /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL */
6443 /* TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO */
6444 /* A NODE FAILURE. */
6445 /*------------------------------------------------------------------*/
6446 tabortInd = ZCOMMIT_SETUP;
6447 setupFailData(signal);
6448 toCommitHandlingLab(signal);
6449 return;
6450 case CS_COMPLETE_SENT:
6451 jam();
6452 /*--------------------------------------------------------------------*/
6453 /* WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
6454 /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
6455 /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL */
6456 /* TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO */
6457 /* A NODE FAILURE. */
6458 /*--------------------------------------------------------------------*/
6459 tabortInd = ZCOMMIT_SETUP;
6460 setupFailData(signal);
6461 toCompleteHandlingLab(signal);
6462 return;
6463 case CS_ABORTING:
6464 jam();
6465 /*------------------------------------------------------------------*/
6466 /* TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL */
6467 /* NODES THAT HAVE FAILED BEFORE SENDING ABORTED. */
6468 /*------------------------------------------------------------------*/
6469 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
6470 sendAbortedAfterTimeout(signal, 0);
6471 break;
6472 case CS_START_SCAN:{
6473 jam();
6474
6475 /*
6476 We are waiting for application to continue the transaction. In this
6477 particular state we will use the application timeout parameter rather
6478 than the shorter Deadlock detection timeout.
6479 */
6480 if (c_appl_timeout_value == 0 ||
6481 (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
6482 jam();
6483 return;
6484 }//if
6485
6486 ScanRecordPtr scanPtr;
6487 scanPtr.i = apiConnectptr.p->apiScanRec;
6488 ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
6489 scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
6490 break;
6491 }
6492 case CS_WAIT_ABORT_CONF:
6493 jam();
6494 tcConnectptr.i = apiConnectptr.p->currentTcConnect;
6495 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6496 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
6497 hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
6498 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6499 if (hostptr.p->hostStatus == HS_ALIVE) {
6500 /*------------------------------------------------------------------*/
6501 // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
6502 // case.
6503 /*------------------------------------------------------------------*/
6504 warningReport(signal, 20);
6505 apiConnectptr.p->timeOutCounter++;
6506 if (apiConnectptr.p->timeOutCounter > 3) {
6507 /*------------------------------------------------------------------*/
6508 // 100 time-outs are not acceptable. We will shoot down the node
6509 // not responding.
6510 /*------------------------------------------------------------------*/
6511 reportNodeFailed(signal, hostptr.i);
6512 }//if
6513 apiConnectptr.p->currentReplicaNo++;
6514 }//if
6515 tcurrentReplicaNo = (Uint8)Z8NIL;
6516 toAbortHandlingLab(signal);
6517 return;
6518 case CS_WAIT_COMMIT_CONF:
6519 jam();
6520 CRASH_INSERTION(8053);
6521 tcConnectptr.i = apiConnectptr.p->currentTcConnect;
6522 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6523 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
6524 hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
6525 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6526 if (hostptr.p->hostStatus == HS_ALIVE) {
6527 /*------------------------------------------------------------------*/
6528 // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
6529 // case.
6530 /*------------------------------------------------------------------*/
6531 warningReport(signal, 21);
6532 apiConnectptr.p->timeOutCounter++;
6533 if (apiConnectptr.p->timeOutCounter > 3) {
6534 /*------------------------------------------------------------------*/
6535 // 100 time-outs are not acceptable. We will shoot down the node
6536 // not responding.
6537 /*------------------------------------------------------------------*/
6538 reportNodeFailed(signal, hostptr.i);
6539 }//if
6540 apiConnectptr.p->currentReplicaNo++;
6541 }//if
6542 tcurrentReplicaNo = (Uint8)Z8NIL;
6543 toCommitHandlingLab(signal);
6544 return;
6545 case CS_WAIT_COMPLETE_CONF:
6546 jam();
6547 tcConnectptr.i = apiConnectptr.p->currentTcConnect;
6548 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6549 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
6550 hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
6551 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6552 if (hostptr.p->hostStatus == HS_ALIVE) {
6553 /*------------------------------------------------------------------*/
6554 // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
6555 // just in case.
6556 /*------------------------------------------------------------------*/
6557 warningReport(signal, 22);
6558 apiConnectptr.p->timeOutCounter++;
6559 if (apiConnectptr.p->timeOutCounter > 100) {
6560 /*------------------------------------------------------------------*/
6561 // 100 time-outs are not acceptable. We will shoot down the node
6562 // not responding.
6563 /*------------------------------------------------------------------*/
6564 reportNodeFailed(signal, hostptr.i);
6565 }//if
6566 apiConnectptr.p->currentReplicaNo++;
6567 }//if
6568 tcurrentReplicaNo = (Uint8)Z8NIL;
6569 toCompleteHandlingLab(signal);
6570 return;
6571 case CS_FAIL_PREPARED:
6572 jam();
6573 case CS_FAIL_COMMITTING:
6574 jam();
6575 case CS_FAIL_COMMITTED:
6576 jam();
6577 case CS_REC_PREPARING:
6578 jam();
6579 case CS_START_PREPARING:
6580 jam();
6581 case CS_PREPARED:
6582 jam();
6583 case CS_RESTART:
6584 jam();
6585 case CS_FAIL_ABORTED:
6586 jam();
6587 case CS_DISCONNECTED:
6588 jam();
6589 default:
6590 jam();
6591 /*------------------------------------------------------------------*/
6592 /* AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM. */
6593 /*------------------------------------------------------------------*/
6594 DEBUG("State = " << apiConnectptr.p->apiConnectstate);
6595 systemErrorLab(signal, __LINE__);
6596 return;
6597 }//switch
6598 return;
6599 }//Dbtc::timeOutFoundLab()
6600
sendAbortedAfterTimeout(Signal * signal,int Tcheck)6601 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
6602 {
6603 ApiConnectRecord * transP = apiConnectptr.p;
6604 if(transP->abortState == AS_IDLE){
6605 jam();
6606 warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
6607 __LINE__,
6608 apiConnectptr.i,
6609 transP->apiConnectstate,
6610 c_apiConTimer_line[apiConnectptr.i],
6611 transP->firstTcConnect,
6612 c_apiConTimer[apiConnectptr.i]
6613 );
6614 ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
6615 __LINE__,
6616 apiConnectptr.i,
6617 transP->apiConnectstate,
6618 c_apiConTimer_line[apiConnectptr.i],
6619 transP->firstTcConnect,
6620 c_apiConTimer[apiConnectptr.i]
6621 );
6622 ndbrequire(false);
6623 setApiConTimer(apiConnectptr.i, 0, __LINE__);
6624 return;
6625 }
6626
6627 bool found = false;
6628 OperationState tmp[16];
6629
6630 Uint32 TloopCount = 0;
6631 do {
6632 jam();
6633 if (tcConnectptr.i == RNIL) {
6634 jam();
6635
6636 #ifdef VM_TRACE
6637 ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
6638 found, Tcheck, apiConnectptr.p->counter);
6639 #endif
6640 if (found || apiConnectptr.p->counter)
6641 {
6642 jam();
6643 /**
6644 * We sent atleast one ABORT/ABORTED
6645 * or ZABORT_TIMEOUT_BREAK is in job buffer
6646 * wait for reception...
6647 */
6648 return;
6649 }
6650
6651 if (Tcheck == 1)
6652 {
6653 jam();
6654 releaseAbortResources(signal);
6655 return;
6656 }
6657
6658 if (Tcheck == 0)
6659 {
6660 jam();
6661 /*------------------------------------------------------------------
6662 * All nodes had already reported ABORTED for all tcConnect records.
6663 * Crash since it is an error situation that we then received a
6664 * time-out.
6665 *------------------------------------------------------------------*/
6666 char buf[96]; buf[0] = 0;
6667 char buf2[96];
6668 BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
6669 __LINE__, apiConnectptr.i,
6670 apiConnectptr.p->counter);
6671 for(Uint32 i = 0; i<TloopCount; i++)
6672 {
6673 BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
6674 BaseString::snprintf(buf, sizeof(buf), buf2);
6675 }
6676 warningEvent(buf);
6677 ndbout_c(buf);
6678 ndbrequire(false);
6679 releaseAbortResources(signal);
6680 return;
6681 }
6682
6683 return;
6684 }//if
6685 TloopCount++;
6686 if (TloopCount >= 1024) {
6687 jam();
6688 /*------------------------------------------------------------------*/
6689 // Insert a real-time break for large transactions to avoid blowing
6690 // away the job buffer.
6691 /*------------------------------------------------------------------*/
6692 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6693 apiConnectptr.p->counter++;
6694 signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
6695 signal->theData[1] = tcConnectptr.i;
6696 signal->theData[2] = apiConnectptr.i;
6697 if (ERROR_INSERTED(8050))
6698 {
6699 ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
6700 Tcheck, apiConnectptr.p->counter);
6701 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
6702 }
6703 else
6704 {
6705 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
6706 }
6707 return;
6708 }//if
6709 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6710 if(TloopCount < 16){
6711 jam();
6712 tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
6713 }
6714
6715 if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
6716 jam();
6717 /*------------------------------------------------------------------*/
6718 // We have sent an ABORT signal to this node but not yet received any
6719 // reply. We have to send an ABORTED signal on our own in some cases.
6720 // If the node is declared as up and running and still do not respond
6721 // in time to the ABORT signal we will declare it as dead.
6722 /*------------------------------------------------------------------*/
6723 UintR Ti = 0;
6724 arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
6725 for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
6726 jam();
6727 if (tcConnectptr.p->tcNodedata[Ti] != 0) {
6728 TloopCount += 31;
6729 found = true;
6730 hostptr.i = tcConnectptr.p->tcNodedata[Ti];
6731 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6732 if (hostptr.p->hostStatus == HS_ALIVE) {
6733 jam();
6734 /*---------------------------------------------------------------
6735 * A backup replica has not sent ABORTED.
6736 * Could be that a node before him has crashed.
6737 * Send an ABORT signal specifically to this node.
6738 * We will not send to any more nodes after this
6739 * to avoid race problems.
6740 * To also ensure that we use this message also as a heartbeat
6741 * we will move this node to the primary replica seat.
6742 * The primary replica and any failed node after it will
6743 * be removed from the node list. Update also number of nodes.
6744 * Finally break the loop to ensure we don't mess
6745 * things up by executing another loop.
6746 * We also update the timer to ensure we don't get time-out
6747 * too early.
6748 *--------------------------------------------------------------*/
6749 BlockReference TBRef = calcLqhBlockRef(hostptr.i);
6750 signal->theData[0] = tcConnectptr.i;
6751 signal->theData[1] = cownref;
6752 signal->theData[2] = apiConnectptr.p->transid[0];
6753 signal->theData[3] = apiConnectptr.p->transid[1];
6754 sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
6755 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6756 break;
6757 } else {
6758 jam();
6759 /*--------------------------------------------------------------
6760 * The node we are waiting for is dead. We will send ABORTED to
6761 * ourselves vicarious for the failed node.
6762 *--------------------------------------------------------------*/
6763 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6764 signal->theData[0] = tcConnectptr.i;
6765 signal->theData[1] = apiConnectptr.p->transid[0];
6766 signal->theData[2] = apiConnectptr.p->transid[1];
6767 signal->theData[3] = hostptr.i;
6768 signal->theData[4] = ZFALSE;
6769 sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
6770 }//if
6771 }//if
6772 }//for
6773 }//if
6774 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
6775 } while (1);
6776 }//Dbtc::sendAbortedAfterTimeout()
6777
reportNodeFailed(Signal * signal,Uint32 nodeId)6778 void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
6779 {
6780 DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
6781 rep->nodeId = nodeId;
6782 rep->err = DisconnectRep::TcReportNodeFailed;
6783 sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
6784 DisconnectRep::SignalLength, JBB);
6785 }//Dbtc::reportNodeFailed()
6786
6787 /*-------------------------------------------------*/
6788 /* Timeout-loop for scanned fragments. */
6789 /*-------------------------------------------------*/
timeOutLoopStartFragLab(Signal * signal,Uint32 TscanConPtr)6790 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
6791 {
6792 ScanFragRecPtr timeOutPtr[8];
6793 UintR tfragTimer[8];
6794 UintR texpiredTime[8];
6795 UintR TloopCount = 0;
6796 Uint32 TtcTimer = ctcTimer;
6797
6798 while ((TscanConPtr + 8) < cscanFragrecFileSize) {
6799 jam();
6800 timeOutPtr[0].i = TscanConPtr + 0;
6801 timeOutPtr[1].i = TscanConPtr + 1;
6802 timeOutPtr[2].i = TscanConPtr + 2;
6803 timeOutPtr[3].i = TscanConPtr + 3;
6804 timeOutPtr[4].i = TscanConPtr + 4;
6805 timeOutPtr[5].i = TscanConPtr + 5;
6806 timeOutPtr[6].i = TscanConPtr + 6;
6807 timeOutPtr[7].i = TscanConPtr + 7;
6808
6809 c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
6810 c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
6811 c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
6812 c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
6813 c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
6814 c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
6815 c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
6816 c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
6817
6818 tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
6819 tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
6820 tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
6821 tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
6822 tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
6823 tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
6824 tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
6825 tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
6826
6827 texpiredTime[0] = TtcTimer - tfragTimer[0];
6828 texpiredTime[1] = TtcTimer - tfragTimer[1];
6829 texpiredTime[2] = TtcTimer - tfragTimer[2];
6830 texpiredTime[3] = TtcTimer - tfragTimer[3];
6831 texpiredTime[4] = TtcTimer - tfragTimer[4];
6832 texpiredTime[5] = TtcTimer - tfragTimer[5];
6833 texpiredTime[6] = TtcTimer - tfragTimer[6];
6834 texpiredTime[7] = TtcTimer - tfragTimer[7];
6835
6836 for (Uint32 Ti = 0; Ti < 8; Ti++) {
6837 jam();
6838 if (tfragTimer[Ti] != 0) {
6839
6840 if (texpiredTime[Ti] > ctimeOutValue) {
6841 jam();
6842 DEBUG("Fragment timeout found:"<<
6843 " ctimeOutValue=" <<ctimeOutValue
6844 <<", texpiredTime="<<texpiredTime[Ti]<<endl
6845 <<" tfragTimer="<<tfragTimer[Ti]
6846 <<", ctcTimer="<<ctcTimer);
6847 timeOutFoundFragLab(signal, TscanConPtr + Ti);
6848 return;
6849 }//if
6850 }//if
6851 }//for
6852 TscanConPtr += 8;
6853 /*----------------------------------------------------------------*/
6854 /* We split the process up checking 1024 fragmentrecords at a time*/
6855 /* to maintain real time behaviour. */
6856 /*----------------------------------------------------------------*/
6857 if (TloopCount++ > 128 ) {
6858 jam();
6859 signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
6860 signal->theData[1] = TscanConPtr;
6861 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
6862 return;
6863 }//if
6864 }//while
6865 for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
6866 jam();
6867 timeOutPtr[0].i = TscanConPtr;
6868 c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
6869 if (timeOutPtr[0].p->scanFragTimer != 0) {
6870 texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
6871 if (texpiredTime[0] > ctimeOutValue) {
6872 jam();
6873 DEBUG("Fragment timeout found:"<<
6874 " ctimeOutValue=" <<ctimeOutValue
6875 <<", texpiredTime="<<texpiredTime[0]<<endl
6876 <<" tfragTimer="<<tfragTimer[0]
6877 <<", ctcTimer="<<ctcTimer);
6878 timeOutFoundFragLab(signal, TscanConPtr);
6879 return;
6880 }//if
6881 }//if
6882 }//for
6883 ctimeOutCheckFragActive = TOCS_FALSE;
6884
6885 return;
6886 }//timeOutLoopStartFragLab()
6887
6888 /*--------------------------------------------------------------------------*/
6889 /*Handle the heartbeat signal from LQH in a scan process */
6890 // (Set timer on fragrec.)
6891 /*--------------------------------------------------------------------------*/
execSCAN_HBREP(Signal * signal)6892 void Dbtc::execSCAN_HBREP(Signal* signal)
6893 {
6894 jamEntry();
6895
6896 scanFragptr.i = signal->theData[0];
6897 c_scan_frag_pool.getPtr(scanFragptr);
6898 switch (scanFragptr.p->scanFragState){
6899 case ScanFragRec::LQH_ACTIVE:
6900 break;
6901 default:
6902 DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
6903 systemErrorLab(signal, __LINE__);
6904 break;
6905 }
6906
6907 ScanRecordPtr scanptr;
6908 scanptr.i = scanFragptr.p->scanRec;
6909 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
6910
6911 apiConnectptr.i = scanptr.p->scanApiRec;
6912 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6913
6914 if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
6915 apiConnectptr.p->transid[1] == signal->theData[2])){
6916 jam();
6917 /**
6918 * Send signal back to sender so that the crash occurs there
6919 */
6920 // Save original transid
6921 signal->theData[3] = signal->theData[0];
6922 signal->theData[4] = signal->theData[1];
6923 // Set transid to illegal values
6924 signal->theData[1] = RNIL;
6925 signal->theData[2] = RNIL;
6926
6927 sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
6928 DEBUG("SCAN_HBREP with wrong transid("
6929 <<signal->theData[3]<<", "<<signal->theData[4]<<")");
6930 return;
6931 }//if
6932
6933 // Update timer on ScanFragRec
6934 if (scanFragptr.p->scanFragTimer != 0){
6935 updateBuddyTimer(apiConnectptr);
6936 scanFragptr.p->startFragTimer(ctcTimer);
6937 } else {
6938 ndbassert(false);
6939 DEBUG("SCAN_HBREP when scanFragTimer was turned off");
6940 }
6941 }//execSCAN_HBREP()
6942
6943 /*--------------------------------------------------------------------------*/
6944 /* Timeout has occured on a fragment which means a scan has timed out. */
6945 /* If this is true we have an error in LQH/ACC. */
6946 /*--------------------------------------------------------------------------*/
timeOutFoundFragLab(Signal * signal,UintR TscanConPtr)6947 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
6948 {
6949 ScanFragRecPtr ptr;
6950 c_scan_frag_pool.getPtr(ptr, TscanConPtr);
6951 DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
6952
6953 const Uint32 time_out_param= ctimeOutValue;
6954 const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
6955
6956 if (unlikely(time_out_param != old_time_out_param &&
6957 getNodeState().getSingleUserMode()))
6958 {
6959 jam();
6960 ScanRecordPtr scanptr;
6961 scanptr.i = ptr.p->scanRec;
6962 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
6963 ApiConnectRecordPtr TlocalApiConnectptr;
6964 TlocalApiConnectptr.i = scanptr.p->scanApiRec;
6965 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
6966
6967 if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
6968 getNodeState().getSingleUserApi())
6969 {
6970 jam();
6971 Uint32 val = ctcTimer - ptr.p->scanFragTimer;
6972 if (val <= old_time_out_param)
6973 {
6974 jam();
6975 goto next;
6976 }
6977 }
6978 }
6979
6980 /*-------------------------------------------------------------------------*/
6981 // The scan fragment has expired its timeout. Check its state to decide
6982 // what to do.
6983 /*-------------------------------------------------------------------------*/
6984 switch (ptr.p->scanFragState) {
6985 case ScanFragRec::WAIT_GET_PRIMCONF:
6986 jam();
6987 ndbrequire(false);
6988 break;
6989 case ScanFragRec::LQH_ACTIVE:{
6990 jam();
6991
6992 /**
6993 * The LQH expired it's timeout, try to close it
6994 */
6995 Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
6996 Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
6997 ScanRecordPtr scanptr;
6998 scanptr.i = ptr.p->scanRec;
6999 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
7000
7001 if(connectCount != ptr.p->m_connectCount){
7002 jam();
7003 /**
7004 * The node has died
7005 */
7006 ptr.p->scanFragState = ScanFragRec::COMPLETED;
7007 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
7008
7009 run.release(ptr);
7010 ptr.p->stopFragTimer();
7011 }
7012
7013 scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
7014 break;
7015 }
7016 case ScanFragRec::DELIVERED:
7017 jam();
7018 case ScanFragRec::IDLE:
7019 jam();
7020 case ScanFragRec::QUEUED_FOR_DELIVERY:
7021 jam();
7022 /*-----------------------------------------------------------------------
7023 * Should never occur. We will simply report set the timer to zero and
7024 * continue. In a debug version we should crash here but not in a release
7025 * version. In a release version we will simply set the time-out to zero.
7026 *-----------------------------------------------------------------------*/
7027 #ifdef VM_TRACE
7028 systemErrorLab(signal, __LINE__);
7029 #endif
7030 scanFragptr.p->stopFragTimer();
7031 break;
7032 default:
7033 jam();
7034 /*-----------------------------------------------------------------------
7035 * Non-existent state. Crash.
7036 *-----------------------------------------------------------------------*/
7037 systemErrorLab(signal, __LINE__);
7038 break;
7039 }//switch
7040
7041 next:
7042 signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
7043 signal->theData[1] = TscanConPtr + 1;
7044 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
7045 return;
7046 }//timeOutFoundFragLab()
7047
7048
7049 /*
7050 4.3.16 GCP_NOMORETRANS
7051 ----------------------
7052 */
7053 /*****************************************************************************
7054 * G C P _ N O M O R E T R A N S
7055 *
7056 * WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
7057 * THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
7058 * SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
7059 * CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
7060 * FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
7061 * COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
7062 * THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
7063 * THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
7064 * TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
7065 *****************************************************************************/
execGCP_NOMORETRANS(Signal * signal)7066 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
7067 {
7068 jamEntry();
7069 c_gcp_ref = signal->theData[0];
7070 tcheckGcpId = signal->theData[1];
7071 if (cfirstgcp != RNIL) {
7072 jam();
7073 /* A GLOBAL CHECKPOINT IS GOING ON */
7074 gcpPtr.i = cfirstgcp; /* SET POINTER TO FIRST GCP IN QUEUE*/
7075 ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
7076 if (gcpPtr.p->gcpId == tcheckGcpId) {
7077 jam();
7078 if (gcpPtr.p->firstApiConnect != RNIL) {
7079 jam();
7080 gcpPtr.p->gcpNomoretransRec = ZTRUE;
7081 } else {
7082 jam();
7083 gcpTcfinished(signal);
7084 unlinkGcp(signal);
7085 }//if
7086 } else {
7087 jam();
7088 /*------------------------------------------------------------*/
7089 /* IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO */
7090 /* RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE */
7091 /* THE GLOBAL CHECKPOINTS IN ORDER. */
7092 /*------------------------------------------------------------*/
7093 gcpTcfinished(signal);
7094 }//if
7095 } else {
7096 jam();
7097 gcpTcfinished(signal);
7098 }//if
7099 return;
7100 }//Dbtc::execGCP_NOMORETRANS()
7101
7102 /*****************************************************************************/
7103 /* */
7104 /* TAKE OVER MODULE */
7105 /* */
7106 /*****************************************************************************/
7107 /* */
7108 /* THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE */
7109 /* NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT */
7110 /* ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE */
7111 /* FAILED. */
7112 /* */
7113 /* AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
7114 /* CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
7115 /* COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED. */
7116 /* IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO */
7117 /* WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT. */
7118 /*****************************************************************************/
execNODE_FAILREP(Signal * signal)7119 void Dbtc::execNODE_FAILREP(Signal* signal)
7120 {
7121 jamEntry();
7122
7123 NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
7124
7125 cfailure_nr = nodeFail->failNo;
7126 const Uint32 tnoOfNodes = nodeFail->noOfNodes;
7127 const Uint32 tnewMasterId = nodeFail->masterNodeId;
7128
7129 arrGuard(tnoOfNodes, MAX_NDB_NODES);
7130 Uint32 i;
7131 int index = 0;
7132 for (i = 1; i< MAX_NDB_NODES; i++)
7133 {
7134 if(NodeBitmask::get(nodeFail->theNodes, i))
7135 {
7136 cdata[index] = i;
7137 index++;
7138 }//if
7139 }//for
7140
7141 cmasterNodeId = tnewMasterId;
7142
7143 tcNodeFailptr.i = 0;
7144 ptrAss(tcNodeFailptr, tcFailRecord);
7145 for (i = 0; i < tnoOfNodes; i++)
7146 {
7147 jam();
7148 hostptr.i = cdata[i];
7149 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7150
7151 /*------------------------------------------------------------*/
7152 /* SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS */
7153 /* FAILED. */
7154 /*------------------------------------------------------------*/
7155 hostptr.p->hostStatus = HS_DEAD;
7156 hostptr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
7157 c_alive_nodes.clear(hostptr.i);
7158
7159 if (tcNodeFailptr.p->failStatus == FS_LISTENING)
7160 {
7161 jam();
7162 /*------------------------------------------------------------*/
7163 /* THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE */
7164 /* FAILURE. */
7165 /*------------------------------------------------------------*/
7166 if (hostptr.p->lqhTransStatus == LTS_ACTIVE)
7167 {
7168 jam();
7169 /*------------------------------------------------------------*/
7170 /* WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
7171 /* PROTOCOL FOR TC. */
7172 /*------------------------------------------------------------*/
7173 signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
7174 signal->theData[1] = hostptr.i;
7175 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
7176 }//if
7177 }//if
7178
7179 if (getOwnNodeId() != tnewMasterId)
7180 {
7181 jam();
7182 /**
7183 * Only master does takeover currently
7184 */
7185 hostptr.p->m_nf_bits &= ~HostRecord::NF_TAKEOVER;
7186 }
7187 else
7188 {
7189 jam();
7190 signal->theData[0] = hostptr.i;
7191 sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
7192 }
7193
7194 checkScanActiveInFailedLqh(signal, 0, hostptr.i);
7195 checkWaitDropTabFailedLqh(signal, hostptr.i, 0); // nodeid, tableid
7196 nodeFailCheckTransactions(signal, 0, hostptr.i);
7197 }
7198 }//Dbtc::execNODE_FAILREP()
7199
7200 void
checkNodeFailComplete(Signal * signal,Uint32 failedNodeId,Uint32 bit)7201 Dbtc::checkNodeFailComplete(Signal* signal,
7202 Uint32 failedNodeId,
7203 Uint32 bit)
7204 {
7205 hostptr.i = failedNodeId;
7206 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7207 hostptr.p->m_nf_bits &= ~bit;
7208 if (hostptr.p->m_nf_bits == 0)
7209 {
7210 NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
7211 nfRep->blockNo = DBTC;
7212 nfRep->nodeId = cownNodeid;
7213 nfRep->failedNodeId = hostptr.i;
7214 sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
7215 NFCompleteRep::SignalLength, JBB);
7216 }
7217 }
7218
checkScanActiveInFailedLqh(Signal * signal,Uint32 scanPtrI,Uint32 failedNodeId)7219 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
7220 Uint32 scanPtrI,
7221 Uint32 failedNodeId){
7222
7223 ScanRecordPtr scanptr;
7224 for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
7225 jam();
7226 ptrAss(scanptr, scanRecord);
7227 bool found = false;
7228 if (scanptr.p->scanState != ScanRecord::IDLE){
7229 jam();
7230 ScanFragRecPtr ptr;
7231 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
7232
7233 for(run.first(ptr); !ptr.isNull(); ){
7234 jam();
7235 ScanFragRecPtr curr = ptr;
7236 run.next(ptr);
7237 if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
7238 refToNode(curr.p->lqhBlockref) == failedNodeId){
7239 jam();
7240
7241 run.release(curr);
7242 curr.p->scanFragState = ScanFragRec::COMPLETED;
7243 curr.p->stopFragTimer();
7244 found = true;
7245 }
7246 }
7247
7248 ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
7249 for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
7250 {
7251 jam();
7252 if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
7253 {
7254 jam();
7255 found = true;
7256 break;
7257 }
7258 }
7259 }
7260 if(found){
7261 jam();
7262 scanError(signal, scanptr, ZSCAN_LQH_ERROR);
7263 }
7264
7265 // Send CONTINUEB to continue later
7266 signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
7267 signal->theData[1] = scanptr.i + 1; // Check next scanptr
7268 signal->theData[2] = failedNodeId;
7269 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7270 return;
7271 }//for
7272
7273 checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
7274 }
7275
7276 void
nodeFailCheckTransactions(Signal * signal,Uint32 transPtrI,Uint32 failedNodeId)7277 Dbtc::nodeFailCheckTransactions(Signal* signal,
7278 Uint32 transPtrI,
7279 Uint32 failedNodeId)
7280 {
7281 jam();
7282 Ptr<ApiConnectRecord> transPtr;
7283 Uint32 TtcTimer = ctcTimer;
7284 Uint32 TapplTimeout = c_appl_timeout_value;
7285 for (transPtr.i = transPtrI; transPtr.i < capiConnectFilesize; transPtr.i++)
7286 {
7287 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
7288 if (transPtr.p->m_transaction_nodes.get(failedNodeId))
7289 {
7290 jam();
7291
7292 // Force timeout regardless of state
7293 c_appl_timeout_value = 1;
7294 setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
7295 timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
7296 c_appl_timeout_value = TapplTimeout;
7297 }
7298
7299 // Send CONTINUEB to continue later
7300 signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
7301 signal->theData[1] = transPtr.i + 1; // Check next
7302 signal->theData[2] = failedNodeId;
7303 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7304 return;
7305 }
7306
7307 checkNodeFailComplete(signal, failedNodeId,
7308 HostRecord::NF_CHECK_TRANSACTION);
7309 }
7310
7311
7312 void
checkScanFragList(Signal * signal,Uint32 failedNodeId,ScanRecord * scanP,ScanFragList::Head & head)7313 Dbtc::checkScanFragList(Signal* signal,
7314 Uint32 failedNodeId,
7315 ScanRecord * scanP,
7316 ScanFragList::Head & head){
7317
7318 DEBUG("checkScanActiveInFailedLqh: scanFragError");
7319 }
7320
execTAKE_OVERTCCONF(Signal * signal)7321 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
7322 {
7323 jamEntry();
7324 tfailedNodeId = signal->theData[0];
7325 hostptr.i = tfailedNodeId;
7326 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7327
7328 if (signal->getSendersBlockRef() != reference())
7329 {
7330 jam();
7331 return;
7332 }
7333
7334 checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
7335 }//Dbtc::execTAKE_OVERTCCONF()
7336
execTAKE_OVERTCREQ(Signal * signal)7337 void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
7338 {
7339 jamEntry();
7340 tfailedNodeId = signal->theData[0];
7341 tcNodeFailptr.i = 0;
7342 ptrAss(tcNodeFailptr, tcFailRecord);
7343 if (tcNodeFailptr.p->failStatus != FS_IDLE) {
7344 jam();
7345 /*------------------------------------------------------------*/
7346 /* WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
7347 /*------------------------------------------------------------*/
7348 /* IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL */
7349 /* QUEUE THE TAKE OVER AND START IT AS SOON AS THE */
7350 /* PREVIOUS ARE COMPLETED. */
7351 /*------------------------------------------------------------*/
7352 arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
7353 tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
7354 tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
7355 return;
7356 }//if
7357 startTakeOverLab(signal);
7358 }//Dbtc::execTAKE_OVERTCREQ()
7359
7360 /*------------------------------------------------------------*/
7361 /* INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS */
7362 /* AND OPERATIONS DURING TC TAKE OVER. */
7363 /*------------------------------------------------------------*/
startTakeOverLab(Signal * signal)7364 void Dbtc::startTakeOverLab(Signal* signal)
7365 {
7366 for (tindex = 0; tindex <= 511; tindex++) {
7367 ctransidFailHash[tindex] = RNIL;
7368 }//for
7369 for (tindex = 0; tindex <= 1023; tindex++) {
7370 ctcConnectFailHash[tindex] = RNIL;
7371 }//for
7372 tcNodeFailptr.p->failStatus = FS_LISTENING;
7373 tcNodeFailptr.p->takeOverNode = tfailedNodeId;
7374 for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
7375 jam();
7376 ptrAss(hostptr, hostRecord);
7377 if (hostptr.p->hostStatus == HS_ALIVE) {
7378 jam();
7379 tblockref = calcLqhBlockRef(hostptr.i);
7380 hostptr.p->lqhTransStatus = LTS_ACTIVE;
7381 signal->theData[0] = tcNodeFailptr.i;
7382 signal->theData[1] = cownref;
7383 signal->theData[2] = tfailedNodeId;
7384 sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
7385 }//if
7386 }//for
7387 }//Dbtc::startTakeOverLab()
7388
7389 /*------------------------------------------------------------*/
7390 /* A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
7391 /*------------------------------------------------------------*/
execLQH_TRANSCONF(Signal * signal)7392 void Dbtc::execLQH_TRANSCONF(Signal* signal)
7393 {
7394 jamEntry();
7395 LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
7396
7397 tcNodeFailptr.i = lqhTransConf->tcRef;
7398 ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
7399 tnodeid = lqhTransConf->lqhNodeId;
7400 ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
7401 ttransid1 = lqhTransConf->transId1;
7402 ttransid2 = lqhTransConf->transId2;
7403 ttcOprec = lqhTransConf->oldTcOpRec;
7404 treqinfo = lqhTransConf->requestInfo;
7405 tgci = lqhTransConf->gci;
7406 cnodes[0] = lqhTransConf->nextNodeId1;
7407 cnodes[1] = lqhTransConf->nextNodeId2;
7408 cnodes[2] = lqhTransConf->nextNodeId3;
7409 const Uint32 ref = tapplRef = lqhTransConf->apiRef;
7410 tapplOprec = lqhTransConf->apiOpRec;
7411 const Uint32 tableId = lqhTransConf->tableId;
7412
7413 if (ttransStatus == LqhTransConf::LastTransConf){
7414 jam();
7415 /*------------------------------------------------------------*/
7416 /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
7417 /*------------------------------------------------------------*/
7418 nodeTakeOverCompletedLab(signal);
7419 return;
7420 }//if
7421 if (ttransStatus == LqhTransConf::Marker){
7422 jam();
7423 treqinfo = 0;
7424 LqhTransConf::setMarkerFlag(treqinfo, 1);
7425 } else {
7426 TableRecordPtr tabPtr;
7427 tabPtr.i = tableId;
7428 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
7429 switch((DictTabInfo::TableType)tabPtr.p->tableType){
7430 case DictTabInfo::SystemTable:
7431 case DictTabInfo::UserTable:
7432 break;
7433 default:
7434 tapplRef = 0;
7435 tapplOprec = 0;
7436 }
7437 }
7438
7439 findApiConnectFail(signal);
7440
7441 if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
7442 apiConnectptr.p->ndbapiBlockref = ref;
7443 apiConnectptr.p->ndbapiConnect = tapplOprec;
7444 }
7445
7446 if (ttransStatus != LqhTransConf::Marker){
7447 jam();
7448 findTcConnectFail(signal);
7449 }
7450 }//Dbtc::execLQH_TRANSCONF()
7451
7452 /*------------------------------------------------------------*/
7453 /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
7454 /*------------------------------------------------------------*/
nodeTakeOverCompletedLab(Signal * signal)7455 void Dbtc::nodeTakeOverCompletedLab(Signal* signal)
7456 {
7457 Uint32 guard0;
7458
7459 hostptr.i = tnodeid;
7460 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7461 hostptr.p->lqhTransStatus = LTS_IDLE;
7462 for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
7463 jam();
7464 ptrAss(hostptr, hostRecord);
7465 if (hostptr.p->hostStatus == HS_ALIVE) {
7466 if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
7467 jam();
7468 /*------------------------------------------------------------*/
7469 /* NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE */
7470 /* TAKE OVER. */
7471 /*------------------------------------------------------------*/
7472 return;
7473 }//if
7474 }//if
7475 }//for
7476 /*------------------------------------------------------------*/
7477 /* ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
7478 /* OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE */
7479 /* ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE */
7480 /* TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN */
7481 /* UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
7482 /* TO THE APPLICATION IF THAT IS STILL ALIVE. */
7483 /*------------------------------------------------------------*/
7484 tcNodeFailptr.p->currentHashIndexTakeOver = 0;
7485 tcNodeFailptr.p->completedTakeOver = 0;
7486 tcNodeFailptr.p->failStatus = FS_COMPLETING;
7487 guard0 = cnoParallelTakeOver - 1;
7488 /*------------------------------------------------------------*/
7489 /* WE WILL COMPLETE THE TRANSACTIONS BY STARTING A */
7490 /* NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL */
7491 /* COMPLETE ONE TRANSACTION AT A TIME AND IN THAT */
7492 /* TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
7493 /* WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
7494 /* IS COMPLETED. */
7495 /*------------------------------------------------------------*/
7496 arrGuard(guard0, MAX_NDB_NODES);
7497 for (tindex = 0; tindex <= guard0; tindex++) {
7498 jam();
7499 tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
7500 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7501 signal->theData[1] = tcNodeFailptr.i;
7502 signal->theData[2] = tindex;
7503 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7504 }//for
7505 }//Dbtc::nodeTakeOverCompletedLab()
7506
7507 /*------------------------------------------------------------*/
7508 /* COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF */
7509 /* TRANSACTIONS TO COMPLETE. */
7510 /*------------------------------------------------------------*/
completeTransAtTakeOverLab(Signal * signal,UintR TtakeOverInd)7511 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
7512 {
7513 jam();
7514 while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
7515 jam();
7516 apiConnectptr.i =
7517 ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
7518 if (apiConnectptr.i != RNIL) {
7519 jam();
7520 /*------------------------------------------------------------*/
7521 /* WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE */
7522 /* COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT */
7523 /* NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS */
7524 /* TRANSACTION. */
7525 /*------------------------------------------------------------*/
7526 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7527 ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
7528 apiConnectptr.p->nextApiConnect;
7529
7530 completeTransAtTakeOverDoOne(signal, TtakeOverInd);
7531 // One transaction taken care of, return from this function
7532 // and wait for the next CONTINUEB to continue processing
7533 break;
7534
7535 } else {
7536 if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
7537 jam();
7538 tcNodeFailptr.p->currentHashIndexTakeOver++;
7539 } else {
7540 jam();
7541 completeTransAtTakeOverDoLast(signal, TtakeOverInd);
7542 tcNodeFailptr.p->currentHashIndexTakeOver++;
7543 }//if
7544 }//if
7545 }//while
7546 }//Dbtc::completeTransAtTakeOverLab()
7547
7548
7549
7550
completeTransAtTakeOverDoLast(Signal * signal,UintR TtakeOverInd)7551 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
7552 {
7553 Uint32 guard0;
7554 /*------------------------------------------------------------*/
7555 /* THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS */
7556 /* ACTIVITY IS COMPLETED. */
7557 /*------------------------------------------------------------*/
7558 arrGuard(TtakeOverInd, MAX_NDB_NODES);
7559 if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
7560 jam();
7561 systemErrorLab(signal, __LINE__);
7562 return;
7563 }//if
7564 tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
7565 tcNodeFailptr.p->completedTakeOver++;
7566
7567 if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
7568 jam();
7569 /*------------------------------------------------------------*/
7570 /* WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
7571 /* TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL */
7572 /* NODES THAT ARE ALIVE. */
7573 /*------------------------------------------------------------*/
7574 NodeReceiverGroup rg(DBTC, c_alive_nodes);
7575 signal->theData[0] = tcNodeFailptr.p->takeOverNode;
7576 sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 1, JBB);
7577
7578 if (tcNodeFailptr.p->queueIndex > 0) {
7579 jam();
7580 /*------------------------------------------------------------*/
7581 /* THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START */
7582 /* THE TAKE OVER. */
7583 /*------------------------------------------------------------*/
7584 tfailedNodeId = tcNodeFailptr.p->queueList[0];
7585 guard0 = tcNodeFailptr.p->queueIndex - 1;
7586 arrGuard(guard0 + 1, MAX_NDB_NODES);
7587 for (tindex = 0; tindex <= guard0; tindex++) {
7588 jam();
7589 tcNodeFailptr.p->queueList[tindex] =
7590 tcNodeFailptr.p->queueList[tindex + 1];
7591 }//for
7592 tcNodeFailptr.p->queueIndex--;
7593 startTakeOverLab(signal);
7594 return;
7595 } else {
7596 jam();
7597 tcNodeFailptr.p->failStatus = FS_IDLE;
7598 }//if
7599 }//if
7600 return;
7601 }//Dbtc::completeTransAtTakeOverDoLast()
7602
completeTransAtTakeOverDoOne(Signal * signal,UintR TtakeOverInd)7603 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
7604 {
7605 apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
7606 apiConnectptr.p->takeOverInd = TtakeOverInd;
7607
7608 switch (apiConnectptr.p->apiConnectstate) {
7609 case CS_FAIL_COMMITTED:
7610 jam();
7611 /*------------------------------------------------------------*/
7612 /* ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
7613 /* HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT */
7614 /* COMMITTED TO THE APPLICATION AND CONTINUE WITH THE */
7615 /* COMPLETE PHASE. */
7616 /*------------------------------------------------------------*/
7617 sendTCKEY_FAILCONF(signal, apiConnectptr.p);
7618 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7619 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7620 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7621 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7622 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7623 toCompleteHandlingLab(signal);
7624 return;
7625 case CS_FAIL_COMMITTING:
7626 jam();
7627 /*------------------------------------------------------------*/
7628 /* AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
7629 /* PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
7630 /* THEN CONTINUE AS AFTER COMMITTED. */
7631 /*------------------------------------------------------------*/
7632 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7633 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7634 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7635 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7636 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7637 toCommitHandlingLab(signal);
7638 return;
7639 case CS_FAIL_ABORTING:
7640 case CS_FAIL_PREPARED:
7641 jam();
7642 /*------------------------------------------------------------*/
7643 /* WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
7644 /* STATE IN THIS VERSION. IN LATER VERSIONS WE WILL */
7645 /* HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT */
7646 /* TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
7647 /* HAVE HEARD FROM THE TRANSACTION COORDINATOR. */
7648 /* */
7649 /* IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE */
7650 /* PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL */
7651 /* LATER VERSIONS. */
7652 /*------------------------------------------------------------*/
7653 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7654 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7655 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7656 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7657 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7658 toAbortHandlingLab(signal);
7659 return;
7660 case CS_FAIL_ABORTED:
7661 jam();
7662 sendTCKEY_FAILREF(signal, apiConnectptr.p);
7663
7664 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7665 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
7666 signal->theData[2] = apiConnectptr.p->takeOverInd;
7667 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7668 releaseTakeOver(signal);
7669 break;
7670 case CS_FAIL_COMPLETED:
7671 jam();
7672 sendTCKEY_FAILCONF(signal, apiConnectptr.p);
7673
7674 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7675 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
7676 signal->theData[2] = apiConnectptr.p->takeOverInd;
7677 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7678 releaseApiConnectFail(signal);
7679 break;
7680 default:
7681 jam();
7682 systemErrorLab(signal, __LINE__);
7683 return;
7684 }//switch
7685 }//Dbtc::completeTransAtTakeOverDoOne()
7686
7687 void
sendTCKEY_FAILREF(Signal * signal,const ApiConnectRecord * regApiPtr)7688 Dbtc::sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord * regApiPtr){
7689 jam();
7690
7691 const Uint32 ref = regApiPtr->ndbapiBlockref;
7692 if(ref != 0){
7693 signal->theData[0] = regApiPtr->ndbapiConnect;
7694 signal->theData[1] = regApiPtr->transid[0];
7695 signal->theData[2] = regApiPtr->transid[1];
7696
7697 sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
7698 }
7699 }
7700
7701 void
sendTCKEY_FAILCONF(Signal * signal,ApiConnectRecord * regApiPtr)7702 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
7703 jam();
7704 TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
7705
7706 const Uint32 ref = regApiPtr->ndbapiBlockref;
7707 const Uint32 marker = regApiPtr->commitAckMarker;
7708 if(ref != 0){
7709 failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
7710 failConf->transId1 = regApiPtr->transid[0];
7711 failConf->transId2 = regApiPtr->transid[1];
7712
7713 sendSignal(regApiPtr->ndbapiBlockref,
7714 GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB);
7715 }
7716 regApiPtr->commitAckMarker = RNIL;
7717 }
7718
7719 /*------------------------------------------------------------*/
7720 /* THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A */
7721 /* NODE FAILURE BEFORE THE COMMIT DECISION. */
7722 /*------------------------------------------------------------*/
7723 /* ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
7724 /*------------------------------------------------------------*/
execABORTCONF(Signal * signal)7725 void Dbtc::execABORTCONF(Signal* signal)
7726 {
7727 UintR compare_transid1, compare_transid2;
7728
7729 jamEntry();
7730 tcConnectptr.i = signal->theData[0];
7731 tnodeid = signal->theData[2];
7732 if (ERROR_INSERTED(8045)) {
7733 CLEAR_ERROR_INSERT_VALUE;
7734 sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
7735 return;
7736 }//if
7737 if (tcConnectptr.i >= ctcConnectFilesize) {
7738 errorReport(signal, 5);
7739 return;
7740 }//if
7741 ptrAss(tcConnectptr, tcConnectRecord);
7742 if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
7743 warningReport(signal, 16);
7744 return;
7745 }//if
7746 apiConnectptr.i = tcConnectptr.p->apiConnect;
7747 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7748 if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
7749 warningReport(signal, 17);
7750 return;
7751 }//if
7752 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
7753 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
7754 compare_transid1 = compare_transid1 | compare_transid2;
7755 if (compare_transid1 != 0) {
7756 warningReport(signal, 18);
7757 return;
7758 }//if
7759 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7760 if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
7761 tnodeid) {
7762 warningReport(signal, 19);
7763 return;
7764 }//if
7765 tcurrentReplicaNo = (Uint8)Z8NIL;
7766 tcConnectptr.p->tcConnectstate = OS_ABORTING;
7767 toAbortHandlingLab(signal);
7768 }//Dbtc::execABORTCONF()
7769
toAbortHandlingLab(Signal * signal)7770 void Dbtc::toAbortHandlingLab(Signal* signal)
7771 {
7772 do {
7773 if (tcurrentReplicaNo != (Uint8)Z8NIL) {
7774 jam();
7775 arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
7776 const LqhTransConf::OperationStatus stat =
7777 (LqhTransConf::OperationStatus)
7778 tcConnectptr.p->failData[tcurrentReplicaNo];
7779 switch(stat){
7780 case LqhTransConf::InvalidStatus:
7781 case LqhTransConf::Aborted:
7782 jam();
7783 /*empty*/;
7784 break;
7785 case LqhTransConf::Prepared:
7786 jam();
7787 hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
7788 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7789 if (hostptr.p->hostStatus == HS_ALIVE) {
7790 jam();
7791 tblockref = calcLqhBlockRef(hostptr.i);
7792 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7793 tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
7794 apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
7795 apiConnectptr.p->timeOutCounter = 0;
7796 signal->theData[0] = tcConnectptr.i;
7797 signal->theData[1] = cownref;
7798 signal->theData[2] = apiConnectptr.p->transid[0];
7799 signal->theData[3] = apiConnectptr.p->transid[1];
7800 signal->theData[4] = apiConnectptr.p->tcBlockref;
7801 signal->theData[5] = tcConnectptr.p->tcOprec;
7802 sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
7803 return;
7804 }//if
7805 break;
7806 default:
7807 jam();
7808 systemErrorLab(signal, __LINE__);
7809 return;
7810 }//switch
7811 }//if
7812 if (apiConnectptr.p->currentReplicaNo > 0) {
7813 jam();
7814 /*------------------------------------------------------------*/
7815 /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
7816 /* ABORTED. */
7817 /*------------------------------------------------------------*/
7818 apiConnectptr.p->currentReplicaNo--;
7819 tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
7820 } else {
7821 /*------------------------------------------------------------*/
7822 /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
7823 /*------------------------------------------------------------*/
7824 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7825 if (tcConnectptr.i == RNIL) {
7826 /*------------------------------------------------------------*/
7827 /* WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
7828 /* THE ABORT STATUS TO THE APPLICATION AND CONTINUE */
7829 /* WITH THE NEXT TRANSACTION. */
7830 /*------------------------------------------------------------*/
7831 if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
7832 jam();
7833 sendTCKEY_FAILREF(signal, apiConnectptr.p);
7834 const Uint32 marker = apiConnectptr.p->commitAckMarker;
7835 if(marker != RNIL){
7836 jam();
7837
7838 CommitAckMarkerPtr tmp;
7839 tmp.i = marker;
7840 tmp.p = m_commitAckMarkerHash.getPtr(tmp.i);
7841
7842 m_commitAckMarkerHash.release(tmp);
7843 apiConnectptr.p->commitAckMarker = RNIL;
7844 }
7845
7846 /*------------------------------------------------------------*/
7847 /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
7848 /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
7849 /*------------------------------------------------------------*/
7850 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7851 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
7852 signal->theData[2] = apiConnectptr.p->takeOverInd;
7853 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7854 releaseTakeOver(signal);
7855 } else {
7856 jam();
7857 releaseAbortResources(signal);
7858 }//if
7859 return;
7860 }//if
7861 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7862 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7863 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7864 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7865 }//if
7866 } while (1);
7867 }//Dbtc::toAbortHandlingLab()
7868
7869 /*------------------------------------------------------------*/
7870 /* THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A */
7871 /* NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE. */
7872 /*------------------------------------------------------------*/
7873 /* COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
7874 /*------------------------------------------------------------*/
execCOMMITCONF(Signal * signal)7875 void Dbtc::execCOMMITCONF(Signal* signal)
7876 {
7877 UintR compare_transid1, compare_transid2;
7878
7879 jamEntry();
7880 tcConnectptr.i = signal->theData[0];
7881 tnodeid = signal->theData[1];
7882 if (ERROR_INSERTED(8046)) {
7883 CLEAR_ERROR_INSERT_VALUE;
7884 sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
7885 return;
7886 }//if
7887 if (tcConnectptr.i >= ctcConnectFilesize) {
7888 errorReport(signal, 4);
7889 return;
7890 }//if
7891 ptrAss(tcConnectptr, tcConnectRecord);
7892 if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
7893 warningReport(signal, 8);
7894 return;
7895 }//if
7896 apiConnectptr.i = tcConnectptr.p->apiConnect;
7897 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7898 if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
7899 warningReport(signal, 9);
7900 return;
7901 }//if
7902 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
7903 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
7904 compare_transid1 = compare_transid1 | compare_transid2;
7905 if (compare_transid1 != 0) {
7906 warningReport(signal, 10);
7907 return;
7908 }//if
7909 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7910 if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
7911 tnodeid) {
7912 warningReport(signal, 11);
7913 return;
7914 }//if
7915 if (ERROR_INSERTED(8026)) {
7916 jam();
7917 systemErrorLab(signal, __LINE__);
7918 }//if
7919 tcurrentReplicaNo = (Uint8)Z8NIL;
7920 tcConnectptr.p->tcConnectstate = OS_COMMITTED;
7921 toCommitHandlingLab(signal);
7922 }//Dbtc::execCOMMITCONF()
7923
toCommitHandlingLab(Signal * signal)7924 void Dbtc::toCommitHandlingLab(Signal* signal)
7925 {
7926 do {
7927 if (tcurrentReplicaNo != (Uint8)Z8NIL) {
7928 jam();
7929 arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
7930 switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
7931 case LqhTransConf::InvalidStatus:
7932 jam();
7933 /*empty*/;
7934 break;
7935 case LqhTransConf::Committed:
7936 jam();
7937 /*empty*/;
7938 break;
7939 case LqhTransConf::Prepared:
7940 jam();
7941 /*------------------------------------------------------------*/
7942 /* THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR */
7943 /* COMMIT REQUEST FROM TC. */
7944 /*------------------------------------------------------------*/
7945 hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
7946 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7947 if (hostptr.p->hostStatus == HS_ALIVE) {
7948 jam();
7949 tblockref = calcLqhBlockRef(hostptr.i);
7950 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7951 apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
7952 apiConnectptr.p->timeOutCounter = 0;
7953 tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
7954 signal->theData[0] = tcConnectptr.i;
7955 signal->theData[1] = cownref;
7956 signal->theData[2] = apiConnectptr.p->globalcheckpointid;
7957 signal->theData[3] = apiConnectptr.p->transid[0];
7958 signal->theData[4] = apiConnectptr.p->transid[1];
7959 signal->theData[5] = apiConnectptr.p->tcBlockref;
7960 signal->theData[6] = tcConnectptr.p->tcOprec;
7961 sendSignal(tblockref, GSN_COMMITREQ, signal, 7, JBB);
7962 return;
7963 }//if
7964 break;
7965 default:
7966 jam();
7967 systemErrorLab(signal, __LINE__);
7968 return;
7969 break;
7970 }//switch
7971 }//if
7972 if (apiConnectptr.p->currentReplicaNo > 0) {
7973 jam();
7974 /*------------------------------------------------------------*/
7975 /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
7976 /* COMMITTED. */
7977 /*------------------------------------------------------------*/
7978 apiConnectptr.p->currentReplicaNo--;
7979 tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
7980 } else {
7981 /*------------------------------------------------------------*/
7982 /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
7983 /*------------------------------------------------------------*/
7984 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7985 if (tcConnectptr.i == RNIL) {
7986 /*------------------------------------------------------------*/
7987 /* WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
7988 /* THE COMMIT STATUS TO THE APPLICATION AND CONTINUE */
7989 /* WITH THE COMPLETE PHASE. */
7990 /*------------------------------------------------------------*/
7991 if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
7992 jam();
7993 sendTCKEY_FAILCONF(signal, apiConnectptr.p);
7994 } else {
7995 jam();
7996 sendApiCommit(signal);
7997 }//if
7998 apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
7999 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8000 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8001 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8002 apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
8003 toCompleteHandlingLab(signal);
8004 return;
8005 }//if
8006 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
8007 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8008 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
8009 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8010 }//if
8011 } while (1);
8012 }//Dbtc::toCommitHandlingLab()
8013
8014 /*------------------------------------------------------------*/
8015 /* COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE */
8016 /* HAVE FAILED. */
8017 /*------------------------------------------------------------*/
8018 /* THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION */
8019 /*------------------------------------------------------------*/
execCOMPLETECONF(Signal * signal)8020 void Dbtc::execCOMPLETECONF(Signal* signal)
8021 {
8022 UintR compare_transid1, compare_transid2;
8023
8024 jamEntry();
8025 tcConnectptr.i = signal->theData[0];
8026 tnodeid = signal->theData[1];
8027 if (ERROR_INSERTED(8047)) {
8028 CLEAR_ERROR_INSERT_VALUE;
8029 sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
8030 return;
8031 }//if
8032 if (tcConnectptr.i >= ctcConnectFilesize) {
8033 errorReport(signal, 3);
8034 return;
8035 }//if
8036 ptrAss(tcConnectptr, tcConnectRecord);
8037 if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
8038 warningReport(signal, 12);
8039 return;
8040 }//if
8041 apiConnectptr.i = tcConnectptr.p->apiConnect;
8042 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8043 if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
8044 warningReport(signal, 13);
8045 return;
8046 }//if
8047 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
8048 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
8049 compare_transid1 = compare_transid1 | compare_transid2;
8050 if (compare_transid1 != 0) {
8051 warningReport(signal, 14);
8052 return;
8053 }//if
8054 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
8055 if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
8056 tnodeid) {
8057 warningReport(signal, 15);
8058 return;
8059 }//if
8060 if (ERROR_INSERTED(8028)) {
8061 jam();
8062 systemErrorLab(signal, __LINE__);
8063 }//if
8064 tcConnectptr.p->tcConnectstate = OS_COMPLETED;
8065 tcurrentReplicaNo = (Uint8)Z8NIL;
8066 toCompleteHandlingLab(signal);
8067 }//Dbtc::execCOMPLETECONF()
8068
toCompleteHandlingLab(Signal * signal)8069 void Dbtc::toCompleteHandlingLab(Signal* signal)
8070 {
8071 do {
8072 if (tcurrentReplicaNo != (Uint8)Z8NIL) {
8073 jam();
8074 arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
8075 switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
8076 case LqhTransConf::InvalidStatus:
8077 jam();
8078 /*empty*/;
8079 break;
8080 default:
8081 jam();
8082 /*------------------------------------------------------------*/
8083 /* THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
8084 /* IT MUST HAVE FAILED. */
8085 /*------------------------------------------------------------*/
8086 /*------------------------------------------------------------*/
8087 /* SEND COMPLETEREQ TO THE NEXT REPLICA. */
8088 /*------------------------------------------------------------*/
8089 hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
8090 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8091 if (hostptr.p->hostStatus == HS_ALIVE) {
8092 jam();
8093 tblockref = calcLqhBlockRef(hostptr.i);
8094 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8095 tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
8096 apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
8097 apiConnectptr.p->timeOutCounter = 0;
8098 tcConnectptr.p->apiConnect = apiConnectptr.i;
8099 signal->theData[0] = tcConnectptr.i;
8100 signal->theData[1] = cownref;
8101 signal->theData[2] = apiConnectptr.p->transid[0];
8102 signal->theData[3] = apiConnectptr.p->transid[1];
8103 signal->theData[4] = apiConnectptr.p->tcBlockref;
8104 signal->theData[5] = tcConnectptr.p->tcOprec;
8105 sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
8106 return;
8107 }//if
8108 break;
8109 }//switch
8110 }//if
8111 if (apiConnectptr.p->currentReplicaNo != 0) {
8112 jam();
8113 /*------------------------------------------------------------*/
8114 /* THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE */
8115 /* NEED TO CONTINUE WITH THOSE REPLICAS. */
8116 /*------------------------------------------------------------*/
8117 apiConnectptr.p->currentReplicaNo--;
8118 tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
8119 } else {
8120 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
8121 if (tcConnectptr.i == RNIL) {
8122 /*------------------------------------------------------------*/
8123 /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
8124 /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
8125 /*------------------------------------------------------------*/
8126 if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
8127 jam();
8128 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
8129 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
8130 signal->theData[2] = apiConnectptr.p->takeOverInd;
8131 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8132 releaseTakeOver(signal);
8133 } else {
8134 jam();
8135 releaseTransResources(signal);
8136 }//if
8137 return;
8138 }//if
8139 /*------------------------------------------------------------*/
8140 /* WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
8141 /* COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
8142 /* FIRST REPLICA SINCE IT IS THE COMPLETE PHASE. */
8143 /*------------------------------------------------------------*/
8144 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
8145 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8146 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8147 apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
8148 }//if
8149 } while (1);
8150 }//Dbtc::toCompleteHandlingLab()
8151
8152 /*------------------------------------------------------------*/
8153 /* */
8154 /* FIND THE API CONNECT RECORD FOR THIS TRANSACTION */
8155 /* DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS */
8156 /* YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT */
8157 /* INTO THE HASH TABLE. */
8158 /*------------------------------------------------------------*/
findApiConnectFail(Signal * signal)8159 void Dbtc::findApiConnectFail(Signal* signal)
8160 {
8161 ApiConnectRecordPtr fafPrevApiConnectptr;
8162 ApiConnectRecordPtr fafNextApiConnectptr;
8163 UintR tfafHashNumber;
8164
8165 tfafHashNumber = ttransid1 & 511;
8166 fafPrevApiConnectptr.i = RNIL;
8167 ptrNull(fafPrevApiConnectptr);
8168 arrGuard(tfafHashNumber, 512);
8169 fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
8170 ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
8171 FAF_LOOP:
8172 jam();
8173 if (fafNextApiConnectptr.i == RNIL) {
8174 jam();
8175 if (cfirstfreeApiConnectFail == RNIL) {
8176 jam();
8177 systemErrorLab(signal, __LINE__);
8178 return;
8179 }//if
8180 seizeApiConnectFail(signal);
8181 if (fafPrevApiConnectptr.i == RNIL) {
8182 jam();
8183 ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
8184 } else {
8185 jam();
8186 ptrGuard(fafPrevApiConnectptr);
8187 fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
8188 }//if
8189 apiConnectptr.p->nextApiConnect = RNIL;
8190 initApiConnectFail(signal);
8191 } else {
8192 jam();
8193 fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
8194 fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
8195 apiConnectptr.i = fafNextApiConnectptr.i;
8196 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8197 fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
8198 ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
8199 if ((apiConnectptr.p->transid[1] != ttransid2) ||
8200 (apiConnectptr.p->transid[0] != ttransid1)) {
8201 goto FAF_LOOP;
8202 }//if
8203 updateApiStateFail(signal);
8204 }//if
8205 }//Dbtc::findApiConnectFail()
8206
8207 /*----------------------------------------------------------*/
8208 /* FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW */
8209 /*----------------------------------------------------------*/
findTcConnectFail(Signal * signal)8210 void Dbtc::findTcConnectFail(Signal* signal)
8211 {
8212 UintR tftfHashNumber;
8213
8214 tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
8215 tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
8216 do {
8217 if (tcConnectptr.i == RNIL) {
8218 jam();
8219 if (cfirstfreeTcConnectFail == RNIL) {
8220 jam();
8221 systemErrorLab(signal, __LINE__);
8222 return;
8223 }//if
8224 seizeTcConnectFail(signal);
8225 linkTcInConnectionlist(signal);
8226 tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
8227 ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
8228 initTcConnectFail(signal);
8229 return;
8230 } else {
8231 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8232 if (tcConnectptr.p->tcOprec != ttcOprec) {
8233 jam(); /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
8234 tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
8235 } else {
8236 updateTcStateFail(signal);
8237 return;
8238 }//if
8239 }//if
8240 } while (1);
8241 }//Dbtc::findTcConnectFail()
8242
8243 /*----------------------------------------------------------*/
8244 /* INITIALISE AN API CONNECT FAIL RECORD */
8245 /*----------------------------------------------------------*/
initApiConnectFail(Signal * signal)8246 void Dbtc::initApiConnectFail(Signal* signal)
8247 {
8248 apiConnectptr.p->transid[0] = ttransid1;
8249 apiConnectptr.p->transid[1] = ttransid2;
8250 apiConnectptr.p->firstTcConnect = RNIL;
8251 apiConnectptr.p->currSavePointId = 0;
8252 apiConnectptr.p->lastTcConnect = RNIL;
8253 tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
8254
8255 apiConnectptr.p->tcBlockref = tblockref;
8256 apiConnectptr.p->ndbapiBlockref = 0;
8257 apiConnectptr.p->ndbapiConnect = 0;
8258 apiConnectptr.p->buddyPtr = RNIL;
8259 apiConnectptr.p->m_transaction_nodes.clear();
8260 apiConnectptr.p->singleUserMode = 0;
8261 setApiConTimer(apiConnectptr.i, 0, __LINE__);
8262 switch(ttransStatus){
8263 case LqhTransConf::Committed:
8264 jam();
8265 apiConnectptr.p->globalcheckpointid = tgci;
8266 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
8267 break;
8268 case LqhTransConf::Prepared:
8269 jam();
8270 apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
8271 break;
8272 case LqhTransConf::Aborted:
8273 jam();
8274 apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
8275 break;
8276 case LqhTransConf::Marker:
8277 jam();
8278 apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
8279 break;
8280 default:
8281 jam();
8282 systemErrorLab(signal, __LINE__);
8283 }//if
8284 apiConnectptr.p->commitAckMarker = RNIL;
8285 if(LqhTransConf::getMarkerFlag(treqinfo)){
8286 jam();
8287 CommitAckMarkerPtr tmp;
8288 m_commitAckMarkerHash.seize(tmp);
8289
8290 ndbrequire(tmp.i != RNIL);
8291
8292 apiConnectptr.p->commitAckMarker = tmp.i;
8293 tmp.p->transid1 = ttransid1;
8294 tmp.p->transid2 = ttransid2;
8295 tmp.p->apiNodeId = refToNode(tapplRef);
8296 tmp.p->noOfLqhs = 1;
8297 tmp.p->lqhNodeId[0] = tnodeid;
8298 tmp.p->apiConnectPtr = apiConnectptr.i;
8299
8300 #if defined VM_TRACE || defined ERROR_INSERT
8301 {
8302 CommitAckMarkerPtr check;
8303 ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
8304 }
8305 #endif
8306 m_commitAckMarkerHash.add(tmp);
8307 }
8308 }//Dbtc::initApiConnectFail()
8309
8310 /*------------------------------------------------------------*/
8311 /* INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
8312 /* THE TC CONNECT RECORD. */
8313 /*------------------------------------------------------------*/
initTcConnectFail(Signal * signal)8314 void Dbtc::initTcConnectFail(Signal* signal)
8315 {
8316 tcConnectptr.p->apiConnect = apiConnectptr.i;
8317 tcConnectptr.p->tcOprec = ttcOprec;
8318 Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
8319 for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
8320 tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
8321 }//for
8322 tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
8323 tcConnectptr.p->failData[treplicaNo] = ttransStatus;
8324 tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
8325 tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
8326
8327 }//Dbtc::initTcConnectFail()
8328
8329 /*----------------------------------------------------------*/
8330 /* INITIALISE TC NODE FAIL RECORD. */
8331 /*----------------------------------------------------------*/
initTcFail(Signal * signal)8332 void Dbtc::initTcFail(Signal* signal)
8333 {
8334 tcNodeFailptr.i = 0;
8335 ptrAss(tcNodeFailptr, tcFailRecord);
8336 tcNodeFailptr.p->queueIndex = 0;
8337 tcNodeFailptr.p->failStatus = FS_IDLE;
8338 }//Dbtc::initTcFail()
8339
8340 /*----------------------------------------------------------*/
8341 /* RELEASE_TAKE_OVER */
8342 /*----------------------------------------------------------*/
releaseTakeOver(Signal * signal)8343 void Dbtc::releaseTakeOver(Signal* signal)
8344 {
8345 TcConnectRecordPtr rtoNextTcConnectptr;
8346
8347 rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
8348 do {
8349 jam();
8350 tcConnectptr.i = rtoNextTcConnectptr.i;
8351 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8352 rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
8353 releaseTcConnectFail(signal);
8354 } while (rtoNextTcConnectptr.i != RNIL);
8355 releaseApiConnectFail(signal);
8356 }//Dbtc::releaseTakeOver()
8357
8358 /*---------------------------------------------------------------------------*/
8359 /* SETUP_FAIL_DATA */
8360 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE */
8361 /* FAILURE SITUATIONS. */
8362 /*---------------------------------------------------------------------------*/
setupFailData(Signal * signal)8363 void Dbtc::setupFailData(Signal* signal)
8364 {
8365 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8366 do {
8367 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8368 switch (tcConnectptr.p->tcConnectstate) {
8369 case OS_PREPARED:
8370 case OS_COMMITTING:
8371 jam();
8372 arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
8373 for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
8374 jam();
8375 /*-------------------------------------------------------------------
8376 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
8377 * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
8378 * COMMIT/ABORT DECISION.
8379 *------------------------------------------------------------------*/
8380 tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
8381 }//for
8382 break;
8383 case OS_COMMITTED:
8384 case OS_COMPLETING:
8385 jam();
8386 arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
8387 for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
8388 jam();
8389 /*-------------------------------------------------------------------
8390 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
8391 * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
8392 * COMPLETE MESSAGE.
8393 *------------------------------------------------------------------*/
8394 tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
8395 }//for
8396 break;
8397 case OS_COMPLETED:
8398 jam();
8399 arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
8400 for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
8401 jam();
8402 /*-------------------------------------------------------------------
8403 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
8404 * IN THIS CASE ALL LQH'S ARE COMPLETED.
8405 *-------------------------------------------------------------------*/
8406 tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
8407 }//for
8408 break;
8409 default:
8410 jam();
8411 sendSystemError(signal, __LINE__);
8412 break;
8413 }//switch
8414 if (tabortInd != ZCOMMIT_SETUP) {
8415 jam();
8416 for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
8417 hostptr.i = tcConnectptr.p->tcNodedata[Ti];
8418 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8419 if (hostptr.p->hostStatus != HS_ALIVE) {
8420 jam();
8421 /*-----------------------------------------------------------------
8422 * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
8423 *-----------------------------------------------------------------*/
8424 tabortInd = ZTRUE;
8425 }//if
8426 }//for
8427 }//if
8428 tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
8429 tcConnectptr.p->tcOprec = tcConnectptr.i;
8430 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
8431 } while (tcConnectptr.i != RNIL);
8432 apiConnectptr.p->tcBlockref = cownref;
8433 apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
8434 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8435 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8436 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
8437 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8438 }//Dbtc::setupFailData()
8439
8440 /*----------------------------------------------------------*/
8441 /* UPDATE THE STATE OF THE API CONNECT FOR THIS PART. */
8442 /*----------------------------------------------------------*/
updateApiStateFail(Signal * signal)8443 void Dbtc::updateApiStateFail(Signal* signal)
8444 {
8445 if(LqhTransConf::getMarkerFlag(treqinfo)){
8446 jam();
8447 const Uint32 marker = apiConnectptr.p->commitAckMarker;
8448 if(marker == RNIL){
8449 jam();
8450
8451 CommitAckMarkerPtr tmp;
8452 m_commitAckMarkerHash.seize(tmp);
8453 ndbrequire(tmp.i != RNIL);
8454
8455 apiConnectptr.p->commitAckMarker = tmp.i;
8456 tmp.p->transid1 = ttransid1;
8457 tmp.p->transid2 = ttransid2;
8458 tmp.p->apiNodeId = refToNode(tapplRef);
8459 tmp.p->noOfLqhs = 1;
8460 tmp.p->lqhNodeId[0] = tnodeid;
8461 tmp.p->apiConnectPtr = apiConnectptr.i;
8462 #if defined VM_TRACE || defined ERROR_INSERT
8463 {
8464 CommitAckMarkerPtr check;
8465 ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
8466 }
8467 #endif
8468 m_commitAckMarkerHash.add(tmp);
8469 } else {
8470 jam();
8471
8472 CommitAckMarkerPtr tmp;
8473 tmp.i = marker;
8474 tmp.p = m_commitAckMarkerHash.getPtr(marker);
8475
8476 const Uint32 noOfLqhs = tmp.p->noOfLqhs;
8477 ndbrequire(noOfLqhs < MAX_REPLICAS);
8478 tmp.p->lqhNodeId[noOfLqhs] = tnodeid;
8479 tmp.p->noOfLqhs = (noOfLqhs + 1);
8480 }
8481 }
8482
8483 switch (ttransStatus) {
8484 case LqhTransConf::Committed:
8485 jam();
8486 switch (apiConnectptr.p->apiConnectstate) {
8487 case CS_FAIL_COMMITTING:
8488 case CS_FAIL_COMMITTED:
8489 jam();
8490 ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
8491 break;
8492 case CS_FAIL_PREPARED:
8493 jam();
8494 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
8495 apiConnectptr.p->globalcheckpointid = tgci;
8496 break;
8497 case CS_FAIL_COMPLETED:
8498 jam();
8499 apiConnectptr.p->globalcheckpointid = tgci;
8500 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
8501 break;
8502 default:
8503 jam();
8504 systemErrorLab(signal, __LINE__);
8505 break;
8506 }//switch
8507 break;
8508 case LqhTransConf::Prepared:
8509 jam();
8510 switch (apiConnectptr.p->apiConnectstate) {
8511 case CS_FAIL_COMMITTED:
8512 jam();
8513 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
8514 break;
8515 case CS_FAIL_ABORTED:
8516 jam();
8517 apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
8518 break;
8519 case CS_FAIL_COMMITTING:
8520 case CS_FAIL_PREPARED:
8521 case CS_FAIL_ABORTING:
8522 jam();
8523 /*empty*/;
8524 break;
8525 default:
8526 jam();
8527 systemErrorLab(signal, __LINE__);
8528 break;
8529 }//switch
8530 break;
8531 case LqhTransConf::Aborted:
8532 jam();
8533 switch (apiConnectptr.p->apiConnectstate) {
8534 case CS_FAIL_COMMITTING:
8535 case CS_FAIL_COMMITTED:
8536 jam();
8537 systemErrorLab(signal, __LINE__);
8538 break;
8539 case CS_FAIL_PREPARED:
8540 jam();
8541 apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
8542 break;
8543 case CS_FAIL_ABORTING:
8544 case CS_FAIL_ABORTED:
8545 jam();
8546 /*empty*/;
8547 break;
8548 default:
8549 jam();
8550 systemErrorLab(signal, __LINE__);
8551 break;
8552 }//switch
8553 break;
8554 case LqhTransConf::Marker:
8555 jam();
8556 break;
8557 default:
8558 jam();
8559 systemErrorLab(signal, __LINE__);
8560 break;
8561 }//switch
8562 }//Dbtc::updateApiStateFail()
8563
8564 /*------------------------------------------------------------*/
8565 /* UPDATE_TC_STATE_FAIL */
8566 /* */
8567 /* WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
8568 /* WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY */
8569 /* BETWEEN THE DIFFERENT REPLICAS. */
8570 /*------------------------------------------------------------*/
updateTcStateFail(Signal * signal)8571 void Dbtc::updateTcStateFail(Signal* signal)
8572 {
8573 const Uint8 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
8574 const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
8575 const Uint8 tdirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
8576
8577 TcConnectRecord * regTcPtr = tcConnectptr.p;
8578
8579 ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
8580 ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
8581 ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
8582 ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
8583
8584 regTcPtr->tcNodedata[treplicaNo] = tnodeid;
8585 regTcPtr->failData[treplicaNo] = ttransStatus;
8586 }//Dbtc::updateTcStateFail()
8587
execTCGETOPSIZEREQ(Signal * signal)8588 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
8589 {
8590 jamEntry();
8591 CRASH_INSERTION(8000);
8592
8593 UintR Tuserpointer = signal->theData[0]; /* DBDIH POINTER */
8594 BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
8595 signal->theData[0] = Tuserpointer;
8596 signal->theData[1] = coperationsize;
8597 sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
8598 }//Dbtc::execTCGETOPSIZEREQ()
8599
execTC_CLOPSIZEREQ(Signal * signal)8600 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
8601 {
8602 jamEntry();
8603 CRASH_INSERTION(8001);
8604
8605 tuserpointer = signal->theData[0];
8606 tusersblkref = signal->theData[1];
8607 /* DBDIH BLOCK REFERENCE */
8608 coperationsize = 0;
8609 signal->theData[0] = tuserpointer;
8610 sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
8611 }//Dbtc::execTC_CLOPSIZEREQ()
8612
8613 /* ######################################################################### */
8614 /* ####### ERROR MODULE ####### */
8615 /* ######################################################################### */
tabStateErrorLab(Signal * signal)8616 void Dbtc::tabStateErrorLab(Signal* signal)
8617 {
8618 terrorCode = ZSTATE_ERROR;
8619 releaseAtErrorLab(signal);
8620 }//Dbtc::tabStateErrorLab()
8621
wrongSchemaVersionErrorLab(Signal * signal)8622 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
8623 {
8624 const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
8625
8626 TableRecordPtr tabPtr;
8627 tabPtr.i = tcKeyReq->tableId;
8628 const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
8629 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
8630
8631 terrorCode = tabPtr.p->getErrorCode(schemVer);
8632
8633 abortErrorLab(signal);
8634 }//Dbtc::wrongSchemaVersionErrorLab()
8635
noFreeConnectionErrorLab(Signal * signal)8636 void Dbtc::noFreeConnectionErrorLab(Signal* signal)
8637 {
8638 terrorCode = ZNO_FREE_TC_CONNECTION;
8639 abortErrorLab(signal); /* RECORD. OTHERWISE GOTO ERRORHANDLING */
8640 }//Dbtc::noFreeConnectionErrorLab()
8641
aiErrorLab(Signal * signal)8642 void Dbtc::aiErrorLab(Signal* signal)
8643 {
8644 terrorCode = ZLENGTH_ERROR;
8645 abortErrorLab(signal);
8646 }//Dbtc::aiErrorLab()
8647
seizeAttrbuferrorLab(Signal * signal)8648 void Dbtc::seizeAttrbuferrorLab(Signal* signal)
8649 {
8650 terrorCode = ZGET_ATTRBUF_ERROR;
8651 abortErrorLab(signal);
8652 }//Dbtc::seizeAttrbuferrorLab()
8653
seizeDatabuferrorLab(Signal * signal)8654 void Dbtc::seizeDatabuferrorLab(Signal* signal)
8655 {
8656 terrorCode = ZGET_DATAREC_ERROR;
8657 releaseAtErrorLab(signal);
8658 }//Dbtc::seizeDatabuferrorLab()
8659
releaseAtErrorLab(Signal * signal)8660 void Dbtc::releaseAtErrorLab(Signal* signal)
8661 {
8662 ptrGuard(tcConnectptr);
8663 tcConnectptr.p->tcConnectstate = OS_ABORTING;
8664 /*-------------------------------------------------------------------------*
8665 * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
8666 * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
8667 * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
8668 * TO HANDLE THIS PROBLEM.
8669 * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
8670 * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
8671 * ANY SIGNALS.
8672 *-------------------------------------------------------------------------*/
8673 tcConnectptr.p->noOfNodes = 0;
8674 abortErrorLab(signal);
8675 }//Dbtc::releaseAtErrorLab()
8676
warningHandlerLab(Signal * signal,int line)8677 void Dbtc::warningHandlerLab(Signal* signal, int line)
8678 {
8679 ndbassert(false);
8680 }//Dbtc::warningHandlerLab()
8681
systemErrorLab(Signal * signal,int line)8682 void Dbtc::systemErrorLab(Signal* signal, int line)
8683 {
8684 progError(line, NDBD_EXIT_NDBREQUIRE);
8685 }//Dbtc::systemErrorLab()
8686
8687
8688 /* ######################################################################### *
8689 * ####### SCAN MODULE ####### *
8690 * ######################################################################### *
8691
8692 The application orders a scan of a table. We divide the scan into a scan on
8693 each fragment. The scan uses the primary replicas since the scan might be
8694 used for an update in a separate transaction.
8695
8696 Scans are always done as a separate transaction. Locks from the scan
8697 can be overtaken by another transaction. Scans can never lock the entire
8698 table. Locks are released immediately after the read has been verified
8699 by the application. There is not even an option to leave the locks.
8700 The reason is that this would hurt real-time behaviour too much.
8701
8702 -# The first step in handling a scan of a table is to receive all signals
8703 defining the scan. If failures occur during this step we release all
8704 resource and reply with SCAN_TABREF providing the error code.
8705 If system load is too high, the request will not be allowed.
8706
8707 -# The second step retrieves the number of fragments that exist in the
8708 table. It also ensures that the table actually exist. After this,
8709 the scan is ready to be parallelised. The idea is that the receiving
8710 process (hereafter called delivery process) will start up a number
8711 of scan processes. Each of these scan processes will
8712 independently scan one fragment at a time. The delivery
8713 process object is the scan record and the scan process object is
8714 the scan fragment record plus the scan operation record.
8715
8716 -# The third step is thus performed in parallel. In the third step each
8717 scan process retrieves the primary replica of the fragment it will
8718 scan. Then it starts the scan as soon as the load on that node permits.
8719
8720 The LQH returns either when it retrieved the maximum number of tuples or
8721 when it has retrived at least one tuple and is hindered by a lock to
8722 retrieve the next tuple. This is to ensure that a scan process never
8723 can be involved in a deadlock situation.
8724
8725 When the scan process receives a number of tuples to report to the
8726 application it checks the state of the delivery process. Only one delivery
8727 at a time is handled by the application. Thus if the delivery process
8728 has already sent a number of tuples to the application this set of tuples
8729 are queued.
8730
8731 When the application requests the next set of tuples it is immediately
8732 delivered if any are queued, otherwise it waits for the next scan
8733 process that is ready to deliver.
8734
8735
8736 ERROR HANDLING
8737
8738 As already mentioned it is rather easy to handle errors before the scan
8739 processes have started. In this case it is enough to release the resources
8740 and send SCAN_TAB_REF.
8741
8742 If an error occurs in any of the scan processes then we have to stop all
8743 scan processes. We do however only stop the delivery process and ask
8744 the api to order us to close the scan. The reason is that we can easily
8745 enter into difficult timing problems since the application and this
8746 block is out of synch we will thus always start by report the error to
8747 the application and wait for a close request. This error report uses the
8748 SCAN_TABREF signal with a special error code that the api must check for.
8749
8750
8751 CLOSING AN ACTIVE SCAN
8752
8753 The application can close a scan for several reasons before it is completed.
8754 One reason was mentioned above where an error in a scan process led to a
8755 request to close the scan. Another reason could simply be that the
8756 application found what it looked for and is thus not interested in the
8757 rest of the scan.
8758
8759 IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
8760
8761 When a close scan request is received, all scan processes are stopped and all
8762 resources belonging to those scan processes are released. Stopping the scan
8763 processes most often includes communication with an LQH where the local scan
8764 is controlled. Finally all resources belonging to the scan is released and
8765 the SCAN_TABCONF is sent with an indication of that the scan is closed.
8766
8767
8768 CLOSING A COMPLETED SCAN
8769
8770 When all scan processes are completed then a report is sent to the
8771 application which indicates that no more tuples can be fetched.
8772 The application will send a close scan and the same action as when
8773 closing an active scan is performed.
8774 In this case it will of course not find any active scan processes.
8775 It will even find all scan processes already released.
8776
8777 The reason for requiring the api to close the scan is the same as above.
8778 It is to avoid any timing problems due to that the api and this block
8779 is out of synch.
8780
8781 * ######################################################################## */
execSCAN_TABREQ(Signal * signal)8782 void Dbtc::execSCAN_TABREQ(Signal* signal)
8783 {
8784 const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
8785 const Uint32 ri = scanTabReq->requestInfo;
8786 const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
8787 const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
8788 const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
8789 const Uint32 transid1 = scanTabReq->transId1;
8790 const Uint32 transid2 = scanTabReq->transId2;
8791 const Uint32 tmpXX = scanTabReq->buddyConPtr;
8792 const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
8793 Uint32 currSavePointId = 0;
8794
8795 Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
8796 Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
8797 Uint32 scanParallel = scanConcurrency;
8798 Uint32 errCode;
8799 ScanRecordPtr scanptr;
8800
8801 jamEntry();
8802
8803 SegmentedSectionPtr api_op_ptr;
8804 signal->getSection(api_op_ptr, 0);
8805 copy(&cdata[0], api_op_ptr);
8806 releaseSections(signal);
8807
8808 apiConnectptr.i = scanTabReq->apiConnectPtr;
8809 tabptr.i = scanTabReq->tableId;
8810
8811 if (apiConnectptr.i >= capiConnectFilesize)
8812 {
8813 jam();
8814 warningHandlerLab(signal, __LINE__);
8815 return;
8816 }//if
8817
8818 ptrAss(apiConnectptr, apiConnectRecord);
8819 ApiConnectRecord * transP = apiConnectptr.p;
8820
8821 if (transP->apiConnectstate != CS_CONNECTED) {
8822 jam();
8823 // could be left over from TCKEYREQ rollback
8824 if (transP->apiConnectstate == CS_ABORTING &&
8825 transP->abortState == AS_IDLE) {
8826 jam();
8827 } else if(transP->apiConnectstate == CS_STARTED &&
8828 transP->firstTcConnect == RNIL){
8829 jam();
8830 // left over from simple/dirty read
8831 } else {
8832 jam();
8833 jamLine(transP->apiConnectstate);
8834 errCode = ZSTATE_ERROR;
8835 goto SCAN_TAB_error_no_state_change;
8836 }
8837 }
8838
8839 if(tabptr.i >= ctabrecFilesize)
8840 {
8841 errCode = ZUNKNOWN_TABLE_ERROR;
8842 goto SCAN_TAB_error;
8843 }
8844
8845 ptrAss(tabptr, tableRecord);
8846 if ((aiLength == 0) ||
8847 (!tabptr.p->checkTable(schemaVersion)) ||
8848 (scanConcurrency == 0) ||
8849 (cfirstfreeTcConnect == RNIL) ||
8850 (cfirstfreeScanrec == RNIL)) {
8851 goto SCAN_error_check;
8852 }
8853 if (buddyPtr != RNIL) {
8854 jam();
8855 ApiConnectRecordPtr buddyApiPtr;
8856 buddyApiPtr.i = buddyPtr;
8857 ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
8858 if ((transid1 == buddyApiPtr.p->transid[0]) &&
8859 (transid2 == buddyApiPtr.p->transid[1])) {
8860 jam();
8861
8862 if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
8863 // transaction has been aborted
8864 jam();
8865 errCode = buddyApiPtr.p->returncode;
8866 goto SCAN_TAB_error;
8867 }//if
8868 currSavePointId = buddyApiPtr.p->currSavePointId;
8869 buddyApiPtr.p->currSavePointId++;
8870 }
8871 }
8872
8873 if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
8874 getNodeState().getSingleUserApi() !=
8875 refToNode(apiConnectptr.p->ndbapiBlockref))
8876 {
8877 errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
8878 goto SCAN_TAB_error;
8879 }
8880
8881 seizeTcConnect(signal);
8882 tcConnectptr.p->apiConnect = apiConnectptr.i;
8883 tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
8884 apiConnectptr.p->lastTcConnect = tcConnectptr.i;
8885
8886 seizeCacheRecord(signal);
8887 cachePtr.p->keylen = keyLen;
8888 cachePtr.p->save1 = 0;
8889 cachePtr.p->distributionKey = scanTabReq->distributionKey;
8890 cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
8891 scanptr = seizeScanrec(signal);
8892
8893 ndbrequire(transP->apiScanRec == RNIL);
8894 ndbrequire(scanptr.p->scanApiRec == RNIL);
8895
8896 initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag);
8897
8898 transP->apiScanRec = scanptr.i;
8899 transP->returncode = 0;
8900 transP->transid[0] = transid1;
8901 transP->transid[1] = transid2;
8902 transP->buddyPtr = buddyPtr;
8903
8904 // The scan is started
8905 transP->apiConnectstate = CS_START_SCAN;
8906 transP->currSavePointId = currSavePointId;
8907
8908 /**********************************************************
8909 * We start the timer on scanRec to be able to discover a
8910 * timeout in the API the API now is in charge!
8911 ***********************************************************/
8912 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8913 updateBuddyTimer(apiConnectptr);
8914
8915 /***********************************************************
8916 * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
8917 * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
8918 * IF ANY TO RECEIVE.
8919 **********************************************************/
8920 scanptr.p->scanState = ScanRecord::WAIT_AI;
8921
8922 if (ERROR_INSERTED(8038))
8923 {
8924 /**
8925 * Force API_FAILREQ
8926 */
8927 DisconnectRep * const rep = (DisconnectRep *)signal->getDataPtrSend();
8928 rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
8929 rep->err = 8038;
8930
8931 EXECUTE_DIRECT(CMVMI, GSN_DISCONNECT_REP, signal, 2);
8932 CLEAR_ERROR_INSERT_VALUE;
8933 }
8934
8935 return;
8936
8937 SCAN_error_check:
8938 if (aiLength == 0) {
8939 jam()
8940 errCode = ZSCAN_AI_LEN_ERROR;
8941 goto SCAN_TAB_error;
8942 }//if
8943 if (!tabptr.p->checkTable(schemaVersion)){
8944 jam();
8945 errCode = tabptr.p->getErrorCode(schemaVersion);
8946 goto SCAN_TAB_error;
8947 }//if
8948 if (scanConcurrency == 0) {
8949 jam();
8950 errCode = ZNO_CONCURRENCY_ERROR;
8951 goto SCAN_TAB_error;
8952 }//if
8953 if (cfirstfreeTcConnect == RNIL) {
8954 jam();
8955 errCode = ZNO_FREE_TC_CONNECTION;
8956 goto SCAN_TAB_error;
8957 }//if
8958 ndbrequire(cfirstfreeScanrec == RNIL);
8959 jam();
8960 errCode = ZNO_SCANREC_ERROR;
8961 goto SCAN_TAB_error;
8962
8963 SCAN_TAB_error:
8964 jam();
8965 /**
8966 * Prepare for up coming ATTRINFO/KEYINFO
8967 */
8968 transP->apiConnectstate = CS_ABORTING;
8969 transP->abortState = AS_IDLE;
8970 transP->transid[0] = transid1;
8971 transP->transid[1] = transid2;
8972
8973 SCAN_TAB_error_no_state_change:
8974
8975 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
8976 ref->apiConnectPtr = transP->ndbapiConnect;
8977 ref->transId1 = transid1;
8978 ref->transId2 = transid2;
8979 ref->errorCode = errCode;
8980 ref->closeNeeded = 0;
8981 sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
8982 signal, ScanTabRef::SignalLength, JBB);
8983 return;
8984 }//Dbtc::execSCAN_TABREQ()
8985
initScanrec(ScanRecordPtr scanptr,const ScanTabReq * scanTabReq,UintR scanParallel,UintR noOprecPerFrag)8986 void Dbtc::initScanrec(ScanRecordPtr scanptr,
8987 const ScanTabReq * scanTabReq,
8988 UintR scanParallel,
8989 UintR noOprecPerFrag)
8990 {
8991 const UintR ri = scanTabReq->requestInfo;
8992 scanptr.p->scanTcrec = tcConnectptr.i;
8993 scanptr.p->scanApiRec = apiConnectptr.i;
8994 scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
8995 scanptr.p->scanKeyLen = scanTabReq->attrLenKeyLen >> 16;
8996 scanptr.p->scanTableref = tabptr.i;
8997 scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
8998 scanptr.p->scanParallel = scanParallel;
8999 scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
9000 scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
9001 scanptr.p->batch_size_rows = noOprecPerFrag;
9002
9003 Uint32 tmp = 0;
9004 ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
9005 ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
9006 ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
9007 ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
9008 ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
9009 ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
9010 ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
9011 ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
9012 ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
9013
9014 scanptr.p->scanRequestInfo = tmp;
9015 scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
9016 scanptr.p->scanState = ScanRecord::RUNNING;
9017 scanptr.p->m_queued_count = 0;
9018
9019 ScanFragList list(c_scan_frag_pool,
9020 scanptr.p->m_running_scan_frags);
9021 for (Uint32 i = 0; i < scanParallel; i++) {
9022 jam();
9023 ScanFragRecPtr ptr;
9024 ndbrequire(list.seize(ptr));
9025 ptr.p->scanFragState = ScanFragRec::IDLE;
9026 ptr.p->scanRec = scanptr.i;
9027 ptr.p->scanFragId = 0;
9028 ptr.p->m_apiPtr = cdata[i];
9029 }//for
9030
9031 (* (ScanTabReq::getRangeScanFlag(ri) ?
9032 &c_counters.c_range_scan_count :
9033 &c_counters.c_scan_count))++;
9034 }//Dbtc::initScanrec()
9035
scanTabRefLab(Signal * signal,Uint32 errCode)9036 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
9037 {
9038 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
9039 ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9040 ref->transId1 = apiConnectptr.p->transid[0];
9041 ref->transId2 = apiConnectptr.p->transid[1];
9042 ref->errorCode = errCode;
9043 ref->closeNeeded = 0;
9044 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
9045 signal, ScanTabRef::SignalLength, JBB);
9046 }//Dbtc::scanTabRefLab()
9047
9048 /*---------------------------------------------------------------------------*/
9049 /* */
9050 /* RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST. */
9051 /*---------------------------------------------------------------------------*/
scanAttrinfoLab(Signal * signal,UintR Tlen)9052 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
9053 {
9054 ScanRecordPtr scanptr;
9055 scanptr.i = apiConnectptr.p->apiScanRec;
9056 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9057 tcConnectptr.i = scanptr.p->scanTcrec;
9058 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9059 cachePtr.i = apiConnectptr.p->cachePtr;
9060 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
9061 CacheRecord * const regCachePtr = cachePtr.p;
9062 ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
9063
9064 regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
9065 if (regCachePtr->currReclenAi < scanptr.p->scanAiLength) {
9066 if (cfirstfreeAttrbuf == RNIL) {
9067 goto scanAttrinfo_attrbuf_error;
9068 }//if
9069 saveAttrbuf(signal);
9070 } else {
9071 if (regCachePtr->currReclenAi > scanptr.p->scanAiLength) {
9072 goto scanAttrinfo_len_error;
9073 } else {
9074 /* CURR_RECLEN_AI = SCAN_AI_LENGTH */
9075 if (cfirstfreeAttrbuf == RNIL) {
9076 goto scanAttrinfo_attrbuf2_error;
9077 }//if
9078 saveAttrbuf(signal);
9079 /**************************************************
9080 * WE HAVE NOW RECEIVED ALL INFORMATION CONCERNING
9081 * THIS SCAN. WE ARE READY TO START THE ACTUAL
9082 * EXECUTION OF THE SCAN QUERY
9083 **************************************************/
9084 diFcountReqLab(signal, scanptr);
9085 return;
9086 }//if
9087 }//if
9088 return;
9089
9090 scanAttrinfo_attrbuf_error:
9091 jam();
9092 abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
9093 return;
9094
9095 scanAttrinfo_attrbuf2_error:
9096 jam();
9097 abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
9098 return;
9099
9100 scanAttrinfo_len_error:
9101 jam();
9102 abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
9103 return;
9104 }//Dbtc::scanAttrinfoLab()
9105
diFcountReqLab(Signal * signal,ScanRecordPtr scanptr)9106 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
9107 {
9108 /**
9109 * Check so that the table is not being dropped
9110 */
9111 TableRecordPtr tabPtr;
9112 tabPtr.i = scanptr.p->scanTableref;
9113 tabPtr.p = &tableRecord[tabPtr.i];
9114 if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
9115 ;
9116 } else {
9117 abortScanLab(signal, scanptr,
9118 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
9119 true);
9120 return;
9121 }
9122
9123 scanptr.p->scanNextFragId = 0;
9124 scanptr.p->m_booked_fragments_count= 0;
9125 scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
9126
9127 if(!cachePtr.p->distributionKeyIndicator)
9128 {
9129 jam();
9130 /*************************************************
9131 * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
9132 * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
9133 ***************************************************/
9134 DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
9135 req->m_connectionData = tcConnectptr.p->dihConnectptr;
9136 req->m_tableRef = scanptr.p->scanTableref;
9137 sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal,
9138 DihFragCountReq::SignalLength, JBB);
9139 }
9140 else
9141 {
9142 signal->theData[0] = tcConnectptr.p->dihConnectptr;
9143 signal->theData[1] = tabPtr.i;
9144 signal->theData[2] = cachePtr.p->distributionKey;
9145 EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
9146 UintR TerrorIndicator = signal->theData[0];
9147 jamEntry();
9148 if (TerrorIndicator != 0) {
9149 DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
9150 ref->m_connectionData = tcConnectptr.i;
9151 ref->m_error = signal->theData[1];
9152 execDI_FCOUNTREF(signal);
9153 return;
9154 }
9155
9156 UintR Tdata1 = signal->theData[1];
9157 scanptr.p->scanNextFragId = Tdata1;
9158 DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
9159 conf->m_connectionData = tcConnectptr.i;
9160 conf->m_fragmentCount = 1; // Frag count
9161 execDI_FCOUNTCONF(signal);
9162 }
9163 return;
9164 }//Dbtc::diFcountReqLab()
9165
9166 /********************************************************************
9167 * execDI_FCOUNTCONF
9168 *
9169 * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
9170 * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
9171 * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
9172 * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
9173 * CLOSES THE SCAN.
9174 ********************************************************************/
execDI_FCOUNTCONF(Signal * signal)9175 void Dbtc::execDI_FCOUNTCONF(Signal* signal)
9176 {
9177 jamEntry();
9178 DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
9179 tcConnectptr.i = conf->m_connectionData;
9180 Uint32 tfragCount = conf->m_fragmentCount;
9181 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9182 apiConnectptr.i = tcConnectptr.p->apiConnect;
9183 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9184 ScanRecordPtr scanptr;
9185 scanptr.i = apiConnectptr.p->apiScanRec;
9186 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9187 ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
9188 if (apiConnectptr.p->apiFailState == ZTRUE) {
9189 jam();
9190 releaseScanResources(scanptr, true);
9191 handleApiFailState(signal, apiConnectptr.i);
9192 return;
9193 }//if
9194 if (tfragCount == 0) {
9195 jam();
9196 abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
9197 return;
9198 }//if
9199
9200 /**
9201 * Check so that the table is not being dropped
9202 */
9203 TableRecordPtr tabPtr;
9204 tabPtr.i = scanptr.p->scanTableref;
9205 tabPtr.p = &tableRecord[tabPtr.i];
9206 if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
9207 ;
9208 } else {
9209 abortScanLab(signal, scanptr,
9210 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
9211 true);
9212 return;
9213 }
9214
9215 scanptr.p->scanParallel = tfragCount;
9216 scanptr.p->scanNoFrag = tfragCount;
9217 scanptr.p->scanState = ScanRecord::RUNNING;
9218
9219 setApiConTimer(apiConnectptr.i, 0, __LINE__);
9220 updateBuddyTimer(apiConnectptr);
9221
9222 ScanFragRecPtr ptr;
9223 ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9224 for (list.first(ptr); !ptr.isNull() && tfragCount;
9225 list.next(ptr), tfragCount--){
9226 jam();
9227
9228 ptr.p->lqhBlockref = 0;
9229 ptr.p->startFragTimer(ctcTimer);
9230 ptr.p->scanFragId = scanptr.p->scanNextFragId++;
9231 ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
9232 ptr.p->startFragTimer(ctcTimer);
9233
9234 signal->theData[0] = tcConnectptr.p->dihConnectptr;
9235 signal->theData[1] = ptr.i;
9236 signal->theData[2] = scanptr.p->scanTableref;
9237 signal->theData[3] = ptr.p->scanFragId;
9238 sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
9239 }//for
9240
9241 ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
9242 for (; !ptr.isNull();)
9243 {
9244 ptr.p->m_ops = 0;
9245 ptr.p->m_totalLen = 0;
9246 ptr.p->m_scan_frag_conf_status = 1;
9247 ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
9248 ptr.p->stopFragTimer();
9249
9250 ScanFragRecPtr tmp = ptr;
9251 list.next(ptr);
9252 list.remove(tmp);
9253 queued.add(tmp);
9254 scanptr.p->m_queued_count++;
9255 }
9256 }//Dbtc::execDI_FCOUNTCONF()
9257
9258 /******************************************************
9259 * execDI_FCOUNTREF
9260 ******************************************************/
execDI_FCOUNTREF(Signal * signal)9261 void Dbtc::execDI_FCOUNTREF(Signal* signal)
9262 {
9263 jamEntry();
9264 DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
9265 tcConnectptr.i = ref->m_connectionData;
9266 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9267 const Uint32 errCode = ref->m_error;
9268 apiConnectptr.i = tcConnectptr.p->apiConnect;
9269 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9270 ScanRecordPtr scanptr;
9271 scanptr.i = apiConnectptr.p->apiScanRec;
9272 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9273 ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
9274 if (apiConnectptr.p->apiFailState == ZTRUE) {
9275 jam();
9276 releaseScanResources(scanptr, true);
9277 handleApiFailState(signal, apiConnectptr.i);
9278 return;
9279 }//if
9280 abortScanLab(signal, scanptr, errCode, true);
9281 }//Dbtc::execDI_FCOUNTREF()
9282
abortScanLab(Signal * signal,ScanRecordPtr scanptr,Uint32 errCode,bool not_started)9283 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
9284 bool not_started)
9285 {
9286 scanTabRefLab(signal, errCode);
9287 releaseScanResources(scanptr, not_started);
9288 }//Dbtc::abortScanLab()
9289
releaseScanResources(ScanRecordPtr scanPtr,bool not_started)9290 void Dbtc::releaseScanResources(ScanRecordPtr scanPtr,
9291 bool not_started)
9292 {
9293 if (apiConnectptr.p->cachePtr != RNIL) {
9294 cachePtr.i = apiConnectptr.p->cachePtr;
9295 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
9296 releaseKeys();
9297 releaseAttrinfo();
9298 }//if
9299 tcConnectptr.i = scanPtr.p->scanTcrec;
9300 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9301 releaseTcCon();
9302
9303 if (not_started)
9304 {
9305 jam();
9306 ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
9307 ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
9308 run.release();
9309 queue.release();
9310 }
9311
9312 ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
9313 ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
9314 ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
9315
9316 ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
9317 ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
9318
9319 // link into free list
9320 scanPtr.p->nextScan = cfirstfreeScanrec;
9321 scanPtr.p->scanState = ScanRecord::IDLE;
9322 scanPtr.p->scanTcrec = RNIL;
9323 scanPtr.p->scanApiRec = RNIL;
9324 cfirstfreeScanrec = scanPtr.i;
9325
9326 apiConnectptr.p->apiScanRec = RNIL;
9327 apiConnectptr.p->apiConnectstate = CS_CONNECTED;
9328 setApiConTimer(apiConnectptr.i, 0, __LINE__);
9329 }//Dbtc::releaseScanResources()
9330
9331
9332 /****************************************************************
9333 * execDIGETPRIMCONF
9334 *
9335 * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT.
9336 * WE ARE NOW READY TO ASK FOR PERMISSION TO LOAD THIS
9337 * SPECIFIC NODE WITH A SCAN OPERATION.
9338 ****************************************************************/
execDIGETPRIMCONF(Signal * signal)9339 void Dbtc::execDIGETPRIMCONF(Signal* signal)
9340 {
9341 jamEntry();
9342 // tcConnectptr.i in theData[0] is not used
9343 scanFragptr.i = signal->theData[1];
9344 c_scan_frag_pool.getPtr(scanFragptr);
9345
9346 tnodeid = signal->theData[2];
9347 arrGuard(tnodeid, MAX_NDB_NODES);
9348
9349 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
9350 scanFragptr.p->stopFragTimer();
9351
9352 ScanRecordPtr scanptr;
9353 scanptr.i = scanFragptr.p->scanRec;
9354 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9355
9356 /**
9357 * This must be false as select count(*) otherwise
9358 * can "pass" committing on backup fragments and
9359 * get incorrect row count
9360 */
9361 if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
9362 {
9363 jam();
9364 Uint32 max = 3+signal->theData[6];
9365 Uint32 nodeid = getOwnNodeId();
9366 for(Uint32 i = 3; i<max; i++)
9367 if(signal->theData[i] == nodeid)
9368 {
9369 jam();
9370 tnodeid = nodeid;
9371 break;
9372 }
9373 }
9374
9375 {
9376 /**
9377 * Check table
9378 */
9379 TableRecordPtr tabPtr;
9380 tabPtr.i = scanptr.p->scanTableref;
9381 ptrAss(tabPtr, tableRecord);
9382 Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
9383 if(tabPtr.p->checkTable(schemaVersion) == false){
9384 jam();
9385 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9386
9387 run.release(scanFragptr);
9388 scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
9389 return;
9390 }
9391 }
9392
9393 tcConnectptr.i = scanptr.p->scanTcrec;
9394 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9395 apiConnectptr.i = scanptr.p->scanApiRec;
9396 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9397 cachePtr.i = apiConnectptr.p->cachePtr;
9398 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
9399 switch (scanptr.p->scanState) {
9400 case ScanRecord::CLOSING_SCAN:
9401 jam();
9402 updateBuddyTimer(apiConnectptr);
9403 {
9404 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9405
9406 run.release(scanFragptr);
9407 }
9408 close_scan_req_send_conf(signal, scanptr);
9409 return;
9410 default:
9411 jam();
9412 /*empty*/;
9413 break;
9414 }//switch
9415 Uint32 ref = calcLqhBlockRef(tnodeid);
9416 scanFragptr.p->lqhBlockref = ref;
9417 scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
9418 sendScanFragReq(signal, scanptr.p, scanFragptr.p);
9419 if(ERROR_INSERTED(8035))
9420 globalTransporterRegistry.performSend();
9421 attrbufptr.i = cachePtr.p->firstAttrbuf;
9422 while (attrbufptr.i != RNIL) {
9423 jam();
9424 ptrCheckGuard(attrbufptr, cattrbufFilesize, attrbufRecord);
9425 sendAttrinfo(signal,
9426 scanFragptr.i,
9427 attrbufptr.p,
9428 ref);
9429 attrbufptr.i = attrbufptr.p->attrbuf[ZINBUF_NEXT];
9430 if(ERROR_INSERTED(8035))
9431 globalTransporterRegistry.performSend();
9432 }//while
9433 scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9434 scanFragptr.p->startFragTimer(ctcTimer);
9435 updateBuddyTimer(apiConnectptr);
9436 /*********************************************
9437 * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
9438 * WAIT FOR THE FIRST SCANNED RECORDS
9439 *********************************************/
9440 }//Dbtc::execDIGETPRIMCONF
9441
9442 /***************************************************
9443 * execDIGETPRIMREF
9444 *
9445 * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
9446 * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
9447 * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
9448 ***************************************************/
execDIGETPRIMREF(Signal * signal)9449 void Dbtc::execDIGETPRIMREF(Signal* signal)
9450 {
9451 jamEntry();
9452 // tcConnectptr.i in theData[0] is not used.
9453 scanFragptr.i = signal->theData[1];
9454 const Uint32 errCode = signal->theData[2];
9455 c_scan_frag_pool.getPtr(scanFragptr);
9456 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
9457
9458 ScanRecordPtr scanptr;
9459 scanptr.i = scanFragptr.p->scanRec;
9460 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9461
9462 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9463
9464 run.release(scanFragptr);
9465
9466 scanError(signal, scanptr, errCode);
9467 }//Dbtc::execDIGETPRIMREF()
9468
9469 /**
9470 * Dbtc::execSCAN_FRAGREF
9471 * Our attempt to scan a fragment was refused
9472 * set error code and close all other fragment
9473 * scan's belonging to this scan
9474 */
execSCAN_FRAGREF(Signal * signal)9475 void Dbtc::execSCAN_FRAGREF(Signal* signal)
9476 {
9477 const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
9478
9479 jamEntry();
9480 const Uint32 errCode = ref->errorCode;
9481
9482 scanFragptr.i = ref->senderData;
9483 c_scan_frag_pool.getPtr(scanFragptr);
9484
9485 ScanRecordPtr scanptr;
9486 scanptr.i = scanFragptr.p->scanRec;
9487 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9488
9489 apiConnectptr.i = scanptr.p->scanApiRec;
9490 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9491
9492 Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
9493 Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
9494 transid1 = transid1 | transid2;
9495 if (transid1 != 0) {
9496 jam();
9497 systemErrorLab(signal, __LINE__);
9498 }//if
9499
9500 /**
9501 * Set errorcode, close connection to this lqh fragment,
9502 * stop fragment timer and call scanFragError to start
9503 * close of the other fragment scans
9504 */
9505 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
9506 {
9507 scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
9508 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9509
9510 run.release(scanFragptr);
9511 scanFragptr.p->stopFragTimer();
9512 }
9513 scanError(signal, scanptr, errCode);
9514 }//Dbtc::execSCAN_FRAGREF()
9515
9516 /**
9517 * Dbtc::scanError
9518 *
9519 * Called when an error occurs during
9520 */
scanError(Signal * signal,ScanRecordPtr scanptr,Uint32 errorCode)9521 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
9522 {
9523 jam();
9524 ScanRecord* scanP = scanptr.p;
9525
9526 DEBUG("scanError, errorCode = "<< errorCode <<
9527 ", scanState = " << scanptr.p->scanState);
9528
9529 apiConnectptr.i = scanP->scanApiRec;
9530 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9531 ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
9532
9533 if(scanP->scanState == ScanRecord::CLOSING_SCAN){
9534 jam();
9535 close_scan_req_send_conf(signal, scanptr);
9536 return;
9537 }
9538
9539 ndbrequire(scanP->scanState == ScanRecord::RUNNING);
9540
9541 /**
9542 * Close scan wo/ having received an order to do so
9543 */
9544 close_scan_req(signal, scanptr, false);
9545
9546 const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
9547 if(apiFail){
9548 jam();
9549 return;
9550 }
9551
9552 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
9553 ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9554 ref->transId1 = apiConnectptr.p->transid[0];
9555 ref->transId2 = apiConnectptr.p->transid[1];
9556 ref->errorCode = errorCode;
9557 ref->closeNeeded = 1;
9558 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
9559 signal, ScanTabRef::SignalLength, JBB);
9560 }//Dbtc::scanError()
9561
9562 /************************************************************
9563 * execSCAN_FRAGCONF
9564 *
9565 * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
9566 * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
9567 ************************************************************/
execSCAN_FRAGCONF(Signal * signal)9568 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
9569 {
9570 Uint32 transid1, transid2, total_len;
9571 jamEntry();
9572
9573 const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
9574 const Uint32 noCompletedOps = conf->completedOps;
9575 const Uint32 status = conf->fragmentCompleted;
9576
9577 scanFragptr.i = conf->senderData;
9578 c_scan_frag_pool.getPtr(scanFragptr);
9579
9580 ScanRecordPtr scanptr;
9581 scanptr.i = scanFragptr.p->scanRec;
9582 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9583
9584 apiConnectptr.i = scanptr.p->scanApiRec;
9585 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9586
9587 transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
9588 transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
9589 total_len= conf->total_len;
9590 transid1 = transid1 | transid2;
9591 if (transid1 != 0) {
9592 jam();
9593 systemErrorLab(signal, __LINE__);
9594 }//if
9595
9596 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
9597
9598 if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
9599 jam();
9600 if(status == 0){
9601 /**
9602 * We have started closing = we sent a close -> ignore this
9603 */
9604 return;
9605 } else {
9606 jam();
9607 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9608
9609 run.release(scanFragptr);
9610 scanFragptr.p->stopFragTimer();
9611 scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
9612 }
9613 close_scan_req_send_conf(signal, scanptr);
9614 return;
9615 }
9616
9617 if(noCompletedOps == 0 && status != 0 &&
9618 scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
9619 /**
9620 * Start on next fragment
9621 */
9622 scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
9623 scanFragptr.p->startFragTimer(ctcTimer);
9624
9625 tcConnectptr.i = scanptr.p->scanTcrec;
9626 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9627 scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
9628 signal->theData[0] = tcConnectptr.p->dihConnectptr;
9629 signal->theData[1] = scanFragptr.i;
9630 signal->theData[2] = scanptr.p->scanTableref;
9631 signal->theData[3] = scanFragptr.p->scanFragId;
9632 sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
9633 return;
9634 }
9635 /*
9636 Uint32 totalLen = 0;
9637 for(Uint32 i = 0; i<noCompletedOps; i++){
9638 Uint32 tmp = conf->opReturnDataLen[i];
9639 totalLen += tmp;
9640 }
9641 */
9642 {
9643 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9644 ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
9645
9646 run.remove(scanFragptr);
9647 queued.add(scanFragptr);
9648 scanptr.p->m_queued_count++;
9649 }
9650
9651 scanFragptr.p->m_scan_frag_conf_status = status;
9652 scanFragptr.p->m_ops = noCompletedOps;
9653 scanFragptr.p->m_totalLen = total_len;
9654 scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
9655 scanFragptr.p->stopFragTimer();
9656
9657 if(scanptr.p->m_queued_count > /** Min */ 0){
9658 jam();
9659 sendScanTabConf(signal, scanptr);
9660 }
9661 }//Dbtc::execSCAN_FRAGCONF()
9662
9663 /****************************************************************************
9664 * execSCAN_NEXTREQ
9665 *
9666 * THE APPLICATION HAVE PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
9667 * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
9668 ****************************************************************************/
execSCAN_NEXTREQ(Signal * signal)9669 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
9670 {
9671 const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
9672 const UintR transid1 = req->transId1;
9673 const UintR transid2 = req->transId2;
9674 const UintR stopScan = req->stopScan;
9675
9676 jamEntry();
9677
9678 apiConnectptr.i = req->apiConnectPtr;
9679 if (apiConnectptr.i >= capiConnectFilesize) {
9680 jam();
9681 warningHandlerLab(signal, __LINE__);
9682 return;
9683 }//if
9684 ptrAss(apiConnectptr, apiConnectRecord);
9685
9686 /**
9687 * Check transid
9688 */
9689 const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
9690 const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
9691 if ((ctransid1 | ctransid2) != 0){
9692 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
9693 ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9694 ref->transId1 = transid1;
9695 ref->transId2 = transid2;
9696 ref->errorCode = ZSTATE_ERROR;
9697 ref->closeNeeded = 0;
9698 sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
9699 signal, ScanTabRef::SignalLength, JBB);
9700 DEBUG("Wrong transid");
9701 return;
9702 }
9703
9704 /**
9705 * Check state of API connection
9706 */
9707 if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
9708 jam();
9709 if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
9710 jam();
9711 /*********************************************************************
9712 * The application sends a SCAN_NEXTREQ after experiencing a time-out.
9713 * We will send a SCAN_TABREF to indicate a time-out occurred.
9714 *********************************************************************/
9715 DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
9716 ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
9717 ndbrequire(false); //B2 indication of strange things going on
9718 scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
9719 return;
9720 }
9721 DEBUG("scanTabRefLab: ZSTATE_ERROR");
9722 DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate);
9723 ndbrequire(false); //B2 indication of strange things going on
9724 scanTabRefLab(signal, ZSTATE_ERROR);
9725 return;
9726 }//if
9727
9728 /*******************************************************
9729 * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
9730 ********************************************************/
9731 // Stop the timer that is used to check for timeout in the API
9732 setApiConTimer(apiConnectptr.i, 0, __LINE__);
9733 ScanRecordPtr scanptr;
9734 scanptr.i = apiConnectptr.p->apiScanRec;
9735 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9736 ScanRecord* scanP = scanptr.p;
9737
9738 const Uint32 len = signal->getLength() - 4;
9739
9740 if (stopScan == ZTRUE) {
9741 jam();
9742 /*********************************************************************
9743 * APPLICATION IS CLOSING THE SCAN.
9744 **********************************************************************/
9745 close_scan_req(signal, scanptr, true);
9746 return;
9747 }//if
9748
9749 if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
9750 jam();
9751 /**
9752 * The scan is closing (typically due to error)
9753 * but the API hasn't understood it yet
9754 *
9755 * Wait for API close request
9756 */
9757 return;
9758 }
9759
9760 // Copy op ptrs so I dont overwrite them when sending...
9761 memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len);
9762
9763 ScanFragNextReq tmp;
9764 tmp.closeFlag = ZFALSE;
9765 tmp.transId1 = apiConnectptr.p->transid[0];
9766 tmp.transId2 = apiConnectptr.p->transid[1];
9767 tmp.batch_size_rows = scanP->batch_size_rows;
9768 tmp.batch_size_bytes = scanP->batch_byte_size;
9769
9770 ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
9771 ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
9772 for(Uint32 i = 0 ; i<len; i++){
9773 jam();
9774 scanFragptr.i = signal->theData[i+25];
9775 c_scan_frag_pool.getPtr(scanFragptr);
9776 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
9777
9778 scanFragptr.p->startFragTimer(ctcTimer);
9779 scanFragptr.p->m_ops = 0;
9780
9781 if(scanFragptr.p->m_scan_frag_conf_status)
9782 {
9783 /**
9784 * last scan was complete
9785 */
9786 jam();
9787 ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
9788 jam();
9789 ndbassert(scanptr.p->m_booked_fragments_count);
9790 scanptr.p->m_booked_fragments_count--;
9791 scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
9792
9793 tcConnectptr.i = scanptr.p->scanTcrec;
9794 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9795 scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
9796 signal->theData[0] = tcConnectptr.p->dihConnectptr;
9797 signal->theData[1] = scanFragptr.i;
9798 signal->theData[2] = scanptr.p->scanTableref;
9799 signal->theData[3] = scanFragptr.p->scanFragId;
9800 sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
9801 }
9802 else
9803 {
9804 jam();
9805 scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9806 ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
9807 * req = tmp;
9808 req->senderData = scanFragptr.i;
9809 sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9810 ScanFragNextReq::SignalLength, JBB);
9811 }
9812 delivered.remove(scanFragptr);
9813 running.add(scanFragptr);
9814 }//for
9815
9816 }//Dbtc::execSCAN_NEXTREQ()
9817
9818 void
close_scan_req(Signal * signal,ScanRecordPtr scanPtr,bool req_received)9819 Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
9820
9821 ScanRecord* scanP = scanPtr.p;
9822 ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
9823 ScanRecord::ScanState old = scanPtr.p->scanState;
9824 scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
9825 scanPtr.p->m_close_scan_req = req_received;
9826
9827 if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
9828 {
9829 jam();
9830 scanPtr.p->scanState = old;
9831 return; // Will continue on execDI_FCOUNTCONF
9832 }
9833
9834 /**
9835 * Queue : Action
9836 * ============= : =================
9837 * completed : -
9838 * running : close -> LQH
9839 * delivered w/ : close -> LQH
9840 * delivered wo/ : move to completed
9841 * queued w/ : close -> LQH
9842 * queued wo/ : move to completed
9843 */
9844
9845 ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
9846 nextReq->closeFlag = ZTRUE;
9847 nextReq->transId1 = apiConnectptr.p->transid[0];
9848 nextReq->transId2 = apiConnectptr.p->transid[1];
9849
9850 {
9851 ScanFragRecPtr ptr;
9852 ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
9853 ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
9854 ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
9855
9856 // Close running
9857 for(running.first(ptr); !ptr.isNull(); ){
9858 ScanFragRecPtr curr = ptr; // Remove while iterating...
9859 running.next(ptr);
9860
9861 switch(curr.p->scanFragState){
9862 case ScanFragRec::IDLE:
9863 jam(); // real early abort
9864 ndbrequire(old == ScanRecord::WAIT_AI);
9865 running.release(curr);
9866 continue;
9867 case ScanFragRec::WAIT_GET_PRIMCONF:
9868 jam();
9869 continue;
9870 case ScanFragRec::LQH_ACTIVE:
9871 jam();
9872 break;
9873 default:
9874 jamLine(curr.p->scanFragState);
9875 ndbrequire(false);
9876 }
9877
9878 curr.p->startFragTimer(ctcTimer);
9879 curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9880 nextReq->senderData = curr.i;
9881 sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9882 ScanFragNextReq::SignalLength, JBB);
9883 }
9884
9885 // Close delivered
9886 for(delivered.first(ptr); !ptr.isNull(); ){
9887 jam();
9888 ScanFragRecPtr curr = ptr; // Remove while iterating...
9889 delivered.next(ptr);
9890
9891 ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
9892 delivered.remove(curr);
9893
9894 if(curr.p->m_ops > 0 && curr.p->m_scan_frag_conf_status == 0){
9895 jam();
9896 running.add(curr);
9897 curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9898 curr.p->startFragTimer(ctcTimer);
9899 nextReq->senderData = curr.i;
9900 sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9901 ScanFragNextReq::SignalLength, JBB);
9902
9903 } else {
9904 jam();
9905 c_scan_frag_pool.release(curr);
9906 curr.p->scanFragState = ScanFragRec::COMPLETED;
9907 curr.p->stopFragTimer();
9908 }
9909 }//for
9910
9911 /**
9912 * All queued with data should be closed
9913 */
9914 for(queued.first(ptr); !ptr.isNull(); ){
9915 jam();
9916 ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
9917 ScanFragRecPtr curr = ptr; // Remove while iterating...
9918 queued.next(ptr);
9919
9920 queued.remove(curr);
9921 scanP->m_queued_count--;
9922
9923 if(curr.p->m_ops > 0){
9924 jam();
9925 running.add(curr);
9926 curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9927 curr.p->startFragTimer(ctcTimer);
9928 nextReq->senderData = curr.i;
9929 sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9930 ScanFragNextReq::SignalLength, JBB);
9931 } else {
9932 jam();
9933 c_scan_frag_pool.release(curr);
9934 curr.p->scanFragState = ScanFragRec::COMPLETED;
9935 curr.p->stopFragTimer();
9936 }
9937 }
9938 }
9939 close_scan_req_send_conf(signal, scanPtr);
9940 }
9941
9942 void
close_scan_req_send_conf(Signal * signal,ScanRecordPtr scanPtr)9943 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
9944
9945 jam();
9946
9947 ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
9948 ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
9949 //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
9950
9951 #if 0
9952 {
9953 ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
9954 ScanFragRecPtr ptr;
9955 for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
9956 ndbrequire(ptr.p->scanFragTimer == 0);
9957 ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
9958 }
9959 }
9960 #endif
9961
9962 if(!scanPtr.p->m_running_scan_frags.isEmpty()){
9963 jam();
9964 return;
9965 }
9966
9967 const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
9968
9969 if(!scanPtr.p->m_close_scan_req){
9970 jam();
9971 /**
9972 * The API hasn't order closing yet
9973 */
9974 return;
9975 }
9976
9977 Uint32 ref = apiConnectptr.p->ndbapiBlockref;
9978 if(!apiFail && ref){
9979 jam();
9980 ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
9981 conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9982 conf->requestInfo = ScanTabConf::EndOfData;
9983 conf->transId1 = apiConnectptr.p->transid[0];
9984 conf->transId2 = apiConnectptr.p->transid[1];
9985 sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
9986 }
9987
9988 releaseScanResources(scanPtr);
9989
9990 if(apiFail){
9991 jam();
9992 /**
9993 * API has failed
9994 */
9995 handleApiFailState(signal, apiConnectptr.i);
9996 }
9997 }
9998
9999 Dbtc::ScanRecordPtr
seizeScanrec(Signal * signal)10000 Dbtc::seizeScanrec(Signal* signal) {
10001 ScanRecordPtr scanptr;
10002 scanptr.i = cfirstfreeScanrec;
10003 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10004 cfirstfreeScanrec = scanptr.p->nextScan;
10005 scanptr.p->nextScan = RNIL;
10006 ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
10007 return scanptr;
10008 }//Dbtc::seizeScanrec()
10009
sendScanFragReq(Signal * signal,ScanRecord * scanP,ScanFragRec * scanFragP)10010 void Dbtc::sendScanFragReq(Signal* signal,
10011 ScanRecord* scanP,
10012 ScanFragRec* scanFragP)
10013 {
10014 ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
10015 Uint32 requestInfo = scanP->scanRequestInfo;
10016 ScanFragReq::setScanPrio(requestInfo, 1);
10017 apiConnectptr.i = scanP->scanApiRec;
10018 req->tableId = scanP->scanTableref;
10019 req->schemaVersion = scanP->scanSchemaVersion;
10020 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10021 req->senderData = scanFragptr.i;
10022 req->requestInfo = requestInfo;
10023 req->fragmentNoKeyLen = scanFragP->scanFragId | (scanP->scanKeyLen << 16);
10024 req->resultRef = apiConnectptr.p->ndbapiBlockref;
10025 req->savePointId = apiConnectptr.p->currSavePointId;
10026 req->transId1 = apiConnectptr.p->transid[0];
10027 req->transId2 = apiConnectptr.p->transid[1];
10028 req->clientOpPtr = scanFragP->m_apiPtr;
10029 req->batch_size_rows= scanP->batch_size_rows;
10030 req->batch_size_bytes= scanP->batch_byte_size;
10031 sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
10032 ScanFragReq::SignalLength, JBB);
10033 if(scanP->scanKeyLen > 0)
10034 {
10035 tcConnectptr.i = scanFragptr.i;
10036 packKeyData000Lab(signal, scanFragP->lqhBlockref, scanP->scanKeyLen);
10037 }
10038 updateBuddyTimer(apiConnectptr);
10039 scanFragP->startFragTimer(ctcTimer);
10040 }//Dbtc::sendScanFragReq()
10041
10042
sendScanTabConf(Signal * signal,ScanRecordPtr scanPtr)10043 void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
10044 jam();
10045 Uint32* ops = signal->getDataPtrSend()+4;
10046 Uint32 op_count = scanPtr.p->m_queued_count;
10047 if(4 + 3 * op_count > 25){
10048 jam();
10049 ops += 21;
10050 }
10051
10052 int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
10053 Uint32 booked = scanPtr.p->m_booked_fragments_count;
10054
10055 ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
10056 conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
10057 conf->requestInfo = op_count;
10058 conf->transId1 = apiConnectptr.p->transid[0];
10059 conf->transId2 = apiConnectptr.p->transid[1];
10060 ScanFragRecPtr ptr;
10061 {
10062 ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
10063 ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
10064 for(queued.first(ptr); !ptr.isNull(); ){
10065 ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
10066 ScanFragRecPtr curr = ptr; // Remove while iterating...
10067 queued.next(ptr);
10068
10069 bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
10070 if(curr.p->m_scan_frag_conf_status)
10071 booked++;
10072
10073 * ops++ = curr.p->m_apiPtr;
10074 * ops++ = done ? RNIL : curr.i;
10075 * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
10076
10077 queued.remove(curr);
10078 if(!done){
10079 delivered.add(curr);
10080 curr.p->scanFragState = ScanFragRec::DELIVERED;
10081 curr.p->stopFragTimer();
10082 } else {
10083 c_scan_frag_pool.release(curr);
10084 curr.p->scanFragState = ScanFragRec::COMPLETED;
10085 curr.p->stopFragTimer();
10086 }
10087 }
10088 }
10089
10090 scanPtr.p->m_booked_fragments_count = booked;
10091 if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
10092 scanPtr.p->m_running_scan_frags.isEmpty())
10093 {
10094 conf->requestInfo = op_count | ScanTabConf::EndOfData;
10095 releaseScanResources(scanPtr);
10096 }
10097 else
10098 {
10099 if (scanPtr.p->m_running_scan_frags.isEmpty())
10100 {
10101 jam();
10102 /**
10103 * All scan frags delivered...waiting for API
10104 */
10105 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10106 }
10107 }
10108
10109 if(4 + 3 * op_count > 25){
10110 jam();
10111 LinearSectionPtr ptr[3];
10112 ptr[0].p = signal->getDataPtrSend()+25;
10113 ptr[0].sz = 3 * op_count;
10114 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
10115 ScanTabConf::SignalLength, JBB, ptr, 1);
10116 } else {
10117 jam();
10118 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
10119 ScanTabConf::SignalLength + 3 * op_count, JBB);
10120 }
10121 scanPtr.p->m_queued_count = 0;
10122 }//Dbtc::sendScanTabConf()
10123
10124
gcpTcfinished(Signal * signal)10125 void Dbtc::gcpTcfinished(Signal* signal)
10126 {
10127 signal->theData[0] = c_gcp_ref;
10128 signal->theData[1] = tcheckGcpId;
10129 sendSignal(cdihblockref, GSN_GCP_TCFINISHED, signal, 2, JBB);
10130 }//Dbtc::gcpTcfinished()
10131
initApiConnect(Signal * signal)10132 void Dbtc::initApiConnect(Signal* signal)
10133 {
10134 Uint32 tiacTmp;
10135 Uint32 guard4;
10136
10137 tiacTmp = capiConnectFilesize / 3;
10138 ndbrequire(tiacTmp > 0);
10139 guard4 = tiacTmp + 1;
10140 for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
10141 refresh_watch_dog();
10142 ptrAss(cachePtr, cacheRecord);
10143 cachePtr.p->firstAttrbuf = RNIL;
10144 cachePtr.p->lastAttrbuf = RNIL;
10145 cachePtr.p->firstKeybuf = RNIL;
10146 cachePtr.p->lastKeybuf = RNIL;
10147 cachePtr.p->nextCacheRec = cachePtr.i + 1;
10148 }//for
10149 cachePtr.i = tiacTmp;
10150 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10151 cachePtr.p->nextCacheRec = RNIL;
10152 cfirstfreeCacheRec = 0;
10153
10154 guard4 = tiacTmp - 1;
10155 for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
10156 refresh_watch_dog();
10157 jam();
10158 ptrAss(apiConnectptr, apiConnectRecord);
10159 apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
10160 apiConnectptr.p->apiFailState = ZFALSE;
10161 setApiConTimer(apiConnectptr.i, 0, __LINE__);
10162 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10163 apiConnectptr.p->cachePtr = RNIL;
10164 apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
10165 apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
10166 apiConnectptr.p->commitAckMarker = RNIL;
10167 apiConnectptr.p->firstTcConnect = RNIL;
10168 apiConnectptr.p->lastTcConnect = RNIL;
10169 apiConnectptr.p->triggerPending = false;
10170 apiConnectptr.p->isIndexOp = false;
10171 apiConnectptr.p->accumulatingIndexOp = RNIL;
10172 apiConnectptr.p->executingIndexOp = RNIL;
10173 apiConnectptr.p->buddyPtr = RNIL;
10174 apiConnectptr.p->currSavePointId = 0;
10175 apiConnectptr.p->m_transaction_nodes.clear();
10176 apiConnectptr.p->singleUserMode = 0;
10177 }//for
10178 apiConnectptr.i = tiacTmp - 1;
10179 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10180 apiConnectptr.p->nextApiConnect = RNIL;
10181 cfirstfreeApiConnect = 0;
10182 guard4 = (2 * tiacTmp) - 1;
10183 for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
10184 {
10185 refresh_watch_dog();
10186 jam();
10187 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10188 apiConnectptr.p->apiConnectstate = CS_RESTART;
10189 apiConnectptr.p->apiFailState = ZFALSE;
10190 setApiConTimer(apiConnectptr.i, 0, __LINE__);
10191 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10192 apiConnectptr.p->cachePtr = RNIL;
10193 apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
10194 apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
10195 apiConnectptr.p->commitAckMarker = RNIL;
10196 apiConnectptr.p->firstTcConnect = RNIL;
10197 apiConnectptr.p->lastTcConnect = RNIL;
10198 apiConnectptr.p->triggerPending = false;
10199 apiConnectptr.p->isIndexOp = false;
10200 apiConnectptr.p->accumulatingIndexOp = RNIL;
10201 apiConnectptr.p->executingIndexOp = RNIL;
10202 apiConnectptr.p->buddyPtr = RNIL;
10203 apiConnectptr.p->currSavePointId = 0;
10204 apiConnectptr.p->m_transaction_nodes.clear();
10205 apiConnectptr.p->singleUserMode = 0;
10206 }//for
10207 apiConnectptr.i = (2 * tiacTmp) - 1;
10208 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10209 apiConnectptr.p->nextApiConnect = RNIL;
10210 cfirstfreeApiConnectCopy = tiacTmp;
10211 guard4 = (3 * tiacTmp) - 1;
10212 for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
10213 apiConnectptr.i++) {
10214 refresh_watch_dog();
10215 jam();
10216 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10217 setApiConTimer(apiConnectptr.i, 0, __LINE__);
10218 apiConnectptr.p->apiFailState = ZFALSE;
10219 apiConnectptr.p->apiConnectstate = CS_RESTART;
10220 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10221 apiConnectptr.p->cachePtr = RNIL;
10222 apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
10223 apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
10224 apiConnectptr.p->commitAckMarker = RNIL;
10225 apiConnectptr.p->firstTcConnect = RNIL;
10226 apiConnectptr.p->lastTcConnect = RNIL;
10227 apiConnectptr.p->triggerPending = false;
10228 apiConnectptr.p->isIndexOp = false;
10229 apiConnectptr.p->accumulatingIndexOp = RNIL;
10230 apiConnectptr.p->executingIndexOp = RNIL;
10231 apiConnectptr.p->buddyPtr = RNIL;
10232 apiConnectptr.p->currSavePointId = 0;
10233 apiConnectptr.p->m_transaction_nodes.clear();
10234 apiConnectptr.p->singleUserMode = 0;
10235 }//for
10236 apiConnectptr.i = (3 * tiacTmp) - 1;
10237 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10238 apiConnectptr.p->nextApiConnect = RNIL;
10239 cfirstfreeApiConnectFail = 2 * tiacTmp;
10240 }//Dbtc::initApiConnect()
10241
initattrbuf(Signal * signal)10242 void Dbtc::initattrbuf(Signal* signal)
10243 {
10244 ndbrequire(cattrbufFilesize > 0);
10245 for (attrbufptr.i = 0; attrbufptr.i < cattrbufFilesize; attrbufptr.i++) {
10246 refresh_watch_dog();
10247 jam();
10248 ptrAss(attrbufptr, attrbufRecord);
10249 attrbufptr.p->attrbuf[ZINBUF_NEXT] = attrbufptr.i + 1; /* NEXT ATTRBUF */
10250 }//for
10251 attrbufptr.i = cattrbufFilesize - 1;
10252 ptrAss(attrbufptr, attrbufRecord);
10253 attrbufptr.p->attrbuf[ZINBUF_NEXT] = RNIL; /* NEXT ATTRBUF */
10254 cfirstfreeAttrbuf = 0;
10255 }//Dbtc::initattrbuf()
10256
initdatabuf(Signal * signal)10257 void Dbtc::initdatabuf(Signal* signal)
10258 {
10259 ndbrequire(cdatabufFilesize > 0);
10260 for (databufptr.i = 0; databufptr.i < cdatabufFilesize; databufptr.i++) {
10261 refresh_watch_dog();
10262 ptrAss(databufptr, databufRecord);
10263 databufptr.p->nextDatabuf = databufptr.i + 1;
10264 }//for
10265 databufptr.i = cdatabufFilesize - 1;
10266 ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
10267 databufptr.p->nextDatabuf = RNIL;
10268 cfirstfreeDatabuf = 0;
10269 }//Dbtc::initdatabuf()
10270
initgcp(Signal * signal)10271 void Dbtc::initgcp(Signal* signal)
10272 {
10273 ndbrequire(cgcpFilesize > 0);
10274 for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
10275 ptrAss(gcpPtr, gcpRecord);
10276 gcpPtr.p->nextGcp = gcpPtr.i + 1;
10277 }//for
10278 gcpPtr.i = cgcpFilesize - 1;
10279 ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
10280 gcpPtr.p->nextGcp = RNIL;
10281 cfirstfreeGcp = 0;
10282 cfirstgcp = RNIL;
10283 clastgcp = RNIL;
10284 }//Dbtc::initgcp()
10285
inithost(Signal * signal)10286 void Dbtc::inithost(Signal* signal)
10287 {
10288 cpackedListIndex = 0;
10289 ndbrequire(chostFilesize > 0);
10290 for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
10291 jam();
10292 ptrAss(hostptr, hostRecord);
10293 hostptr.p->hostStatus = HS_DEAD;
10294 hostptr.p->inPackedList = false;
10295 hostptr.p->lqhTransStatus = LTS_IDLE;
10296 hostptr.p->noOfWordsTCKEYCONF = 0;
10297 hostptr.p->noOfWordsTCINDXCONF = 0;
10298 hostptr.p->noOfPackedWordsLqh = 0;
10299 hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
10300 hostptr.p->m_nf_bits = 0;
10301 }//for
10302 c_alive_nodes.clear();
10303 }//Dbtc::inithost()
10304
initialiseRecordsLab(Signal * signal,UintR Tdata0,Uint32 retRef,Uint32 retData)10305 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
10306 Uint32 retRef, Uint32 retData)
10307 {
10308 switch (Tdata0) {
10309 case 0:
10310 jam();
10311 initApiConnect(signal);
10312 break;
10313 case 1:
10314 jam();
10315 initattrbuf(signal);
10316 break;
10317 case 2:
10318 jam();
10319 initdatabuf(signal);
10320 break;
10321 case 3:
10322 jam();
10323 initgcp(signal);
10324 break;
10325 case 4:
10326 jam();
10327 inithost(signal);
10328 break;
10329 case 5:
10330 jam();
10331 // UNUSED Free to initialise something
10332 break;
10333 case 6:
10334 jam();
10335 initTable(signal);
10336 break;
10337 case 7:
10338 jam();
10339 initialiseScanrec(signal);
10340 break;
10341 case 8:
10342 jam();
10343 initialiseScanOprec(signal);
10344 break;
10345 case 9:
10346 jam();
10347 initialiseScanFragrec(signal);
10348 break;
10349 case 10:
10350 jam();
10351 initialiseTcConnect(signal);
10352 break;
10353 case 11:
10354 jam();
10355 initTcFail(signal);
10356
10357 {
10358 ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
10359 conf->senderRef = reference();
10360 conf->senderData = retData;
10361 sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
10362 ReadConfigConf::SignalLength, JBB);
10363 }
10364 return;
10365 break;
10366 default:
10367 jam();
10368 systemErrorLab(signal, __LINE__);
10369 return;
10370 break;
10371 }//switch
10372
10373 signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
10374 signal->theData[1] = Tdata0 + 1;
10375 signal->theData[2] = 0;
10376 signal->theData[3] = retRef;
10377 signal->theData[4] = retData;
10378 sendSignal(DBTC_REF, GSN_CONTINUEB, signal, 5, JBB);
10379 }
10380
10381 /* ========================================================================= */
10382 /* ======= INITIALISE_SCANREC ======= */
10383 /* */
10384 /* ========================================================================= */
initialiseScanrec(Signal * signal)10385 void Dbtc::initialiseScanrec(Signal* signal)
10386 {
10387 ScanRecordPtr scanptr;
10388 ndbrequire(cscanrecFileSize > 0);
10389 for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
10390 refresh_watch_dog();
10391 jam();
10392 ptrAss(scanptr, scanRecord);
10393 new (scanptr.p) ScanRecord();
10394 scanptr.p->scanState = ScanRecord::IDLE;
10395 scanptr.p->scanApiRec = RNIL;
10396 scanptr.p->nextScan = scanptr.i + 1;
10397 }//for
10398 scanptr.i = cscanrecFileSize - 1;
10399 ptrAss(scanptr, scanRecord);
10400 scanptr.p->nextScan = RNIL;
10401 cfirstfreeScanrec = 0;
10402 }//Dbtc::initialiseScanrec()
10403
initialiseScanFragrec(Signal * signal)10404 void Dbtc::initialiseScanFragrec(Signal* signal)
10405 {
10406 }//Dbtc::initialiseScanFragrec()
10407
initialiseScanOprec(Signal * signal)10408 void Dbtc::initialiseScanOprec(Signal* signal)
10409 {
10410 }//Dbtc::initialiseScanOprec()
10411
initTable(Signal * signal)10412 void Dbtc::initTable(Signal* signal)
10413 {
10414
10415 ndbrequire(ctabrecFilesize > 0);
10416 for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
10417 refresh_watch_dog();
10418 ptrAss(tabptr, tableRecord);
10419 tabptr.p->currentSchemaVersion = 0;
10420 tabptr.p->m_flags = 0;
10421 tabptr.p->set_storedTable(true);
10422 tabptr.p->tableType = 0;
10423 tabptr.p->set_enabled(false);
10424 tabptr.p->set_dropping(false);
10425 tabptr.p->noOfKeyAttr = 0;
10426 tabptr.p->hasCharAttr = 0;
10427 tabptr.p->noOfDistrKeys = 0;
10428 tabptr.p->hasVarKeys = 0;
10429 }//for
10430 }//Dbtc::initTable()
10431
initialiseTcConnect(Signal * signal)10432 void Dbtc::initialiseTcConnect(Signal* signal)
10433 {
10434 ndbrequire(ctcConnectFilesize >= 2);
10435
10436 // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
10437 Uint32 titcTmp = ctcConnectFilesize / 2;
10438 for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
10439 refresh_watch_dog();
10440 jam();
10441 ptrAss(tcConnectptr, tcConnectRecord);
10442 tcConnectptr.p->tcConnectstate = OS_RESTART;
10443 tcConnectptr.p->apiConnect = RNIL;
10444 tcConnectptr.p->noOfNodes = 0;
10445 tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
10446 }//for
10447 tcConnectptr.i = titcTmp - 1;
10448 ptrAss(tcConnectptr, tcConnectRecord);
10449 tcConnectptr.p->nextTcConnect = RNIL;
10450 cfirstfreeTcConnectFail = 0;
10451
10452 // Place other half in cfirstfreeTcConnect list
10453 for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
10454 tcConnectptr.i++) {
10455 refresh_watch_dog();
10456 jam();
10457 ptrAss(tcConnectptr, tcConnectRecord);
10458 tcConnectptr.p->tcConnectstate = OS_RESTART;
10459 tcConnectptr.p->apiConnect = RNIL;
10460 tcConnectptr.p->noOfNodes = 0;
10461 tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
10462 }//for
10463 tcConnectptr.i = ctcConnectFilesize - 1;
10464 ptrAss(tcConnectptr, tcConnectRecord);
10465 tcConnectptr.p->nextTcConnect = RNIL;
10466 cfirstfreeTcConnect = titcTmp;
10467 c_counters.cconcurrentOp = 0;
10468 }//Dbtc::initialiseTcConnect()
10469
10470 /* ------------------------------------------------------------------------- */
10471 /* ---- LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS */
10472 /* WAITING FOR COMPLETION. */
10473 /* ------------------------------------------------------------------------- */
linkGciInGcilist(Signal * signal)10474 void Dbtc::linkGciInGcilist(Signal* signal)
10475 {
10476 GcpRecordPtr tmpGcpPointer;
10477 if (cfirstgcp == RNIL) {
10478 jam();
10479 cfirstgcp = gcpPtr.i;
10480 } else {
10481 jam();
10482 tmpGcpPointer.i = clastgcp;
10483 ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
10484 tmpGcpPointer.p->nextGcp = gcpPtr.i;
10485 }//if
10486 clastgcp = gcpPtr.i;
10487 }//Dbtc::linkGciInGcilist()
10488
10489 /* ------------------------------------------------------------------------- */
10490 /* ------- LINK SECONDARY KEY BUFFER IN OPERATION RECORD ------- */
10491 /* ------------------------------------------------------------------------- */
linkKeybuf(Signal * signal)10492 void Dbtc::linkKeybuf(Signal* signal)
10493 {
10494 seizeDatabuf(signal);
10495 tmpDatabufptr.i = cachePtr.p->lastKeybuf;
10496 cachePtr.p->lastKeybuf = databufptr.i;
10497 if (tmpDatabufptr.i == RNIL) {
10498 jam();
10499 cachePtr.p->firstKeybuf = databufptr.i;
10500 } else {
10501 jam();
10502 ptrCheckGuard(tmpDatabufptr, cdatabufFilesize, databufRecord);
10503 tmpDatabufptr.p->nextDatabuf = databufptr.i;
10504 }//if
10505 }//Dbtc::linkKeybuf()
10506
10507 /* ------------------------------------------------------------------------- */
10508 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS --- */
10509 /* ------------------------------------------------------------------------- */
linkTcInConnectionlist(Signal * signal)10510 void Dbtc::linkTcInConnectionlist(Signal* signal)
10511 {
10512 /* POINTER FOR THE CONNECT_RECORD */
10513 TcConnectRecordPtr ltcTcConnectptr;
10514
10515 tcConnectptr.p->nextTcConnect = RNIL;
10516 ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
10517 ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
10518 apiConnectptr.p->lastTcConnect = tcConnectptr.i;
10519 if (ltcTcConnectptr.i == RNIL) {
10520 jam();
10521 apiConnectptr.p->firstTcConnect = tcConnectptr.i;
10522 } else {
10523 jam();
10524 ptrGuard(ltcTcConnectptr);
10525 ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
10526 }//if
10527 }//Dbtc::linkTcInConnectionlist()
10528
10529 /*---------------------------------------------------------------------------*/
10530 /* RELEASE_ABORT_RESOURCES */
10531 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
10532 /* SENDS THE ABORT DECISION TO THE APPLICATION. */
10533 /*---------------------------------------------------------------------------*/
releaseAbortResources(Signal * signal)10534 void Dbtc::releaseAbortResources(Signal* signal)
10535 {
10536 TcConnectRecordPtr rarTcConnectptr;
10537
10538 c_counters.cabortCount++;
10539 if (apiConnectptr.p->cachePtr != RNIL) {
10540 cachePtr.i = apiConnectptr.p->cachePtr;
10541 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10542 releaseAttrinfo();
10543 releaseKeys();
10544 }//if
10545 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10546 while (tcConnectptr.i != RNIL) {
10547 jam();
10548 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10549 // Clear any markers that were set in CS_RECEIVING state
10550 clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
10551 rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
10552 releaseTcCon();
10553 tcConnectptr.i = rarTcConnectptr.i;
10554 }//while
10555 apiConnectptr.p->firstTcConnect = RNIL;
10556 apiConnectptr.p->lastTcConnect = RNIL;
10557 apiConnectptr.p->m_transaction_nodes.clear();
10558 apiConnectptr.p->singleUserMode = 0;
10559
10560 // MASV let state be CS_ABORTING until all
10561 // signals in the "air" have been received. Reset to CS_CONNECTED
10562 // will be done when a TCKEYREQ with start flag is recieved
10563 // or releaseApiCon is called
10564 // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
10565 apiConnectptr.p->apiConnectstate = CS_ABORTING;
10566 apiConnectptr.p->abortState = AS_IDLE;
10567 releaseAllSeizedIndexOperations(apiConnectptr.p);
10568 if(apiConnectptr.p->m_exec_flag || apiConnectptr.p->apiFailState == ZTRUE){
10569 jam();
10570 bool ok = false;
10571 Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
10572 ReturnSignal ret = apiConnectptr.p->returnsignal;
10573 apiConnectptr.p->returnsignal = RS_NO_RETURN;
10574 apiConnectptr.p->m_exec_flag = 0;
10575 switch(ret){
10576 case RS_TCROLLBACKCONF:
10577 jam();
10578 ok = true;
10579 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
10580 signal->theData[1] = apiConnectptr.p->transid[0];
10581 signal->theData[2] = apiConnectptr.p->transid[1];
10582 sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
10583 break;
10584 case RS_TCROLLBACKREP:{
10585 jam();
10586 ok = true;
10587 TcRollbackRep * const tcRollbackRep =
10588 (TcRollbackRep *) signal->getDataPtr();
10589
10590 tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
10591 tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
10592 tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
10593 tcRollbackRep->returnCode = apiConnectptr.p->returncode;
10594 tcRollbackRep->errorData = apiConnectptr.p->errorData;
10595 sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
10596 TcRollbackRep::SignalLength, JBB);
10597 }
10598 break;
10599 case RS_NO_RETURN:
10600 jam();
10601 ok = true;
10602 break;
10603 case RS_TCKEYCONF:
10604 case RS_TC_COMMITCONF:
10605 break;
10606 }
10607 if(!ok){
10608 jam();
10609 ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
10610 sendSystemError(signal, __LINE__);
10611 }//if
10612
10613 }
10614 setApiConTimer(apiConnectptr.i, 0,
10615 100000+c_apiConTimer_line[apiConnectptr.i]);
10616 if (apiConnectptr.p->apiFailState == ZTRUE) {
10617 jam();
10618 handleApiFailState(signal, apiConnectptr.i);
10619 return;
10620 }//if
10621 }//Dbtc::releaseAbortResources()
10622
releaseApiCon(Signal * signal,UintR TapiConnectPtr)10623 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
10624 {
10625 ApiConnectRecordPtr TlocalApiConnectptr;
10626
10627 TlocalApiConnectptr.i = TapiConnectPtr;
10628 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
10629 TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
10630 cfirstfreeApiConnect = TlocalApiConnectptr.i;
10631 setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
10632 TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
10633 ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
10634 ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
10635 TlocalApiConnectptr.p->ndbapiBlockref = 0;
10636 }//Dbtc::releaseApiCon()
10637
releaseApiConnectFail(Signal * signal)10638 void Dbtc::releaseApiConnectFail(Signal* signal)
10639 {
10640 apiConnectptr.p->apiConnectstate = CS_RESTART;
10641 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10642 setApiConTimer(apiConnectptr.i, 0, __LINE__);
10643 apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
10644 cfirstfreeApiConnectFail = apiConnectptr.i;
10645 }//Dbtc::releaseApiConnectFail()
10646
releaseGcp(Signal * signal)10647 void Dbtc::releaseGcp(Signal* signal)
10648 {
10649 ptrGuard(gcpPtr);
10650 gcpPtr.p->nextGcp = cfirstfreeGcp;
10651 cfirstfreeGcp = gcpPtr.i;
10652 }//Dbtc::releaseGcp()
10653
releaseKeys()10654 void Dbtc::releaseKeys()
10655 {
10656 UintR Tmp;
10657 databufptr.i = cachePtr.p->firstKeybuf;
10658 while (databufptr.i != RNIL) {
10659 jam();
10660 ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
10661 Tmp = databufptr.p->nextDatabuf;
10662 databufptr.p->nextDatabuf = cfirstfreeDatabuf;
10663 cfirstfreeDatabuf = databufptr.i;
10664 databufptr.i = Tmp;
10665 }//while
10666 cachePtr.p->firstKeybuf = RNIL;
10667 cachePtr.p->lastKeybuf = RNIL;
10668 }//Dbtc::releaseKeys()
10669
releaseTcConnectFail(Signal * signal)10670 void Dbtc::releaseTcConnectFail(Signal* signal)
10671 {
10672 ptrGuard(tcConnectptr);
10673 tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
10674 cfirstfreeTcConnectFail = tcConnectptr.i;
10675 }//Dbtc::releaseTcConnectFail()
10676
seizeApiConnect(Signal * signal)10677 void Dbtc::seizeApiConnect(Signal* signal)
10678 {
10679 if (cfirstfreeApiConnect != RNIL) {
10680 jam();
10681 terrorCode = ZOK;
10682 apiConnectptr.i = cfirstfreeApiConnect; /* ASSIGN A FREE RECORD FROM */
10683 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10684 cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
10685 apiConnectptr.p->nextApiConnect = RNIL;
10686 setApiConTimer(apiConnectptr.i, 0, __LINE__);
10687 apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
10688 apiConnectptr.p->triggerPending = false;
10689 apiConnectptr.p->isIndexOp = false;
10690 } else {
10691 jam();
10692 terrorCode = ZNO_FREE_API_CONNECTION;
10693 }//if
10694 }//Dbtc::seizeApiConnect()
10695
seizeApiConnectFail(Signal * signal)10696 void Dbtc::seizeApiConnectFail(Signal* signal)
10697 {
10698 apiConnectptr.i = cfirstfreeApiConnectFail;
10699 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10700 cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
10701 }//Dbtc::seizeApiConnectFail()
10702
seizeDatabuf(Signal * signal)10703 void Dbtc::seizeDatabuf(Signal* signal)
10704 {
10705 databufptr.i = cfirstfreeDatabuf;
10706 ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
10707 cfirstfreeDatabuf = databufptr.p->nextDatabuf;
10708 databufptr.p->nextDatabuf = RNIL;
10709 }//Dbtc::seizeDatabuf()
10710
seizeTcConnect(Signal * signal)10711 void Dbtc::seizeTcConnect(Signal* signal)
10712 {
10713 tcConnectptr.i = cfirstfreeTcConnect;
10714 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10715 cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
10716 c_counters.cconcurrentOp++;
10717 tcConnectptr.p->isIndexOp = false;
10718 }//Dbtc::seizeTcConnect()
10719
seizeTcConnectFail(Signal * signal)10720 void Dbtc::seizeTcConnectFail(Signal* signal)
10721 {
10722 tcConnectptr.i = cfirstfreeTcConnectFail;
10723 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10724 cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
10725 }//Dbtc::seizeTcConnectFail()
10726
sendAttrinfo(Signal * signal,UintR TattrinfoPtr,AttrbufRecord * const regAttrPtr,UintR TBref)10727 void Dbtc::sendAttrinfo(Signal* signal,
10728 UintR TattrinfoPtr,
10729 AttrbufRecord * const regAttrPtr,
10730 UintR TBref)
10731 {
10732 UintR TdataPos;
10733 UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6, sig7;
10734 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
10735 TdataPos = regAttrPtr->attrbuf[ZINBUF_DATA_LEN];
10736 sig0 = TattrinfoPtr;
10737 sig1 = regApiPtr->transid[0];
10738 sig2 = regApiPtr->transid[1];
10739
10740 signal->theData[0] = sig0;
10741 signal->theData[1] = sig1;
10742 signal->theData[2] = sig2;
10743
10744 sig0 = regAttrPtr->attrbuf[0];
10745 sig1 = regAttrPtr->attrbuf[1];
10746 sig2 = regAttrPtr->attrbuf[2];
10747 sig3 = regAttrPtr->attrbuf[3];
10748 sig4 = regAttrPtr->attrbuf[4];
10749 sig5 = regAttrPtr->attrbuf[5];
10750 sig6 = regAttrPtr->attrbuf[6];
10751 sig7 = regAttrPtr->attrbuf[7];
10752
10753 signal->theData[3] = sig0;
10754 signal->theData[4] = sig1;
10755 signal->theData[5] = sig2;
10756 signal->theData[6] = sig3;
10757 signal->theData[7] = sig4;
10758 signal->theData[8] = sig5;
10759 signal->theData[9] = sig6;
10760 signal->theData[10] = sig7;
10761
10762 if (TdataPos > 8) {
10763 sig0 = regAttrPtr->attrbuf[8];
10764 sig1 = regAttrPtr->attrbuf[9];
10765 sig2 = regAttrPtr->attrbuf[10];
10766 sig3 = regAttrPtr->attrbuf[11];
10767 sig4 = regAttrPtr->attrbuf[12];
10768 sig5 = regAttrPtr->attrbuf[13];
10769 sig6 = regAttrPtr->attrbuf[14];
10770
10771 jam();
10772 signal->theData[11] = sig0;
10773 signal->theData[12] = sig1;
10774 signal->theData[13] = sig2;
10775 signal->theData[14] = sig3;
10776 signal->theData[15] = sig4;
10777 signal->theData[16] = sig5;
10778 signal->theData[17] = sig6;
10779
10780 if (TdataPos > 15) {
10781
10782 sig0 = regAttrPtr->attrbuf[15];
10783 sig1 = regAttrPtr->attrbuf[16];
10784 sig2 = regAttrPtr->attrbuf[17];
10785 sig3 = regAttrPtr->attrbuf[18];
10786 sig4 = regAttrPtr->attrbuf[19];
10787 sig5 = regAttrPtr->attrbuf[20];
10788 sig6 = regAttrPtr->attrbuf[21];
10789
10790 jam();
10791 signal->theData[18] = sig0;
10792 signal->theData[19] = sig1;
10793 signal->theData[20] = sig2;
10794 signal->theData[21] = sig3;
10795 signal->theData[22] = sig4;
10796 signal->theData[23] = sig5;
10797 signal->theData[24] = sig6;
10798 }//if
10799 }//if
10800 sendSignal(TBref, GSN_ATTRINFO, signal, TdataPos + 3, JBB);
10801 }//Dbtc::sendAttrinfo()
10802
sendContinueTimeOutControl(Signal * signal,Uint32 TapiConPtr)10803 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
10804 {
10805 signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
10806 signal->theData[1] = TapiConPtr;
10807 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
10808 }//Dbtc::sendContinueTimeOutControl()
10809
sendKeyinfo(Signal * signal,BlockReference TBRef,Uint32 len)10810 void Dbtc::sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len)
10811 {
10812 signal->theData[0] = tcConnectptr.i;
10813 signal->theData[1] = apiConnectptr.p->transid[0];
10814 signal->theData[2] = apiConnectptr.p->transid[1];
10815 signal->theData[3] = cdata[0];
10816 signal->theData[4] = cdata[1];
10817 signal->theData[5] = cdata[2];
10818 signal->theData[6] = cdata[3];
10819 signal->theData[7] = cdata[4];
10820 signal->theData[8] = cdata[5];
10821 signal->theData[9] = cdata[6];
10822 signal->theData[10] = cdata[7];
10823 signal->theData[11] = cdata[8];
10824 signal->theData[12] = cdata[9];
10825 signal->theData[13] = cdata[10];
10826 signal->theData[14] = cdata[11];
10827 signal->theData[15] = cdata[12];
10828 signal->theData[16] = cdata[13];
10829 signal->theData[17] = cdata[14];
10830 signal->theData[18] = cdata[15];
10831 signal->theData[19] = cdata[16];
10832 signal->theData[20] = cdata[17];
10833 signal->theData[21] = cdata[18];
10834 signal->theData[22] = cdata[19];
10835 sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
10836 }//Dbtc::sendKeyinfo()
10837
sendSystemError(Signal * signal,int line)10838 void Dbtc::sendSystemError(Signal* signal, int line)
10839 {
10840 progError(line, NDBD_EXIT_NDBREQUIRE);
10841 }//Dbtc::sendSystemError()
10842
10843 /* ========================================================================= */
10844 /* ------- LINK ACTUAL GCP OUT OF LIST ------- */
10845 /* ------------------------------------------------------------------------- */
unlinkGcp(Signal * signal)10846 void Dbtc::unlinkGcp(Signal* signal)
10847 {
10848 if (cfirstgcp == gcpPtr.i) {
10849 jam();
10850 cfirstgcp = gcpPtr.p->nextGcp;
10851 if (gcpPtr.i == clastgcp) {
10852 jam();
10853 clastgcp = RNIL;
10854 }//if
10855 } else {
10856 jam();
10857 /* --------------------------------------------------------------------
10858 * WE ARE TRYING TO REMOVE A GLOBAL CHECKPOINT WHICH WAS NOT THE OLDEST.
10859 * THIS IS A SYSTEM ERROR.
10860 * ------------------------------------------------------------------- */
10861 sendSystemError(signal, __LINE__);
10862 }//if
10863 gcpPtr.p->nextGcp = cfirstfreeGcp;
10864 cfirstfreeGcp = gcpPtr.i;
10865 }//Dbtc::unlinkGcp()
10866
10867 void
execDUMP_STATE_ORD(Signal * signal)10868 Dbtc::execDUMP_STATE_ORD(Signal* signal)
10869 {
10870 DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
10871 if(signal->theData[0] == DumpStateOrd::CommitAckMarkersSize){
10872 infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
10873 m_commitAckMarkerPool.getNoOfFree(),
10874 m_commitAckMarkerPool.getSize());
10875 }
10876 if(signal->theData[0] == DumpStateOrd::CommitAckMarkersDump){
10877 infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
10878 m_commitAckMarkerPool.getNoOfFree(),
10879 m_commitAckMarkerPool.getSize());
10880
10881 CommitAckMarkerIterator iter;
10882 for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
10883 m_commitAckMarkerHash.next(iter)){
10884 infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
10885 " Api: %d Lghs(%d): %d %d %d %d bucket = %d",
10886 iter.curr.i,
10887 iter.curr.p->transid1,
10888 iter.curr.p->transid2,
10889 iter.curr.p->apiNodeId,
10890 iter.curr.p->noOfLqhs,
10891 iter.curr.p->lqhNodeId[0],
10892 iter.curr.p->lqhNodeId[1],
10893 iter.curr.p->lqhNodeId[2],
10894 iter.curr.p->lqhNodeId[3],
10895 iter.bucket);
10896 }
10897 }
10898 // Dump all ScanFragRecs
10899 if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
10900 Uint32 recordNo = 0;
10901 if (signal->getLength() == 1)
10902 infoEvent("TC: Dump all ScanFragRec - size: %d",
10903 cscanFragrecFileSize);
10904 else if (signal->getLength() == 2)
10905 recordNo = dumpState->args[1];
10906 else
10907 return;
10908
10909 dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
10910 dumpState->args[1] = recordNo;
10911 execDUMP_STATE_ORD(signal);
10912
10913 if (recordNo < cscanFragrecFileSize-1){
10914 dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
10915 dumpState->args[1] = recordNo+1;
10916 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
10917 }
10918 }
10919
10920 // Dump one ScanFragRec
10921 if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
10922 Uint32 recordNo = RNIL;
10923 if (signal->getLength() == 2)
10924 recordNo = dumpState->args[1];
10925 else
10926 return;
10927
10928 if (recordNo >= cscanFragrecFileSize)
10929 return;
10930
10931 ScanFragRecPtr sfp;
10932 sfp.i = recordNo;
10933 c_scan_frag_pool.getPtr(sfp);
10934 infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
10935 sfp.i,
10936 sfp.p->scanFragState,
10937 sfp.p->scanFragId);
10938 infoEvent(" nodeid=%d, timer=%d",
10939 refToNode(sfp.p->lqhBlockref),
10940 sfp.p->scanFragTimer);
10941 }
10942
10943 // Dump all ScanRecords
10944 if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
10945 Uint32 recordNo = 0;
10946 if (signal->getLength() == 1)
10947 infoEvent("TC: Dump all ScanRecord - size: %d",
10948 cscanrecFileSize);
10949 else if (signal->getLength() == 2)
10950 recordNo = dumpState->args[1];
10951 else
10952 return;
10953
10954 dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
10955 dumpState->args[1] = recordNo;
10956 execDUMP_STATE_ORD(signal);
10957
10958 if (recordNo < cscanrecFileSize-1){
10959 dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
10960 dumpState->args[1] = recordNo+1;
10961 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
10962 }
10963 }
10964
10965 // Dump all active ScanRecords
10966 if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
10967 Uint32 recordNo = 0;
10968 if (signal->getLength() == 1)
10969 infoEvent("TC: Dump active ScanRecord - size: %d",
10970 cscanrecFileSize);
10971 else if (signal->getLength() == 2)
10972 recordNo = dumpState->args[1];
10973 else
10974 return;
10975
10976 ScanRecordPtr sp;
10977 sp.i = recordNo;
10978 ptrAss(sp, scanRecord);
10979 if (sp.p->scanState != ScanRecord::IDLE){
10980 dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
10981 dumpState->args[1] = recordNo;
10982 execDUMP_STATE_ORD(signal);
10983 }
10984
10985 if (recordNo < cscanrecFileSize-1){
10986 dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
10987 dumpState->args[1] = recordNo+1;
10988 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
10989 }
10990 }
10991
10992 // Dump one ScanRecord
10993 // and associated ScanFragRec and ApiConnectRecord
10994 if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
10995 Uint32 recordNo = RNIL;
10996 if (signal->getLength() == 2)
10997 recordNo = dumpState->args[1];
10998 else
10999 return;
11000
11001 if (recordNo >= cscanrecFileSize)
11002 return;
11003
11004 ScanRecordPtr sp;
11005 sp.i = recordNo;
11006 ptrAss(sp, scanRecord);
11007 infoEvent("Dbtc::ScanRecord[%d]: state=%d"
11008 "nextfrag=%d, nofrag=%d",
11009 sp.i,
11010 sp.p->scanState,
11011 sp.p->scanNextFragId,
11012 sp.p->scanNoFrag);
11013 infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
11014 sp.p->scanAiLength,
11015 sp.p->scanParallel,
11016 sp.p->scanReceivedOperations,
11017 sp.p->batch_size_rows);
11018 infoEvent(" schv=%d, tab=%d, sproc=%d",
11019 sp.p->scanSchemaVersion,
11020 sp.p->scanTableref,
11021 sp.p->scanStoredProcId);
11022 infoEvent(" apiRec=%d, next=%d",
11023 sp.p->scanApiRec, sp.p->nextScan);
11024
11025 if (sp.p->scanState != ScanRecord::IDLE){
11026 // Request dump of ScanFragRec
11027 ScanFragRecPtr sfptr;
11028 #define DUMP_SFR(x){\
11029 ScanFragList list(c_scan_frag_pool, x);\
11030 for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
11031 dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
11032 dumpState->args[1] = sfptr.i;\
11033 execDUMP_STATE_ORD(signal);\
11034 }}
11035
11036 DUMP_SFR(sp.p->m_running_scan_frags);
11037 DUMP_SFR(sp.p->m_queued_scan_frags);
11038 DUMP_SFR(sp.p->m_delivered_scan_frags);
11039
11040 // Request dump of ApiConnectRecord
11041 dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
11042 dumpState->args[1] = sp.p->scanApiRec;
11043 execDUMP_STATE_ORD(signal);
11044 }
11045
11046 }
11047
11048 // Dump all ApiConnectRecord(s)
11049 if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
11050 Uint32 recordNo = 0;
11051 if (signal->getLength() == 1)
11052 infoEvent("TC: Dump all ApiConnectRecord - size: %d",
11053 capiConnectFilesize);
11054 else if (signal->getLength() == 2)
11055 recordNo = dumpState->args[1];
11056 else
11057 return;
11058
11059 dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
11060 dumpState->args[1] = recordNo;
11061 execDUMP_STATE_ORD(signal);
11062
11063 if (recordNo < capiConnectFilesize-1){
11064 dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
11065 dumpState->args[1] = recordNo+1;
11066 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
11067 }
11068 }
11069
11070 // Dump one ApiConnectRecord
11071 if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
11072 Uint32 recordNo = RNIL;
11073 if (signal->getLength() == 2)
11074 recordNo = dumpState->args[1];
11075 else
11076 return;
11077
11078 if (recordNo >= capiConnectFilesize)
11079 return;
11080
11081 ApiConnectRecordPtr ap;
11082 ap.i = recordNo;
11083 ptrAss(ap, apiConnectRecord);
11084 infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
11085 "apiFailState=%d",
11086 ap.i,
11087 ap.p->apiConnectstate,
11088 ap.p->abortState,
11089 ap.p->apiFailState);
11090 infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
11091 ap.p->transid[0],
11092 ap.p->transid[1],
11093 ap.p->ndbapiBlockref,
11094 ap.p->apiScanRec);
11095 infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
11096 "retsig=%d",
11097 ctcTimer, getApiConTimer(ap.i),
11098 ap.p->counter,
11099 ap.p->returncode,
11100 ap.p->returnsignal);
11101 infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
11102 "tckeyrec=%d",
11103 ap.p->lqhkeyconfrec,
11104 ap.p->lqhkeyreqrec,
11105 ap.p->tckeyrec);
11106 infoEvent(" next=%d ",
11107 ap.p->nextApiConnect);
11108 }
11109
11110 if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
11111 jam();
11112 if(signal->getLength() > 1){
11113 set_timeout_value(signal->theData[1]);
11114 }
11115 }
11116
11117 if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
11118 jam();
11119 if(signal->getLength() > 1){
11120 set_appl_timeout_value(signal->theData[1]);
11121 }
11122 }
11123
11124 if (dumpState->args[0] == DumpStateOrd::StartTcTimer){
11125 c_counters.c_trans_status = TransCounters::Started;
11126 c_counters.reset();
11127 }
11128
11129 if (dumpState->args[0] == DumpStateOrd::StopTcTimer){
11130 c_counters.c_trans_status = TransCounters::Off;
11131 Uint32 len = c_counters.report(signal);
11132 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
11133 c_counters.reset();
11134 }
11135
11136 if (dumpState->args[0] == DumpStateOrd::StartPeriodicTcTimer){
11137 c_counters.c_trans_status = TransCounters::Timer;
11138 c_counters.reset();
11139 signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
11140 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
11141 }
11142
11143 if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
11144 {
11145 static int frequency = 1;
11146 if (signal->getLength() > 1)
11147 frequency = signal->theData[1];
11148 else
11149 if (refToBlock(signal->getSendersBlockRef()) != DBTC)
11150 frequency = 1;
11151
11152 if (frequency)
11153 {
11154 dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
11155 execDUMP_STATE_ORD(signal);
11156 dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
11157
11158 Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
11159 sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
11160 }
11161 }
11162
11163 if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
11164 {
11165 infoEvent("IndexOpCount: pool: %d free: %d",
11166 c_theIndexOperationPool.getSize(),
11167 c_theIndexOperationPool.getNoOfFree());
11168 }
11169
11170 if (dumpState->args[0] == 2514)
11171 {
11172 if (signal->getLength() == 2)
11173 {
11174 dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
11175 execDUMP_STATE_ORD(signal);
11176 }
11177
11178 NodeReceiverGroup rg(CMVMI, c_alive_nodes);
11179 dumpState->args[0] = 15;
11180 sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
11181
11182 signal->theData[0] = 2515;
11183 sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, 1000, 1);
11184 return;
11185 }
11186
11187 if (dumpState->args[0] == 2515)
11188 {
11189 NdbNodeBitmask mask = c_alive_nodes;
11190 mask.clear(getOwnNodeId());
11191 NodeReceiverGroup rg(NDBCNTR, mask);
11192
11193 sendSignal(rg, GSN_SYSTEM_ERROR, signal, 1, JBB);
11194 sendSignalWithDelay(cownref, GSN_SYSTEM_ERROR, signal, 300, 1);
11195 return;
11196 }
11197 }//Dbtc::execDUMP_STATE_ORD()
11198
execABORT_ALL_REQ(Signal * signal)11199 void Dbtc::execABORT_ALL_REQ(Signal* signal)
11200 {
11201 jamEntry();
11202 AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
11203 AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
11204
11205 const Uint32 senderData = req->senderData;
11206 const BlockReference senderRef = req->senderRef;
11207
11208 if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
11209 jam();
11210
11211 ref->senderData = senderData;
11212 ref->errorCode = AbortAllRef::InvalidState;
11213 sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
11214 AbortAllRef::SignalLength, JBB);
11215 return;
11216 }
11217
11218 if(c_abortRec.clientRef != 0){
11219 jam();
11220
11221 ref->senderData = senderData;
11222 ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
11223 sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
11224 AbortAllRef::SignalLength, JBB);
11225 return;
11226 }
11227
11228 if(refToNode(senderRef) != getOwnNodeId()){
11229 jam();
11230
11231 ref->senderData = senderData;
11232 ref->errorCode = AbortAllRef::FunctionNotImplemented;
11233 sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
11234 AbortAllRef::SignalLength, JBB);
11235 return;
11236 }
11237
11238 c_abortRec.clientRef = senderRef;
11239 c_abortRec.clientData = senderData;
11240 c_abortRec.oldTimeOutValue = ctimeOutValue;
11241
11242 ctimeOutValue = 0;
11243 const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
11244
11245 checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
11246 }
11247
checkAbortAllTimeout(Signal * signal,Uint32 sleepTime)11248 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
11249 {
11250
11251 ndbrequire(c_abortRec.clientRef != 0);
11252
11253 if(sleepTime > 0){
11254 jam();
11255
11256 sleepTime -= 1;
11257 signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
11258 signal->theData[1] = sleepTime;
11259 sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
11260 return;
11261 }
11262
11263 AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
11264 conf->senderData = c_abortRec.clientData;
11265 sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
11266 AbortAllConf::SignalLength, JBB);
11267
11268 ctimeOutValue = c_abortRec.oldTimeOutValue;
11269 c_abortRec.clientRef = 0;
11270 }
11271
11272 /* **************************************************************** */
11273 /* ---------------------------------------------------------------- */
11274 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
11275 /* ---------------------------------------------------------------- */
11276 /* **************************************************************** */
11277
execCREATE_TRIG_REQ(Signal * signal)11278 void Dbtc::execCREATE_TRIG_REQ(Signal* signal)
11279 {
11280 jamEntry();
11281 CreateTrigReq * const createTrigReq =
11282 (CreateTrigReq *)&signal->theData[0];
11283 TcDefinedTriggerData* triggerData;
11284 DefinedTriggerPtr triggerPtr;
11285 BlockReference sender = signal->senderBlockRef();
11286
11287 releaseSections(signal);
11288
11289 triggerPtr.i = createTrigReq->getTriggerId();
11290 if (ERROR_INSERTED(8033) ||
11291 !c_theDefinedTriggers.seizeId(triggerPtr,
11292 createTrigReq->getTriggerId())) {
11293 jam();
11294 CLEAR_ERROR_INSERT_VALUE;
11295 // Failed to allocate trigger record
11296 CreateTrigRef * const createTrigRef =
11297 (CreateTrigRef *)&signal->theData[0];
11298
11299 createTrigRef->setConnectionPtr(createTrigReq->getConnectionPtr());
11300 createTrigRef->setErrorCode(CreateTrigRef::TooManyTriggers);
11301 sendSignal(sender, GSN_CREATE_TRIG_REF,
11302 signal, CreateTrigRef::SignalLength, JBB);
11303 return;
11304 }
11305
11306 triggerData = triggerPtr.p;
11307 triggerData->triggerId = createTrigReq->getTriggerId();
11308 triggerData->triggerType = createTrigReq->getTriggerType();
11309 triggerData->triggerEvent = createTrigReq->getTriggerEvent();
11310 triggerData->attributeMask = createTrigReq->getAttributeMask();
11311 if (triggerData->triggerType == TriggerType::SECONDARY_INDEX)
11312 triggerData->indexId = createTrigReq->getIndexId();
11313 CreateTrigConf * const createTrigConf =
11314 (CreateTrigConf *)&signal->theData[0];
11315
11316 createTrigConf->setConnectionPtr(createTrigReq->getConnectionPtr());
11317 sendSignal(sender, GSN_CREATE_TRIG_CONF,
11318 signal, CreateTrigConf::SignalLength, JBB);
11319 }
11320
11321
execDROP_TRIG_REQ(Signal * signal)11322 void Dbtc::execDROP_TRIG_REQ(Signal* signal)
11323 {
11324 jamEntry();
11325 DropTrigReq * const dropTrigReq = (DropTrigReq *)&signal->theData[0];
11326 BlockReference sender = signal->senderBlockRef();
11327
11328 if (ERROR_INSERTED(8035) ||
11329 (c_theDefinedTriggers.getPtr(dropTrigReq->getTriggerId())) == NULL) {
11330 jam();
11331 CLEAR_ERROR_INSERT_VALUE;
11332 // Failed to find find trigger record
11333 DropTrigRef * const dropTrigRef = (DropTrigRef *)&signal->theData[0];
11334
11335 dropTrigRef->setConnectionPtr(dropTrigReq->getConnectionPtr());
11336 dropTrigRef->setErrorCode(DropTrigRef::TriggerNotFound);
11337 sendSignal(sender, GSN_DROP_TRIG_REF,
11338 signal, DropTrigRef::SignalLength, JBB);
11339 return;
11340 }
11341
11342 // Release trigger record
11343 c_theDefinedTriggers.release(dropTrigReq->getTriggerId());
11344
11345 DropTrigConf * const dropTrigConf = (DropTrigConf *)&signal->theData[0];
11346
11347 dropTrigConf->setConnectionPtr(dropTrigReq->getConnectionPtr());
11348 sendSignal(sender, GSN_DROP_TRIG_CONF,
11349 signal, DropTrigConf::SignalLength, JBB);
11350 }
11351
execCREATE_INDX_REQ(Signal * signal)11352 void Dbtc::execCREATE_INDX_REQ(Signal* signal)
11353 {
11354 jamEntry();
11355 CreateIndxReq * const createIndxReq =
11356 (CreateIndxReq *)signal->getDataPtr();
11357 TcIndexData* indexData;
11358 TcIndexDataPtr indexPtr;
11359 BlockReference sender = signal->senderBlockRef();
11360
11361 if (ERROR_INSERTED(8034) ||
11362 !c_theIndexes.seizeId(indexPtr, createIndxReq->getIndexId())) {
11363 jam();
11364 CLEAR_ERROR_INSERT_VALUE;
11365 // Failed to allocate index record
11366 CreateIndxRef * const createIndxRef =
11367 (CreateIndxRef *)&signal->theData[0];
11368
11369 createIndxRef->setConnectionPtr(createIndxReq->getConnectionPtr());
11370 createIndxRef->setErrorCode(CreateIndxRef::TooManyIndexes);
11371 releaseSections(signal);
11372 sendSignal(sender, GSN_CREATE_INDX_REF,
11373 signal, CreateIndxRef::SignalLength, JBB);
11374 return;
11375 }
11376 indexData = indexPtr.p;
11377 // Indexes always start in state IS_BUILDING
11378 // Will become IS_ONLINE in execALTER_INDX_REQ
11379 indexData->indexState = IS_BUILDING;
11380 indexData->indexId = indexPtr.i;
11381 indexData->primaryTableId = createIndxReq->getTableId();
11382
11383 // So far need only attribute count
11384 SegmentedSectionPtr ssPtr;
11385 signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
11386 SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
11387 r0.reset(); // undo implicit first()
11388 if (!r0.getWord(&indexData->attributeList.sz) ||
11389 !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
11390 ndbrequire(false);
11391 }
11392 indexData->primaryKeyPos = indexData->attributeList.sz;
11393
11394 releaseSections(signal);
11395
11396 CreateIndxConf * const createIndxConf =
11397 (CreateIndxConf *)&signal->theData[0];
11398
11399 createIndxConf->setConnectionPtr(createIndxReq->getConnectionPtr());
11400 createIndxConf->setTableId(createIndxReq->getTableId());
11401 createIndxConf->setIndexId(createIndxReq->getIndexId());
11402 sendSignal(sender, GSN_CREATE_INDX_CONF,
11403 signal, CreateIndxConf::SignalLength, JBB);
11404 }
11405
execALTER_INDX_REQ(Signal * signal)11406 void Dbtc::execALTER_INDX_REQ(Signal* signal)
11407 {
11408 jamEntry();
11409 AlterIndxReq * const alterIndxReq = (AlterIndxReq *)signal->getDataPtr();
11410 TcIndexData* indexData;
11411 //BlockReference sender = signal->senderBlockRef();
11412 BlockReference sender = (BlockReference) alterIndxReq->getUserRef();
11413 Uint32 connectionPtr = alterIndxReq->getConnectionPtr();
11414 AlterIndxReq::RequestType requestType = alterIndxReq->getRequestType();
11415 Uint32 tableId = alterIndxReq->getTableId();
11416 Uint32 indexId = alterIndxReq->getIndexId();
11417 bool online = (alterIndxReq->getOnline() == 1) ? true : false;
11418
11419 if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
11420 jam();
11421 // Failed to find index record
11422 AlterIndxRef * const alterIndxRef =
11423 (AlterIndxRef *)signal->getDataPtrSend();
11424
11425 alterIndxRef->setUserRef(reference());
11426 alterIndxRef->setConnectionPtr(connectionPtr);
11427 alterIndxRef->setRequestType(requestType);
11428 alterIndxRef->setTableId(tableId);
11429 alterIndxRef->setIndexId(indexId);
11430 alterIndxRef->setErrorCode(AlterIndxRef::IndexNotFound);
11431 alterIndxRef->setErrorLine(__LINE__);
11432 alterIndxRef->setErrorNode(getOwnNodeId());
11433 sendSignal(sender, GSN_ALTER_INDX_REF,
11434 signal, AlterIndxRef::SignalLength, JBB);
11435 return;
11436 }
11437 // Found index record, alter it's state
11438 if (online) {
11439 jam();
11440 indexData->indexState = IS_ONLINE;
11441 } else {
11442 jam();
11443 indexData->indexState = IS_BUILDING;
11444 }//if
11445 AlterIndxConf * const alterIndxConf =
11446 (AlterIndxConf *)signal->getDataPtrSend();
11447
11448 alterIndxConf->setUserRef(reference());
11449 alterIndxConf->setConnectionPtr(connectionPtr);
11450 alterIndxConf->setRequestType(requestType);
11451 alterIndxConf->setTableId(tableId);
11452 alterIndxConf->setIndexId(indexId);
11453 sendSignal(sender, GSN_ALTER_INDX_CONF,
11454 signal, AlterIndxConf::SignalLength, JBB);
11455 }
11456
execFIRE_TRIG_ORD(Signal * signal)11457 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
11458 {
11459 jamEntry();
11460 FireTrigOrd * const fireOrd = (FireTrigOrd *)signal->getDataPtr();
11461 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
11462 ApiConnectRecordPtr transPtr;
11463 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
11464 TcConnectRecordPtr opPtr;
11465 /**
11466 * TODO
11467 * Check transid,
11468 * Fix overload i.e invalid word count
11469 */
11470 TcFiredTriggerData key;
11471 key.fireingOperation = fireOrd->getConnectionPtr();
11472 key.nodeId = refToNode(signal->getSendersBlockRef());
11473 FiredTriggerPtr trigPtr;
11474 if(c_firedTriggerHash.find(trigPtr, key)){
11475
11476 c_firedTriggerHash.remove(trigPtr);
11477
11478 trigPtr.p->fragId= fireOrd->fragId;
11479 bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
11480 ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
11481 ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
11482 if(ok){
11483 opPtr.i = key.fireingOperation;
11484 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
11485 transPtr.i = opPtr.p->apiConnect;
11486 transPtr.p = &localApiConnectRecord[transPtr.i];
11487
11488 opPtr.p->noReceivedTriggers++;
11489 opPtr.p->triggerExecutionCount++;
11490
11491 // Insert fired trigger in execution queue
11492 transPtr.p->theFiredTriggers.add(trigPtr);
11493 if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
11494 executeTriggers(signal, &transPtr);
11495 }
11496 return;
11497 }
11498 jam();
11499 c_theFiredTriggerPool.release(trigPtr);
11500 }
11501 jam();
11502 /**
11503 * Failed to find record or invalid word counts
11504 */
11505 ndbrequire(false);
11506 }
11507
execTRIG_ATTRINFO(Signal * signal)11508 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
11509 {
11510 jamEntry();
11511 TrigAttrInfo * const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtr();
11512 Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
11513 const Uint32 *src = trigAttrInfo->getData();
11514 FiredTriggerPtr firedTrigPtr;
11515
11516 TcFiredTriggerData key;
11517 key.fireingOperation = trigAttrInfo->getConnectionPtr();
11518 key.nodeId = refToNode(signal->getSendersBlockRef());
11519 if(!c_firedTriggerHash.find(firedTrigPtr, key)){
11520 jam();
11521 if(!c_firedTriggerHash.seize(firedTrigPtr)){
11522 jam();
11523 /**
11524 * Will be handled when FIRE_TRIG_ORD arrives
11525 */
11526 ndbout_c("op: %d node: %d failed to seize",
11527 key.fireingOperation, key.nodeId);
11528 return;
11529 }
11530 ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
11531 firedTrigPtr.p->beforeValues.getSize() == 0 &&
11532 firedTrigPtr.p->afterValues.getSize() == 0);
11533
11534 firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
11535 firedTrigPtr.p->fireingOperation = key.fireingOperation;
11536 firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
11537 c_firedTriggerHash.add(firedTrigPtr);
11538 }
11539
11540 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
11541 switch (trigAttrInfo->getAttrInfoType()) {
11542 case(TrigAttrInfo::PRIMARY_KEY):
11543 jam();
11544 {
11545 LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
11546 buf.append(src, attrInfoLength);
11547 }
11548 break;
11549 case(TrigAttrInfo::BEFORE_VALUES):
11550 jam();
11551 {
11552 LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
11553 buf.append(src, attrInfoLength);
11554 }
11555 break;
11556 case(TrigAttrInfo::AFTER_VALUES):
11557 jam();
11558 {
11559 LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
11560 buf.append(src, attrInfoLength);
11561 }
11562 break;
11563 default:
11564 ndbrequire(false);
11565 }
11566 }
11567
execDROP_INDX_REQ(Signal * signal)11568 void Dbtc::execDROP_INDX_REQ(Signal* signal)
11569 {
11570 jamEntry();
11571 DropIndxReq * const dropIndxReq = (DropIndxReq *)signal->getDataPtr();
11572 TcIndexData* indexData;
11573 BlockReference sender = signal->senderBlockRef();
11574
11575 if (ERROR_INSERTED(8036) ||
11576 (indexData = c_theIndexes.getPtr(dropIndxReq->getIndexId())) == NULL) {
11577 jam();
11578 CLEAR_ERROR_INSERT_VALUE;
11579 // Failed to find index record
11580 DropIndxRef * const dropIndxRef =
11581 (DropIndxRef *)signal->getDataPtrSend();
11582
11583 dropIndxRef->setConnectionPtr(dropIndxReq->getConnectionPtr());
11584 dropIndxRef->setErrorCode(DropIndxRef::IndexNotFound);
11585 sendSignal(sender, GSN_DROP_INDX_REF,
11586 signal, DropIndxRef::SignalLength, JBB);
11587 return;
11588 }
11589 // Release index record
11590 c_theIndexes.release(dropIndxReq->getIndexId());
11591
11592 DropIndxConf * const dropIndxConf =
11593 (DropIndxConf *)signal->getDataPtrSend();
11594
11595 dropIndxConf->setConnectionPtr(dropIndxReq->getConnectionPtr());
11596 sendSignal(sender, GSN_DROP_INDX_CONF,
11597 signal, DropIndxConf::SignalLength, JBB);
11598 }
11599
execTCINDXREQ(Signal * signal)11600 void Dbtc::execTCINDXREQ(Signal* signal)
11601 {
11602 jamEntry();
11603
11604 TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
11605 const UintR TapiIndex = tcIndxReq->apiConnectPtr;
11606 Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
11607 Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
11608 Uint32 * dataPtr = &tcIndxReq->scanInfo;
11609 Uint32 indexBufSize = 8; // Maximum for index in TCINDXREQ
11610 Uint32 attrBufSize = 5; // Maximum for attrInfo in TCINDXREQ
11611 ApiConnectRecordPtr transPtr;
11612 transPtr.i = TapiIndex;
11613 if (transPtr.i >= capiConnectFilesize) {
11614 jam();
11615 warningHandlerLab(signal, __LINE__);
11616 return;
11617 }//if
11618 ptrAss(transPtr, apiConnectRecord);
11619 ApiConnectRecord * const regApiPtr = transPtr.p;
11620 // Seize index operation
11621 TcIndexOperationPtr indexOpPtr;
11622 if ((startFlag == 1) &&
11623 (regApiPtr->apiConnectstate == CS_CONNECTED ||
11624 (regApiPtr->apiConnectstate == CS_STARTED &&
11625 regApiPtr->firstTcConnect == RNIL)) ||
11626 (regApiPtr->apiConnectstate == CS_ABORTING &&
11627 regApiPtr->abortState == AS_IDLE)) {
11628 jam();
11629 // This is a newly started transaction, clean-up
11630 releaseAllSeizedIndexOperations(regApiPtr);
11631
11632 regApiPtr->apiConnectstate = CS_STARTED;
11633 regApiPtr->transid[0] = tcIndxReq->transId1;
11634 regApiPtr->transid[1] = tcIndxReq->transId2;
11635 }//if
11636
11637 if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
11638 getNodeState().getSingleUserApi() !=
11639 refToNode(regApiPtr->ndbapiBlockref))
11640 {
11641 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
11642 regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
11643 apiConnectptr = transPtr;
11644 abortErrorLab(signal);
11645 return;
11646 }
11647
11648 if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
11649 jam();
11650 // Failed to allocate index operation
11651 terrorCode = 288;
11652 regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
11653 apiConnectptr = transPtr;
11654 abortErrorLab(signal);
11655 return;
11656 }
11657 TcIndexOperation* indexOp = indexOpPtr.p;
11658 indexOp->indexOpId = indexOpPtr.i;
11659
11660 // Save original signal
11661 indexOp->tcIndxReq = *tcIndxReq;
11662 indexOp->connectionIndex = TapiIndex;
11663 regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
11664
11665 // If operation is readTupleExclusive or updateTuple then read index
11666 // table with exclusive lock
11667 Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
11668 Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
11669 indexOp->expectedKeyInfo = indexLength;
11670 Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
11671 indexOp->expectedAttrInfo = attrLength;
11672 Uint32 includedAttrLength = MIN(attrLength, attrBufSize);
11673
11674 int ret;
11675 if ((ret = saveINDXKEYINFO(signal,
11676 indexOp,
11677 dataPtr,
11678 includedIndexLength)) == 0)
11679 {
11680 jam();
11681 // We have received all we need
11682 readIndexTable(signal, regApiPtr, indexOp);
11683 return;
11684 }
11685 else if (ret == -1)
11686 {
11687 jam();
11688 return;
11689 }
11690
11691 dataPtr += includedIndexLength;
11692 if (saveINDXATTRINFO(signal,
11693 indexOp,
11694 dataPtr,
11695 includedAttrLength) == 0) {
11696 jam();
11697 // We have received all we need
11698 readIndexTable(signal, regApiPtr, indexOp);
11699 return;
11700 }
11701 }
11702
11703
sendTcIndxConf(Signal * signal,UintR TcommitFlag)11704 void Dbtc::sendTcIndxConf(Signal* signal, UintR TcommitFlag)
11705 {
11706 HostRecordPtr localHostptr;
11707 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
11708 const UintR TopWords = (UintR)regApiPtr->tcindxrec;
11709 localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
11710 const Uint32 type = getNodeInfo(localHostptr.i).m_type;
11711 const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
11712 const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
11713 const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL ? 0 : 1);
11714 ptrAss(localHostptr, hostRecord);
11715 UintR TcurrLen = localHostptr.p->noOfWordsTCINDXCONF;
11716 UintR confInfo = 0;
11717 TcIndxConf::setNoOfOperations(confInfo, (TopWords >> 1));
11718 TcIndxConf::setCommitFlag(confInfo, TcommitFlag == 1);
11719 TcIndxConf::setMarkerFlag(confInfo, Tmarker);
11720 const UintR TpacketLen = 6 + TopWords;
11721 regApiPtr->tcindxrec = 0;
11722
11723 if(TcommitFlag || (regApiPtr->lqhkeyreqrec == regApiPtr->lqhkeyconfrec)){
11724 jam();
11725 regApiPtr->m_exec_flag = 0;
11726 }
11727
11728 if ((TpacketLen > 25) || !is_api){
11729 TcIndxConf * const tcIndxConf = (TcIndxConf *)signal->getDataPtrSend();
11730
11731 jam();
11732 tcIndxConf->apiConnectPtr = regApiPtr->ndbapiConnect;
11733 tcIndxConf->gci = regApiPtr->globalcheckpointid;;
11734 tcIndxConf->confInfo = confInfo;
11735 tcIndxConf->transId1 = regApiPtr->transid[0];
11736 tcIndxConf->transId2 = regApiPtr->transid[1];
11737 copyFromToLen(®ApiPtr->tcIndxSendArray[0],
11738 (UintR*)&tcIndxConf->operations,
11739 (UintR)ZTCOPCONF_SIZE);
11740 sendSignal(regApiPtr->ndbapiBlockref,
11741 GSN_TCINDXCONF, signal, (TpacketLen - 1), JBB);
11742 return;
11743 } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
11744 jam();
11745 sendPackedTCINDXCONF(signal, localHostptr.p, localHostptr.i);
11746 TcurrLen = 0;
11747 } else {
11748 jam();
11749 updatePackedList(signal, localHostptr.p, localHostptr.i);
11750 }//if
11751 // -------------------------------------------------------------------------
11752 // The header contains the block reference of receiver plus the real signal
11753 // length - 3, since we have the real signal length plus one additional word
11754 // for the header we have to do - 4.
11755 // -------------------------------------------------------------------------
11756 UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
11757 UintR Tpack1 = regApiPtr->ndbapiConnect;
11758 UintR Tpack2 = regApiPtr->globalcheckpointid;
11759 UintR Tpack3 = confInfo;
11760 UintR Tpack4 = regApiPtr->transid[0];
11761 UintR Tpack5 = regApiPtr->transid[1];
11762
11763 localHostptr.p->noOfWordsTCINDXCONF = TcurrLen + TpacketLen;
11764
11765 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 0] = Tpack0;
11766 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 1] = Tpack1;
11767 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 2] = Tpack2;
11768 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 3] = Tpack3;
11769 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 4] = Tpack4;
11770 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 5] = Tpack5;
11771
11772 UintR Ti;
11773 for (Ti = 6; Ti < TpacketLen; Ti++) {
11774 localHostptr.p->packedWordsTCINDXCONF[TcurrLen + Ti] =
11775 regApiPtr->tcIndxSendArray[Ti - 6];
11776 }//for
11777 }//Dbtc::sendTcIndxConf()
11778
execINDXKEYINFO(Signal * signal)11779 void Dbtc::execINDXKEYINFO(Signal* signal)
11780 {
11781 jamEntry();
11782 Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
11783 IndxKeyInfo * const indxKeyInfo = (IndxKeyInfo *)signal->getDataPtr();
11784 const Uint32 *src = indxKeyInfo->getData();
11785 const UintR TconnectIndex = indxKeyInfo->connectPtr;
11786 ApiConnectRecordPtr transPtr;
11787 transPtr.i = TconnectIndex;
11788 if (transPtr.i >= capiConnectFilesize) {
11789 jam();
11790 warningHandlerLab(signal, __LINE__);
11791 return;
11792 }//if
11793 ptrAss(transPtr, apiConnectRecord);
11794 ApiConnectRecord * const regApiPtr = transPtr.p;
11795 TcIndexOperationPtr indexOpPtr;
11796 TcIndexOperation* indexOp;
11797
11798 if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
11799 {
11800 TCKEY_abort(signal, 19);
11801 return;
11802 }
11803
11804 if (regApiPtr->apiConnectstate == CS_ABORTING)
11805 {
11806 jam();
11807 return;
11808 }
11809
11810 if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
11811 {
11812 indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
11813 if (saveINDXKEYINFO(signal,
11814 indexOp,
11815 src,
11816 keyInfoLength) == 0) {
11817 jam();
11818 // We have received all we need
11819 readIndexTable(signal, regApiPtr, indexOp);
11820 }
11821 }
11822 }
11823
execINDXATTRINFO(Signal * signal)11824 void Dbtc::execINDXATTRINFO(Signal* signal)
11825 {
11826 jamEntry();
11827 Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
11828 IndxAttrInfo * const indxAttrInfo = (IndxAttrInfo *)signal->getDataPtr();
11829 const Uint32 *src = indxAttrInfo->getData();
11830 const UintR TconnectIndex = indxAttrInfo->connectPtr;
11831 ApiConnectRecordPtr transPtr;
11832 transPtr.i = TconnectIndex;
11833 if (transPtr.i >= capiConnectFilesize) {
11834 jam();
11835 warningHandlerLab(signal, __LINE__);
11836 return;
11837 }//if
11838 ptrAss(transPtr, apiConnectRecord);
11839 ApiConnectRecord * const regApiPtr = transPtr.p;
11840 TcIndexOperationPtr indexOpPtr;
11841 TcIndexOperation* indexOp;
11842
11843 if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
11844 {
11845 TCKEY_abort(signal, 19);
11846 return;
11847 }
11848
11849 if (regApiPtr->apiConnectstate == CS_ABORTING)
11850 {
11851 jam();
11852 return;
11853 }
11854
11855 if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
11856 {
11857 indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
11858 if (saveINDXATTRINFO(signal,
11859 indexOp,
11860 src,
11861 attrInfoLength) == 0) {
11862 jam();
11863 // We have received all we need
11864 readIndexTable(signal, regApiPtr, indexOp);
11865 return;
11866 }
11867 return;
11868 }
11869 }
11870
11871 /**
11872 * Save signal INDXKEYINFO
11873 * Return true if we have received all needed data
11874 */
11875 int
saveINDXKEYINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)11876 Dbtc::saveINDXKEYINFO(Signal* signal,
11877 TcIndexOperation* indexOp,
11878 const Uint32 *src,
11879 Uint32 len)
11880 {
11881 if (ERROR_INSERTED(8052) || !indexOp->keyInfo.append(src, len)) {
11882 jam();
11883 // Failed to seize keyInfo, abort transaction
11884 #ifdef VM_TRACE
11885 ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize keyinfo\n");
11886 #endif
11887 // Abort transaction
11888 apiConnectptr.i = indexOp->connectionIndex;
11889 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11890 releaseIndexOperation(apiConnectptr.p, indexOp);
11891 terrorCode = 289;
11892 if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
11893 apiConnectptr.p->m_exec_flag= 1;
11894 abortErrorLab(signal);
11895 return -1;
11896 }
11897 if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
11898 jam();
11899 return 0;
11900 }
11901 return 1;
11902 }
11903
receivedAllINDXKEYINFO(TcIndexOperation * indexOp)11904 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
11905 {
11906 return (indexOp->keyInfo.getSize() == indexOp->expectedKeyInfo);
11907 }
11908
11909 /**
11910 * Save signal INDXATTRINFO
11911 * Return true if we have received all needed data
11912 */
11913 int
saveINDXATTRINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)11914 Dbtc::saveINDXATTRINFO(Signal* signal,
11915 TcIndexOperation* indexOp,
11916 const Uint32 *src,
11917 Uint32 len)
11918 {
11919 if (ERROR_INSERTED(8051) || !indexOp->attrInfo.append(src, len)) {
11920 jam();
11921 #ifdef VM_TRACE
11922 ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize attrInfo\n");
11923 #endif
11924 apiConnectptr.i = indexOp->connectionIndex;
11925 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11926 releaseIndexOperation(apiConnectptr.p, indexOp);
11927 terrorCode = 289;
11928 if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
11929 apiConnectptr.p->m_exec_flag= 1;
11930 abortErrorLab(signal);
11931 return -1;
11932 }
11933 if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
11934 jam();
11935 return 0;
11936 }
11937 return 1;
11938 }
11939
receivedAllINDXATTRINFO(TcIndexOperation * indexOp)11940 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
11941 {
11942 return (indexOp->attrInfo.getSize() == indexOp->expectedAttrInfo);
11943 }
11944
saveTRANSID_AI(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)11945 bool Dbtc::saveTRANSID_AI(Signal* signal,
11946 TcIndexOperation* indexOp,
11947 const Uint32 *src,
11948 Uint32 len)
11949 {
11950 Uint32 currentTransIdAILength = indexOp->transIdAI.getSize();
11951
11952 if (currentTransIdAILength == 0) {
11953 jam();
11954 // Read first AttributeHeader to get expected size
11955 // of the single key attribute expected
11956 AttributeHeader* head = (AttributeHeader *) src;
11957 indexOp->expectedTransIdAI = head->getHeaderSize() + head->getDataSize();
11958 }
11959 if (!indexOp->transIdAI.append(src, len)) {
11960 jam();
11961 #ifdef VM_TRACE
11962 ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize transIdAI\n");
11963 #endif
11964 apiConnectptr.i = indexOp->connectionIndex;
11965 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11966 releaseIndexOperation(apiConnectptr.p, indexOp);
11967 terrorCode = 4000;
11968 abortErrorLab(signal);
11969 return false;
11970 }
11971 return true;
11972 }
11973
receivedAllTRANSID_AI(TcIndexOperation * indexOp)11974 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
11975 {
11976 return (indexOp->transIdAI.getSize() == indexOp->expectedTransIdAI);
11977 }
11978
11979 /**
11980 * Receive signal TCINDXCONF
11981 * This can be either the return of reading an index table
11982 * or performing an index operation
11983 */
execTCKEYCONF(Signal * signal)11984 void Dbtc::execTCKEYCONF(Signal* signal)
11985 {
11986 TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtr();
11987 TcIndexOperationPtr indexOpPtr;
11988
11989 jamEntry();
11990 indexOpPtr.i = tcKeyConf->apiConnectPtr;
11991 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
11992 Uint32 confInfo = tcKeyConf->confInfo;
11993
11994 /**
11995 * Check on TCKEYCONF wheater the the transaction was committed
11996 */
11997 Uint32 Tcommit = TcKeyConf::getCommitFlag(confInfo);
11998
11999 indexOpPtr.p = indexOp;
12000 if (!indexOp) {
12001 jam();
12002 // Missing index operation
12003 return;
12004 }
12005 const UintR TconnectIndex = indexOp->connectionIndex;
12006 ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
12007 apiConnectptr.p = regApiPtr;
12008 apiConnectptr.i = TconnectIndex;
12009 switch(indexOp->indexOpState) {
12010 case(IOS_NOOP): {
12011 jam();
12012 // Should never happen, abort
12013 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12014
12015 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12016 tcIndxRef->transId[0] = regApiPtr->transid[0];
12017 tcIndxRef->transId[1] = regApiPtr->transid[1];
12018 tcIndxRef->errorCode = 4349;
12019 tcIndxRef->errorData = 0;
12020 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12021 TcKeyRef::SignalLength, JBB);
12022 return;
12023 }
12024 case(IOS_INDEX_ACCESS): {
12025 jam();
12026 // Wait for TRANSID_AI
12027 indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
12028 break;
12029 }
12030 case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
12031 jam();
12032 // Double TCKEYCONF, should never happen, abort
12033 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12034
12035 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12036 tcIndxRef->transId[0] = regApiPtr->transid[0];
12037 tcIndxRef->transId[1] = regApiPtr->transid[1];
12038 tcIndxRef->errorCode = 4349;
12039 tcIndxRef->errorData = 0;
12040 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12041 TcKeyRef::SignalLength, JBB);
12042 return;
12043 }
12044 case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
12045 jam();
12046 // Continue with index operation
12047 executeIndexOperation(signal, regApiPtr, indexOp);
12048 break;
12049 }
12050 case(IOS_INDEX_OPERATION): {
12051 // We are done, send TCINDXCONF
12052 jam();
12053 Uint32 Ttcindxrec = regApiPtr->tcindxrec;
12054 // Copy reply from TcKeyConf
12055
12056 ndbassert(regApiPtr->noIndexOp);
12057 regApiPtr->noIndexOp--; // Decrease count
12058 regApiPtr->tcIndxSendArray[Ttcindxrec] = indexOp->tcIndxReq.senderData;
12059 regApiPtr->tcIndxSendArray[Ttcindxrec + 1] =
12060 tcKeyConf->operations[0].attrInfoLen;
12061 regApiPtr->tcindxrec = Ttcindxrec + 2;
12062 if (regApiPtr->noIndexOp == 0) {
12063 jam();
12064 sendTcIndxConf(signal, Tcommit);
12065 } else if (regApiPtr->tcindxrec == ZTCOPCONF_SIZE) {
12066 jam();
12067 sendTcIndxConf(signal, 0);
12068 }
12069 releaseIndexOperation(regApiPtr, indexOp);
12070 break;
12071 }
12072 }
12073 }
12074
execTCKEYREF(Signal * signal)12075 void Dbtc::execTCKEYREF(Signal* signal)
12076 {
12077 TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
12078 TcIndexOperationPtr indexOpPtr;
12079
12080 jamEntry();
12081 indexOpPtr.i = tcKeyRef->connectPtr;
12082 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
12083 indexOpPtr.p = indexOp;
12084 if (!indexOp) {
12085 jam();
12086 // Missing index operation
12087 return;
12088 }
12089 const UintR TconnectIndex = indexOp->connectionIndex;
12090 ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
12091
12092 switch(indexOp->indexOpState) {
12093 case(IOS_NOOP): {
12094 jam();
12095 // Should never happen, abort
12096 break;
12097 }
12098 case(IOS_INDEX_ACCESS):
12099 case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
12100 case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
12101 jam();
12102 /**
12103 * Increase count as it will be decreased below...
12104 * (and the code is written to handle failing lookup on "real" table
12105 * not lookup on index table)
12106 */
12107 regApiPtr->noIndexOp++;
12108 // else continue
12109 }
12110 case(IOS_INDEX_OPERATION): {
12111 // Send TCINDXREF
12112
12113 jam();
12114 TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
12115 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12116
12117 ndbassert(regApiPtr->noIndexOp);
12118 regApiPtr->noIndexOp--; // Decrease count
12119 tcIndxRef->connectPtr = tcIndxReq->senderData;
12120 tcIndxRef->transId[0] = tcKeyRef->transId[0];
12121 tcIndxRef->transId[1] = tcKeyRef->transId[1];
12122 tcIndxRef->errorCode = tcKeyRef->errorCode;
12123 tcIndxRef->errorData = 0;
12124
12125 releaseIndexOperation(regApiPtr, indexOp);
12126
12127 sendSignal(regApiPtr->ndbapiBlockref,
12128 GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
12129 return;
12130 }
12131 }
12132 }
12133
execTRANSID_AI_R(Signal * signal)12134 void Dbtc::execTRANSID_AI_R(Signal* signal){
12135 TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
12136 Uint32 sigLen = signal->length();
12137 Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
12138 Uint32 recBlockref = transIdAI->attrData[dataLen];
12139
12140 jamEntry();
12141
12142 /**
12143 * Forward signal to final destination
12144 * Truncate last word since that was used to hold the final dest.
12145 */
12146 sendSignal(recBlockref, GSN_TRANSID_AI,
12147 signal, sigLen - 1, JBB);
12148 }
12149
execKEYINFO20_R(Signal * signal)12150 void Dbtc::execKEYINFO20_R(Signal* signal){
12151 KeyInfo20 * const keyInfo = (KeyInfo20 *)signal->getDataPtr();
12152 Uint32 sigLen = signal->length();
12153 Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
12154 Uint32 recBlockref = keyInfo->keyData[dataLen];
12155
12156 jamEntry();
12157
12158 /**
12159 * Forward signal to final destination
12160 * Truncate last word since that was used to hold the final dest.
12161 */
12162 sendSignal(recBlockref, GSN_KEYINFO20,
12163 signal, sigLen - 1, JBB);
12164 }
12165
12166
execTRANSID_AI(Signal * signal)12167 void Dbtc::execTRANSID_AI(Signal* signal)
12168 {
12169 TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
12170
12171 jamEntry();
12172 TcIndexOperationPtr indexOpPtr;
12173 indexOpPtr.i = transIdAI->connectPtr;
12174 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
12175 indexOpPtr.p = indexOp;
12176 if (!indexOp) {
12177 jam();
12178 // Missing index operation
12179 }
12180 const UintR TconnectIndex = indexOp->connectionIndex;
12181 // ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
12182 ApiConnectRecordPtr transPtr;
12183
12184 transPtr.i = TconnectIndex;
12185 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
12186 ApiConnectRecord * const regApiPtr = transPtr.p;
12187
12188 // Acccumulate attribute data
12189 if (!saveTRANSID_AI(signal,
12190 indexOp,
12191 transIdAI->getData(),
12192 signal->getLength() - TransIdAI::HeaderLength)) {
12193 jam();
12194 // Failed to allocate space for TransIdAI
12195 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12196
12197 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12198 tcIndxRef->transId[0] = regApiPtr->transid[0];
12199 tcIndxRef->transId[1] = regApiPtr->transid[1];
12200 tcIndxRef->errorCode = 4000;
12201 tcIndxRef->errorData = 0;
12202 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12203 TcKeyRef::SignalLength, JBB);
12204 return;
12205 }
12206
12207 switch(indexOp->indexOpState) {
12208 case(IOS_NOOP): {
12209 jam();
12210 // Should never happen, abort
12211 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12212
12213 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12214 tcIndxRef->transId[0] = regApiPtr->transid[0];
12215 tcIndxRef->transId[1] = regApiPtr->transid[1];
12216 tcIndxRef->errorCode = 4349;
12217 tcIndxRef->errorData = 0;
12218 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12219 TcKeyRef::SignalLength, JBB);
12220 return;
12221 break;
12222 }
12223 case(IOS_INDEX_ACCESS): {
12224 jam();
12225 // Check if all TRANSID_AI have been received
12226 if (receivedAllTRANSID_AI(indexOp)) {
12227 jam();
12228 // Wait for TRANSID_AI
12229 indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
12230 }
12231 break;
12232 }
12233 case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
12234 jam();
12235 #ifdef VM_TRACE
12236 ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
12237 #endif
12238 /*
12239 // Too many TRANSID_AI
12240 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12241
12242 tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
12243 tcIndxRef->transId[0] = regApiPtr->transid[0];
12244 tcIndxRef->transId[1] = regApiPtr->transid[1];
12245 tcIndxRef->errorCode = 4349;
12246 tcIndxRef->errorData = 0;
12247 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12248 TcKeyRef::SignalLength, JBB);
12249 */
12250 break;
12251 }
12252 case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
12253 jam();
12254 // Check if all TRANSID_AI have been received
12255 if (receivedAllTRANSID_AI(indexOp)) {
12256 jam();
12257 // Continue with index operation
12258 executeIndexOperation(signal, regApiPtr, indexOp);
12259 }
12260 // else continue waiting for more TRANSID_AI
12261 break;
12262 }
12263 case(IOS_INDEX_OPERATION): {
12264 // Should never receive TRANSID_AI in this state!!
12265 jam();
12266 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12267
12268 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12269 tcIndxRef->transId[0] = regApiPtr->transid[0];
12270 tcIndxRef->transId[1] = regApiPtr->transid[1];
12271 tcIndxRef->errorCode = 4349;
12272 tcIndxRef->errorData = regApiPtr->errorData;
12273 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12274 TcKeyRef::SignalLength, JBB);
12275 return;
12276 }
12277 }
12278 }
12279
execTCROLLBACKREP(Signal * signal)12280 void Dbtc::execTCROLLBACKREP(Signal* signal)
12281 {
12282 TcRollbackRep* tcRollbackRep = (TcRollbackRep *)signal->getDataPtr();
12283 jamEntry();
12284 TcIndexOperationPtr indexOpPtr;
12285 indexOpPtr.i = tcRollbackRep->connectPtr;
12286 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
12287 indexOpPtr.p = indexOp;
12288 tcRollbackRep = (TcRollbackRep *)signal->getDataPtrSend();
12289 tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
12290 sendSignal(apiConnectptr.p->ndbapiBlockref,
12291 GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
12292 }
12293
12294 /**
12295 * Read index table with the index attributes as PK
12296 */
readIndexTable(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)12297 void Dbtc::readIndexTable(Signal* signal,
12298 ApiConnectRecord* regApiPtr,
12299 TcIndexOperation* indexOp)
12300 {
12301 Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
12302 Uint32 dataPos = 0;
12303 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
12304 Uint32 * dataPtr = &tcKeyReq->scanInfo;
12305 Uint32 tcKeyLength = TcKeyReq::StaticLength;
12306 Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
12307 AttributeBuffer::DataBufferIterator keyIter;
12308 Uint32 keyLength = TcKeyReq::getKeyLength(tcKeyRequestInfo);
12309 TcIndexData* indexData;
12310 Uint32 transId1 = indexOp->tcIndxReq.transId1;
12311 Uint32 transId2 = indexOp->tcIndxReq.transId2;
12312
12313 const Operation_t opType =
12314 (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
12315
12316 // Find index table
12317 if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
12318 jam();
12319 // Failed to find index record
12320 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12321
12322 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12323 tcIndxRef->transId[0] = regApiPtr->transid[0];
12324 tcIndxRef->transId[1] = regApiPtr->transid[1];
12325 tcIndxRef->errorCode = 4000;
12326 // tcIndxRef->errorData = ??; Where to find indexId
12327 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12328 TcKeyRef::SignalLength, JBB);
12329 return;
12330 }
12331 tcKeyReq->transId1 = transId1;
12332 tcKeyReq->transId2 = transId2;
12333 tcKeyReq->tableId = indexData->indexId;
12334 tcKeyLength += MIN(keyLength, keyBufSize);
12335 tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
12336 TcKeyReq::setOperationType(tcKeyRequestInfo,
12337 opType == ZREAD ? ZREAD : ZREAD_EX);
12338 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
12339 TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
12340 tcKeyReq->senderData = indexOp->indexOpId;
12341 indexOp->indexOpState = IOS_INDEX_ACCESS;
12342 regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
12343 regApiPtr->accumulatingIndexOp = RNIL;
12344 regApiPtr->isIndexOp = 2;
12345
12346 if (ERROR_INSERTED(8037))
12347 {
12348 ndbout_c("shifting index version");
12349 tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
12350 }
12351
12352 Uint32 remainingKey = indexOp->keyInfo.getSize();
12353 bool moreKeyData = indexOp->keyInfo.first(keyIter);
12354 // *********** KEYINFO in TCKEYREQ ***********
12355 while((dataPos < keyBufSize) &&
12356 (remainingKey-- != 0)) {
12357 *dataPtr++ = *keyIter.data;
12358 dataPos++;
12359 moreKeyData = indexOp->keyInfo.next(keyIter);
12360 }
12361 // *********** ATTRINFO in TCKEYREQ ***********
12362 tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
12363 AttributeHeader::init(dataPtr, indexData->primaryKeyPos, 0);
12364 tcKeyLength++;
12365 tcKeyReq->requestInfo = tcKeyRequestInfo;
12366
12367 ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
12368 ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
12369 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
12370 jamEntry();
12371
12372 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12373 {
12374 goto err;
12375 }
12376
12377 // *********** KEYINFO ***********
12378 if (moreKeyData) {
12379 jam();
12380 // Send KEYINFO sequence
12381 KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
12382
12383 keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
12384 keyInfo->transId[0] = transId1;
12385 keyInfo->transId[1] = transId2;
12386 dataPtr = (Uint32 *) &keyInfo->keyData;
12387 dataPos = 0;
12388 while(remainingKey-- != 0) {// If we have not read complete key
12389 *dataPtr++ = *keyIter.data;
12390 dataPos++;
12391 if (dataPos == KeyInfo::DataLength) {
12392 // Flush KEYINFO
12393 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12394 KeyInfo::HeaderLength + KeyInfo::DataLength);
12395 jamEntry();
12396 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12397 {
12398 goto err;
12399 }
12400 dataPos = 0;
12401 dataPtr = (Uint32 *) &keyInfo->keyData;
12402 }
12403 moreKeyData = indexOp->keyInfo.next(keyIter);
12404 }
12405 if (dataPos != 0) {
12406 // Flush last KEYINFO
12407 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12408 KeyInfo::HeaderLength + dataPos);
12409 jamEntry();
12410 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12411 {
12412 goto err;
12413 }
12414 }
12415 }
12416
12417 /**
12418 * "Fool" TC not to start commiting transaction since it always will
12419 * have one outstanding lqhkeyreq
12420 * This is later decreased when the index read is complete
12421 */
12422 regApiPtr->lqhkeyreqrec++;
12423
12424 /**
12425 * Remember ptr to index read operation
12426 * (used to set correct save point id on index operation later)
12427 */
12428 indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
12429
12430 done:
12431 return;
12432
12433 err:
12434 jam();
12435 goto done;
12436 }
12437
12438 /**
12439 * Execute the index operation with the result from
12440 * the index table read as PK
12441 */
executeIndexOperation(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)12442 void Dbtc::executeIndexOperation(Signal* signal,
12443 ApiConnectRecord* regApiPtr,
12444 TcIndexOperation* indexOp) {
12445
12446 Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
12447 Uint32 attrBufSize = 5;
12448 Uint32 dataPos = 0;
12449 TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
12450 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
12451 /*
12452 Data points to distrGroupHashValue since scanInfo is used to send
12453 fragment id of receiving fragment
12454 */
12455 Uint32 * dataPtr = &tcKeyReq->distrGroupHashValue;
12456 Uint32 tcKeyLength = TcKeyReq::StaticLength;
12457 Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
12458 TcIndexData* indexData;
12459 AttributeBuffer::DataBufferIterator attrIter;
12460 AttributeBuffer::DataBufferIterator aiIter;
12461 bool moreKeyData = indexOp->transIdAI.first(aiIter);
12462
12463 // Find index table
12464 if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
12465 jam();
12466 // Failed to find index record
12467 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12468
12469 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12470 tcIndxRef->transId[0] = regApiPtr->transid[0];
12471 tcIndxRef->transId[1] = regApiPtr->transid[1];
12472 tcIndxRef->errorCode = 4349;
12473 tcIndxRef->errorData = 0;
12474 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12475 TcKeyRef::SignalLength, JBB);
12476 return;
12477 }
12478 // Find schema version of primary table
12479 TableRecordPtr tabPtr;
12480 tabPtr.i = indexData->primaryTableId;
12481 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
12482
12483 tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
12484 tcKeyReq->attrLen = tcIndxReq->attrLen;
12485 tcKeyReq->tableId = indexData->primaryTableId;
12486 tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
12487 tcKeyReq->transId1 = regApiPtr->transid[0];
12488 tcKeyReq->transId2 = regApiPtr->transid[1];
12489 tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
12490 indexOp->indexOpState = IOS_INDEX_OPERATION;
12491 regApiPtr->isIndexOp = 1;
12492 regApiPtr->executingIndexOp = indexOp->indexOpId;;
12493 regApiPtr->noIndexOp++; // Increase count
12494
12495 /*
12496 Filter out AttributeHeader:s since this should not be in key.
12497 Also filter out fragment id from primary key and handle that
12498 separately by setting it as Distribution Key and set indicator.
12499 */
12500
12501 AttributeHeader* attrHeader = (AttributeHeader *) aiIter.data;
12502
12503 Uint32 headerSize = attrHeader->getHeaderSize();
12504 Uint32 keySize = attrHeader->getDataSize() - 1;
12505 TcKeyReq::setKeyLength(tcKeyRequestInfo, keySize);
12506 // Skip header
12507 if (headerSize == 1) {
12508 jam();
12509 moreKeyData = indexOp->transIdAI.next(aiIter);
12510 } else {
12511 jam();
12512 moreKeyData = indexOp->transIdAI.next(aiIter, headerSize - 1);
12513 }//if
12514 tcKeyReq->scanInfo = *aiIter.data; //Fragment Id
12515 moreKeyData = indexOp->transIdAI.next(aiIter);
12516 TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
12517 while(// If we have not read complete key
12518 (keySize != 0) &&
12519 (dataPos < keyBufSize)) {
12520 *dataPtr++ = *aiIter.data;
12521 dataPos++;
12522 keySize--;
12523 moreKeyData = indexOp->transIdAI.next(aiIter);
12524 }
12525 tcKeyLength += dataPos;
12526
12527 Uint32 attributesLength = indexOp->attrInfo.getSize();
12528 if (attributesLength <= attrBufSize) {
12529 jam();
12530 // ATTRINFO fits in TCKEYREQ
12531 // Pack ATTRINFO IN TCKEYREQ
12532 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, indexOp->attrInfo.getSize());
12533 // Insert IndxAttrInfo
12534 for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
12535 moreAttrData;
12536 moreAttrData = indexOp->attrInfo.next(attrIter)) {
12537 *dataPtr++ = *attrIter.data;
12538 }
12539 tcKeyLength += attributesLength;
12540 } else {
12541 jam();
12542 // No ATTRINFO in TCKEYREQ
12543 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
12544 }
12545
12546 TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
12547 TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
12548 TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
12549 tcKeyReq->requestInfo = tcKeyRequestInfo;
12550
12551 ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
12552 ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
12553
12554 /**
12555 * Decrease lqhkeyreqrec to compensate for addition
12556 * during read of index table
12557 * I.e. let TC start committing when other operations has completed
12558 */
12559 regApiPtr->lqhkeyreqrec--;
12560
12561 /**
12562 * Fix savepoint id -
12563 * fix so that index operation has the same savepoint id
12564 * as the read of the index table (TCINDXREQ)
12565 */
12566 TcConnectRecordPtr tmp;
12567 tmp.i = indexOp->indexReadTcConnect;
12568 ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
12569 const Uint32 currSavePointId = regApiPtr->currSavePointId;
12570 regApiPtr->currSavePointId = tmp.p->savePointId;
12571 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
12572 jamEntry();
12573
12574 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12575 {
12576 jam();
12577 return;
12578 }
12579
12580 regApiPtr->currSavePointId = currSavePointId;
12581
12582 // *********** KEYINFO ***********
12583 if (moreKeyData) {
12584 jam();
12585 // Send KEYINFO sequence
12586 KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
12587
12588 keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
12589 keyInfo->transId[0] = regApiPtr->transid[0];
12590 keyInfo->transId[1] = regApiPtr->transid[1];
12591 dataPtr = (Uint32 *) &keyInfo->keyData;
12592 dataPos = 0;
12593 // Pack any part of a key attribute that did no fit TCKEYREQ
12594 while(keySize-- != 0) {// If we have not read complete key
12595 *dataPtr++ = *aiIter.data;
12596 dataPos++;
12597 if (dataPos == KeyInfo::DataLength) {
12598 // Flush KEYINFO
12599 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12600 KeyInfo::HeaderLength + KeyInfo::DataLength);
12601 jamEntry();
12602
12603 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12604 {
12605 jam();
12606 return;
12607 }
12608
12609 dataPos = 0;
12610 dataPtr = (Uint32 *) &keyInfo->keyData;
12611 }
12612 moreKeyData = indexOp->transIdAI.next(aiIter);
12613 }
12614 if (dataPos != 0) {
12615 // Flush last KEYINFO
12616 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12617 KeyInfo::HeaderLength + dataPos);
12618 jamEntry();
12619
12620 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12621 {
12622 jam();
12623 return;
12624 }
12625 }
12626 }
12627
12628 // *********** ATTRINFO ***********
12629 if (attributesLength > attrBufSize) {
12630 jam();
12631 // No ATTRINFO in TcKeyReq
12632 TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
12633 // Send ATTRINFO sequence
12634 AttrInfo * const attrInfo = (AttrInfo *)signal->getDataPtrSend();
12635 Uint32 attrInfoPos = 0;
12636
12637 attrInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
12638 attrInfo->transId[0] = regApiPtr->transid[0];
12639 attrInfo->transId[1] = regApiPtr->transid[1];
12640 dataPtr = (Uint32 *) &attrInfo->attrData;
12641
12642
12643 // Insert attribute values (insert key values of primary table)
12644 for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
12645 moreAttrData;
12646 moreAttrData = indexOp->attrInfo.next(attrIter)) {
12647 *dataPtr++ = *attrIter.data;
12648 attrInfoPos++;
12649 if (attrInfoPos == AttrInfo::DataLength) {
12650 // Flush ATTRINFO
12651 EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
12652 AttrInfo::HeaderLength + AttrInfo::DataLength);
12653 jamEntry();
12654
12655 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12656 {
12657 jam();
12658 return;
12659 }
12660
12661 attrInfoPos = 0;
12662 dataPtr = (Uint32 *) &attrInfo->attrData;
12663 }
12664 }
12665 if (attrInfoPos != 0) {
12666 // Send last ATTRINFO
12667 EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
12668 AttrInfo::HeaderLength + attrInfoPos);
12669 jamEntry();
12670 }
12671 }
12672 }
12673
seizeIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperationPtr & indexOpPtr)12674 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
12675 TcIndexOperationPtr& indexOpPtr)
12676 {
12677 if (regApiPtr->theSeizedIndexOperations.seize(indexOpPtr))
12678 {
12679 ndbassert(indexOpPtr.p->expectedKeyInfo == 0);
12680 ndbassert(indexOpPtr.p->keyInfo.getSize() == 0);
12681 ndbassert(indexOpPtr.p->expectedAttrInfo == 0);
12682 ndbassert(indexOpPtr.p->attrInfo.getSize() == 0);
12683 ndbassert(indexOpPtr.p->expectedTransIdAI == 0);
12684 ndbassert(indexOpPtr.p->transIdAI.getSize() == 0);
12685 return true;
12686 }
12687
12688 return false;
12689 }
12690
releaseIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)12691 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
12692 TcIndexOperation* indexOp)
12693 {
12694 indexOp->indexOpState = IOS_NOOP;
12695 indexOp->expectedKeyInfo = 0;
12696 indexOp->keyInfo.release();
12697 indexOp->expectedAttrInfo = 0;
12698 indexOp->attrInfo.release();
12699 indexOp->expectedTransIdAI = 0;
12700 indexOp->transIdAI.release();
12701 regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
12702 }
12703
releaseAllSeizedIndexOperations(ApiConnectRecord * regApiPtr)12704 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
12705 {
12706 TcIndexOperationPtr seizedIndexOpPtr;
12707
12708 regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
12709 while(seizedIndexOpPtr.i != RNIL) {
12710 jam();
12711 TcIndexOperation* indexOp = seizedIndexOpPtr.p;
12712
12713 indexOp->indexOpState = IOS_NOOP;
12714 indexOp->expectedKeyInfo = 0;
12715 indexOp->keyInfo.release();
12716 indexOp->expectedAttrInfo = 0;
12717 indexOp->attrInfo.release();
12718 indexOp->expectedTransIdAI = 0;
12719 indexOp->transIdAI.release();
12720 regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
12721 }
12722 regApiPtr->theSeizedIndexOperations.release();
12723 }
12724
saveTriggeringOpState(Signal * signal,TcConnectRecord * trigOp)12725 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
12726 {
12727 LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
12728 copyFromToLen((UintR*)lqhKeyConf,
12729 &trigOp->savedState[0],
12730 LqhKeyConf::SignalLength);
12731 }
12732
continueTriggeringOp(Signal * signal,TcConnectRecord * trigOp)12733 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
12734 {
12735 LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
12736 copyFromToLen(&trigOp->savedState[0],
12737 (UintR*)lqhKeyConf,
12738 LqhKeyConf::SignalLength);
12739
12740 lqhKeyConf->noFiredTriggers = 0;
12741 trigOp->noReceivedTriggers = 0;
12742
12743 // All triggers executed successfully, continue operation
12744 execLQHKEYCONF(signal);
12745 }
12746
scheduleFiredTrigger(ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)12747 void Dbtc::scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
12748 TcConnectRecordPtr* opPtr)
12749 {
12750 // Set initial values for trigger fireing operation
12751 opPtr->p->triggerExecutionCount++;
12752
12753 // Insert fired trigger in execution queue
12754 transPtr->p->theFiredTriggers.add(opPtr->p->accumulatingTriggerData);
12755 opPtr->p->accumulatingTriggerData.i = RNIL;
12756 opPtr->p->accumulatingTriggerData.p = NULL;
12757 }
12758
executeTriggers(Signal * signal,ApiConnectRecordPtr * transPtr)12759 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
12760 {
12761 ApiConnectRecord* regApiPtr = transPtr->p;
12762 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
12763 TcConnectRecordPtr opPtr;
12764 FiredTriggerPtr trigPtr;
12765
12766 if (!regApiPtr->theFiredTriggers.isEmpty()) {
12767 jam();
12768 if ((regApiPtr->apiConnectstate == CS_STARTED) ||
12769 (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
12770 jam();
12771 regApiPtr->theFiredTriggers.first(trigPtr);
12772 while (trigPtr.i != RNIL) {
12773 jam();
12774 // Execute all ready triggers in parallel
12775 opPtr.i = trigPtr.p->fireingOperation;
12776 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
12777 FiredTriggerPtr nextTrigPtr = trigPtr;
12778 regApiPtr->theFiredTriggers.next(nextTrigPtr);
12779 if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
12780 jam();
12781 // Fireing operation is ready to have a trigger executing
12782 executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
12783 // Should allow for interleaving here by sending a CONTINUEB and
12784 // return
12785 // Release trigger records
12786 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
12787 LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
12788 tmp1.release();
12789 LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
12790 tmp2.release();
12791 LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
12792 tmp3.release();
12793 regApiPtr->theFiredTriggers.release(trigPtr);
12794 }
12795 trigPtr = nextTrigPtr;
12796 }
12797 return;
12798 // No more triggers, continue transaction after last executed trigger has
12799 // reurned (in execLQHKEYCONF or execLQHKEYREF)
12800 } else {
12801 // Wait until transaction is ready to execute a trigger
12802 jam();
12803 if (!regApiPtr->triggerPending) {
12804 jam();
12805 regApiPtr->triggerPending = true;
12806 signal->theData[0] = TcContinueB::TRIGGER_PENDING;
12807 signal->theData[1] = transPtr->i;
12808 sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
12809 }
12810 // else
12811 // We are already waiting for a pending trigger (CONTINUEB)
12812 }
12813 }
12814 }
12815
executeTrigger(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)12816 void Dbtc::executeTrigger(Signal* signal,
12817 TcFiredTriggerData* firedTriggerData,
12818 ApiConnectRecordPtr* transPtr,
12819 TcConnectRecordPtr* opPtr)
12820 {
12821 TcDefinedTriggerData* definedTriggerData;
12822
12823 if ((definedTriggerData =
12824 c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
12825 != NULL) {
12826 switch(definedTriggerData->triggerType) {
12827 case(TriggerType::SECONDARY_INDEX):
12828 jam();
12829 executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
12830 transPtr, opPtr);
12831 break;
12832 default:
12833 ndbrequire(false);
12834 }
12835 }
12836 }
12837
executeIndexTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)12838 void Dbtc::executeIndexTrigger(Signal* signal,
12839 TcDefinedTriggerData* definedTriggerData,
12840 TcFiredTriggerData* firedTriggerData,
12841 ApiConnectRecordPtr* transPtr,
12842 TcConnectRecordPtr* opPtr)
12843 {
12844 TcIndexData* indexData;
12845
12846 indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
12847 ndbassert(indexData != NULL);
12848
12849 switch (definedTriggerData->triggerEvent) {
12850 case(TriggerEvent::TE_INSERT): {
12851 jam();
12852 insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
12853 break;
12854 }
12855 case(TriggerEvent::TE_DELETE): {
12856 jam();
12857 deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
12858 break;
12859 }
12860 case(TriggerEvent::TE_UPDATE): {
12861 jam();
12862 deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr,
12863 indexData, true); // Hold the triggering operation
12864 insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
12865 break;
12866 }
12867 default:
12868 ndbrequire(false);
12869 }
12870 }
12871
releaseFiredTriggerData(DLFifoList<TcFiredTriggerData> * triggers)12872 void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
12873 {
12874 FiredTriggerPtr trigPtr;
12875
12876 triggers->first(trigPtr);
12877 while (trigPtr.i != RNIL) {
12878 jam();
12879 // Release trigger records
12880
12881 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
12882 LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
12883 tmp1.release();
12884 LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
12885 tmp2.release();
12886 LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
12887 tmp3.release();
12888
12889 triggers->next(trigPtr);
12890 }
12891 triggers->release();
12892 }
12893
insertIntoIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData,bool holdOperation)12894 void Dbtc::insertIntoIndexTable(Signal* signal,
12895 TcFiredTriggerData* firedTriggerData,
12896 ApiConnectRecordPtr* transPtr,
12897 TcConnectRecordPtr* opPtr,
12898 TcIndexData* indexData,
12899 bool holdOperation)
12900 {
12901 ApiConnectRecord* regApiPtr = transPtr->p;
12902 TcConnectRecord* opRecord = opPtr->p;
12903 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
12904 Uint32 tcKeyRequestInfo = 0;
12905 Uint32 tcKeyLength = TcKeyReq::StaticLength;
12906 TableRecordPtr indexTabPtr;
12907 AttributeBuffer::DataBufferIterator iter;
12908 Uint32 attrId = 0;
12909 Uint32 keyLength = 0;
12910 Uint32 totalPrimaryKeyLength = 1; // fragment length
12911 Uint32 hops;
12912
12913 indexTabPtr.i = indexData->indexId;
12914 ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
12915 tcKeyReq->apiConnectPtr = transPtr->i;
12916 tcKeyReq->senderData = opPtr->i;
12917 if (holdOperation) {
12918 jam();
12919 opRecord->triggerExecutionCount++;
12920 }//if
12921 // Calculate key length and renumber attribute id:s
12922 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
12923 LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
12924 bool skipNull = false;
12925 for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) {
12926 jam();
12927 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
12928
12929 // Filter out NULL valued attributes
12930 if (attrHeader->isNULL()) {
12931 skipNull = true;
12932 break;
12933 }
12934 attrHeader->setAttributeId(attrId);
12935 keyLength += attrHeader->getDataSize();
12936 hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
12937 moreKeyAttrs = afterValues.next(iter, hops);
12938 }
12939 if (skipNull) {
12940 jam();
12941 opRecord->triggerExecutionCount--;
12942 if (opRecord->triggerExecutionCount == 0) {
12943 /*
12944 We have completed current trigger execution
12945 Continue triggering operation
12946 */
12947 jam();
12948 continueTriggeringOp(signal, opRecord);
12949 }//if
12950 return;
12951 }//if
12952
12953 // Calculate total length of primary key to be stored in index table
12954 LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
12955 for(bool moreAttrData = keyValues.first(iter); moreAttrData; ) {
12956 jam();
12957 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
12958
12959 totalPrimaryKeyLength += attrHeader->getDataSize();
12960 hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
12961 moreAttrData = keyValues.next(iter, hops);
12962 }
12963 AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength << 2);
12964 Uint32 attributesLength = afterValues.getSize() +
12965 pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
12966
12967 TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
12968 tcKeyReq->attrLen = attributesLength;
12969 tcKeyReq->tableId = indexData->indexId;
12970 TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
12971 TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
12972 tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
12973 tcKeyReq->transId1 = regApiPtr->transid[0];
12974 tcKeyReq->transId2 = regApiPtr->transid[1];
12975 Uint32 * dataPtr = &tcKeyReq->scanInfo;
12976 // Write first part of key in TCKEYREQ
12977 Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
12978 Uint32 attrBufSize = 5; // Maximum for key in TCKEYREQ
12979 Uint32 dataPos = 0;
12980 // Filter out AttributeHeader:s since this should no be in key
12981 bool moreKeyData = afterValues.first(iter);
12982 Uint32 headerSize = 0, keyAttrSize = 0, dataSize = 0, headAndData = 0;
12983
12984 while (moreKeyData && (dataPos < keyBufSize)) {
12985 /*
12986 * If we have not read complete key
12987 * and it fits in the signal
12988 */
12989 jam();
12990 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
12991
12992 headerSize = attrHeader->getHeaderSize();
12993 keyAttrSize = attrHeader->getDataSize();
12994 headAndData = headerSize + attrHeader->getDataSize();
12995 // Skip header
12996 if (headerSize == 1) {
12997 jam();
12998 moreKeyData = afterValues.next(iter);
12999 } else {
13000 jam();
13001 moreKeyData = afterValues.next(iter, headerSize - 1);
13002 }//if
13003 while((keyAttrSize != 0) && (dataPos < keyBufSize)) {
13004 // If we have not read complete key
13005 jam();
13006 *dataPtr++ = *iter.data;
13007 dataPos++;
13008 keyAttrSize--;
13009 moreKeyData = afterValues.next(iter);
13010 }
13011 if (keyAttrSize != 0) {
13012 jam();
13013 break;
13014 }//if
13015 }
13016
13017 tcKeyLength += dataPos;
13018 /*
13019 Size of attrinfo is unique index attributes one by one, header for each
13020 of them (all contained in the afterValues data structure), plus a header,
13021 the primary key (compacted) and the fragment id before the primary key
13022 */
13023 if (attributesLength <= attrBufSize) {
13024 jam();
13025 // ATTRINFO fits in TCKEYREQ
13026 // Pack ATTRINFO IN TCKEYREQ as one attribute
13027 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, attributesLength);
13028 bool moreAttrData;
13029 // Insert primary key attributes (insert after values of primary table)
13030 for(moreAttrData = afterValues.first(iter);
13031 moreAttrData;
13032 moreAttrData = afterValues.next(iter)) {
13033 *dataPtr++ = *iter.data;
13034 }
13035 // Insert attribute values (insert key values of primary table)
13036 // as one attribute
13037 pkAttrHeader.insertHeader(dataPtr);
13038 dataPtr += pkAttrHeader.getHeaderSize();
13039 /*
13040 Insert fragment id before primary key as part of reference to tuple
13041 */
13042 *dataPtr++ = firedTriggerData->fragId;
13043 moreAttrData = keyValues.first(iter);
13044 while(moreAttrData) {
13045 jam();
13046 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13047
13048 headerSize = attrHeader->getHeaderSize();
13049 dataSize = attrHeader->getDataSize();
13050 // Skip header
13051 if (headerSize == 1) {
13052 jam();
13053 moreAttrData = keyValues.next(iter);
13054 } else {
13055 jam();
13056 moreAttrData = keyValues.next(iter, headerSize - 1);
13057 }//if
13058 // Copy attribute data
13059 while(dataSize-- != 0) {
13060 *dataPtr++ = *iter.data;
13061 moreAttrData = keyValues.next(iter);
13062 }
13063 }
13064 tcKeyLength += attributesLength;
13065 } else {
13066 jam();
13067 // No ATTRINFO in TCKEYREQ
13068 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
13069 }
13070 tcKeyReq->requestInfo = tcKeyRequestInfo;
13071
13072 /**
13073 * Fix savepoint id -
13074 * fix so that insert has same savepoint id as triggering operation
13075 */
13076 const Uint32 currSavePointId = regApiPtr->currSavePointId;
13077 regApiPtr->currSavePointId = opRecord->savePointId;
13078 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
13079 jamEntry();
13080
13081 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13082 {
13083 jam();
13084 return;
13085 }
13086
13087 regApiPtr->currSavePointId = currSavePointId;
13088 tcConnectptr.p->currentIndexId = indexData->indexId;
13089
13090 // *********** KEYINFO ***********
13091 if (moreKeyData) {
13092 jam();
13093 // Send KEYINFO sequence
13094 KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
13095
13096 keyInfo->connectPtr = transPtr->i;
13097 keyInfo->transId[0] = regApiPtr->transid[0];
13098 keyInfo->transId[1] = regApiPtr->transid[1];
13099 dataPtr = (Uint32 *) &keyInfo->keyData;
13100 dataPos = 0;
13101 // Pack any part of a key attribute that did no fit TCKEYREQ
13102 while((keyAttrSize != 0) && (dataPos < KeyInfo::DataLength)) {
13103 // If we have not read complete key
13104 *dataPtr++ = *iter.data;
13105 dataPos++;
13106 keyAttrSize--;
13107 if (dataPos == KeyInfo::DataLength) {
13108 jam();
13109 // Flush KEYINFO
13110 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13111 sendSignal(reference(), GSN_KEYINFO, signal,
13112 KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13113 #else
13114 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13115 KeyInfo::HeaderLength + KeyInfo::DataLength);
13116 jamEntry();
13117 #endif
13118 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13119 {
13120 jam();
13121 return;
13122 }
13123
13124 dataPtr = (Uint32 *) &keyInfo->keyData;
13125 dataPos = 0;
13126 }
13127 moreKeyData = afterValues.next(iter);
13128 }
13129
13130 while(moreKeyData) {
13131 jam();
13132 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13133
13134 headerSize = attrHeader->getHeaderSize();
13135 keyAttrSize = attrHeader->getDataSize();
13136 headAndData = headerSize + attrHeader->getDataSize();
13137 // Skip header
13138 if (headerSize == 1) {
13139 jam();
13140 moreKeyData = afterValues.next(iter);
13141 } else {
13142 jam();
13143 moreKeyData = afterValues.next(iter, headerSize - 1);
13144 }//if
13145 while (keyAttrSize-- != 0) {
13146 *dataPtr++ = *iter.data;
13147 dataPos++;
13148 if (dataPos == KeyInfo::DataLength) {
13149 jam();
13150 // Flush KEYINFO
13151 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13152 sendSignal(reference(), GSN_KEYINFO, signal,
13153 KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13154 #else
13155 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13156 KeyInfo::HeaderLength + KeyInfo::DataLength);
13157 jamEntry();
13158 #endif
13159
13160 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13161 {
13162 jam();
13163 return;
13164 }
13165
13166 dataPtr = (Uint32 *) &keyInfo->keyData;
13167 dataPos = 0;
13168 }
13169 moreKeyData = afterValues.next(iter);
13170 }
13171 }
13172 if (dataPos != 0) {
13173 jam();
13174 // Flush last KEYINFO
13175 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13176 sendSignal(reference(), GSN_KEYINFO, signal,
13177 KeyInfo::HeaderLength + dataPos, JBA);
13178 #else
13179 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13180 KeyInfo::HeaderLength + dataPos);
13181 jamEntry();
13182 #endif
13183 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13184 {
13185 jam();
13186 return;
13187 }
13188 }
13189 }
13190
13191 // *********** ATTRINFO ***********
13192 if (attributesLength > attrBufSize) {
13193 jam();
13194 // No ATTRINFO in TcKeyReq
13195 TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
13196 // Send ATTRINFO sequence
13197 AttrInfo * const attrInfo = (AttrInfo *)signal->getDataPtrSend();
13198 Uint32 attrInfoPos = 0;
13199
13200 attrInfo->connectPtr = transPtr->i;
13201 attrInfo->transId[0] = regApiPtr->transid[0];
13202 attrInfo->transId[1] = regApiPtr->transid[1];
13203 dataPtr = (Uint32 *) &attrInfo->attrData;
13204
13205 bool moreAttrData;
13206 // Insert primary key attributes (insert after values of primary table)
13207 for(moreAttrData = afterValues.first(iter);
13208 moreAttrData;
13209 moreAttrData = afterValues.next(iter)) {
13210 *dataPtr++ = *iter.data;
13211 attrInfoPos++;
13212 if (attrInfoPos == AttrInfo::DataLength) {
13213 jam();
13214 // Flush ATTRINFO
13215 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13216 sendSignal(reference(), GSN_ATTRINFO, signal,
13217 AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
13218 #else
13219 EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13220 AttrInfo::HeaderLength + AttrInfo::DataLength);
13221 jamEntry();
13222 #endif
13223 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13224 {
13225 jam();
13226 return;
13227 }
13228
13229 dataPtr = (Uint32 *) &attrInfo->attrData;
13230 attrInfoPos = 0;
13231 }
13232 }
13233 // Insert attribute values (insert key values of primary table)
13234 // as one attribute
13235 pkAttrHeader.insertHeader(dataPtr);
13236 dataPtr += pkAttrHeader.getHeaderSize();
13237 attrInfoPos += pkAttrHeader.getHeaderSize();
13238 /*
13239 Add fragment id before primary key
13240 TODO: This code really needs to be made into a long signal
13241 to remove this messy code.
13242 */
13243 if (attrInfoPos == AttrInfo::DataLength)
13244 {
13245 jam();
13246 // Flush ATTRINFO
13247 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13248 sendSignal(reference(), GSN_ATTRINFO, signal,
13249 AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
13250 #else
13251 EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13252 AttrInfo::HeaderLength + AttrInfo::DataLength);
13253 jamEntry();
13254 #endif
13255 dataPtr = (Uint32 *) &attrInfo->attrData;
13256 attrInfoPos = 0;
13257 }
13258 attrInfoPos++;
13259 *dataPtr++ = firedTriggerData->fragId;
13260
13261 moreAttrData = keyValues.first(iter);
13262 while(moreAttrData) {
13263 jam();
13264 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13265
13266 headerSize = attrHeader->getHeaderSize();
13267 dataSize = attrHeader->getDataSize();
13268 // Skip header
13269 if (headerSize == 1) {
13270 jam();
13271 moreAttrData = keyValues.next(iter);
13272 } else {
13273 jam();
13274 moreAttrData = keyValues.next(iter, headerSize - 1);
13275 }//if
13276 while(dataSize-- != 0) { // If we have not read complete key
13277 if (attrInfoPos == AttrInfo::DataLength) {
13278 jam();
13279 // Flush ATTRINFO
13280 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13281 sendSignal(reference(), GSN_ATTRINFO, signal,
13282 AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
13283 #else
13284 EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13285 AttrInfo::HeaderLength + AttrInfo::DataLength);
13286 jamEntry();
13287 #endif
13288 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13289 {
13290 jam();
13291 return;
13292 }
13293
13294 dataPtr = (Uint32 *) &attrInfo->attrData;
13295 attrInfoPos = 0;
13296 }
13297 *dataPtr++ = *iter.data;
13298 attrInfoPos++;
13299 moreAttrData = keyValues.next(iter);
13300 }
13301 }
13302 if (attrInfoPos != 0) {
13303 jam();
13304 // Flush last ATTRINFO
13305 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13306 sendSignal(reference(), GSN_ATTRINFO, signal,
13307 AttrInfo::HeaderLength + attrInfoPos, JBA);
13308 #else
13309 EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13310 AttrInfo::HeaderLength + attrInfoPos);
13311 jamEntry();
13312 #endif
13313 }
13314 }
13315 }
13316
deleteFromIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData,bool holdOperation)13317 void Dbtc::deleteFromIndexTable(Signal* signal,
13318 TcFiredTriggerData* firedTriggerData,
13319 ApiConnectRecordPtr* transPtr,
13320 TcConnectRecordPtr* opPtr,
13321 TcIndexData* indexData,
13322 bool holdOperation)
13323 {
13324 ApiConnectRecord* regApiPtr = transPtr->p;
13325 TcConnectRecord* opRecord = opPtr->p;
13326 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
13327 Uint32 tcKeyRequestInfo = 0;
13328 Uint32 tcKeyLength = 12; // Static length
13329 TableRecordPtr indexTabPtr;
13330 AttributeBuffer::DataBufferIterator iter;
13331 Uint32 attrId = 0;
13332 Uint32 keyLength = 0;
13333 Uint32 hops;
13334
13335 indexTabPtr.i = indexData->indexId;
13336 ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
13337 tcKeyReq->apiConnectPtr = transPtr->i;
13338 tcKeyReq->senderData = opPtr->i;
13339 if (holdOperation) {
13340 jam();
13341 opRecord->triggerExecutionCount++;
13342 }//if
13343 // Calculate key length and renumber attribute id:s
13344 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13345 LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
13346 bool skipNull = false;
13347 for(bool moreKeyAttrs = beforeValues.first(iter);
13348 (moreKeyAttrs);
13349 attrId++) {
13350 jam();
13351 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13352
13353 // Filter out NULL valued attributes
13354 if (attrHeader->isNULL()) {
13355 skipNull = true;
13356 break;
13357 }
13358 attrHeader->setAttributeId(attrId);
13359 keyLength += attrHeader->getDataSize();
13360 hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
13361 moreKeyAttrs = beforeValues.next(iter, hops);
13362 }
13363
13364 if (skipNull) {
13365 jam();
13366 opRecord->triggerExecutionCount--;
13367 if (opRecord->triggerExecutionCount == 0) {
13368 /*
13369 We have completed current trigger execution
13370 Continue triggering operation
13371 */
13372 jam();
13373 continueTriggeringOp(signal, opRecord);
13374 }//if
13375 return;
13376 }//if
13377
13378 TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
13379 tcKeyReq->attrLen = 0;
13380 tcKeyReq->tableId = indexData->indexId;
13381 TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
13382 TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
13383 tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
13384 tcKeyReq->transId1 = regApiPtr->transid[0];
13385 tcKeyReq->transId2 = regApiPtr->transid[1];
13386 Uint32 * dataPtr = &tcKeyReq->scanInfo;
13387 // Write first part of key in TCKEYREQ
13388 Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
13389 Uint32 dataPos = 0;
13390 // Filter out AttributeHeader:s since this should no be in key
13391 bool moreKeyData = beforeValues.first(iter);
13392 Uint32 headerSize = 0, keyAttrSize = 0, headAndData = 0;
13393
13394 while (moreKeyData &&
13395 (dataPos < keyBufSize)) {
13396 /*
13397 If we have not read complete key
13398 and it fits in the signal
13399 */
13400 jam();
13401 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13402
13403 headerSize = attrHeader->getHeaderSize();
13404 keyAttrSize = attrHeader->getDataSize();
13405 headAndData = headerSize + attrHeader->getDataSize();
13406 // Skip header
13407 if (headerSize == 1) {
13408 jam();
13409 moreKeyData = beforeValues.next(iter);
13410 } else {
13411 jam();
13412 moreKeyData = beforeValues.next(iter, headerSize - 1);
13413 }//if
13414 while((keyAttrSize != 0) &&
13415 (dataPos < keyBufSize)) {
13416 // If we have not read complete key
13417 jam();
13418 *dataPtr++ = *iter.data;
13419 dataPos++;
13420 keyAttrSize--;
13421 moreKeyData = beforeValues.next(iter);
13422 }
13423 if (keyAttrSize != 0) {
13424 jam();
13425 break;
13426 }//if
13427 }
13428
13429 tcKeyLength += dataPos;
13430 tcKeyReq->requestInfo = tcKeyRequestInfo;
13431
13432 /**
13433 * Fix savepoint id -
13434 * fix so that delete has same savepoint id as triggering operation
13435 */
13436 const Uint32 currSavePointId = regApiPtr->currSavePointId;
13437 regApiPtr->currSavePointId = opRecord->savePointId;
13438 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
13439 jamEntry();
13440
13441 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13442 {
13443 jam();
13444 return;
13445 }
13446
13447 regApiPtr->currSavePointId = currSavePointId;
13448 tcConnectptr.p->currentIndexId = indexData->indexId;
13449
13450 // *********** KEYINFO ***********
13451 if (moreKeyData) {
13452 jam();
13453 // Send KEYINFO sequence
13454 KeyInfo * const keyInfo = (KeyInfo *)signal->getDataPtrSend();
13455
13456 keyInfo->connectPtr = transPtr->i;
13457 keyInfo->transId[0] = regApiPtr->transid[0];
13458 keyInfo->transId[1] = regApiPtr->transid[1];
13459 dataPtr = (Uint32 *) &keyInfo->keyData;
13460 dataPos = 0;
13461 // Pack any part of a key attribute that did no fit TCKEYREQ
13462 while((keyAttrSize != 0) &&
13463 (dataPos < KeyInfo::DataLength)) {
13464 // If we have not read complete key
13465 *dataPtr++ = *iter.data;
13466 dataPos++;
13467 keyAttrSize--;
13468 if (dataPos == KeyInfo::DataLength) {
13469 jam();
13470 // Flush KEYINFO
13471 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13472 sendSignal(reference(), GSN_KEYINFO, signal,
13473 KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13474 #else
13475 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13476 KeyInfo::HeaderLength + KeyInfo::DataLength);
13477 jamEntry();
13478 #endif
13479 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13480 {
13481 jam();
13482 return;
13483 }
13484
13485 dataPtr = (Uint32 *) &keyInfo->keyData;
13486 dataPos = 0;
13487 }
13488 moreKeyData = beforeValues.next(iter);
13489 }
13490
13491 while(moreKeyData) {
13492 jam();
13493 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13494
13495 headerSize = attrHeader->getHeaderSize();
13496 keyAttrSize = attrHeader->getDataSize();
13497 headAndData = headerSize + attrHeader->getDataSize();
13498 // Skip header
13499 if (headerSize == 1) {
13500 jam();
13501 moreKeyData = beforeValues.next(iter);
13502 } else {
13503 jam();
13504 moreKeyData = beforeValues.next(iter,
13505 headerSize - 1);
13506 }//if
13507 while (keyAttrSize-- != 0) {
13508 *dataPtr++ = *iter.data;
13509 dataPos++;
13510 if (dataPos == KeyInfo::DataLength) {
13511 jam();
13512 // Flush KEYINFO
13513 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13514 sendSignal(reference(), GSN_KEYINFO, signal,
13515 KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13516 #else
13517 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13518 KeyInfo::HeaderLength + KeyInfo::DataLength);
13519 jamEntry();
13520 #endif
13521 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13522 {
13523 jam();
13524 return;
13525 }
13526
13527 dataPtr = (Uint32 *) &keyInfo->keyData;
13528 dataPos = 0;
13529 }
13530 moreKeyData = beforeValues.next(iter);
13531 }
13532 }
13533 if (dataPos != 0) {
13534 jam();
13535 // Flush last KEYINFO
13536 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13537 sendSignal(reference(), GSN_KEYINFO, signal,
13538 KeyInfo::HeaderLength + dataPos, JBA);
13539 #else
13540 EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13541 KeyInfo::HeaderLength + dataPos);
13542 jamEntry();
13543 #endif
13544 }
13545 }
13546 }
13547
13548 Uint32
getErrorCode(Uint32 schemaVersion) const13549 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
13550 if(!get_enabled())
13551 return ZNO_SUCH_TABLE;
13552 if(get_dropping())
13553 return ZDROP_TABLE_IN_PROGRESS;
13554 if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
13555 return ZWRONG_SCHEMA_VERSION_ERROR;
13556 ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
13557 __FILE__, __LINE__);
13558 return 0;
13559 }
13560
13561 void
execROUTE_ORD(Signal * signal)13562 Dbtc::execROUTE_ORD(Signal* signal)
13563 {
13564 jamEntry();
13565 if(!assembleFragments(signal)){
13566 jam();
13567 return;
13568 }
13569
13570 RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
13571 Uint32 dstRef = ord->dstRef;
13572 Uint32 srcRef = ord->srcRef;
13573 Uint32 gsn = ord->gsn;
13574
13575 if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
13576 {
13577 jam();
13578 Uint32 secCount = signal->getNoOfSections();
13579 SegmentedSectionPtr ptr[3];
13580 ndbrequire(secCount >= 1 && secCount <= 3);
13581
13582 jamLine(secCount);
13583 for (Uint32 i = 0; i<secCount; i++)
13584 signal->getSection(ptr[i], i);
13585
13586 /**
13587 * Put section 0 in signal->theData
13588 */
13589 ndbrequire(ptr[0].sz <= 25);
13590 copy(signal->theData, ptr[0]);
13591
13592 signal->header.m_noOfSections = 0;
13593
13594 /**
13595 * Shift rest of sections
13596 */
13597 for(Uint32 i = 1; i<secCount; i++)
13598 {
13599 signal->setSection(ptr[i], i - 1);
13600 }
13601
13602 sendSignal(dstRef, gsn, signal, ptr[0].sz, JBB);
13603
13604 signal->header.m_noOfSections = 0;
13605 signal->setSection(ptr[0], 0);
13606 releaseSections(signal);
13607 return ;
13608 }
13609
13610 warningEvent("Unable to route GSN: %d from %x to %x",
13611 gsn, srcRef, dstRef);
13612 }
13613