1 /*
2 Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
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, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25 #define DBTC_C
26
27 #include "Dbtc.hpp"
28 #include "md5_hash.hpp"
29 #include <RefConvert.hpp>
30 #include <ndb_limits.h>
31 #include <ndb_rand.h>
32
33 #include <signaldata/DiGetNodes.hpp>
34 #include <signaldata/EventReport.hpp>
35 #include <signaldata/TcKeyReq.hpp>
36 #include <signaldata/TcKeyConf.hpp>
37 #include <signaldata/TcKeyRef.hpp>
38 #include <signaldata/KeyInfo.hpp>
39 #include <signaldata/AttrInfo.hpp>
40 #include <signaldata/TransIdAI.hpp>
41 #include <signaldata/TcRollbackRep.hpp>
42 #include <signaldata/NodeFailRep.hpp>
43 #include <signaldata/ReadNodesConf.hpp>
44 #include <signaldata/NFCompleteRep.hpp>
45 #include <signaldata/LqhKey.hpp>
46 #include <signaldata/TcCommit.hpp>
47 #include <signaldata/TcContinueB.hpp>
48 #include <signaldata/TcKeyFailConf.hpp>
49 #include <signaldata/AbortAll.hpp>
50 #include <signaldata/DihScanTab.hpp>
51 #include <signaldata/ScanFrag.hpp>
52 #include <signaldata/ScanTab.hpp>
53 #include <signaldata/PrepDropTab.hpp>
54 #include <signaldata/DropTab.hpp>
55 #include <signaldata/AlterTab.hpp>
56 #include <signaldata/CreateTrig.hpp>
57 #include <signaldata/CreateTrigImpl.hpp>
58 #include <signaldata/DropTrig.hpp>
59 #include <signaldata/DropTrigImpl.hpp>
60 #include <signaldata/FireTrigOrd.hpp>
61 #include <signaldata/TrigAttrInfo.hpp>
62 #include <signaldata/CreateIndx.hpp>
63 #include <signaldata/CreateIndxImpl.hpp>
64 #include <signaldata/DropIndx.hpp>
65 #include <signaldata/DropIndxImpl.hpp>
66 #include <signaldata/AlterIndx.hpp>
67 #include <signaldata/AlterIndxImpl.hpp>
68 #include <signaldata/ScanTab.hpp>
69 #include <signaldata/SystemError.hpp>
70 #include <signaldata/DumpStateOrd.hpp>
71 #include <signaldata/DisconnectRep.hpp>
72 #include <signaldata/TcHbRep.hpp>
73
74 #include <signaldata/PrepDropTab.hpp>
75 #include <signaldata/DropTab.hpp>
76 #include <signaldata/TcIndx.hpp>
77 #include <signaldata/IndxKeyInfo.hpp>
78 #include <signaldata/IndxAttrInfo.hpp>
79 #include <signaldata/PackedSignal.hpp>
80 #include <signaldata/SignalDroppedRep.hpp>
81 #include <AttributeHeader.hpp>
82 #include <signaldata/DictTabInfo.hpp>
83 #include <AttributeDescriptor.hpp>
84 #include <SectionReader.hpp>
85 #include <KeyDescriptor.hpp>
86
87 #include <NdbOut.hpp>
88 #include <DebuggerNames.hpp>
89 #include <signaldata/CheckNodeGroups.hpp>
90
91 #include <signaldata/RouteOrd.hpp>
92 #include <signaldata/GCP.hpp>
93
94 #include <signaldata/DbinfoScan.hpp>
95 #include <signaldata/TransIdAI.hpp>
96 #include <signaldata/CreateTab.hpp>
97
98 // Use DEBUG to print messages that should be
99 // seen only when we debug the product
100 #ifdef VM_TRACE
101 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
102 #else
103 #define DEBUG(x)
104 #endif
105
106 #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
107
108 #ifdef VM_TRACE
109 NdbOut &
operator <<(NdbOut & out,Dbtc::ConnectionState state)110 operator<<(NdbOut& out, Dbtc::ConnectionState state){
111 switch(state){
112 case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
113 case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
114 case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
115 case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
116 case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
117 case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
118 case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
119 case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
120 case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
121 case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
122 case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
123 case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
124 case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
125 case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
126 case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
127 case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
128 case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
129 case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
130 case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
131 case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
132 case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
133 case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
134 case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
135 case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
136 case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
137 case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
138 default:
139 out << "Unknown: " << (int)state; break;
140 }
141 return out;
142 }
143 NdbOut &
operator <<(NdbOut & out,Dbtc::OperationState state)144 operator<<(NdbOut& out, Dbtc::OperationState state){
145 out << (int)state;
146 return out;
147 }
148 NdbOut &
operator <<(NdbOut & out,Dbtc::AbortState state)149 operator<<(NdbOut& out, Dbtc::AbortState state){
150 out << (int)state;
151 return out;
152 }
153 NdbOut &
operator <<(NdbOut & out,Dbtc::ReturnSignal state)154 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
155 out << (int)state;
156 return out;
157 }
158 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanRecord::ScanState state)159 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
160 out << (int)state;
161 return out;
162 }
163 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanFragRec::ScanFragState state)164 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
165 out << (int)state;
166 return out;
167 }
168 #endif
169
170 extern int ErrorSignalReceive;
171 extern int ErrorMaxSegmentsToSeize;
172
173 void
updateBuddyTimer(ApiConnectRecordPtr apiPtr)174 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
175 {
176 if (apiPtr.p->buddyPtr != RNIL) {
177 jam();
178 ApiConnectRecordPtr buddyApiPtr;
179 buddyApiPtr.i = apiPtr.p->buddyPtr;
180 ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
181 if (getApiConTimer(buddyApiPtr.i) != 0) {
182 if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
183 (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
184 jam();
185 setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
186 } else {
187 jam();
188 // Not a buddy anymore since not the same transid
189 apiPtr.p->buddyPtr = RNIL;
190 }//if
191 }//if
192 }//if
193 }
194
195 static
196 inline
197 bool
tc_testbit(Uint32 flags,Uint32 flag)198 tc_testbit(Uint32 flags, Uint32 flag)
199 {
200 return (flags & flag) != 0;
201 }
202
203 static
204 inline
205 void
tc_clearbit(Uint32 & flags,Uint32 flag)206 tc_clearbit(Uint32 & flags, Uint32 flag)
207 {
208 flags &= ~(Uint32)flag;
209 }
210
execCONTINUEB(Signal * signal)211 void Dbtc::execCONTINUEB(Signal* signal)
212 {
213 UintR tcase;
214
215 jamEntry();
216 tcase = signal->theData[0];
217 UintR Tdata0 = signal->theData[1];
218 UintR Tdata1 = signal->theData[2];
219 UintR Tdata2 = signal->theData[3];
220 switch (tcase) {
221 case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
222 jam();
223 ndbrequire(false);
224 return;
225 case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
226 jam();
227 tcNodeFailptr.i = Tdata0;
228 ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
229 completeTransAtTakeOverLab(signal, Tdata1);
230 return;
231 case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
232 jam();
233 timeOutLoopStartLab(signal, Tdata0);
234 return;
235 case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
236 jam();
237 tnodeid = Tdata0;
238 tcNodeFailptr.i = 0;
239 ptrAss(tcNodeFailptr, tcFailRecord);
240 nodeTakeOverCompletedLab(signal);
241 return;
242 case TcContinueB::ZINITIALISE_RECORDS:
243 jam();
244 initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
245 return;
246 case TcContinueB::ZSEND_COMMIT_LOOP:
247 jam();
248 apiConnectptr.i = Tdata0;
249 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
250 tcConnectptr.i = Tdata1;
251 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
252 commit020Lab(signal);
253 return;
254 case TcContinueB::ZSEND_COMPLETE_LOOP:
255 jam();
256 apiConnectptr.i = Tdata0;
257 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
258 tcConnectptr.i = Tdata1;
259 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
260 complete010Lab(signal);
261 return;
262 case TcContinueB::ZHANDLE_FAILED_API_NODE:
263 jam();
264 handleFailedApiNode(signal, Tdata0, Tdata1);
265 return;
266 case TcContinueB::ZTRANS_EVENT_REP:
267 jam();
268 /* Send transaction counters report */
269 {
270 const Uint32 len = c_counters.build_event_rep(signal);
271 sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
272 }
273
274 {
275 const Uint32 report_interval = 5000;
276 const Uint32 len = c_counters.build_continueB(signal);
277 signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
278 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, report_interval, len);
279 }
280 return;
281 case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
282 jam();
283 timeOutLoopStartFragLab(signal, Tdata0);
284 return;
285 case TcContinueB::ZABORT_BREAK:
286 jam();
287 tcConnectptr.i = Tdata0;
288 apiConnectptr.i = Tdata1;
289 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
290 apiConnectptr.p->counter--;
291 abort015Lab(signal);
292 return;
293 case TcContinueB::ZABORT_TIMEOUT_BREAK:
294 jam();
295 tcConnectptr.i = Tdata0;
296 apiConnectptr.i = Tdata1;
297 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
298 apiConnectptr.p->counter--;
299 sendAbortedAfterTimeout(signal, 1);
300 return;
301 case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
302 jam();
303 removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
304 return;
305 case TcContinueB::ZWAIT_ABORT_ALL:
306 jam();
307 checkAbortAllTimeout(signal, Tdata0);
308 return;
309 case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
310 jam();
311 checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
312 return;
313 case TcContinueB::ZNF_CHECK_TRANSACTIONS:
314 jam();
315 nodeFailCheckTransactions(signal, Tdata0, Tdata1);
316 return;
317 case TcContinueB::TRIGGER_PENDING:
318 jam();
319 ApiConnectRecordPtr transPtr;
320 transPtr.i = Tdata0;
321 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
322 #ifdef ERROR_INSERT
323 if (ERROR_INSERTED(8082))
324 {
325 /* Max of 100000 TRIGGER_PENDING TcContinueBs to
326 * single ApiConnectRecord
327 * See testBlobs -bug 45768
328 */
329 if (++transPtr.p->continueBCount > 100000)
330 {
331 ndbrequire(false);
332 }
333 }
334 #endif
335 /* Check that ConnectRecord is for the same Trans Id */
336 if (likely((transPtr.p->transid[0] == Tdata1) &&
337 (transPtr.p->transid[1] == Tdata2)))
338 {
339 ndbrequire(tc_testbit(transPtr.p->m_flags,
340 ApiConnectRecord::TF_TRIGGER_PENDING));
341 tc_clearbit(transPtr.p->m_flags, ApiConnectRecord::TF_TRIGGER_PENDING);
342 /* Try executing triggers now */
343 executeTriggers(signal, &transPtr);
344 }
345 return;
346 case TcContinueB::DelayTCKEYCONF:
347 jam();
348 apiConnectptr.i = Tdata0;
349 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
350 sendtckeyconf(signal, Tdata1);
351 return;
352 case TcContinueB::ZSEND_FIRE_TRIG_REQ:
353 jam();
354 apiConnectptr.i = Tdata0;
355 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
356 if (unlikely(! (apiConnectptr.p->transid[0] == Tdata1 &&
357 apiConnectptr.p->transid[1] == Tdata2 &&
358 apiConnectptr.p->apiConnectstate == CS_SEND_FIRE_TRIG_REQ)))
359 {
360 warningReport(signal, 29);
361 return;
362 }
363 sendFireTrigReq(signal, apiConnectptr, signal->theData[4]);
364 return;
365 default:
366 ndbrequire(false);
367 }//switch
368 }
369
execDIGETNODESREF(Signal * signal)370 void Dbtc::execDIGETNODESREF(Signal* signal)
371 {
372 jamEntry();
373 terrorCode = signal->theData[1];
374 releaseAtErrorLab(signal);
375 }
376
execINCL_NODEREQ(Signal * signal)377 void Dbtc::execINCL_NODEREQ(Signal* signal)
378 {
379 jamEntry();
380 tblockref = signal->theData[0];
381 hostptr.i = signal->theData[1];
382 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
383 hostptr.p->hostStatus = HS_ALIVE;
384 c_alive_nodes.set(hostptr.i);
385
386 signal->theData[0] = hostptr.i;
387 signal->theData[1] = cownref;
388
389 if (ERROR_INSERTED(8039))
390 {
391 CLEAR_ERROR_INSERT_VALUE;
392 Uint32 save = signal->theData[0];
393 signal->theData[0] = 9999;
394 sendSignal(numberToRef(CMVMI, hostptr.i),
395 GSN_NDB_TAMPER, signal, 1, JBB);
396 signal->theData[0] = save;
397 sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
398 return;
399 }
400
401 Uint32 Tnode = hostptr.i;
402 Uint32 lqhWorkers = getNodeInfo(Tnode).m_lqh_workers;
403 if (lqhWorkers == 1)
404 {
405 jam();
406 hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, 1, Tnode);
407 }
408 else
409 {
410 jam();
411 hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, Tnode);
412 }
413
414 sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
415
416 if (m_deferred_enabled)
417 {
418 jam();
419 if (!ndbd_deferred_unique_constraints(getNodeInfo(Tnode).m_version))
420 {
421 jam();
422 m_deferred_enabled = 0;
423 }
424 }
425 }
426
execREAD_NODESREF(Signal * signal)427 void Dbtc::execREAD_NODESREF(Signal* signal)
428 {
429 jamEntry();
430 ndbrequire(false);
431 }
432
433 // create table prepare
execTC_SCHVERREQ(Signal * signal)434 void Dbtc::execTC_SCHVERREQ(Signal* signal)
435 {
436 jamEntry();
437 if (! assembleFragments(signal)) {
438 jam();
439 return;
440 }
441 const TcSchVerReq* req = CAST_CONSTPTR(TcSchVerReq, signal->getDataPtr());
442 tabptr.i = req->tableId;
443 ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
444 tabptr.p->currentSchemaVersion = req->tableVersion;
445 tabptr.p->m_flags = 0;
446 tabptr.p->set_storedTable((bool)req->tableLogged);
447 BlockReference retRef = req->senderRef;
448 tabptr.p->tableType = (Uint8)req->tableType;
449 BlockReference retPtr = req->senderData;
450 Uint32 noOfKeyAttr = req->noOfPrimaryKeys;
451 tabptr.p->singleUserMode = (Uint8)req->singleUserMode;
452 Uint32 userDefinedPartitioning = (Uint8)req->userDefinedPartition;
453 ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
454
455 const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
456 ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
457
458 ndbrequire(tabptr.p->get_prepared() == false);
459 ndbrequire(tabptr.p->get_enabled() == false);
460 tabptr.p->set_prepared(true);
461 tabptr.p->set_enabled(false);
462 tabptr.p->set_dropping(false);
463 tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
464 tabptr.p->hasCharAttr = desc->hasCharAttr;
465 tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
466 tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
467 tabptr.p->set_user_defined_partitioning(userDefinedPartitioning);
468
469 TcSchVerConf * conf = (TcSchVerConf*)signal->getDataPtr();
470 conf->senderRef = reference();
471 conf->senderData = retPtr;
472 sendSignal(retRef, GSN_TC_SCHVERCONF, signal,
473 TcSchVerConf::SignalLength, JBB);
474 }//Dbtc::execTC_SCHVERREQ()
475
476 // create table commit
execTAB_COMMITREQ(Signal * signal)477 void Dbtc::execTAB_COMMITREQ(Signal* signal)
478 {
479 jamEntry();
480 Uint32 senderData = signal->theData[0];
481 Uint32 senderRef = signal->theData[1];
482 tabptr.i = signal->theData[2];
483 ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
484
485 ndbrequire(tabptr.p->get_prepared() == true);
486 ndbrequire(tabptr.p->get_enabled() == false);
487 tabptr.p->set_enabled(true);
488 tabptr.p->set_prepared(false);
489 tabptr.p->set_dropping(false);
490
491 signal->theData[0] = senderData;
492 signal->theData[1] = reference();
493 signal->theData[2] = tabptr.i;
494 sendSignal(senderRef, GSN_TAB_COMMITCONF, signal, 3, JBB);
495 }
496
497 void
execPREP_DROP_TAB_REQ(Signal * signal)498 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
499 {
500 jamEntry();
501
502 PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
503
504 TableRecordPtr tabPtr;
505 tabPtr.i = req->tableId;
506 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
507
508 Uint32 senderRef = req->senderRef;
509 Uint32 senderData = req->senderData;
510
511 if(!tabPtr.p->get_enabled())
512 {
513 jam();
514 PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
515 ref->senderRef = reference();
516 ref->senderData = senderData;
517 ref->tableId = tabPtr.i;
518 ref->errorCode = PrepDropTabRef::NoSuchTable;
519 sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
520 PrepDropTabRef::SignalLength, JBB);
521 return;
522 }
523
524 if(tabPtr.p->get_dropping())
525 {
526 jam();
527 PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
528 ref->senderRef = reference();
529 ref->senderData = senderData;
530 ref->tableId = tabPtr.i;
531 ref->errorCode = PrepDropTabRef::DropInProgress;
532 sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
533 PrepDropTabRef::SignalLength, JBB);
534 return;
535 }
536
537 tabPtr.p->set_dropping(true);
538 tabPtr.p->set_prepared(false);
539
540 PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
541 conf->tableId = tabPtr.i;
542 conf->senderRef = reference();
543 conf->senderData = senderData;
544 sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
545 PrepDropTabConf::SignalLength, JBB);
546 }
547
548 void
execDROP_TAB_REQ(Signal * signal)549 Dbtc::execDROP_TAB_REQ(Signal* signal)
550 {
551 jamEntry();
552
553 DropTabReq* req = (DropTabReq*)signal->getDataPtr();
554
555 TableRecordPtr tabPtr;
556 tabPtr.i = req->tableId;
557 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
558
559 Uint32 senderRef = req->senderRef;
560 Uint32 senderData = req->senderData;
561 DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
562
563 if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
564 jam();
565 DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
566 ref->senderRef = reference();
567 ref->senderData = senderData;
568 ref->tableId = tabPtr.i;
569 ref->errorCode = DropTabRef::NoSuchTable;
570 sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
571 DropTabRef::SignalLength, JBB);
572 return;
573 }
574
575 if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
576 jam();
577 DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
578 ref->senderRef = reference();
579 ref->senderData = senderData;
580 ref->tableId = tabPtr.i;
581 ref->errorCode = DropTabRef::DropWoPrep;
582 sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
583 DropTabRef::SignalLength, JBB);
584 return;
585 }
586
587 tabPtr.p->set_enabled(false);
588 tabPtr.p->set_prepared(false);
589 tabPtr.p->set_dropping(false);
590
591 DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
592 conf->tableId = tabPtr.i;
593 conf->senderRef = reference();
594 conf->senderData = senderData;
595 sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
596 PrepDropTabConf::SignalLength, JBB);
597 }
598
execALTER_TAB_REQ(Signal * signal)599 void Dbtc::execALTER_TAB_REQ(Signal * signal)
600 {
601 const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
602 const Uint32 senderRef = req->senderRef;
603 const Uint32 senderData = req->senderData;
604 const Uint32 tableVersion = req->tableVersion;
605 const Uint32 newTableVersion = req->newTableVersion;
606 AlterTabReq::RequestType requestType =
607 (AlterTabReq::RequestType) req->requestType;
608
609 TableRecordPtr tabPtr;
610 tabPtr.i = req->tableId;
611 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
612
613 switch (requestType) {
614 case AlterTabReq::AlterTablePrepare:
615 jam();
616 break;
617 case AlterTabReq::AlterTableRevert:
618 jam();
619 tabPtr.p->currentSchemaVersion = tableVersion;
620 break;
621 case AlterTabReq::AlterTableCommit:
622 jam();
623 tabPtr.p->currentSchemaVersion = newTableVersion;
624 break;
625 default:
626 ndbrequire(false);
627 break;
628 }
629
630 // Request handled successfully
631 AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
632 conf->senderRef = reference();
633 conf->senderData = senderData;
634 conf->connectPtr = RNIL;
635 sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
636 AlterTabConf::SignalLength, JBB);
637 }
638
639 /* ***************************************************************************/
640 /* START / RESTART */
641 /* ***************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)642 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
643 {
644 const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
645 Uint32 ref = req->senderRef;
646 Uint32 senderData = req->senderData;
647 ndbrequire(req->noOfParameters == 0);
648
649 jamEntry();
650
651 const ndb_mgm_configuration_iterator * p =
652 m_ctx.m_config.getOwnConfigIterator();
653 ndbrequire(p != 0);
654
655 initData();
656
657 UintR apiConnect;
658 UintR tcConnect;
659 UintR tables;
660 UintR localScan;
661 UintR tcScan;
662
663 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
664 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
665 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
666 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
667 ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
668
669 ccacheFilesize = (apiConnect/3) + 1;
670 capiConnectFilesize = apiConnect;
671 ctcConnectFilesize = tcConnect;
672 ctabrecFilesize = tables;
673 cscanrecFileSize = tcScan;
674 cscanFragrecFileSize = localScan;
675
676 initRecords();
677 initialiseRecordsLab(signal, 0, ref, senderData);
678
679 Uint32 val = 3000;
680 ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
681 set_timeout_value(val);
682
683 val = 1500;
684 ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
685 cDbHbInterval = (val < 10) ? 10 : val;
686
687 val = 3000;
688 ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
689 set_appl_timeout_value(val);
690
691 val = 1;
692 //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
693 set_no_parallel_takeover(val);
694
695 val = ~(Uint32)0;
696 ndb_mgm_get_int_parameter(p, CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION, &val);
697 m_max_writes_per_trans = val;
698
699 ctimeOutCheckDelay = 50; // 500ms
700 }//Dbtc::execSIZEALT_REP()
701
execSTTOR(Signal * signal)702 void Dbtc::execSTTOR(Signal* signal)
703 {
704 Uint16 tphase;
705
706 jamEntry();
707 /* START CASE */
708 tphase = signal->theData[1];
709 csignalKey = signal->theData[6];
710 c_sttor_ref = signal->getSendersBlockRef();
711 switch (tphase) {
712 case ZSPH1:
713 jam();
714 startphase1x010Lab(signal);
715 return;
716 default:
717 jam();
718 sttorryLab(signal); /* START PHASE 255 */
719 return;
720 }//switch
721 }//Dbtc::execSTTOR()
722
sttorryLab(Signal * signal)723 void Dbtc::sttorryLab(Signal* signal)
724 {
725 signal->theData[0] = csignalKey;
726 signal->theData[1] = 3; /* BLOCK CATEGORY */
727 signal->theData[2] = 2; /* SIGNAL VERSION NUMBER */
728 signal->theData[3] = ZSPH1;
729 signal->theData[4] = 255;
730 sendSignal(c_sttor_ref, GSN_STTORRY, signal, 5, JBB);
731 }//Dbtc::sttorryLab()
732
733 /* ***************************************************************************/
734 /* INTERNAL START / RESTART */
735 /*****************************************************************************/
execNDB_STTOR(Signal * signal)736 void Dbtc::execNDB_STTOR(Signal* signal)
737 {
738 Uint16 tndbstartphase;
739 Uint16 tstarttype;
740
741 jamEntry();
742 tusersblkref = signal->theData[0];
743 tnodeid = signal->theData[1];
744 tndbstartphase = signal->theData[2]; /* START PHASE */
745 tstarttype = signal->theData[3]; /* START TYPE */
746 c_sttor_ref = signal->getSendersBlockRef();
747 switch (tndbstartphase) {
748 case ZINTSPH1:
749 jam();
750 intstartphase1x010Lab(signal);
751 return;
752 case ZINTSPH2:
753 jam();
754 ndbsttorry010Lab(signal);
755 return;
756 case ZINTSPH3:
757 {
758 jam();
759 intstartphase3x010Lab(signal); /* SEIZE CONNECT RECORD IN EACH LQH*/
760
761 /* Start transaction counters event reporting. */
762 const Uint32 len = c_counters.build_continueB(signal);
763 signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
764 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
765 return;
766 }
767 case ZINTSPH6:
768 jam();
769 csystemStart = SSS_TRUE;
770 break;
771 default:
772 jam();
773 break;
774 }//switch
775 ndbsttorry010Lab(signal);
776 return;
777 }//Dbtc::execNDB_STTOR()
778
ndbsttorry010Lab(Signal * signal)779 void Dbtc::ndbsttorry010Lab(Signal* signal)
780 {
781 signal->theData[0] = cownref;
782 sendSignal(c_sttor_ref, GSN_NDB_STTORRY, signal, 1, JBB);
783 }//Dbtc::ndbsttorry010Lab()
784
785 void
set_timeout_value(Uint32 timeOut)786 Dbtc::set_timeout_value(Uint32 timeOut)
787 {
788 timeOut = timeOut / 10;
789 if (timeOut < 2) {
790 jam();
791 timeOut = 100;
792 }//if
793 ctimeOutValue = timeOut;
794 }
795
796 void
set_appl_timeout_value(Uint32 timeOut)797 Dbtc::set_appl_timeout_value(Uint32 timeOut)
798 {
799 if (timeOut)
800 {
801 timeOut /= 10;
802 if (timeOut < ctimeOutValue) {
803 jam();
804 c_appl_timeout_value = ctimeOutValue;
805 }//if
806 }
807 c_appl_timeout_value = timeOut;
808 }
809
810 void
set_no_parallel_takeover(Uint32 noParallelTakeOver)811 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
812 {
813 if (noParallelTakeOver == 0) {
814 jam();
815 noParallelTakeOver = 1;
816 } else if (noParallelTakeOver > MAX_NDB_NODES) {
817 jam();
818 noParallelTakeOver = MAX_NDB_NODES;
819 }//if
820 cnoParallelTakeOver = noParallelTakeOver;
821 }
822
823 /* ***************************************************************************/
824 /* S T A R T P H A S E 1 X */
825 /* INITIALISE BLOCKREF AND BLOCKNUMBERS */
826 /* ***************************************************************************/
startphase1x010Lab(Signal * signal)827 void Dbtc::startphase1x010Lab(Signal* signal)
828 {
829 csystemStart = SSS_FALSE;
830 ctimeOutCheckCounter = 0;
831 ctimeOutCheckFragCounter = 0;
832 ctimeOutMissedHeartbeats = 0;
833 ctimeOutCheckHeartbeat = 0;
834 ctimeOutCheckLastHeartbeat = 0;
835 ctimeOutCheckActive = TOCS_FALSE;
836 ctimeOutCheckFragActive = TOCS_FALSE;
837 sttorryLab(signal);
838 }//Dbtc::startphase1x010Lab()
839
840 /*****************************************************************************/
841 /* I N T S T A R T P H A S E 1 X */
842 /* INITIALISE ALL RECORDS. */
843 /*****************************************************************************/
intstartphase1x010Lab(Signal * signal)844 void Dbtc::intstartphase1x010Lab(Signal* signal)
845 {
846 cownNodeid = tnodeid;
847 cownref = reference();
848 clqhblockref = calcLqhBlockRef(cownNodeid);
849 cdihblockref = calcDihBlockRef(cownNodeid);
850 cdictblockref = calcDictBlockRef(cownNodeid);
851 cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
852 cerrorBlockref = calcNdbCntrBlockRef(cownNodeid);
853 coperationsize = 0;
854 cfailure_nr = 0;
855 ndbsttorry010Lab(signal);
856 }//Dbtc::intstartphase1x010Lab()
857
858 /*****************************************************************************/
859 /* I N T S T A R T P H A S E 3 X */
860 /* PREPARE DISTRIBUTED CONNECTIONS */
861 /*****************************************************************************/
intstartphase3x010Lab(Signal * signal)862 void Dbtc::intstartphase3x010Lab(Signal* signal)
863 {
864 signal->theData[0] = cownref;
865 sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
866 }//Dbtc::intstartphase3x010Lab()
867
execREAD_NODESCONF(Signal * signal)868 void Dbtc::execREAD_NODESCONF(Signal* signal)
869 {
870 UintR guard0;
871
872 jamEntry();
873
874 ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
875
876 csystemnodes = readNodes->noOfNodes;
877 cmasterNodeId = readNodes->masterNodeId;
878
879 con_lineNodes = 0;
880 arrGuard(csystemnodes, MAX_NDB_NODES);
881 guard0 = csystemnodes - 1;
882 arrGuard(guard0, MAX_NDB_NODES); // Check not zero nodes
883
884 for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
885 jam();
886 if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
887 hostptr.i = i;
888 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
889
890 if (NdbNodeBitmask::get(readNodes->inactiveNodes, i)) {
891 jam();
892 hostptr.p->hostStatus = HS_DEAD;
893 } else {
894 jam();
895 con_lineNodes++;
896 hostptr.p->hostStatus = HS_ALIVE;
897 c_alive_nodes.set(i);
898 if (getNodeInfo(i).m_lqh_workers == 1)
899 {
900 jam();
901 hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, 1, i);
902 }
903 else
904 {
905 jam();
906 hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, i);
907 }
908 if (!ndbd_deferred_unique_constraints(getNodeInfo(i).m_version))
909 {
910 jam();
911 m_deferred_enabled = 0;
912 }
913 }//if
914 }//if
915 }//for
916 ndbsttorry010Lab(signal);
917 }//Dbtc::execREAD_NODESCONF()
918
919 /*****************************************************************************/
920 /* A P I _ F A I L R E Q */
921 // An API node has failed for some reason. We need to disconnect all API
922 // connections to the API node. This also includes
923 /*****************************************************************************/
execAPI_FAILREQ(Signal * signal)924 void Dbtc::execAPI_FAILREQ(Signal* signal)
925 {
926 /***************************************************************************
927 * Set the block reference to return API_FAILCONF to. Set the number of api
928 * connects currently closing to one to indicate that we are still in the
929 * process of going through the api connect records. Thus checking for zero
930 * can only be true after all api connect records have been checked.
931 **************************************************************************/
932 jamEntry();
933
934 if (ERROR_INSERTED(8056))
935 {
936 CLEAR_ERROR_INSERT_VALUE;
937 return;
938 }
939 #ifdef ERROR_INSERT
940 if (ERROR_INSERTED(8078))
941 {
942 c_lastFailedApi = signal->theData[0];
943 SET_ERROR_INSERT_VALUE(8079);
944 }
945 #endif
946
947 capiFailRef = signal->theData[1];
948 arrGuard(signal->theData[0], MAX_NODES);
949 capiConnectClosing[signal->theData[0]] = 1;
950 handleFailedApiNode(signal, signal->theData[0], (UintR)0);
951 }
952
953 void
handleFailedApiNode(Signal * signal,UintR TapiFailedNode,UintR TapiConnectPtr)954 Dbtc::handleFailedApiNode(Signal* signal,
955 UintR TapiFailedNode,
956 UintR TapiConnectPtr)
957 {
958 UintR TloopCount = 0;
959 arrGuard(TapiFailedNode, MAX_NODES);
960 apiConnectptr.i = TapiConnectPtr;
961 do {
962 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
963 const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
964 if (TapiNode == TapiFailedNode) {
965 #ifdef VM_TRACE
966 if (apiConnectptr.p->apiFailState != ZFALSE) {
967 ndbout << "Error in previous API fail handling discovered" << endl
968 << " apiConnectptr.i = " << apiConnectptr.i << endl
969 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate
970 << endl
971 << " ndbapiBlockref = " << hex
972 << apiConnectptr.p->ndbapiBlockref << endl
973 << " apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
974 << endl;
975 if (apiConnectptr.p->lastTcConnect != RNIL){
976 jam();
977 tcConnectptr.i = apiConnectptr.p->lastTcConnect;
978 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
979 ndbout << " tcConnectptr.i = " << tcConnectptr.i << endl
980 << " tcConnectstate = " << tcConnectptr.p->tcConnectstate
981 << endl;
982 }
983 }//if
984 #endif
985
986 apiConnectptr.p->returnsignal = RS_NO_RETURN;
987 /***********************************************************************/
988 // The connected node is the failed node.
989 /**********************************************************************/
990 switch(apiConnectptr.p->apiConnectstate) {
991 case CS_DISCONNECTED:
992 /*********************************************************************/
993 // These states do not need any special handling.
994 // Simply continue with the next.
995 /*********************************************************************/
996 jam();
997 break;
998 case CS_ABORTING:
999 /*********************************************************************/
1000 // This could actually mean that the API connection is already
1001 // ready to release if the abortState is IDLE.
1002 /*********************************************************************/
1003 if (apiConnectptr.p->abortState == AS_IDLE) {
1004 jam();
1005 releaseApiCon(signal, apiConnectptr.i);
1006 } else {
1007 jam();
1008 capiConnectClosing[TapiFailedNode]++;
1009 apiConnectptr.p->apiFailState = ZTRUE;
1010 }//if
1011 break;
1012 case CS_WAIT_ABORT_CONF:
1013 case CS_WAIT_COMMIT_CONF:
1014 case CS_START_COMMITTING:
1015 case CS_PREPARE_TO_COMMIT:
1016 case CS_COMMITTING:
1017 case CS_COMMIT_SENT:
1018 /*********************************************************************/
1019 // These states indicate that an abort process or commit process is
1020 // already ongoing. We will set a state in the api record indicating
1021 // that the API node has failed.
1022 // Also we will increase the number of outstanding api records to
1023 // wait for before we can respond with API_FAILCONF.
1024 /*********************************************************************/
1025 jam();
1026 capiConnectClosing[TapiFailedNode]++;
1027 apiConnectptr.p->apiFailState = ZTRUE;
1028 break;
1029 case CS_START_SCAN:
1030 /*********************************************************************/
1031 // The api record was performing a scan operation. We need to check
1032 // on the scan state. Since completing a scan process might involve
1033 // sending several signals we will increase the loop count by 64.
1034 /*********************************************************************/
1035 jam();
1036
1037 apiConnectptr.p->apiFailState = ZTRUE;
1038 capiConnectClosing[TapiFailedNode]++;
1039
1040 ScanRecordPtr scanPtr;
1041 scanPtr.i = apiConnectptr.p->apiScanRec;
1042 ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
1043 close_scan_req(signal, scanPtr, true);
1044
1045 TloopCount += 64;
1046 break;
1047 case CS_CONNECTED:
1048 case CS_REC_COMMITTING:
1049 case CS_RECEIVING:
1050 case CS_STARTED:
1051 /*********************************************************************/
1052 // The api record was in the process of performing a transaction but
1053 // had not yet sent all information.
1054 // We need to initiate an ABORT since the API will not provide any
1055 // more information.
1056 // Since the abort can send many signals we will insert a real-time
1057 // break after checking this record.
1058 /*********************************************************************/
1059 jam();
1060 apiConnectptr.p->apiFailState = ZTRUE;
1061 capiConnectClosing[TapiFailedNode]++;
1062 abort010Lab(signal);
1063 TloopCount = 256;
1064 break;
1065 case CS_PREPARED:
1066 jam();
1067 case CS_REC_PREPARING:
1068 jam();
1069 case CS_START_PREPARING:
1070 jam();
1071 /*********************************************************************/
1072 // Not implemented yet.
1073 /*********************************************************************/
1074 systemErrorLab(signal, __LINE__);
1075 break;
1076 case CS_RESTART:
1077 jam();
1078 case CS_COMPLETING:
1079 jam();
1080 case CS_COMPLETE_SENT:
1081 jam();
1082 case CS_WAIT_COMPLETE_CONF:
1083 jam();
1084 case CS_FAIL_ABORTING:
1085 jam();
1086 case CS_FAIL_ABORTED:
1087 jam();
1088 case CS_FAIL_PREPARED:
1089 jam();
1090 case CS_FAIL_COMMITTING:
1091 jam();
1092 case CS_FAIL_COMMITTED:
1093 /*********************************************************************/
1094 // These states are only valid on copy and fail API connections.
1095 /*********************************************************************/
1096 default:
1097 jam();
1098 systemErrorLab(signal, __LINE__);
1099 break;
1100 }//switch
1101 } else {
1102 jam();
1103 }//if
1104 apiConnectptr.i++;
1105 if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
1106 jam();
1107 /**
1108 * Finished with scanning connection record
1109 *
1110 * Now scan markers
1111 */
1112 removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1113 return;
1114 }//if
1115 } while (TloopCount++ < 256);
1116 signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1117 signal->theData[1] = TapiFailedNode;
1118 signal->theData[2] = apiConnectptr.i;
1119 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1120 }//Dbtc::handleFailedApiNode()
1121
1122 void
removeMarkerForFailedAPI(Signal * signal,Uint32 nodeId,Uint32 startBucket)1123 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1124 Uint32 nodeId,
1125 Uint32 startBucket)
1126 {
1127 TcFailRecordPtr node_fail_ptr;
1128 node_fail_ptr.i = 0;
1129 ptrAss(node_fail_ptr, tcFailRecord);
1130 if(node_fail_ptr.p->failStatus != FS_IDLE) {
1131 jam();
1132 DEBUG("Restarting removeMarkerForFailedAPI");
1133 /**
1134 * TC take-over in progress
1135 * needs to restart as this
1136 * creates new markers
1137 */
1138 signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1139 signal->theData[1] = nodeId;
1140 signal->theData[2] = 0;
1141 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1142 return;
1143 }
1144
1145 CommitAckMarkerIterator iter;
1146 m_commitAckMarkerHash.next(startBucket, iter);
1147
1148 const Uint32 RT_BREAK = 256;
1149 for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1150 jam();
1151
1152 if(iter.curr.i == RNIL){
1153 jam();
1154 /**
1155 * Done with iteration
1156 */
1157 capiConnectClosing[nodeId]--;
1158 if (capiConnectClosing[nodeId] == 0) {
1159 jam();
1160
1161 /********************************************************************/
1162 // No outstanding ABORT or COMMIT's of this failed API node.
1163 // Perform SimulatedBlock level cleanup before sending
1164 // API_FAILCONF
1165 /********************************************************************/
1166 Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1167 nodeId};
1168 simBlockNodeFailure(signal, nodeId, cb);
1169 }
1170 return;
1171 }
1172
1173 if(iter.curr.p->apiNodeId == nodeId){
1174 jam();
1175
1176 /**
1177 * Check so that the record is not still in use
1178 *
1179 */
1180 ApiConnectRecordPtr apiConnectPtr;
1181 apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1182 ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
1183 if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
1184 jam();
1185 /**
1186 * The record is still active
1187 *
1188 * Don't remove it, but continueb instead
1189 */
1190 break;
1191 }
1192 sendRemoveMarkers(signal, iter.curr.p);
1193 m_commitAckMarkerHash.release(iter.curr);
1194
1195 break;
1196 }
1197 m_commitAckMarkerHash.next(iter);
1198 }
1199
1200 signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1201 signal->theData[1] = nodeId;
1202 signal->theData[2] = iter.bucket;
1203 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1204 }
1205
handleApiFailState(Signal * signal,UintR TapiConnectptr)1206 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1207 {
1208 ApiConnectRecordPtr TlocalApiConnectptr;
1209 UintR TfailedApiNode;
1210
1211 TlocalApiConnectptr.i = TapiConnectptr;
1212 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
1213 TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1214 arrGuard(TfailedApiNode, MAX_NODES);
1215 capiConnectClosing[TfailedApiNode]--;
1216 releaseApiCon(signal, TapiConnectptr);
1217 TlocalApiConnectptr.p->apiFailState = ZFALSE;
1218 if (capiConnectClosing[TfailedApiNode] == 0)
1219 {
1220 jam();
1221
1222 /**
1223 * Perform block-level cleanups (e.g assembleFragments...)
1224 */
1225 Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1226 TfailedApiNode};
1227 simBlockNodeFailure(signal, TfailedApiNode, cb);
1228 }//if
1229 }//Dbtc::handleApiFailState()
1230
1231 /****************************************************************************
1232 * T C S E I Z E R E Q
1233 * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1234 * TRANSACTION
1235 * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1236 * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1237 ****************************************************************************/
execTCSEIZEREQ(Signal * signal)1238 void Dbtc::execTCSEIZEREQ(Signal* signal)
1239 {
1240 UintR tapiPointer;
1241 BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
1242
1243 jamEntry();
1244 tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1245 tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1246
1247 if (signal->getLength() > 2)
1248 {
1249 ndbassert(instance() == signal->theData[2]);
1250 }
1251
1252 const NodeState::StartLevel sl =
1253 (NodeState::StartLevel)getNodeState().startLevel;
1254
1255 const NodeId senderNodeId = refToNode(tapiBlockref);
1256 const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1257
1258 {
1259 {
1260 if (!(sl == NodeState::SL_STARTED ||
1261 (sl == NodeState::SL_STARTING && local == true))) {
1262 jam();
1263
1264 Uint32 errCode = 0;
1265 if(!local)
1266 {
1267 switch(sl){
1268 case NodeState::SL_STARTING:
1269 errCode = ZSYSTEM_NOT_STARTED_ERROR;
1270 break;
1271 case NodeState::SL_STOPPING_1:
1272 case NodeState::SL_STOPPING_2:
1273 if (getNodeState().getSingleUserMode())
1274 break;
1275 case NodeState::SL_STOPPING_3:
1276 case NodeState::SL_STOPPING_4:
1277 if(getNodeState().stopping.systemShutdown)
1278 errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1279 else
1280 errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1281 break;
1282 case NodeState::SL_SINGLEUSER:
1283 break;
1284 default:
1285 errCode = ZWRONG_STATE;
1286 break;
1287 }
1288 if (errCode)
1289 {
1290 signal->theData[0] = tapiPointer;
1291 signal->theData[1] = errCode;
1292 sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1293 return;
1294 }
1295 }//if (!(sl == SL_SINGLEUSER))
1296 } //if
1297 }
1298 }
1299
1300 if (ERROR_INSERTED(8078) || ERROR_INSERTED(8079))
1301 {
1302 /* Clear testing of API_FAILREQ behaviour */
1303 CLEAR_ERROR_INSERT_VALUE;
1304 };
1305
1306 seizeApiConnect(signal);
1307 if (terrorCode == ZOK) {
1308 jam();
1309 apiConnectptr.p->ndbapiConnect = tapiPointer;
1310 apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1311 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1312 signal->theData[1] = apiConnectptr.i;
1313 signal->theData[2] = reference();
1314 sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 3, JBB);
1315 return;
1316 }
1317
1318 signal->theData[0] = tapiPointer;
1319 signal->theData[1] = terrorCode;
1320 sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1321 }//Dbtc::execTCSEIZEREQ()
1322
1323 /****************************************************************************/
1324 /* T C R E L E A S E Q */
1325 /* REQUEST TO RELEASE A CONNECT RECORD */
1326 /****************************************************************************/
execTCRELEASEREQ(Signal * signal)1327 void Dbtc::execTCRELEASEREQ(Signal* signal)
1328 {
1329 UintR tapiPointer;
1330 BlockReference tapiBlockref; /* SENDER BLOCK REFERENCE*/
1331
1332 jamEntry();
1333 tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1334 tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1335 tuserpointer = signal->theData[2];
1336 if (tapiPointer >= capiConnectFilesize) {
1337 jam();
1338 signal->theData[0] = tuserpointer;
1339 signal->theData[1] = ZINVALID_CONNECTION;
1340 signal->theData[2] = __LINE__;
1341 sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1342 return;
1343 } else {
1344 jam();
1345 apiConnectptr.i = tapiPointer;
1346 }//if
1347 ptrAss(apiConnectptr, apiConnectRecord);
1348 if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
1349 jam();
1350 signal->theData[0] = tuserpointer;
1351 sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1352 } else {
1353 if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
1354 if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
1355 (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
1356 apiConnectptr.p->abortState == AS_IDLE) ||
1357 (apiConnectptr.p->apiConnectstate == CS_STARTED &&
1358 apiConnectptr.p->firstTcConnect == RNIL))
1359 {
1360 jam(); /* JUST REPLY OK */
1361 apiConnectptr.p->m_transaction_nodes.clear();
1362 releaseApiCon(signal, apiConnectptr.i);
1363 signal->theData[0] = tuserpointer;
1364 sendSignal(tapiBlockref,
1365 GSN_TCRELEASECONF, signal, 1, JBB);
1366 } else {
1367 jam();
1368 signal->theData[0] = tuserpointer;
1369 signal->theData[1] = ZINVALID_CONNECTION;
1370 signal->theData[2] = __LINE__;
1371 signal->theData[3] = apiConnectptr.p->apiConnectstate;
1372 sendSignal(tapiBlockref,
1373 GSN_TCRELEASEREF, signal, 4, JBB);
1374 }
1375 } else {
1376 jam();
1377 signal->theData[0] = tuserpointer;
1378 signal->theData[1] = ZINVALID_CONNECTION;
1379 signal->theData[2] = __LINE__;
1380 signal->theData[3] = tapiBlockref;
1381 signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1382 sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1383 }//if
1384 }//if
1385 }//Dbtc::execTCRELEASEREQ()
1386
1387 /****************************************************************************/
1388 // Error Handling for TCKEYREQ messages
1389 /****************************************************************************/
signalErrorRefuseLab(Signal * signal)1390 void Dbtc::signalErrorRefuseLab(Signal* signal)
1391 {
1392 ptrGuard(apiConnectptr);
1393 if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1394 jam();
1395 apiConnectptr.p->abortState = AS_IDLE;
1396 apiConnectptr.p->apiConnectstate = CS_ABORTING;
1397 }//if
1398 sendSignalErrorRefuseLab(signal);
1399 }//Dbtc::signalErrorRefuseLab()
1400
sendSignalErrorRefuseLab(Signal * signal)1401 void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
1402 {
1403 ndbassert(false);
1404 ptrGuard(apiConnectptr);
1405 if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1406 jam();
1407 ndbrequire(false);
1408 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1409 signal->theData[1] = signal->theData[ttransid_ptr];
1410 signal->theData[2] = signal->theData[ttransid_ptr + 1];
1411 signal->theData[3] = ZSIGNAL_ERROR;
1412 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1413 signal, 4, JBB);
1414 }
1415 }//Dbtc::sendSignalErrorRefuseLab()
1416
abortBeginErrorLab(Signal * signal)1417 void Dbtc::abortBeginErrorLab(Signal* signal)
1418 {
1419 apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1420 apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1421 abortErrorLab(signal);
1422 }//Dbtc::abortBeginErrorLab()
1423
printState(Signal * signal,int place)1424 void Dbtc::printState(Signal* signal, int place)
1425 {
1426 #ifdef VM_TRACE // Change to if 0 to disable these printouts
1427 ndbout << "-- Dbtc::printState -- " << endl;
1428 ndbout << "Received from place = " << place
1429 << " apiConnectptr.i = " << apiConnectptr.i
1430 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
1431 ndbout << "ctcTimer = " << ctcTimer
1432 << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
1433 << " Transid = " << apiConnectptr.p->transid[0]
1434 << " " << apiConnectptr.p->transid[1] << endl;
1435 ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
1436 << " counter = " << apiConnectptr.p->counter
1437 << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
1438 << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
1439 ndbout << "abortState = " << apiConnectptr.p->abortState
1440 << " apiScanRec = " << apiConnectptr.p->apiScanRec
1441 << " returncode = " << apiConnectptr.p->returncode << endl;
1442 ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
1443 << " returnsignal = " << apiConnectptr.p->returnsignal
1444 << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
1445 if (apiConnectptr.p->cachePtr != RNIL) {
1446 jam();
1447 CacheRecord *localCacheRecord = cacheRecord;
1448 UintR TcacheFilesize = ccacheFilesize;
1449 UintR TcachePtr = apiConnectptr.p->cachePtr;
1450 if (TcachePtr < TcacheFilesize) {
1451 jam();
1452 CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1453 ndbout << "currReclenAi = " << regCachePtr->currReclenAi
1454 << " attrlength = " << regCachePtr->attrlength
1455 << " tableref = " << regCachePtr->tableref
1456 << " keylen = " << regCachePtr->keylen << endl;
1457 } else {
1458 jam();
1459 systemErrorLab(signal, __LINE__);
1460 }//if
1461 }//if
1462 #endif
1463 return;
1464 }//Dbtc::printState()
1465
1466 void
TCKEY_abort(Signal * signal,int place)1467 Dbtc::TCKEY_abort(Signal* signal, int place)
1468 {
1469 switch (place) {
1470 case 0:
1471 jam();
1472 terrorCode = ZSTATE_ERROR;
1473 apiConnectptr.p->firstTcConnect = RNIL;
1474 printState(signal, 4);
1475 abortBeginErrorLab(signal);
1476 return;
1477 case 1:
1478 jam();
1479 printState(signal, 3);
1480 sendSignalErrorRefuseLab(signal);
1481 return;
1482 case 2:{
1483 printState(signal, 6);
1484 const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
1485 const Uint32 t1 = tcKeyReq->transId1;
1486 const Uint32 t2 = tcKeyReq->transId2;
1487 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1488 signal->theData[1] = t1;
1489 signal->theData[2] = t2;
1490 signal->theData[3] = ZABORT_ERROR;
1491 ndbrequire(false);
1492 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1493 signal, 4, JBB);
1494 return;
1495 }
1496 case 3:
1497 jam();
1498 printState(signal, 7);
1499 noFreeConnectionErrorLab(signal);
1500 return;
1501 case 4:
1502 jam();
1503 terrorCode = ZERO_KEYLEN_ERROR;
1504 releaseAtErrorLab(signal);
1505 return;
1506 case 5:
1507 jam();
1508 terrorCode = ZNO_AI_WITH_UPDATE;
1509 releaseAtErrorLab(signal);
1510 return;
1511 case 6:
1512 jam();
1513 warningHandlerLab(signal, __LINE__);
1514 return;
1515
1516 case 7:
1517 jam();
1518 tabStateErrorLab(signal);
1519 return;
1520
1521 case 8:
1522 jam();
1523 wrongSchemaVersionErrorLab(signal);
1524 return;
1525
1526 case 9:
1527 jam();
1528 terrorCode = ZSTATE_ERROR;
1529 releaseAtErrorLab(signal);
1530 return;
1531
1532 case 10:
1533 jam();
1534 systemErrorLab(signal, __LINE__);
1535 return;
1536
1537 case 11:
1538 jam();
1539 terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
1540 releaseAtErrorLab(signal);
1541 return;
1542
1543 case 12:
1544 jam();
1545 terrorCode = ZSIMPLE_READ_WITHOUT_AI;
1546 releaseAtErrorLab(signal);
1547 return;
1548
1549 case 13:
1550 jam();
1551 switch (tcConnectptr.p->tcConnectstate) {
1552 case OS_WAIT_KEYINFO:
1553 jam();
1554 printState(signal, 8);
1555 terrorCode = ZSTATE_ERROR;
1556 abortErrorLab(signal);
1557 return;
1558 default:
1559 jam();
1560 /********************************************************************/
1561 /* MISMATCH BETWEEN STATE ON API CONNECTION AND THIS */
1562 /* PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB */
1563 /* INTERNAL ERROR. */
1564 /********************************************************************/
1565 systemErrorLab(signal, __LINE__);
1566 return;
1567 }//switch
1568 return;
1569
1570 case 15:
1571 jam();
1572 terrorCode = ZSCAN_NODE_ERROR;
1573 releaseAtErrorLab(signal);
1574 return;
1575
1576 case 16:
1577 jam();
1578 systemErrorLab(signal, __LINE__);
1579 return;
1580
1581 case 17:
1582 jam();
1583 systemErrorLab(signal, __LINE__);
1584 return;
1585
1586 case 18:
1587 jam();
1588 warningHandlerLab(signal, __LINE__);
1589 return;
1590
1591 case 19:
1592 jam();
1593 return;
1594
1595 case 20:
1596 jam();
1597 warningHandlerLab(signal, __LINE__);
1598 return;
1599
1600 case 21:
1601 jam();
1602 systemErrorLab(signal, __LINE__);
1603 return;
1604
1605 case 22:
1606 jam();
1607 systemErrorLab(signal, __LINE__);
1608 return;
1609
1610 case 23:
1611 jam();
1612 systemErrorLab(signal, __LINE__);
1613 return;
1614
1615 case 24:
1616 jam();
1617 appendToSectionErrorLab(signal);
1618 return;
1619
1620 case 25:
1621 jam();
1622 warningHandlerLab(signal, __LINE__);
1623 return;
1624
1625 case 26:
1626 jam();
1627 return;
1628
1629 case 27:
1630 systemErrorLab(signal, __LINE__);
1631 jam();
1632 return;
1633
1634 case 28:
1635 jam();
1636 // NOT USED
1637 return;
1638
1639 case 29:
1640 jam();
1641 systemErrorLab(signal, __LINE__);
1642 return;
1643
1644 case 30:
1645 jam();
1646 systemErrorLab(signal, __LINE__);
1647 return;
1648
1649 case 31:
1650 jam();
1651 systemErrorLab(signal, __LINE__);
1652 return;
1653
1654 case 32:
1655 jam();
1656 systemErrorLab(signal, __LINE__);
1657 return;
1658
1659 case 33:
1660 jam();
1661 systemErrorLab(signal, __LINE__);
1662 return;
1663
1664 case 34:
1665 jam();
1666 systemErrorLab(signal, __LINE__);
1667 return;
1668
1669 case 35:
1670 jam();
1671 systemErrorLab(signal, __LINE__);
1672 return;
1673
1674 case 36:
1675 jam();
1676 systemErrorLab(signal, __LINE__);
1677 return;
1678
1679 case 37:
1680 jam();
1681 systemErrorLab(signal, __LINE__);
1682 return;
1683
1684 case 38:
1685 jam();
1686 systemErrorLab(signal, __LINE__);
1687 return;
1688
1689 case 39:
1690 jam();
1691 systemErrorLab(signal, __LINE__);
1692 return;
1693
1694 case 40:
1695 jam();
1696 systemErrorLab(signal, __LINE__);
1697 return;
1698
1699 case 41:
1700 jam();
1701 systemErrorLab(signal, __LINE__);
1702 return;
1703
1704 case 42:
1705 jam();
1706 systemErrorLab(signal, __LINE__);
1707 return;
1708
1709 case 43:
1710 jam();
1711 systemErrorLab(signal, __LINE__);
1712 return;
1713
1714 case 44:
1715 jam();
1716 systemErrorLab(signal, __LINE__);
1717 return;
1718
1719 case 45:
1720 jam();
1721 systemErrorLab(signal, __LINE__);
1722 return;
1723
1724 case 46:
1725 jam();
1726 systemErrorLab(signal, __LINE__);
1727 return;
1728
1729 case 47:
1730 jam();
1731 terrorCode = apiConnectptr.p->returncode;
1732 releaseAtErrorLab(signal);
1733 return;
1734
1735 case 48:
1736 jam();
1737 terrorCode = ZCOMMIT_TYPE_ERROR;
1738 releaseAtErrorLab(signal);
1739 return;
1740
1741 case 49:
1742 jam();
1743 abortErrorLab(signal);
1744 return;
1745
1746 case 50:
1747 jam();
1748 systemErrorLab(signal, __LINE__);
1749 return;
1750
1751 case 51:
1752 jam();
1753 abortErrorLab(signal);
1754 return;
1755
1756 case 52:
1757 jam();
1758 abortErrorLab(signal);
1759 return;
1760
1761 case 53:
1762 jam();
1763 abortErrorLab(signal);
1764 return;
1765
1766 case 54:
1767 jam();
1768 abortErrorLab(signal);
1769 return;
1770
1771 case 55:
1772 jam();
1773 printState(signal, 5);
1774 sendSignalErrorRefuseLab(signal);
1775 return;
1776
1777 case 56:{
1778 jam();
1779 terrorCode = ZNO_FREE_TC_MARKER;
1780 abortErrorLab(signal);
1781 return;
1782 }
1783 case 57:{
1784 jam();
1785 /**
1786 * Initialize object before starting error handling
1787 */
1788 initApiConnectRec(signal, apiConnectptr.p, true);
1789 start_failure:
1790 switch(getNodeState().startLevel){
1791 case NodeState::SL_STOPPING_2:
1792 if (getNodeState().getSingleUserMode())
1793 {
1794 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1795 break;
1796 }
1797 case NodeState::SL_STOPPING_3:
1798 case NodeState::SL_STOPPING_4:
1799 if(getNodeState().stopping.systemShutdown)
1800 terrorCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1801 else
1802 terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1803 break;
1804 case NodeState::SL_SINGLEUSER:
1805 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1806 break;
1807 case NodeState::SL_STOPPING_1:
1808 if (getNodeState().getSingleUserMode())
1809 {
1810 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
1811 break;
1812 }
1813 default:
1814 terrorCode = ZWRONG_STATE;
1815 break;
1816 }
1817 abortErrorLab(signal);
1818 return;
1819 }
1820
1821 case 58:{
1822 jam();
1823 releaseAtErrorLab(signal);
1824 return;
1825 }
1826
1827 case 59:{
1828 jam();
1829 terrorCode = ZABORTINPROGRESS;
1830 abortErrorLab(signal);
1831 return;
1832 }
1833
1834 case 60:
1835 {
1836 jam();
1837 initApiConnectRec(signal, apiConnectptr.p, true);
1838 apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
1839 goto start_failure;
1840 }
1841 case 61:
1842 {
1843 jam();
1844 terrorCode = ZUNLOCKED_IVAL_TOO_HIGH;
1845 abortErrorLab(signal);
1846 return;
1847 }
1848 case 62:
1849 {
1850 jam();
1851 terrorCode = ZUNLOCKED_OP_HAS_BAD_STATE;
1852 abortErrorLab(signal);
1853 return;
1854 }
1855 case 63:
1856 {
1857 jam();
1858 /* Function not implemented yet */
1859 terrorCode = 4003;
1860 abortErrorLab(signal);
1861 return;
1862 }
1863 case 64:
1864 {
1865 jam();
1866 /* Invalid distribution key */
1867 terrorCode = ZBAD_DIST_KEY;
1868 abortErrorLab(signal);
1869 return;
1870 }
1871 case 65:
1872 {
1873 jam();
1874 terrorCode = ZTRANS_TOO_BIG;
1875 abortErrorLab(signal);
1876 return;
1877 }
1878 default:
1879 jam();
1880 systemErrorLab(signal, __LINE__);
1881 return;
1882 }//switch
1883 }
1884
1885 static
1886 inline
1887 bool
compare_transid(Uint32 * val0,Uint32 * val1)1888 compare_transid(Uint32* val0, Uint32* val1)
1889 {
1890 Uint32 tmp0 = val0[0] ^ val1[0];
1891 Uint32 tmp1 = val0[1] ^ val1[1];
1892 return (tmp0 | tmp1) == 0;
1893 }
1894
execKEYINFO(Signal * signal)1895 void Dbtc::execKEYINFO(Signal* signal)
1896 {
1897 jamEntry();
1898 apiConnectptr.i = signal->theData[0];
1899 tmaxData = 20;
1900 if (apiConnectptr.i >= capiConnectFilesize) {
1901 TCKEY_abort(signal, 18);
1902 return;
1903 }//if
1904 ptrAss(apiConnectptr, apiConnectRecord);
1905 ttransid_ptr = 1;
1906 if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
1907 {
1908 TCKEY_abort(signal, 19);
1909 return;
1910 }//if
1911 switch (apiConnectptr.p->apiConnectstate) {
1912 case CS_RECEIVING:
1913 case CS_REC_COMMITTING:
1914 case CS_START_SCAN:
1915 jam();
1916 /*empty*/;
1917 break;
1918 /* OK */
1919 case CS_ABORTING:
1920 jam();
1921 return; /* IGNORE */
1922 case CS_CONNECTED:
1923 jam();
1924 /****************************************************************>*/
1925 /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
1926 /* SET STATE TO ABORTING. */
1927 /****************************************************************>*/
1928 printState(signal, 11);
1929 signalErrorRefuseLab(signal);
1930 return;
1931 case CS_STARTED:
1932 jam();
1933 /****************************************************************>*/
1934 /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
1935 /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
1936 /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
1937 /****************************************************************>*/
1938 terrorCode = ZSIGNAL_ERROR;
1939 printState(signal, 2);
1940 abortErrorLab(signal);
1941 return;
1942 default:
1943 jam();
1944 warningHandlerLab(signal, __LINE__);
1945 return;
1946 }//switch
1947
1948 CacheRecord *localCacheRecord = cacheRecord;
1949 UintR TcacheFilesize = ccacheFilesize;
1950 UintR TcachePtr = apiConnectptr.p->cachePtr;
1951 UintR TtcTimer = ctcTimer;
1952 CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1953 if (TcachePtr >= TcacheFilesize) {
1954 TCKEY_abort(signal, 42);
1955 return;
1956 }//if
1957 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
1958 cachePtr.i = TcachePtr;
1959 cachePtr.p = regCachePtr;
1960
1961 tcConnectptr.i = apiConnectptr.p->lastTcConnect;
1962 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
1963 switch (tcConnectptr.p->tcConnectstate) {
1964 case OS_WAIT_KEYINFO:
1965 jam();
1966 tckeyreq020Lab(signal);
1967 return;
1968 case OS_WAIT_SCAN:
1969 jam();
1970 scanKeyinfoLab(signal);
1971 return;
1972 default:
1973 jam();
1974 terrorCode = ZSTATE_ERROR;
1975 abortErrorLab(signal);
1976 return;
1977 }//switch
1978 }//Dbtc::execKEYINFO()
1979
1980 /**
1981 * sendKeyInfoTrain
1982 * Method to send a KeyInfo signal train from KeyInfo in the supplied
1983 * Section
1984 * KeyInfo will be taken from the section, starting at the supplied
1985 * offset
1986 */
sendKeyInfoTrain(Signal * signal,BlockReference TBRef,Uint32 connectPtr,Uint32 offset,Uint32 sectionIVal)1987 void Dbtc::sendKeyInfoTrain(Signal* signal,
1988 BlockReference TBRef,
1989 Uint32 connectPtr,
1990 Uint32 offset,
1991 Uint32 sectionIVal)
1992 {
1993 jam();
1994
1995 signal->theData[0] = connectPtr;
1996 signal->theData[1] = apiConnectptr.p->transid[0];
1997 signal->theData[2] = apiConnectptr.p->transid[1];
1998 Uint32 * dst = signal->theData + KeyInfo::HeaderLength;
1999
2000 ndbassert( sectionIVal != RNIL );
2001 SectionReader keyInfoReader(sectionIVal, getSectionSegmentPool());
2002
2003 Uint32 totalLen= keyInfoReader.getSize();
2004
2005 ndbassert( offset < totalLen );
2006
2007 keyInfoReader.step(offset);
2008 totalLen-= offset;
2009
2010 while(totalLen != 0)
2011 {
2012 Uint32 dataInSignal= MIN(KeyInfo::DataLength, totalLen);
2013 keyInfoReader.getWords(dst, dataInSignal);
2014 totalLen-= dataInSignal;
2015
2016 sendSignal(TBRef, GSN_KEYINFO, signal,
2017 KeyInfo::HeaderLength + dataInSignal, JBB);
2018 }
2019 }//Dbtc::sendKeyInfoTrain()
2020
2021 /**
2022 * tckeyreq020Lab
2023 * Handle received KEYINFO signal
2024 */
tckeyreq020Lab(Signal * signal)2025 void Dbtc::tckeyreq020Lab(Signal* signal)
2026 {
2027 CacheRecord * const regCachePtr = cachePtr.p;
2028 UintR TkeyLen = regCachePtr->keylen;
2029 UintR Tlen = regCachePtr->save1;
2030 UintR wordsInSignal= MIN(KeyInfo::DataLength,
2031 (TkeyLen - Tlen));
2032
2033 ndbassert(! regCachePtr->isLongTcKeyReq );
2034 ndbassert( regCachePtr->keyInfoSectionI != RNIL );
2035
2036 /* Add received KeyInfo data to the existing KeyInfo section */
2037 if (! appendToSection(regCachePtr->keyInfoSectionI,
2038 &signal->theData[KeyInfo::HeaderLength],
2039 wordsInSignal))
2040 {
2041 jam();
2042 appendToSectionErrorLab(signal);
2043 return;
2044 }
2045 Tlen+= wordsInSignal;
2046
2047 if (Tlen < TkeyLen)
2048 {
2049 /* More KeyInfo still to be read
2050 * Set timer and state and wait
2051 */
2052 jam();
2053 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2054 regCachePtr->save1 = Tlen;
2055 tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2056 return;
2057 }
2058 else
2059 {
2060 /* Have all the KeyInfo ... continue processing
2061 * TCKEYREQ
2062 */
2063 jam();
2064 tckeyreq050Lab(signal);
2065 return;
2066 }
2067 }//Dbtc::tckeyreq020Lab()
2068
execATTRINFO(Signal * signal)2069 void Dbtc::execATTRINFO(Signal* signal)
2070 {
2071 UintR Tdata1 = signal->theData[0];
2072 UintR Tlength = signal->length();
2073 UintR TapiConnectFilesize = capiConnectFilesize;
2074 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2075
2076 jamEntry();
2077 apiConnectptr.i = Tdata1;
2078 ttransid_ptr = 1;
2079 if (Tdata1 >= TapiConnectFilesize) {
2080 DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2081 TCKEY_abort(signal, 18);
2082 return;
2083 }//if
2084
2085 ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
2086 apiConnectptr.p = regApiPtr;
2087
2088 if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
2089 {
2090 DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2091 << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2092 TCKEY_abort(signal, 19);
2093 return;
2094 }//if
2095 if (Tlength < 4) {
2096 DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2097 TCKEY_abort(signal, 20);
2098 return;
2099 }
2100 Tlength -= AttrInfo::HeaderLength;
2101 UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2102 UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2103 UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2104
2105 if (TcompBOTH) {
2106 jam();
2107 if (ERROR_INSERTED(8015)) {
2108 CLEAR_ERROR_INSERT_VALUE;
2109 return;
2110 }//if
2111 if (ERROR_INSERTED(8016)) {
2112 CLEAR_ERROR_INSERT_VALUE;
2113 return;
2114 }//if
2115 CacheRecord *localCacheRecord = cacheRecord;
2116 UintR TcacheFilesize = ccacheFilesize;
2117 UintR TcachePtr = regApiPtr->cachePtr;
2118 UintR TtcTimer = ctcTimer;
2119 CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2120 if (TcachePtr >= TcacheFilesize) {
2121 TCKEY_abort(signal, 43);
2122 return;
2123 }//if
2124
2125 /* Update TC global cache ptr */
2126 cachePtr.i= TcachePtr;
2127 cachePtr.p= regCachePtr;
2128
2129 regCachePtr->currReclenAi+= Tlength;
2130 int TattrlengthRemain = regCachePtr->attrlength -
2131 regCachePtr->currReclenAi;
2132
2133 /* Setup tcConnectptr to ensure that error handling etc.
2134 * can access required state
2135 */
2136 tcConnectptr.i = regApiPtr->lastTcConnect;
2137 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2138
2139 /* Add AttrInfo to any existing AttrInfo we have
2140 * Some short TCKEYREQ signals have no ATTRINFO in
2141 * the TCKEYREQ itself
2142 */
2143 if (! appendToSection(regCachePtr->attrInfoSectionI,
2144 &signal->theData[AttrInfo::HeaderLength],
2145 Tlength))
2146 {
2147 DEBUG("No more section segments available");
2148 appendToSectionErrorLab(signal);
2149 return;
2150 }//if
2151
2152 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2153
2154 if (TattrlengthRemain == 0) {
2155 /****************************************************************>*/
2156 /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
2157 /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2158 /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2159 /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
2160 /* OPERATIONS. */
2161 /****************************************************************>*/
2162 if (TcompRECEIVING) {
2163 jam();
2164 regApiPtr->apiConnectstate = CS_STARTED;
2165 } else {
2166 jam();
2167 regApiPtr->apiConnectstate = CS_START_COMMITTING;
2168 }//if
2169 attrinfoDihReceivedLab(signal);
2170 } else if (TattrlengthRemain < 0) {
2171 jam();
2172 DEBUG("ATTRINFO wrong total length="<<Tlength
2173 <<", TattrlengthRemain="<<TattrlengthRemain
2174 <<", TattrLen="<< regCachePtr->attrlength
2175 <<", TcurrReclenAi="<< regCachePtr->currReclenAi);
2176 tcConnectptr.i = regApiPtr->lastTcConnect;
2177 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2178 aiErrorLab(signal);
2179 }//if
2180 return;
2181 } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
2182 jam();
2183 scanAttrinfoLab(signal, Tlength);
2184 return;
2185 } else {
2186 switch (regApiPtr->apiConnectstate) {
2187 case CS_ABORTING:
2188 jam();
2189 /* JUST IGNORE THE SIGNAL*/
2190 // DEBUG("Drop ATTRINFO, CS_ABORTING");
2191 return;
2192 case CS_CONNECTED:
2193 jam();
2194 /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2195 // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2196 return;
2197 case CS_STARTED:
2198 jam();
2199 /****************************************************************>*/
2200 /* MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND */
2201 /* SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED */
2202 /* WE ALSO NEED TO ABORT THIS TRANSACTION. */
2203 /****************************************************************>*/
2204 terrorCode = ZSIGNAL_ERROR;
2205 printState(signal, 1);
2206 abortErrorLab(signal);
2207 return;
2208 default:
2209 jam();
2210 /****************************************************************>*/
2211 /* SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2212 /* SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED. */
2213 /****************************************************************>*/
2214 DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2215 printState(signal, 9);
2216 return;
2217 }//switch
2218 }//if
2219 }//Dbtc::execATTRINFO()
2220
2221 /* *********************************************************************>> */
2222 /* */
2223 /* MODULE: HASH MODULE */
2224 /* DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION */
2225 /* *********************************************************************> */
hash(Signal * signal)2226 void Dbtc::hash(Signal* signal)
2227 {
2228 UintR* Tdata32;
2229
2230 CacheRecord * const regCachePtr = cachePtr.p;
2231 SegmentedSectionPtr keyInfoSection;
2232 UintR keylen = (UintR)regCachePtr->keylen;
2233 Uint32 distKey = regCachePtr->distributionKeyIndicator;
2234
2235 getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
2236
2237 ndbassert( keyInfoSection.sz <= MAX_KEY_SIZE_IN_WORDS );
2238 ndbassert( keyInfoSection.sz == keylen );
2239 /* Copy KeyInfo section from segmented storage into linear storage
2240 * in signal->theData
2241 */
2242 if (keylen <= SectionSegment::DataLength)
2243 {
2244 /* No need to copy keyinfo into a linear space
2245 * Note that we require that the data in the section is
2246 * 64-bit aligned for md5_hash below
2247 */
2248 ndbassert( keyInfoSection.p != NULL );
2249
2250 Tdata32= &keyInfoSection.p->theData[0];
2251 }
2252 else
2253 {
2254 /* Copy segmented keyinfo into linear space in the signal */
2255 Tdata32= signal->theData;
2256 copy(Tdata32, keyInfoSection);
2257 }
2258
2259 Uint32 tmp[4];
2260 if(!regCachePtr->m_special_hash)
2261 {
2262 md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2263 }
2264 else
2265 {
2266 if (regCachePtr->m_no_hash)
2267 {
2268 /* No need for tuple key hash at LQH */
2269 ndbassert(distKey); /* User must supply distkey */
2270 Uint32 zero[4] = {0, 0, 0, 0};
2271 *tmp = *zero;
2272 }
2273 else
2274 {
2275 handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2276 }
2277 }
2278
2279 /* Primary key hash value is first word of hash on PK columns
2280 * Distribution key hash value is second word of hash on distribution
2281 * key columns, or a user defined value
2282 */
2283 thashValue = tmp[0];
2284 if (distKey){
2285 jam();
2286 tdistrHashValue = regCachePtr->distributionKey;
2287 } else {
2288 jam();
2289 tdistrHashValue = tmp[1];
2290 }//if
2291 }//Dbtc::hash()
2292
2293 bool
handle_special_hash(Uint32 dstHash[4],const Uint32 * src,Uint32 srcLen,Uint32 tabPtrI,bool distr)2294 Dbtc::handle_special_hash(Uint32 dstHash[4],
2295 const Uint32* src, Uint32 srcLen,
2296 Uint32 tabPtrI,
2297 bool distr)
2298 {
2299 const Uint32 MAX_KEY_SIZE_IN_LONG_WORDS=
2300 (MAX_KEY_SIZE_IN_WORDS + 1) / 2;
2301 Uint64 alignedWorkspace[MAX_KEY_SIZE_IN_LONG_WORDS * MAX_XFRM_MULTIPLY];
2302 Uint32* workspace= (Uint32*)alignedWorkspace;
2303 const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2304 const bool hasVarKeys = tabPtrP->hasVarKeys;
2305 const bool hasCharAttr = tabPtrP->hasCharAttr;
2306 const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2307
2308 const Uint32 *hashInput = workspace;
2309 Uint32 inputLen = 0;
2310 Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2311 Uint32 * keyPartLenPtr;
2312
2313 /* Normalise KeyInfo into workspace if necessary */
2314 if(hasCharAttr || (compute_distkey && hasVarKeys))
2315 {
2316 keyPartLenPtr = keyPartLen;
2317 inputLen = xfrm_key(tabPtrI,
2318 src,
2319 workspace,
2320 sizeof(alignedWorkspace) >> 2,
2321 keyPartLenPtr);
2322 if (unlikely(inputLen == 0))
2323 {
2324 goto error;
2325 }
2326 }
2327 else
2328 {
2329 /* Keyinfo already suitable for hash */
2330 hashInput = src;
2331 inputLen = srcLen;
2332 keyPartLenPtr = 0;
2333 }
2334
2335 /* Calculate primary key hash */
2336 md5_hash(dstHash, (Uint64*)hashInput, inputLen);
2337
2338 /* If the distribution key != primary key then we have to
2339 * form a distribution key from the primary key and calculate
2340 * a separate distribution hash based on this
2341 */
2342 if(compute_distkey)
2343 {
2344 jam();
2345
2346 Uint32 distrKeyHash[4];
2347 /* Reshuffle primary key columns to get just distribution key */
2348 Uint32 len = create_distr_key(tabPtrI, hashInput, workspace, keyPartLenPtr);
2349 /* Calculate distribution key hash */
2350 md5_hash(distrKeyHash, (Uint64*) workspace, len);
2351
2352 /* Just one word used for distribution */
2353 dstHash[1] = distrKeyHash[1];
2354 }
2355 return true; // success
2356
2357 error:
2358 terrorCode = ZINVALID_KEY;
2359 return false;
2360 }
2361
2362 /*
2363 INIT_API_CONNECT_REC
2364 ---------------------------
2365 */
2366 /* ========================================================================= */
2367 /* ======= INIT_API_CONNECT_REC ======= */
2368 /* */
2369 /* ========================================================================= */
initApiConnectRec(Signal * signal,ApiConnectRecord * const regApiPtr,bool releaseIndexOperations)2370 void Dbtc::initApiConnectRec(Signal* signal,
2371 ApiConnectRecord * const regApiPtr,
2372 bool releaseIndexOperations)
2373 {
2374 const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2375 UintR TfailureNr = cfailure_nr;
2376 UintR Ttransid0 = tcKeyReq->transId1;
2377 UintR Ttransid1 = tcKeyReq->transId2;
2378
2379 tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
2380 regApiPtr->returncode = 0;
2381 regApiPtr->returnsignal = RS_TCKEYCONF;
2382 ndbassert(regApiPtr->firstTcConnect == RNIL);
2383 regApiPtr->firstTcConnect = RNIL;
2384 regApiPtr->lastTcConnect = RNIL;
2385 regApiPtr->globalcheckpointid = 0;
2386 regApiPtr->lqhkeyconfrec = 0;
2387 regApiPtr->lqhkeyreqrec = 0;
2388 regApiPtr->tckeyrec = 0;
2389 regApiPtr->tcindxrec = 0;
2390 tc_clearbit(regApiPtr->m_flags,
2391 ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
2392 regApiPtr->no_commit_ack_markers = 0;
2393 regApiPtr->failureNr = TfailureNr;
2394 regApiPtr->transid[0] = Ttransid0;
2395 regApiPtr->transid[1] = Ttransid1;
2396 regApiPtr->commitAckMarker = RNIL;
2397 regApiPtr->buddyPtr = RNIL;
2398 regApiPtr->currSavePointId = 0;
2399 regApiPtr->m_transaction_nodes.clear();
2400 regApiPtr->singleUserMode = 0;
2401 regApiPtr->m_pre_commit_pass = 0;
2402 // Trigger data
2403 releaseFiredTriggerData(®ApiPtr->theFiredTriggers);
2404 // Index data
2405 tc_clearbit(regApiPtr->m_flags,
2406 ApiConnectRecord::TF_INDEX_OP_RETURN);
2407 regApiPtr->noIndexOp = 0;
2408 if(releaseIndexOperations)
2409 releaseAllSeizedIndexOperations(regApiPtr);
2410 regApiPtr->immediateTriggerId = RNIL;
2411
2412 tc_clearbit(regApiPtr->m_flags,
2413 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
2414 c_counters.ctransCount++;
2415
2416 #ifdef ERROR_INSERT
2417 regApiPtr->continueBCount = 0;
2418 #endif
2419
2420 regApiPtr->m_write_count = 0;
2421 }//Dbtc::initApiConnectRec()
2422
2423 int
seizeTcRecord(Signal * signal)2424 Dbtc::seizeTcRecord(Signal* signal)
2425 {
2426 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2427 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
2428 UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
2429 UintR TtcConnectFilesize = ctcConnectFilesize;
2430 tcConnectptr.i = TfirstfreeTcConnect;
2431 if (TfirstfreeTcConnect >= TtcConnectFilesize) {
2432 int place = 3;
2433 if (TfirstfreeTcConnect != RNIL) {
2434 place = 10;
2435 }//if
2436 TCKEY_abort(signal, place);
2437 return 1;
2438 }//if
2439 //--------------------------------------------------------------------------
2440 // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
2441 //--------------------------------------------------------------------------
2442 TcConnectRecord * const regTcPtr =
2443 &localTcConnectRecord[TfirstfreeTcConnect];
2444
2445 UintR TlastTcConnect = regApiPtr->lastTcConnect;
2446 UintR TtcConnectptrIndex = tcConnectptr.i;
2447 TcConnectRecordPtr tmpTcConnectptr;
2448
2449 cfirstfreeTcConnect = regTcPtr->nextTcConnect;
2450 tcConnectptr.p = regTcPtr;
2451
2452 c_counters.cconcurrentOp++;
2453
2454 regTcPtr->prevTcConnect = TlastTcConnect;
2455 regTcPtr->nextTcConnect = RNIL;
2456 regTcPtr->noFiredTriggers = 0;
2457 regTcPtr->noReceivedTriggers = 0;
2458 regTcPtr->triggerExecutionCount = 0;
2459 regTcPtr->triggeringOperation = RNIL;
2460 regTcPtr->m_special_op_flags = 0;
2461 regTcPtr->indexOp = RNIL;
2462 regTcPtr->currentTriggerId = RNIL;
2463 regTcPtr->tcConnectstate = OS_ABORTING;
2464 regTcPtr->noOfNodes = 0;
2465
2466 regApiPtr->lastTcConnect = TtcConnectptrIndex;
2467
2468 if (TlastTcConnect == RNIL) {
2469 jam();
2470 regApiPtr->firstTcConnect = TtcConnectptrIndex;
2471 } else {
2472 tmpTcConnectptr.i = TlastTcConnect;
2473 jam();
2474 ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
2475 tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
2476 }//if
2477 return 0;
2478 }//Dbtc::seizeTcRecord()
2479
2480 int
seizeCacheRecord(Signal * signal)2481 Dbtc::seizeCacheRecord(Signal* signal)
2482 {
2483 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2484 UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2485 UintR TcacheFilesize = ccacheFilesize;
2486 CacheRecord *localCacheRecord = cacheRecord;
2487 if (TfirstfreeCacheRec >= TcacheFilesize) {
2488 TCKEY_abort(signal, 41);
2489 return 1;
2490 }//if
2491 CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
2492
2493 regApiPtr->cachePtr = TfirstfreeCacheRec;
2494 cfirstfreeCacheRec = regCachePtr->nextCacheRec;
2495 cachePtr.i = TfirstfreeCacheRec;
2496 cachePtr.p = regCachePtr;
2497
2498 regCachePtr->currReclenAi = 0;
2499 regCachePtr->keyInfoSectionI = RNIL;
2500 regCachePtr->attrInfoSectionI = RNIL;
2501 return 0;
2502 }//Dbtc::seizeCacheRecord()
2503
2504 /*****************************************************************************/
2505 /* T C K E Y R E Q */
2506 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN */
2507 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST */
2508 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES */
2509 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA */
2510 /*****************************************************************************/
execTCKEYREQ(Signal * signal)2511 void Dbtc::execTCKEYREQ(Signal* signal)
2512 {
2513 Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
2514 UintR compare_transid1, compare_transid2;
2515 const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
2516 UintR Treqinfo;
2517 SectionHandle handle(this, signal);
2518
2519 jamEntry();
2520 /*-------------------------------------------------------------------------
2521 * Common error routines are used for several signals, they need to know
2522 * where to find the transaction identifier in the signal.
2523 *-------------------------------------------------------------------------*/
2524 const UintR TapiIndex = tcKeyReq->apiConnectPtr;
2525 const UintR TapiMaxIndex = capiConnectFilesize;
2526 const UintR TtabIndex = tcKeyReq->tableId;
2527 const UintR TtabMaxIndex = ctabrecFilesize;
2528 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2529
2530 ttransid_ptr = 6;
2531 apiConnectptr.i = TapiIndex;
2532 if (TapiIndex >= TapiMaxIndex) {
2533 releaseSections(handle);
2534 TCKEY_abort(signal, 6);
2535 return;
2536 }//if
2537 if (TtabIndex >= TtabMaxIndex) {
2538 releaseSections(handle);
2539 TCKEY_abort(signal, 7);
2540 return;
2541 }//if
2542
2543 #ifdef ERROR_INSERT
2544 if (ERROR_INSERTED(8079))
2545 {
2546 /* Test that no signals received after API_FAILREQ */
2547 if (sendersNodeId == c_lastFailedApi)
2548 {
2549 /* Signal from API node received *after* API_FAILREQ */
2550 ndbrequire(false);
2551 }
2552 }
2553 #endif
2554
2555 Treqinfo = tcKeyReq->requestInfo;
2556 //--------------------------------------------------------------------------
2557 // Optimised version of ptrAss(tabptr, tableRecord)
2558 // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
2559 //--------------------------------------------------------------------------
2560 ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
2561 apiConnectptr.p = regApiPtr;
2562
2563 Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
2564 Uint32 TexecFlag =
2565 TcKeyReq::getExecuteFlag(Treqinfo) ? ApiConnectRecord::TF_EXEC_FLAG : 0;
2566
2567 Uint8 Tspecial_op_flags = regApiPtr->m_special_op_flags;
2568 bool isIndexOpReturn = tc_testbit(regApiPtr->m_flags,
2569 ApiConnectRecord::TF_INDEX_OP_RETURN);
2570 bool isExecutingTrigger = Tspecial_op_flags & TcConnectRecord::SOF_TRIGGER;
2571 regApiPtr->m_special_op_flags = 0; // Reset marker
2572 regApiPtr->m_flags |= TexecFlag;
2573 TableRecordPtr localTabptr;
2574 localTabptr.i = TtabIndex;
2575 localTabptr.p = &tableRecord[TtabIndex];
2576 switch (regApiPtr->apiConnectstate) {
2577 case CS_CONNECTED:{
2578 if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2579 //---------------------------------------------------------------------
2580 // Initialise API connect record if transaction is started.
2581 //---------------------------------------------------------------------
2582 jam();
2583 initApiConnectRec(signal, regApiPtr);
2584 regApiPtr->m_flags |= TexecFlag;
2585 } else {
2586 releaseSections(handle);
2587 if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2588 /*------------------------------------------------------------------
2589 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
2590 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
2591 * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
2592 *-----------------------------------------------------------------*/
2593 TCKEY_abort(signal, 0);
2594 return;
2595 } else {
2596 /**
2597 * getAllowStartTransaction(sendersNodeId) == false
2598 */
2599 TCKEY_abort(signal, TexecFlag ? 60 : 57);
2600 return;
2601 }//if
2602 }
2603 }
2604 break;
2605 case CS_STARTED:
2606 if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
2607 {
2608 /**
2609 * If last operation in last transaction was a simple/dirty read
2610 * it does not have to be committed or rollbacked hence,
2611 * the state will be CS_STARTED
2612 */
2613 jam();
2614 if (unlikely(getNodeState().getSingleUserMode()) &&
2615 getNodeState().getSingleUserApi() != sendersNodeId &&
2616 !localTabptr.p->singleUserMode)
2617 {
2618 releaseSections(handle);
2619 TCKEY_abort(signal, TexecFlag ? 60 : 57);
2620 return;
2621 }
2622 initApiConnectRec(signal, regApiPtr);
2623 regApiPtr->m_flags |= TexecFlag;
2624 } else {
2625 //----------------------------------------------------------------------
2626 // Transaction is started already.
2627 // Check that the operation is on the same transaction.
2628 //-----------------------------------------------------------------------
2629 compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
2630 compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
2631 jam();
2632 compare_transid1 = compare_transid1 | compare_transid2;
2633 if (compare_transid1 != 0) {
2634 releaseSections(handle);
2635 TCKEY_abort(signal, 1);
2636 return;
2637 }//if
2638 }
2639 break;
2640 case CS_ABORTING:
2641 if (regApiPtr->abortState == AS_IDLE) {
2642 if (TstartFlag == 1) {
2643 if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
2644 releaseSections(handle);
2645 TCKEY_abort(signal, TexecFlag ? 60 : 57);
2646 return;
2647 }
2648 //--------------------------------------------------------------------
2649 // Previous transaction had been aborted and the abort was completed.
2650 // It is then OK to start a new transaction again.
2651 //--------------------------------------------------------------------
2652 jam();
2653 initApiConnectRec(signal, regApiPtr);
2654 regApiPtr->m_flags |= TexecFlag;
2655 } else if(TexecFlag) {
2656 releaseSections(handle);
2657 TCKEY_abort(signal, 59);
2658 return;
2659 } else {
2660 //--------------------------------------------------------------------
2661 // The current transaction was aborted successfully.
2662 // We will not do anything before we receive an operation
2663 // with a start indicator. We will ignore this signal.
2664 //--------------------------------------------------------------------
2665 jam();
2666 DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
2667 releaseSections(handle);
2668 return;
2669 }//if
2670 } else {
2671 //----------------------------------------------------------------------
2672 // Previous transaction is still aborting
2673 //----------------------------------------------------------------------
2674 jam();
2675 releaseSections(handle);
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 case CS_SEND_FIRE_TRIG_REQ:
2696 case CS_WAIT_FIRE_TRIG_REQ:
2697 jam();
2698 if(isIndexOpReturn || isExecutingTrigger){
2699 break;
2700 }
2701 default:
2702 jam();
2703 /*----------------------------------------------------------------------
2704 * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
2705 * WHEN IT WAS NOT EXPECTED TO.
2706 * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
2707 * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
2708 * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
2709 * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
2710 * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
2711 *---------------------------------------------------------------------*/
2712 releaseSections(handle);
2713 TCKEY_abort(signal, 55);
2714 return;
2715 }//switch
2716
2717 if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
2718 ;
2719 } else {
2720 /*-----------------------------------------------------------------------*/
2721 /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT. */
2722 /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED. */
2723 /*-----------------------------------------------------------------------*/
2724 releaseSections(handle);
2725 TCKEY_abort(signal, 8);
2726 return;
2727 }//if
2728
2729 //-------------------------------------------------------------------------
2730 // Error Insertion for testing purposes. Test to see what happens when no
2731 // more TC records available.
2732 //-------------------------------------------------------------------------
2733 if (ERROR_INSERTED(8032)) {
2734 releaseSections(handle);
2735 TCKEY_abort(signal, 3);
2736 return;
2737 }//if
2738
2739 if (seizeTcRecord(signal) != 0) {
2740 releaseSections(handle);
2741 return;
2742 }//if
2743
2744 if (seizeCacheRecord(signal) != 0) {
2745 releaseSections(handle);
2746 return;
2747 }//if
2748
2749 CRASH_INSERTION(8063);
2750
2751 TcConnectRecord * const regTcPtr = tcConnectptr.p;
2752 CacheRecord * const regCachePtr = cachePtr.p;
2753
2754 /*
2755 INIT_TC_CONNECT_REC
2756 -------------------------
2757 */
2758 /* ---------------------------------------------------------------------- */
2759 /* ------- INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS ------- */
2760 /* */
2761 /* ---------------------------------------------------------------------- */
2762
2763 UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen);
2764 UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
2765 regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
2766 regCachePtr->apiVersionNo = TapiVersionNo;
2767
2768 /* If we have any sections at all then this is a long TCKEYREQ */
2769 regCachePtr->isLongTcKeyReq= ( handle.m_cnt != 0 );
2770
2771 UintR TapiConnectptrIndex = apiConnectptr.i;
2772 UintR TsenderData = tcKeyReq->senderData;
2773
2774 if (ERROR_INSERTED(8065))
2775 {
2776 ErrorSignalReceive= 1;
2777 ErrorMaxSegmentsToSeize= 10;
2778 }
2779 if (ERROR_INSERTED(8066))
2780 {
2781 ErrorSignalReceive= 1;
2782 ErrorMaxSegmentsToSeize= 1;
2783 }
2784 if (ERROR_INSERTED(8067))
2785 {
2786 ErrorSignalReceive= 1;
2787 ErrorMaxSegmentsToSeize= 0;
2788 }
2789 if (ERROR_INSERTED(8068))
2790 {
2791 ErrorSignalReceive= 0;
2792 ErrorMaxSegmentsToSeize= 0;
2793 CLEAR_ERROR_INSERT_VALUE;
2794 DEBUG("Max segments to seize cleared");
2795 }
2796 #ifdef ERROR_INSERT
2797 if (ErrorSignalReceive)
2798 DEBUG("Max segments to seize : "
2799 << ErrorMaxSegmentsToSeize);
2800 #endif
2801
2802 /* Key and attribute lengths are passed in the header for
2803 * short TCKEYREQ and passed as section lengths for long
2804 * TCKEYREQ
2805 */
2806 UintR TkeyLength = 0;
2807 UintR TattrLen = 0;
2808 UintR titcLenAiInTckeyreq = 0;
2809
2810 if (regCachePtr->isLongTcKeyReq)
2811 {
2812 SegmentedSectionPtr keyInfoSec;
2813 if (handle.getSection(keyInfoSec, TcKeyReq::KeyInfoSectionNum))
2814 TkeyLength= keyInfoSec.sz;
2815
2816 SegmentedSectionPtr attrInfoSec;
2817 if (handle.getSection(attrInfoSec, TcKeyReq::AttrInfoSectionNum))
2818 TattrLen= attrInfoSec.sz;
2819
2820 if (TcKeyReq::getDeferredConstraints(Treqinfo))
2821 {
2822 regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
2823 }
2824 }
2825 else
2826 {
2827 TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
2828 TattrLen= TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
2829 titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
2830 }
2831
2832 regCachePtr->keylen = TkeyLength;
2833 regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
2834 regCachePtr->currReclenAi = titcLenAiInTckeyreq;
2835
2836 regTcPtr->apiConnect = TapiConnectptrIndex;
2837 regTcPtr->clientData = TsenderData;
2838 regTcPtr->commitAckMarker = RNIL;
2839 regTcPtr->m_special_op_flags = Tspecial_op_flags;
2840 regTcPtr->indexOp = regApiPtr->executingIndexOp;
2841 regTcPtr->savePointId = regApiPtr->currSavePointId;
2842 regApiPtr->executingIndexOp = RNIL;
2843
2844 regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
2845
2846 if (isExecutingTrigger)
2847 {
2848 // Save the TcOperationPtr for fireing operation
2849 regTcPtr->triggeringOperation = TsenderData;
2850 // Grab trigger Id from ApiConnectRecord
2851 ndbrequire(regApiPtr->immediateTriggerId != RNIL);
2852 regTcPtr->currentTriggerId= regApiPtr->immediateTriggerId;
2853 }
2854 ndbassert(isExecutingTrigger ||
2855 (regApiPtr->immediateTriggerId == RNIL));
2856
2857 if (TexecFlag){
2858 Uint32 currSPId = regApiPtr->currSavePointId;
2859 regApiPtr->currSavePointId = ++currSPId;
2860 }
2861
2862 regCachePtr->attrlength = TattrLen;
2863 c_counters.cattrinfoCount += TattrLen;
2864
2865 UintR TtabptrIndex = localTabptr.i;
2866 UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
2867 Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
2868 regCachePtr->tableref = TtabptrIndex;
2869 regCachePtr->schemaVersion = TtableSchemaVersion;
2870 regTcPtr->operation = TOperationType;
2871
2872 Uint8 TSimpleFlag = TcKeyReq::getSimpleFlag(Treqinfo);
2873 Uint8 TDirtyFlag = TcKeyReq::getDirtyFlag(Treqinfo);
2874 Uint8 TInterpretedFlag = TcKeyReq::getInterpretedFlag(Treqinfo);
2875 Uint8 TDistrKeyFlag = TcKeyReq::getDistributionKeyFlag(Treqinfo);
2876 Uint8 TNoDiskFlag = TcKeyReq::getNoDiskFlag(Treqinfo);
2877 Uint8 TexecuteFlag = TexecFlag;
2878 Uint8 Treorg = TcKeyReq::getReorgFlag(Treqinfo);
2879 const Uint8 TViaSPJFlag = TcKeyReq::getViaSPJFlag(Treqinfo);
2880 const Uint8 Tqueue = TcKeyReq::getQueueOnRedoProblemFlag(Treqinfo);
2881
2882 if (Treorg)
2883 {
2884 if (TOperationType == ZWRITE)
2885 regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_COPY;
2886 else if (TOperationType == ZDELETE)
2887 regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_DELETE;
2888 else
2889 {
2890 ndbassert(false);
2891 }
2892 }
2893
2894 regTcPtr->dirtyOp = TDirtyFlag;
2895 regTcPtr->opSimple = TSimpleFlag;
2896 regCachePtr->opExec = TInterpretedFlag;
2897 regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
2898 regCachePtr->m_no_disk_flag = TNoDiskFlag;
2899 regCachePtr->viaSPJFlag = TViaSPJFlag;
2900 regCachePtr->m_op_queue = Tqueue;
2901
2902 //-------------------------------------------------------------
2903 // The next step is to read the upto three conditional words.
2904 //-------------------------------------------------------------
2905 Uint32 TkeyIndex;
2906 Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
2907 {
2908 Uint32 TDistrGHIndex = TcKeyReq::getScanIndFlag(Treqinfo);
2909 Uint32 TDistrKeyIndex = TDistrGHIndex;
2910
2911 Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
2912
2913 regCachePtr->scanTakeOverInd = TDistrGHIndex;
2914 regCachePtr->scanInfo = TscanInfo;
2915
2916 regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
2917
2918 TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
2919 }
2920
2921 regCachePtr->m_no_hash = false;
2922
2923 if (TOperationType == ZUNLOCK)
2924 {
2925 /* Unlock op has distribution key containing
2926 * LQH nodeid and fragid
2927 */
2928 ndbassert( regCachePtr->distributionKeyIndicator );
2929 regCachePtr->m_no_hash = 1;
2930 regCachePtr->unlockNodeId = (regCachePtr->distributionKey >> 16);
2931 regCachePtr->distributionKey &= 0xffff;
2932 }
2933
2934 regCachePtr->m_special_hash =
2935 localTabptr.p->hasCharAttr |
2936 (localTabptr.p->noOfDistrKeys > 0) |
2937 regCachePtr->m_no_hash;
2938
2939 if (TkeyLength == 0)
2940 {
2941 releaseSections(handle);
2942 TCKEY_abort(signal, 4);
2943 return;
2944 }
2945
2946 /* KeyInfo and AttrInfo are buffered in segmented sections
2947 * If they arrived in segmented sections then there's nothing to do
2948 * If they arrived in short signals then they are appended into
2949 * segmented sections
2950 */
2951 if (regCachePtr->isLongTcKeyReq)
2952 {
2953 ndbassert( titcLenAiInTckeyreq == 0);
2954 /* Long TcKeyReq - KI and AI already in sections */
2955 SegmentedSectionPtr keyInfoSection, attrInfoSection;
2956
2957 /* Store i value for first long section of KeyInfo
2958 * and AttrInfo in Cache Record
2959 */
2960 handle.getSection(keyInfoSection,
2961 TcKeyReq::KeyInfoSectionNum);
2962
2963 regCachePtr->keyInfoSectionI= keyInfoSection.i;
2964
2965 if (regCachePtr->attrlength != 0)
2966 {
2967 ndbassert( handle.m_cnt == 2 );
2968 handle.getSection(attrInfoSection,
2969 TcKeyReq::AttrInfoSectionNum);
2970 regCachePtr->attrInfoSectionI= attrInfoSection.i;
2971 }
2972 else
2973 {
2974 ndbassert( handle.m_cnt == 1 );
2975 }
2976
2977 /* Detach sections from the handle, we are now responsible
2978 * for always freeing them before returning
2979 * For a long TcKeyReq, they will be freed at the end
2980 * of the processing this signal.
2981 */
2982 handle.clear();
2983 }
2984 else
2985 {
2986 /* Short TcKeyReq - need to receive KI and AI into
2987 * segmented sections
2988 * We store any KI and AI from the TCKeyReq now and
2989 * will then wait for further signals if necessary
2990 */
2991 ndbassert( handle.m_cnt == 0 );
2992 Uint32 keyInfoInTCKeyReq= MIN(TkeyLength, TcKeyReq::MaxKeyInfo);
2993
2994 bool ok= appendToSection(regCachePtr->keyInfoSectionI,
2995 &TOptionalDataPtr[TkeyIndex],
2996 keyInfoInTCKeyReq);
2997 if (!ok)
2998 {
2999 jam();
3000 appendToSectionErrorLab(signal);
3001 return;
3002 }
3003
3004 if (titcLenAiInTckeyreq != 0)
3005 {
3006 Uint32 TAIDataIndex= TkeyIndex + keyInfoInTCKeyReq;
3007
3008 ok= appendToSection(regCachePtr->attrInfoSectionI,
3009 &TOptionalDataPtr[TAIDataIndex],
3010 titcLenAiInTckeyreq);
3011 if (!ok)
3012 {
3013 jam();
3014 appendToSectionErrorLab(signal);
3015 return;
3016 }
3017 }
3018 }
3019
3020 if (TOperationType == ZUNLOCK)
3021 {
3022 jam();
3023 // TODO : Consider adding counter for unlock operations
3024 }
3025 else if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
3026 jam();
3027 c_counters.creadCount++;
3028 }
3029 else
3030 {
3031 /* Insert, Update, Write, Delete */
3032 if (!tc_testbit(regApiPtr->m_flags,
3033 ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED))
3034 {
3035 if(regApiPtr->commitAckMarker != RNIL)
3036 regTcPtr->commitAckMarker = regApiPtr->commitAckMarker;
3037 else
3038 {
3039 jam();
3040 CommitAckMarkerPtr tmp;
3041 if (ERROR_INSERTED(8087))
3042 {
3043 CLEAR_ERROR_INSERT_VALUE;
3044 TCKEY_abort(signal, 56);
3045 return;
3046 }
3047
3048 if (!m_commitAckMarkerHash.seize(tmp))
3049 {
3050 TCKEY_abort(signal, 56);
3051 return;
3052 }
3053 else
3054 {
3055 regTcPtr->commitAckMarker = tmp.i;
3056 regApiPtr->commitAckMarker = tmp.i;
3057 tmp.p->transid1 = tcKeyReq->transId1;
3058 tmp.p->transid2 = tcKeyReq->transId2;
3059 tmp.p->apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
3060 tmp.p->apiConnectPtr = TapiIndex;
3061 tmp.p->m_commit_ack_marker_nodes.clear();
3062 #if defined VM_TRACE || defined ERROR_INSERT
3063 {
3064 CommitAckMarkerPtr check;
3065 ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
3066 }
3067 #endif
3068 m_commitAckMarkerHash.add(tmp);
3069 }
3070 }
3071 regApiPtr->no_commit_ack_markers++;
3072 }
3073
3074 UintR Toperationsize = coperationsize;
3075 /* --------------------------------------------------------------------
3076 * THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
3077 * THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
3078 * TEMP TABLES DON'T PARTICIPATE.
3079 * -------------------------------------------------------------------- */
3080 if (localTabptr.p->get_storedTable()) {
3081 coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
3082 }
3083 c_counters.cwriteCount++;
3084 switch (TOperationType) {
3085 case ZUPDATE:
3086 case ZINSERT:
3087 case ZDELETE:
3088 case ZWRITE:
3089 case ZREFRESH:
3090 jam();
3091 if (unlikely((++ regApiPtr->m_write_count) > m_max_writes_per_trans))
3092 {
3093 TCKEY_abort(signal, 65);
3094 return;
3095 }
3096 break;
3097 default:
3098 TCKEY_abort(signal, 9);
3099 return;
3100 }//switch
3101 }//if
3102
3103 Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
3104 regTcPtr->m_execAbortOption = TabortOption;
3105
3106 /*-------------------------------------------------------------------------
3107 * Check error handling per operation
3108 * If CommitFlag is set state accordingly and check for early abort
3109 *------------------------------------------------------------------------*/
3110 if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
3111 ndbrequire(TexecuteFlag);
3112 regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3113 } else {
3114 /* ---------------------------------------------------------------------
3115 * PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
3116 * ---------------------------------------------------------------------
3117 * ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
3118 * IF PREPARE TRANSACTION THEN
3119 * API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
3120 * SET STATE TO PREPARING
3121 * --------------------------------------------------------------------- */
3122 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3123 jam();
3124 // Trigger execution at commit
3125 regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3126 } else if (!regApiPtr->isExecutingDeferredTriggers()) {
3127 jam();
3128 regApiPtr->apiConnectstate = CS_RECEIVING;
3129 }//if
3130 }//if
3131
3132 if (regCachePtr->isLongTcKeyReq)
3133 {
3134 jam();
3135 /* Have all the KeyInfo (and AttrInfo), process now */
3136 tckeyreq050Lab(signal);
3137 }
3138 else if (TkeyLength <= TcKeyReq::MaxKeyInfo)
3139 {
3140 jam();
3141 /* Have all the KeyInfo, get any extra AttrInfo */
3142 tckeyreq050Lab(signal);
3143 }
3144 else
3145 {
3146 jam();
3147 /* --------------------------------------------------------------------
3148 * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
3149 * SAVE STATE AND WAIT FOR KEYINFO
3150 * --------------------------------------------------------------------*/
3151 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
3152 regCachePtr->save1 = 8;
3153 regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
3154 return;
3155 }//if
3156
3157 return;
3158 }//Dbtc::execTCKEYREQ()
3159
3160 static
3161 void
handle_reorg_trigger(DiGetNodesConf * conf)3162 handle_reorg_trigger(DiGetNodesConf * conf)
3163 {
3164 if (conf->reqinfo & DiGetNodesConf::REORG_MOVING)
3165 {
3166 conf->fragId = conf->nodes[MAX_REPLICAS];
3167 conf->reqinfo = conf->nodes[MAX_REPLICAS+1];
3168 memcpy(conf->nodes, conf->nodes+MAX_REPLICAS+2, sizeof(conf->nodes));
3169 }
3170 else
3171 {
3172 conf->nodes[0] = 0; // Should not execute...
3173 }
3174 }
3175
3176 bool
isRefreshSupported() const3177 Dbtc::isRefreshSupported() const
3178 {
3179 const NodeVersionInfo& nvi = getNodeVersionInfo();
3180 const Uint32 minVer = nvi.m_type[NodeInfo::DB].m_min_version;
3181 const Uint32 maxVer = nvi.m_type[NodeInfo::DB].m_max_version;
3182
3183 if (likely (minVer == maxVer))
3184 {
3185 /* Normal case, use function */
3186 return ndb_refresh_tuple(minVer);
3187 }
3188
3189 /* As refresh feature was introduced across three minor versions
3190 * we check that all data nodes support it. This slow path
3191 * should only be hit during upgrades between versions
3192 */
3193 for (Uint32 i=1; i < MAX_NODES; i++)
3194 {
3195 const NodeInfo& nodeInfo = getNodeInfo(i);
3196 if ((nodeInfo.m_type == NODE_TYPE_DB) &&
3197 (nodeInfo.m_connected) &&
3198 (! ndb_refresh_tuple(nodeInfo.m_version)))
3199 return false;
3200 }
3201 return true;
3202 }
3203
3204 /**
3205 * tckeyreq050Lab
3206 * This method is executed once all KeyInfo has been obtained for
3207 * the TcKeyReq signal
3208 */
tckeyreq050Lab(Signal * signal)3209 void Dbtc::tckeyreq050Lab(Signal* signal)
3210 {
3211 UintR tnoOfBackup;
3212 UintR tnoOfStandby;
3213 UintR tnodeinfo;
3214
3215 terrorCode = 0;
3216
3217 hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
3218
3219 CacheRecord * const regCachePtr = cachePtr.p;
3220 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3221 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3222
3223 UintR TtcTimer = ctcTimer;
3224 UintR ThashValue = thashValue;
3225 UintR TdistrHashValue = tdistrHashValue;
3226 UintR Ttableref = regCachePtr->tableref;
3227 Uint8 Tspecial_op_flags = regTcPtr->m_special_op_flags;
3228
3229 TableRecordPtr localTabptr;
3230 localTabptr.i = Ttableref;
3231 localTabptr.p = &tableRecord[localTabptr.i];
3232 Uint32 schemaVersion = regCachePtr->schemaVersion;
3233 if(localTabptr.p->checkTable(schemaVersion)){
3234 ;
3235 } else {
3236 terrorCode = localTabptr.p->getErrorCode(schemaVersion);
3237 TCKEY_abort(signal, 58);
3238 return;
3239 }
3240
3241 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3242 regCachePtr->hashValue = ThashValue;
3243
3244 ndbassert( signal->getNoOfSections() == 0 );
3245
3246 DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
3247 req->tableId = Ttableref;
3248 req->hashValue = TdistrHashValue;
3249 req->distr_key_indicator = regCachePtr->distributionKeyIndicator;
3250 * (EmulatedJamBuffer**)req->jamBuffer = jamBuffer();
3251
3252 /*-------------------------------------------------------------*/
3253 /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
3254 /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE */
3255 /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION. */
3256 /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
3257 /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
3258 /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB. */
3259 /*-------------------------------------------------------------*/
3260 EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
3261 DiGetNodesReq::SignalLength, 0);
3262 DiGetNodesConf * conf = (DiGetNodesConf *)&signal->theData[0];
3263 UintR Tdata2 = conf->reqinfo;
3264 UintR TerrorIndicator = signal->theData[0];
3265 jamEntry();
3266 if (TerrorIndicator != 0) {
3267 execDIGETNODESREF(signal);
3268 return;
3269 }
3270
3271 if((ERROR_INSERTED(8071) || ERROR_INSERTED(8072)) &&
3272 (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) &&
3273 signal->theData[3] != getOwnNodeId())
3274 {
3275 ndbassert(false);
3276 signal->theData[1] = 626;
3277 execDIGETNODESREF(signal);
3278 return;
3279 }
3280
3281 if((ERROR_INSERTED(8050) || ERROR_INSERTED(8072)) &&
3282 refToBlock(regApiPtr->ndbapiBlockref) != DBUTIL &&
3283 regTcPtr->m_special_op_flags == 0 &&
3284 signal->theData[3] != getOwnNodeId())
3285 {
3286 ndbassert(false);
3287 signal->theData[1] = 626;
3288 execDIGETNODESREF(signal);
3289 return;
3290 }
3291
3292 /****************>>*/
3293 /* DIGETNODESCONF >*/
3294 /* ***************>*/
3295 if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_TRIGGER_BASE)
3296 {
3297 jam();
3298 handle_reorg_trigger(conf);
3299 Tdata2 = conf->reqinfo;
3300 }
3301 else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_DELETE)
3302 {
3303 jam();
3304 handle_reorg_trigger(conf);
3305 Tdata2 = conf->reqinfo;
3306 }
3307 else if (Tdata2 & DiGetNodesConf::REORG_MOVING)
3308 {
3309 jam();
3310 regTcPtr->m_special_op_flags |= TcConnectRecord::SOF_REORG_MOVING;
3311 }
3312 else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_COPY)
3313 {
3314 jam();
3315 conf->nodes[0] = 0;
3316 }
3317
3318 UintR Tdata1 = conf->fragId;
3319 UintR Tdata3 = conf->nodes[0];
3320 UintR Tdata4 = conf->nodes[1];
3321 UintR Tdata5 = conf->nodes[2];
3322 UintR Tdata6 = conf->nodes[3];
3323
3324 regCachePtr->fragmentid = Tdata1;
3325 tnodeinfo = Tdata2;
3326
3327 regTcPtr->tcNodedata[0] = Tdata3;
3328 regTcPtr->tcNodedata[1] = Tdata4;
3329 regTcPtr->tcNodedata[2] = Tdata5;
3330 regTcPtr->tcNodedata[3] = Tdata6;
3331
3332 regTcPtr->lqhInstanceKey = (Tdata2 >> 24) & 127;// 1 bit used for reorg moving
3333
3334 Uint8 Toperation = regTcPtr->operation;
3335 Uint8 TopSimple = regTcPtr->opSimple;
3336 Uint8 TopDirty = regTcPtr->dirtyOp;
3337 tnoOfBackup = tnodeinfo & 3;
3338 tnoOfStandby = (tnodeinfo >> 8) & 3;
3339
3340 regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
3341 if (Toperation == ZREAD || Toperation == ZREAD_EX)
3342 {
3343 regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3344 if (TopSimple == 1 && TopDirty == 0){
3345 jam();
3346 /*-------------------------------------------------------------*/
3347 /* A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND */
3348 /* BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS */
3349 /* NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION */
3350 /* WITH SIMPLE READS. */
3351 /*-------------------------------------------------------------*/
3352 arrGuard(tnoOfBackup, MAX_REPLICAS);
3353 UintR Tindex;
3354 UintR TownNode = cownNodeid;
3355 for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
3356 UintR Tnode = regTcPtr->tcNodedata[Tindex];
3357 jam();
3358 if (Tnode == TownNode) {
3359 jam();
3360 regTcPtr->tcNodedata[0] = Tnode;
3361 }//if
3362 }//for
3363 if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
3364 {
3365 for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
3366 {
3367 UintR Tnode = regTcPtr->tcNodedata[Tindex];
3368 jam();
3369 if (Tnode != TownNode) {
3370 jam();
3371 regTcPtr->tcNodedata[0] = Tnode;
3372 ndbout_c("Choosing %d", Tnode);
3373 }//if
3374 }//for
3375 }
3376 }//if
3377 jam();
3378 regTcPtr->lastReplicaNo = 0;
3379 regTcPtr->noOfNodes = 1;
3380 }
3381 else if (Toperation == ZUNLOCK)
3382 {
3383 regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3384
3385 const Uint32 numNodes = tnoOfBackup + 1;
3386 /* Check that node from dist key is one of the nodes returned */
3387 bool found = false;
3388 for (Uint32 idx = 0; idx < numNodes; idx ++)
3389 {
3390 Uint32 nodeId = regTcPtr->tcNodedata[ idx ];
3391 jam();
3392 if (nodeId == regCachePtr->unlockNodeId)
3393 {
3394 jam();
3395 found = true;
3396 break;
3397 }
3398 }
3399
3400 if (unlikely(!found))
3401 {
3402 /* DIH says the specified node does not store the fragment
3403 * requested
3404 */
3405 jam();
3406 TCKEY_abort(signal, 64);
3407 return;
3408 }
3409
3410 /* Check that the relevant LQH node can handle an unlock request */
3411 Uint32 lqhVersion = getNodeInfo(regCachePtr->unlockNodeId).m_version;
3412
3413 if (unlikely( lqhVersion < NDBD_UNLOCK_OP_SUPPORTED ))
3414 {
3415 TCKEY_abort(signal, 63);
3416 return;
3417 }
3418
3419 /* Select the specified node for the unlock op */
3420 regTcPtr->tcNodedata[0] = regCachePtr->unlockNodeId;
3421 regTcPtr->lastReplicaNo = 0;
3422 regTcPtr->noOfNodes = 1;
3423 }
3424 else {
3425 UintR TlastReplicaNo;
3426 jam();
3427 TlastReplicaNo = tnoOfBackup + tnoOfStandby;
3428 regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
3429 regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
3430
3431 if (unlikely((Toperation == ZREFRESH) &&
3432 (! isRefreshSupported())))
3433 {
3434 /* Function not implemented yet */
3435 TCKEY_abort(signal,63);
3436 return;
3437 }
3438 }//if
3439
3440 if (regCachePtr->isLongTcKeyReq ||
3441 (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength)) {
3442 /****************************************************************>*/
3443 /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS */
3444 /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
3445 /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
3446 /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER */
3447 /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
3448 /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET. */
3449 /****************************************************************>*/
3450 switch (regApiPtr->apiConnectstate) {
3451 case CS_RECEIVING:
3452 jam();
3453 regApiPtr->apiConnectstate = CS_STARTED;
3454 break;
3455 case CS_REC_COMMITTING:
3456 jam();
3457 regApiPtr->apiConnectstate = CS_START_COMMITTING;
3458 break;
3459 case CS_SEND_FIRE_TRIG_REQ:
3460 case CS_WAIT_FIRE_TRIG_REQ:
3461 jam();
3462 break;
3463 default:
3464 jam();
3465 systemErrorLab(signal, __LINE__);
3466 return;
3467 }//switch
3468 attrinfoDihReceivedLab(signal);
3469 return;
3470 } else {
3471 if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
3472 TtcTimer = ctcTimer;
3473 jam();
3474 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3475 regTcPtr->tcConnectstate = OS_WAIT_ATTR;
3476 return;
3477 } else {
3478 TCKEY_abort(signal, 11);
3479 return;
3480 }//if
3481 }//if
3482 return;
3483 }//Dbtc::tckeyreq050Lab()
3484
attrinfoDihReceivedLab(Signal * signal)3485 void Dbtc::attrinfoDihReceivedLab(Signal* signal)
3486 {
3487 CacheRecord * const regCachePtr = cachePtr.p;
3488 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3489 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3490 Uint16 Tnode = regTcPtr->tcNodedata[0];
3491
3492 TableRecordPtr localTabptr;
3493 localTabptr.i = regCachePtr->tableref;
3494 localTabptr.p = &tableRecord[localTabptr.i];
3495
3496 if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
3497 ;
3498 } else {
3499 terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
3500 TCKEY_abort(signal, 58);
3501 return;
3502 }
3503 if (Tnode != 0)
3504 {
3505 jam();
3506 arrGuard(Tnode, MAX_NDB_NODES);
3507 Uint32 instanceKey = regTcPtr->lqhInstanceKey;
3508 BlockReference lqhRef;
3509 if(regCachePtr->viaSPJFlag){
3510 //ndbout << "TC:Choosing SPJ." << endl;
3511 lqhRef = numberToRef(DBSPJ, Tnode); // Only 1 instance
3512 }else{
3513 //ndbout << "TC:Choosing LQH." << endl;
3514 lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3515 }
3516 packLqhkeyreq(signal, lqhRef);
3517 }
3518 else
3519 {
3520 /**
3521 * 1) This is when a reorg trigger fired...
3522 * but the tuple should *not* move
3523 * This should be prevent using the LqhKeyReq::setReorgFlag
3524 *
3525 * 2) This also happens during reorg copy, when a row should *not* be moved
3526 */
3527 jam();
3528 Uint32 trigOp = regTcPtr->triggeringOperation;
3529 Uint32 TclientData = regTcPtr->clientData;
3530 releaseKeys();
3531 releaseAttrinfo();
3532 regApiPtr->lqhkeyreqrec--;
3533 unlinkReadyTcCon(signal);
3534 clearCommitAckMarker(regApiPtr, regTcPtr);
3535 releaseTcCon();
3536
3537 if (trigOp != RNIL)
3538 {
3539 jam();
3540 //ndbassert(false); // see above
3541 TcConnectRecordPtr opPtr;
3542 opPtr.i = trigOp;
3543 ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
3544 trigger_op_finished(signal, apiConnectptr, opPtr.p);
3545 return;
3546 }
3547 else
3548 {
3549 jam();
3550 Uint32 Ttckeyrec = regApiPtr->tckeyrec;
3551 regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
3552 regApiPtr->tcSendArray[Ttckeyrec + 1] = 0;
3553 regApiPtr->tckeyrec = Ttckeyrec + 2;
3554 lqhKeyConf_checkTransactionState(signal, apiConnectptr);
3555 }
3556 }
3557 }//Dbtc::attrinfoDihReceivedLab()
3558
packLqhkeyreq(Signal * signal,BlockReference TBRef)3559 void Dbtc::packLqhkeyreq(Signal* signal,
3560 BlockReference TBRef)
3561 {
3562 CacheRecord * const regCachePtr = cachePtr.p;
3563 UintR Tkeylen = regCachePtr->keylen;
3564
3565 ndbassert( signal->getNoOfSections() == 0 );
3566
3567 sendlqhkeyreq(signal, TBRef);
3568
3569 /* Do we need to send a KeyInfo signal train? */
3570 if ((! regCachePtr->useLongLqhKeyReq) &&
3571 (Tkeylen > LqhKeyReq::MaxKeyInfo))
3572 {
3573 /* Build KeyInfo train from KeyInfo long signal section */
3574 sendKeyInfoTrain(signal,
3575 TBRef,
3576 tcConnectptr.i,
3577 LqhKeyReq::MaxKeyInfo,
3578 regCachePtr->keyInfoSectionI);
3579 }//if
3580
3581 /* Release key storage */
3582 releaseKeys();
3583 packLqhkeyreq040Lab(signal,
3584 TBRef);
3585 }//Dbtc::packLqhkeyreq()
3586
3587
sendlqhkeyreq(Signal * signal,BlockReference TBRef)3588 void Dbtc::sendlqhkeyreq(Signal* signal,
3589 BlockReference TBRef)
3590 {
3591 UintR tslrAttrLen;
3592 UintR Tdata10;
3593 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3594 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3595 CacheRecord * const regCachePtr = cachePtr.p;
3596 Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
3597 UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
3598 #ifdef ERROR_INSERT
3599 if (ERROR_INSERTED(8002)) {
3600 systemErrorLab(signal, __LINE__);
3601 }//if
3602 if (ERROR_INSERTED(8007)) {
3603 if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3604 CLEAR_ERROR_INSERT_VALUE;
3605 return;
3606 }//if
3607 }//if
3608 if (ERROR_INSERTED(8008)) {
3609 if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3610 CLEAR_ERROR_INSERT_VALUE;
3611 return;
3612 }//if
3613 }//if
3614 if (ERROR_INSERTED(8009)) {
3615 if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3616 return;
3617 }//if
3618 }//if
3619 if (ERROR_INSERTED(8010)) {
3620 if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3621 return;
3622 }//if
3623 }//if
3624 #endif
3625 Uint32 Tdeferred = tc_testbit(regApiPtr->m_flags,
3626 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
3627 Uint32 reorg = 0;
3628 Uint32 Tspecial_op = regTcPtr->m_special_op_flags;
3629 if (Tspecial_op == 0)
3630 {
3631 }
3632 else if (Tspecial_op & (TcConnectRecord::SOF_REORG_TRIGGER_BASE |
3633 TcConnectRecord::SOF_REORG_DELETE))
3634 {
3635 reorg = 1;
3636 }
3637 else if (Tspecial_op & TcConnectRecord::SOF_REORG_MOVING)
3638 {
3639 reorg = 2;
3640 }
3641
3642 Uint32 inlineKeyLen= 0;
3643 Uint32 inlineAttrLen= 0;
3644
3645 /* We normally send long LQHKEYREQ unless the
3646 * destination cannot handle it or we are
3647 * testing
3648 */
3649 if (unlikely((version < NDBD_LONG_LQHKEYREQ) ||
3650 ERROR_INSERTED(8069)))
3651 {
3652 /* Short LQHKEYREQ, with some key/attr data inline */
3653 regCachePtr->useLongLqhKeyReq= 0;
3654 inlineKeyLen= regCachePtr->keylen;
3655 inlineAttrLen= regCachePtr->attrlength;
3656 }
3657 else
3658 /* Long LQHKEYREQ, with key/attr data in long sections */
3659 regCachePtr->useLongLqhKeyReq= 1;
3660
3661 tslrAttrLen = 0;
3662 LqhKeyReq::setAttrLen(tslrAttrLen, inlineAttrLen);
3663 /* ---------------------------------------------------------------------- */
3664 // Bit16 == 0 since StoredProcedures are not yet supported.
3665 /* ---------------------------------------------------------------------- */
3666 LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
3667 LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
3668 LqhKeyReq::setReorgFlag(tslrAttrLen, reorg);
3669
3670 Tdata10 = 0;
3671 sig0 = regTcPtr->opSimple;
3672 sig1 = regTcPtr->operation;
3673 sig2 = regTcPtr->dirtyOp;
3674 bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
3675 LqhKeyReq::setKeyLen(Tdata10, inlineKeyLen);
3676 LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
3677 if (unlikely(version < NDBD_ROWID_VERSION))
3678 {
3679 Uint32 op = regTcPtr->operation;
3680 Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
3681 LqhKeyReq::setLockType(Tdata10, lock);
3682 }
3683 /* ---------------------------------------------------------------------- */
3684 // Indicate Application Reference is present in bit 15
3685 /* ---------------------------------------------------------------------- */
3686 LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
3687 LqhKeyReq::setDirtyFlag(Tdata10, sig2);
3688 LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
3689 LqhKeyReq::setSimpleFlag(Tdata10, sig0);
3690 LqhKeyReq::setOperation(Tdata10, sig1);
3691 LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
3692 LqhKeyReq::setQueueOnRedoProblemFlag(Tdata10, regCachePtr->m_op_queue);
3693 LqhKeyReq::setDeferredConstraints(Tdata10, (Tdeferred & m_deferred_enabled));
3694
3695 /* -----------------------------------------------------------------------
3696 * If we are sending a short LQHKEYREQ, then there will be some AttrInfo
3697 * in the LQHKEYREQ.
3698 * Work out how much we'll send
3699 * ----------------------------------------------------------------------- */
3700 UintR aiInLqhKeyReq= 0;
3701
3702 if (! regCachePtr->useLongLqhKeyReq)
3703 {
3704 /* Short LQHKEYREQ :
3705 * Send max 5 words of AttrInfo in LQHKEYREQ
3706 */
3707 aiInLqhKeyReq= MIN(LqhKeyReq::MaxAttrInfo, regCachePtr->attrlength);
3708 }
3709
3710 LqhKeyReq::setAIInLqhKeyReq(Tdata10, aiInLqhKeyReq);
3711 /* -----------------------------------------------------------------------
3712 * Bit 27 == 0 since TC record is the same as the client record.
3713 * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
3714 * ----------------------------------------------------------------------- */
3715 //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
3716 LqhKeyReq::setMarkerFlag(Tdata10, regTcPtr->commitAckMarker != RNIL ? 1 : 0);
3717
3718 /* ************************************************************> */
3719 /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT */
3720 /* IS SENT TO A PRIMARY NODE. */
3721 /* ************************************************************> */
3722
3723 LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
3724
3725 sig0 = tcConnectptr.i;
3726 sig2 = regCachePtr->hashValue;
3727 sig4 = cownref;
3728 sig5 = regTcPtr->savePointId;
3729
3730 lqhKeyReq->clientConnectPtr = sig0;
3731 lqhKeyReq->attrLen = tslrAttrLen;
3732 lqhKeyReq->hashValue = sig2;
3733 lqhKeyReq->requestInfo = Tdata10;
3734 lqhKeyReq->tcBlockref = sig4;
3735 lqhKeyReq->savePointId = sig5;
3736
3737 sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
3738 sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
3739 sig2 = regApiPtr->transid[0];
3740 sig3 = regApiPtr->transid[1];
3741 sig4 =
3742 (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) ?
3743 reference() : regApiPtr->ndbapiBlockref;
3744 sig5 = regTcPtr->clientData;
3745 sig6 = regCachePtr->scanInfo;
3746
3747 if (! dirtyRead)
3748 {
3749 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
3750 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
3751 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
3752 regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
3753 }
3754
3755 lqhKeyReq->tableSchemaVersion = sig0;
3756 lqhKeyReq->fragmentData = sig1;
3757 lqhKeyReq->transId1 = sig2;
3758 lqhKeyReq->transId2 = sig3;
3759 lqhKeyReq->scanInfo = sig6;
3760
3761 lqhKeyReq->variableData[0] = sig4;
3762 lqhKeyReq->variableData[1] = sig5;
3763
3764 UintR nextPos = 2;
3765
3766 if (regTcPtr->lastReplicaNo > 1) {
3767 sig0 = (UintR)regTcPtr->tcNodedata[2] +
3768 (UintR)(regTcPtr->tcNodedata[3] << 16);
3769 lqhKeyReq->variableData[nextPos] = sig0;
3770 nextPos++;
3771 }//if
3772
3773 // Reset trigger count
3774 regTcPtr->noFiredTriggers = 0;
3775 regTcPtr->triggerExecutionCount = 0;
3776
3777 if (regCachePtr->useLongLqhKeyReq)
3778 {
3779 /* Build long LQHKeyReq using Key + AttrInfo sections */
3780 SectionHandle handle(this);
3781 SegmentedSectionPtr keyInfoSection;
3782
3783 getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
3784
3785 handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
3786 handle.m_cnt= 1;
3787
3788 if (regCachePtr->attrlength != 0)
3789 {
3790 SegmentedSectionPtr attrInfoSection;
3791
3792 ndbassert(regCachePtr->attrInfoSectionI != RNIL);
3793 getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
3794
3795 handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
3796 handle.m_cnt= 2;
3797 }
3798
3799 sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3800 nextPos + LqhKeyReq::FixedSignalLength, JBB,
3801 &handle);
3802
3803 /* Long sections were freed as part of sendSignal */
3804 ndbassert( handle.m_cnt == 0 );
3805 regCachePtr->keyInfoSectionI= RNIL;
3806 regCachePtr->attrInfoSectionI= RNIL;
3807 }
3808 else
3809 {
3810 /* Build short LQHKeyReq from Key + AttrInfo sections
3811 *
3812 * Read upto 4 words of KeyInfo from TCKEYREQ KeyInfo section into
3813 * LqhKeyReq signal
3814 */
3815 SegmentedSectionPtr keyInfoSection;
3816
3817 getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
3818 SectionReader keyInfoReader(keyInfoSection, getSectionSegmentPool());
3819
3820 UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo, regCachePtr->keylen);
3821
3822 keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos], keyLenInLqhKeyReq);
3823
3824 nextPos+= keyLenInLqhKeyReq;
3825
3826 if (aiInLqhKeyReq != 0)
3827 {
3828 /* Read upto 5 words of AttrInfo from TCKEYREQ KeyInfo section into
3829 * LqhKeyReq signal
3830 */
3831 SegmentedSectionPtr attrInfoSection;
3832
3833 ndbassert(regCachePtr->attrInfoSectionI != RNIL);
3834
3835 getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
3836 SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
3837
3838 attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos], aiInLqhKeyReq);
3839
3840 nextPos+= aiInLqhKeyReq;
3841 }
3842
3843 sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3844 nextPos + LqhKeyReq::FixedSignalLength, JBB);
3845 }
3846 }//Dbtc::sendlqhkeyreq()
3847
packLqhkeyreq040Lab(Signal * signal,BlockReference TBRef)3848 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
3849 BlockReference TBRef)
3850 {
3851 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3852 CacheRecord * const regCachePtr = cachePtr.p;
3853 #ifdef ERROR_INSERT
3854 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3855
3856 if (ERROR_INSERTED(8009)) {
3857 if (regApiPtr->apiConnectstate == CS_STARTED) {
3858 CLEAR_ERROR_INSERT_VALUE;
3859 return;
3860 }//if
3861 }//if
3862 if (ERROR_INSERTED(8010)) {
3863 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3864 CLEAR_ERROR_INSERT_VALUE;
3865 return;
3866 }//if
3867 }//if
3868 #endif
3869
3870 /* Do we have an ATTRINFO train to send? */
3871 if (!regCachePtr->useLongLqhKeyReq)
3872 {
3873 /* Short LqhKeyReq */
3874 if (regCachePtr->attrlength > LqhKeyReq::MaxAttrInfo)
3875 {
3876 if (unlikely( !sendAttrInfoTrain(signal,
3877 TBRef,
3878 tcConnectptr.i,
3879 LqhKeyReq::MaxAttrInfo,
3880 regCachePtr->attrInfoSectionI)))
3881 {
3882 jam();
3883 TCKEY_abort(signal, 17);
3884 return;
3885 }
3886 }
3887 } // useLongLqhKeyReq
3888
3889 /* Release AttrInfo related storage, and the Cache Record */
3890 releaseAttrinfo();
3891
3892 UintR TtcTimer = ctcTimer;
3893 UintR Tread = (regTcPtr->operation == ZREAD);
3894 UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
3895 UintR Tboth = Tread & Tdirty;
3896 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3897 jam();
3898 /*--------------------------------------------------------------------
3899 * WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
3900 *---------------------------------------------------------------------*/
3901 if (Tboth) {
3902 jam();
3903 releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
3904 return;
3905 }//if
3906 regTcPtr->tcConnectstate = OS_OPERATING;
3907 return;
3908 }//Dbtc::packLqhkeyreq040Lab()
3909
3910 /* ========================================================================= */
3911 /* ------- RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD ------- */
3912 /* ========================================================================= */
releaseAttrinfo()3913 void Dbtc::releaseAttrinfo()
3914 {
3915 CacheRecord * const regCachePtr = cachePtr.p;
3916 Uint32 attrInfoSectionI= cachePtr.p->attrInfoSectionI;
3917
3918 /* Release AttrInfo section if there is one */
3919 releaseSection( attrInfoSectionI );
3920 cachePtr.p->attrInfoSectionI= RNIL;
3921
3922 //---------------------------------------------------
3923 // Now we will release the cache record at the same
3924 // time as releasing the attrinfo records.
3925 //---------------------------------------------------
3926 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3927 UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
3928 UintR TCacheIndex = cachePtr.i;
3929 regCachePtr->nextCacheRec = TfirstfreeCacheRec;
3930 cfirstfreeCacheRec = TCacheIndex;
3931 regApiPtr->cachePtr = RNIL;
3932 return;
3933 }//Dbtc::releaseAttrinfo()
3934
3935 /* ========================================================================= */
3936 /* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION ------- */
3937 /* ========================================================================= */
releaseDirtyRead(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * regTcPtr)3938 void Dbtc::releaseDirtyRead(Signal* signal,
3939 ApiConnectRecordPtr regApiPtr,
3940 TcConnectRecord* regTcPtr)
3941 {
3942 Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
3943 Uint32 TclientData = regTcPtr->clientData;
3944 Uint32 Tnode = regTcPtr->tcNodedata[0];
3945 Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3946 ConnectionState state = regApiPtr.p->apiConnectstate;
3947
3948 regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3949 regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
3950 regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3951
3952 unlinkReadyTcCon(signal);
3953 releaseTcCon();
3954
3955 /**
3956 * No LQHKEYCONF in Simple/Dirty read
3957 * Therefore decrese no LQHKEYCONF(REF) we are waiting for
3958 */
3959 c_counters.csimpleReadCount++;
3960 regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
3961
3962 if(Tlqhkeyreqrec == 0)
3963 {
3964 /**
3965 * Special case of lqhKeyConf_checkTransactionState:
3966 * - commit with zero operations: handle only for simple read
3967 */
3968 sendtckeyconf(signal, state == CS_START_COMMITTING);
3969 regApiPtr.p->apiConnectstate =
3970 (state == CS_START_COMMITTING ? CS_CONNECTED : state);
3971 setApiConTimer(regApiPtr.i, 0, __LINE__);
3972
3973 return;
3974 }
3975
3976 /**
3977 * Emulate LQHKEYCONF
3978 */
3979 lqhKeyConf_checkTransactionState(signal, regApiPtr);
3980 }//Dbtc::releaseDirtyRead()
3981
3982 /* ------------------------------------------------------------------------- */
3983 /* ------- CHECK IF ALL TC CONNECTIONS ARE COMPLETED ------- */
3984 /* ------------------------------------------------------------------------- */
unlinkReadyTcCon(Signal * signal)3985 void Dbtc::unlinkReadyTcCon(Signal* signal)
3986 {
3987 TcConnectRecordPtr urtTcConnectptr;
3988
3989 TcConnectRecord * const regTcPtr = tcConnectptr.p;
3990 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3991 UintR TtcConnectFilesize = ctcConnectFilesize;
3992 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3993 if (regTcPtr->prevTcConnect != RNIL) {
3994 jam();
3995 urtTcConnectptr.i = regTcPtr->prevTcConnect;
3996 ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3997 urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
3998 } else {
3999 jam();
4000 regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
4001 }//if
4002 if (regTcPtr->nextTcConnect != RNIL) {
4003 jam();
4004 urtTcConnectptr.i = regTcPtr->nextTcConnect;
4005 ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4006 urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
4007 } else {
4008 jam();
4009 regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
4010 }//if
4011 }//Dbtc::unlinkReadyTcCon()
4012
releaseTcCon()4013 void Dbtc::releaseTcCon()
4014 {
4015 TcConnectRecord * const regTcPtr = tcConnectptr.p;
4016 UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
4017 UintR TtcConnectptrIndex = tcConnectptr.i;
4018
4019 ndbrequire(regTcPtr->commitAckMarker == RNIL);
4020 regTcPtr->tcConnectstate = OS_CONNECTED;
4021 regTcPtr->nextTcConnect = TfirstfreeTcConnect;
4022 regTcPtr->apiConnect = RNIL;
4023 regTcPtr->m_special_op_flags = 0;
4024 regTcPtr->indexOp = RNIL;
4025 cfirstfreeTcConnect = TtcConnectptrIndex;
4026 c_counters.cconcurrentOp--;
4027 }//Dbtc::releaseTcCon()
4028
execPACKED_SIGNAL(Signal * signal)4029 void Dbtc::execPACKED_SIGNAL(Signal* signal)
4030 {
4031 LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
4032
4033 UintR Ti;
4034 UintR Tstep = 0;
4035 UintR Tlength;
4036 UintR TpackedData[28];
4037 UintR Tdata1, Tdata2, Tdata3, Tdata4;
4038
4039 jamEntry();
4040 Tlength = signal->length();
4041 if (Tlength > 25) {
4042 jam();
4043 systemErrorLab(signal, __LINE__);
4044 return;
4045 }//if
4046 Uint32* TpackDataPtr;
4047 for (Ti = 0; Ti < Tlength; Ti += 4) {
4048 Uint32* TsigDataPtr = &signal->theData[Ti];
4049 Tdata1 = TsigDataPtr[0];
4050 Tdata2 = TsigDataPtr[1];
4051 Tdata3 = TsigDataPtr[2];
4052 Tdata4 = TsigDataPtr[3];
4053
4054 TpackDataPtr = &TpackedData[Ti];
4055 TpackDataPtr[0] = Tdata1;
4056 TpackDataPtr[1] = Tdata2;
4057 TpackDataPtr[2] = Tdata3;
4058 TpackDataPtr[3] = Tdata4;
4059 }//for
4060 while (Tlength > Tstep) {
4061
4062 TpackDataPtr = &TpackedData[Tstep];
4063 Tdata1 = TpackDataPtr[0];
4064 Tdata2 = TpackDataPtr[1];
4065 Tdata3 = TpackDataPtr[2];
4066
4067 lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
4068 lqhKeyConf->opPtr = Tdata2;
4069 lqhKeyConf->userRef = Tdata3;
4070
4071 switch (Tdata1 >> 28) {
4072 case ZCOMMITTED:
4073 signal->header.theLength = 3;
4074 execCOMMITTED(signal);
4075 Tstep += 3;
4076 break;
4077 case ZCOMPLETED:
4078 signal->header.theLength = 3;
4079 execCOMPLETED(signal);
4080 Tstep += 3;
4081 break;
4082 case ZLQHKEYCONF:
4083 jam();
4084 Tdata1 = TpackDataPtr[3];
4085 Tdata2 = TpackDataPtr[4];
4086 Tdata3 = TpackDataPtr[5];
4087 Tdata4 = TpackDataPtr[6];
4088
4089 lqhKeyConf->readLen = Tdata1;
4090 lqhKeyConf->transId1 = Tdata2;
4091 lqhKeyConf->transId2 = Tdata3;
4092 lqhKeyConf->noFiredTriggers = Tdata4;
4093 signal->header.theLength = LqhKeyConf::SignalLength;
4094 execLQHKEYCONF(signal);
4095 Tstep += LqhKeyConf::SignalLength;
4096 break;
4097 case ZFIRE_TRIG_CONF:
4098 jam();
4099 signal->header.theLength = 4;
4100 signal->theData[3] = TpackDataPtr[3];
4101 execFIRE_TRIG_CONF(signal);
4102 Tstep += 4;
4103 break;
4104 default:
4105 systemErrorLab(signal, __LINE__);
4106 return;
4107 }//switch
4108 }//while
4109 return;
4110 }//Dbtc::execPACKED_SIGNAL()
4111
4112
execSIGNAL_DROPPED_REP(Signal * signal)4113 void Dbtc::execSIGNAL_DROPPED_REP(Signal* signal)
4114 {
4115 /* An incoming signal was dropped, handle it
4116 * Dropped signal really means that we ran out of
4117 * long signal buffering to store its sections
4118 */
4119 jamEntry();
4120
4121 if (!assembleDroppedFragments(signal))
4122 {
4123 jam();
4124 return;
4125 }
4126
4127 const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4128 Uint32 originalGSN= rep->originalGsn;
4129
4130 DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4131
4132 switch(originalGSN) {
4133 case GSN_TCKEYREQ:
4134 jam();
4135 /* Fall through */
4136 case GSN_TCINDXREQ:
4137 {
4138 jam();
4139
4140 /* Get original signal data - unfortunately it may
4141 * have been truncated. We must not read beyond
4142 * word # 22
4143 * We will send an Abort to the Api using info from
4144 * the received signal and clean up our transaction
4145 * state
4146 */
4147 const TcKeyReq * const truncatedTcKeyReq =
4148 (TcKeyReq *) &rep->originalData[0];
4149
4150 const UintR apiIndex = truncatedTcKeyReq->apiConnectPtr;
4151
4152 if (apiIndex >= capiConnectFilesize)
4153 {
4154 jam();
4155 warningHandlerLab(signal, __LINE__);
4156 return;
4157 }
4158
4159 /* We have a valid Api ConnectPtr...
4160 * Ensure that we have the necessary information
4161 * to send a rollback to the client
4162 */
4163 apiConnectptr.i = apiIndex;
4164 ApiConnectRecord * const regApiPtr = &apiConnectRecord[apiIndex];
4165 apiConnectptr.p = regApiPtr;
4166 UintR transId1= truncatedTcKeyReq->transId1;
4167 UintR transId2= truncatedTcKeyReq->transId2;
4168
4169 /* Ensure that the apiConnectptr global is initialised
4170 * may not be in cases where we drop the first signal of
4171 * a transaction
4172 */
4173 apiConnectptr.p->transid[0] = transId1;
4174 apiConnectptr.p->transid[1] = transId2;
4175 apiConnectptr.p->returncode = ZGET_DATAREC_ERROR;
4176
4177 /* Set m_exec_flag according to the dropped request */
4178 apiConnectptr.p->m_flags |=
4179 TcKeyReq::getExecuteFlag(truncatedTcKeyReq->requestInfo) ?
4180 ApiConnectRecord::TF_EXEC_FLAG : 0;
4181
4182 DEBUG(" Execute flag set to " << tc_testbit(apiConnectptr.p->m_flags,
4183 ApiConnectRecord::TF_EXEC_FLAG)
4184 );
4185
4186 abortErrorLab(signal);
4187
4188 break;
4189 }
4190 case GSN_SCAN_TABREQ:
4191 {
4192 jam();
4193 /* Get information necessary to send SCAN_TABREF back to client */
4194 // TODO : Handle dropped signal fragments
4195 const ScanTabReq * const truncatedScanTabReq =
4196 (ScanTabReq *) &rep->originalData[0];
4197
4198 Uint32 apiConnectPtr= truncatedScanTabReq->apiConnectPtr;
4199 Uint32 transId1= truncatedScanTabReq->transId1;
4200 Uint32 transId2= truncatedScanTabReq->transId2;
4201
4202 if (apiConnectPtr >= capiConnectFilesize)
4203 {
4204 jam();
4205 warningHandlerLab(signal, __LINE__);
4206 return;
4207 }//if
4208
4209 apiConnectptr.i = apiConnectPtr;
4210 ptrAss(apiConnectptr, apiConnectRecord);
4211 ApiConnectRecord * transP = apiConnectptr.p;
4212
4213 /* Now send the SCAN_TABREF */
4214 ScanTabRef* ref= (ScanTabRef*)&signal->theData[0];
4215 ref->apiConnectPtr = transP->ndbapiConnect;
4216 ref->transId1= transId1;
4217 ref->transId2= transId2;
4218 ref->errorCode= ZGET_ATTRBUF_ERROR;
4219 ref->closeNeeded= 0;
4220
4221 sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
4222 signal, ScanTabRef::SignalLength, JBB);
4223 break;
4224 }
4225 default:
4226 jam();
4227 /* Don't expect dropped signals for other GSNs,
4228 * default handling
4229 * TODO : Can TC get long TRANSID_AI as part of
4230 * Unique index operations?
4231 */
4232 SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
4233 };
4234
4235 return;
4236 }
4237
4238
execLQHKEYCONF(Signal * signal)4239 void Dbtc::execLQHKEYCONF(Signal* signal)
4240 {
4241 const LqhKeyConf * lqhKeyConf = CAST_CONSTPTR(LqhKeyConf,
4242 signal->getDataPtr());
4243 #ifdef UNUSED
4244 ndbout << "TC: Received LQHKEYCONF"
4245 << " transId1=" << lqhKeyConf-> transId1
4246 << " transId2=" << lqhKeyConf-> transId2
4247 << endl;
4248 #endif /*UNUSED*/
4249 UintR compare_transid1, compare_transid2;
4250 BlockReference tlastLqhBlockref;
4251 UintR tlastLqhConnect;
4252 UintR treadlenAi;
4253 UintR TtcConnectptrIndex;
4254 UintR TtcConnectFilesize = ctcConnectFilesize;
4255
4256 tlastLqhConnect = lqhKeyConf->connectPtr;
4257 TtcConnectptrIndex = lqhKeyConf->opPtr;
4258 tlastLqhBlockref = lqhKeyConf->userRef;
4259 treadlenAi = lqhKeyConf->readLen;
4260 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4261
4262 /*------------------------------------------------------------------------
4263 * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
4264 * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
4265 * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
4266 * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
4267 * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
4268 * OPERATIONS ON THE LQH CONNECT RECORD.
4269 *------------------------------------------------------------------------
4270 * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
4271 * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
4272 * PROBLEM WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
4273 * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
4274 * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
4275 * BEFORE ACCEPTING THIS SIGNAL.
4276 * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
4277 * this.
4278 * This is more reason to ignore the signal if not all states are correct.
4279 *------------------------------------------------------------------------*/
4280 if (TtcConnectptrIndex >= TtcConnectFilesize) {
4281 TCKEY_abort(signal, 25);
4282 return;
4283 }//if
4284 TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
4285 OperationState TtcConnectstate = regTcPtr->tcConnectstate;
4286 tcConnectptr.i = TtcConnectptrIndex;
4287 tcConnectptr.p = regTcPtr;
4288 if (TtcConnectstate != OS_OPERATING) {
4289 warningReport(signal, 23);
4290 return;
4291 }//if
4292 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4293 UintR TapiConnectptrIndex = regTcPtr->apiConnect;
4294 UintR TapiConnectFilesize = capiConnectFilesize;
4295 UintR Ttrans1 = lqhKeyConf->transId1;
4296 UintR Ttrans2 = lqhKeyConf->transId2;
4297 Uint32 noFired = LqhKeyConf::getFiredCount(lqhKeyConf->noFiredTriggers);
4298 Uint32 deferred = LqhKeyConf::getDeferredBit(lqhKeyConf->noFiredTriggers);
4299
4300 if (TapiConnectptrIndex >= TapiConnectFilesize) {
4301 TCKEY_abort(signal, 29);
4302 return;
4303 }//if
4304 Ptr<ApiConnectRecord> regApiPtr;
4305 regApiPtr.i = TapiConnectptrIndex;
4306 regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
4307 apiConnectptr.i = TapiConnectptrIndex;
4308 apiConnectptr.p = regApiPtr.p;
4309 compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
4310 compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
4311 compare_transid1 = compare_transid1 | compare_transid2;
4312 if (compare_transid1 != 0) {
4313 warningReport(signal, 24);
4314 return;
4315 }//if
4316
4317 #ifdef ERROR_INSERT
4318 if (ERROR_INSERTED(8029)) {
4319 systemErrorLab(signal, __LINE__);
4320 }//if
4321 if (ERROR_INSERTED(8003)) {
4322 if (regApiPtr.p->apiConnectstate == CS_STARTED) {
4323 CLEAR_ERROR_INSERT_VALUE;
4324 return;
4325 }//if
4326 }//if
4327 if (ERROR_INSERTED(8004)) {
4328 if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
4329 CLEAR_ERROR_INSERT_VALUE;
4330 return;
4331 }//if
4332 }//if
4333 if (ERROR_INSERTED(8005)) {
4334 if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
4335 CLEAR_ERROR_INSERT_VALUE;
4336 return;
4337 }//if
4338 }//if
4339 if (ERROR_INSERTED(8006)) {
4340 if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
4341 CLEAR_ERROR_INSERT_VALUE;
4342 return;
4343 }//if
4344 }//if
4345 if (ERROR_INSERTED(8023)) {
4346 SET_ERROR_INSERT_VALUE(8024);
4347 return;
4348 }//if
4349 #endif
4350 UintR TtcTimer = ctcTimer;
4351 regTcPtr->lastLqhCon = tlastLqhConnect;
4352 regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
4353 regTcPtr->noFiredTriggers = noFired;
4354 regTcPtr->m_special_op_flags |= (deferred) ?
4355 TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
4356 regApiPtr.p->m_flags |= (deferred) ?
4357 ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
4358
4359 UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
4360 UintR TclientData = regTcPtr->clientData;
4361 UintR TdirtyOp = regTcPtr->dirtyOp;
4362 Uint32 TopSimple = regTcPtr->opSimple;
4363 Uint32 Toperation = regTcPtr->operation;
4364 ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4365
4366 if (TapiConnectstate == CS_ABORTING) {
4367 warningReport(signal, 27);
4368 return;
4369 }//if
4370
4371 Uint32 lockingOpI = RNIL;
4372 if (Toperation == ZUNLOCK)
4373 {
4374 /* For unlock operations readlen in TCKEYCONF carries
4375 * the locking operation TC reference
4376 */
4377 lockingOpI = treadlenAi;
4378 treadlenAi = 0;
4379 }
4380
4381 Uint32 commitAckMarker = regTcPtr->commitAckMarker;
4382 regTcPtr->commitAckMarker = RNIL;
4383 setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
4384
4385 if (commitAckMarker != RNIL)
4386 {
4387 const Uint32 noOfLqhs = regTcPtr->noOfNodes;
4388 CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
4389 jam();
4390 regApiPtr.p->m_flags |= ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED;
4391 /**
4392 * Populate LQH array
4393 */
4394 for(Uint32 i = 0; i < noOfLqhs; i++)
4395 tmp->m_commit_ack_marker_nodes.set(regTcPtr->tcNodedata[i]);
4396 }
4397 if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4398 jam();
4399 // This was an internal TCKEYREQ
4400 // will be returned unpacked
4401 regTcPtr->attrInfoLen = treadlenAi;
4402 } else {
4403 if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
4404 jam();
4405
4406 if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
4407 TCKEY_abort(signal, 30);
4408 return;
4409 }
4410
4411 /*
4412 * Skip counting triggering operations the first round
4413 * since they will enter execLQHKEYCONF a second time
4414 * Skip counting internally generated TcKeyReq
4415 */
4416 regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
4417 regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
4418 regApiPtr.p->tckeyrec = Ttckeyrec + 2;
4419 }//if
4420 }//if
4421 if (TdirtyOp == ZTRUE)
4422 {
4423 UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4424 jam();
4425 releaseDirtyWrite(signal);
4426 regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4427 }
4428 else if (Toperation == ZREAD && TopSimple)
4429 {
4430 UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4431 jam();
4432 unlinkReadyTcCon(signal);
4433 releaseTcCon();
4434 regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4435 }
4436 else if (Toperation == ZUNLOCK)
4437 {
4438 jam();
4439 /* We've unlocked and released a read operation in LQH
4440 * The readLenAi member contains the TC OP reference
4441 * for the unlocked operation.
4442 * So here we :
4443 * 1) Validate the TC OP reference
4444 * 2) Release the referenced TC op
4445 * 3) Send TCKEYCONF back to the user
4446 * 4) Release our own TC op
4447 */
4448 Uint32 unlockOpI = tcConnectptr.i;
4449
4450 ndbrequire( noFired == 0 );
4451 ndbrequire( regTcPtr->triggeringOperation == RNIL );
4452
4453 /* Switch to the original locking operation */
4454 if (unlikely( lockingOpI >= ctcConnectFilesize ))
4455 {
4456 jam();
4457 TCKEY_abort(signal, 61);
4458 return;
4459 }
4460 tcConnectptr.i = lockingOpI;
4461 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4462
4463 const TcConnectRecord * regLockTcPtr = tcConnectptr.p;
4464
4465 /* Validate the locking operation's state */
4466 bool locking_op_ok =
4467 ( ( regLockTcPtr->apiConnect == regTcPtr->apiConnect ) &&
4468 ( ( regLockTcPtr->operation == ZREAD ) ||
4469 ( regLockTcPtr->operation == ZREAD_EX ) ) &&
4470 ( regLockTcPtr->tcConnectstate == OS_PREPARED ) &&
4471 ( ! regLockTcPtr->dirtyOp ) &&
4472 ( ! regLockTcPtr->opSimple ) &&
4473 ( ! TcConnectRecord::isIndexOp(regLockTcPtr->m_special_op_flags) ) &&
4474 ( regLockTcPtr->commitAckMarker == RNIL ) );
4475
4476 if (unlikely (! locking_op_ok ))
4477 {
4478 jam();
4479 TCKEY_abort(signal, 63);
4480 return;
4481 }
4482
4483 /* Ok, all checks passed, release the original locking op */
4484 unlinkReadyTcCon(signal);
4485 releaseTcCon();
4486
4487 /* Remove record of original locking op's LQHKEYREQ/CONF
4488 * etc.
4489 */
4490 ndbrequire( regApiPtr.p->lqhkeyreqrec );
4491 ndbrequire( regApiPtr.p->lqhkeyconfrec );
4492 regApiPtr.p->lqhkeyreqrec -= 1;
4493 regApiPtr.p->lqhkeyconfrec -= 1;
4494
4495 /* Switch back to the unlock operation */
4496 tcConnectptr.i = unlockOpI;
4497 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4498
4499 /* Release the unlock operation */
4500 unlinkReadyTcCon(signal);
4501 releaseTcCon();
4502
4503 /* Remove record of unlock op's LQHKEYREQ */
4504 ndbrequire( regApiPtr.p->lqhkeyreqrec );
4505 regApiPtr.p->lqhkeyreqrec -= 1;
4506
4507 /* TCKEYCONF sent below */
4508 }
4509 else
4510 {
4511 jam();
4512 if (noFired == 0) {
4513 jam();
4514 // No triggers to execute
4515 UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4516 regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
4517 regTcPtr->tcConnectstate = OS_PREPARED;
4518 }
4519 }//if
4520
4521 /**
4522 * And now decide what to do next
4523 */
4524 if (regTcPtr->triggeringOperation != RNIL &&
4525 !regApiPtr.p->isExecutingDeferredTriggers()) {
4526 jam();
4527 // This operation was created by a trigger execting operation
4528 // Restart it if we have executed all it's triggers
4529 TcConnectRecordPtr opPtr;
4530
4531 opPtr.i = regTcPtr->triggeringOperation;
4532 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
4533 trigger_op_finished(signal, regApiPtr, opPtr.p);
4534 } else if (noFired == 0) {
4535 // This operation did not fire any triggers, finish operation
4536 jam();
4537 if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4538 jam();
4539 setupIndexOpReturn(regApiPtr.p, regTcPtr);
4540 }
4541 lqhKeyConf_checkTransactionState(signal, regApiPtr);
4542 } else {
4543 // We have fired triggers
4544 jam();
4545 saveTriggeringOpState(signal, regTcPtr);
4546 if (regTcPtr->noReceivedTriggers == noFired)
4547 {
4548 // We have received all data
4549 jam();
4550 executeTriggers(signal, ®ApiPtr);
4551 }
4552 // else wait for more trigger data
4553 }
4554 }//Dbtc::execLQHKEYCONF()
4555
setupIndexOpReturn(ApiConnectRecord * regApiPtr,TcConnectRecord * regTcPtr)4556 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
4557 TcConnectRecord* regTcPtr)
4558 {
4559 regApiPtr->m_flags |= ApiConnectRecord::TF_INDEX_OP_RETURN;
4560 regApiPtr->indexOp = regTcPtr->indexOp;
4561 regApiPtr->clientData = regTcPtr->clientData;
4562 regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
4563 }
4564
4565 /**
4566 * lqhKeyConf_checkTransactionState
4567 *
4568 * This functions checks state variables, and
4569 * decides if it should wait for more LQHKEYCONF signals
4570 * or if it should start commiting
4571 */
4572 void
lqhKeyConf_checkTransactionState(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)4573 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
4574 Ptr<ApiConnectRecord> regApiPtr)
4575 {
4576 /*---------------------------------------------------------------*/
4577 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
4578 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN */
4579 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE */
4580 /* WHOLE TRANSACTION */
4581 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF */
4582 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
4583 /* TRANSACTION */
4584 /*---------------------------------------------------------------*/
4585 ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4586 UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4587 UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4588 int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
4589
4590 apiConnectptr = regApiPtr;
4591 switch (TapiConnectstate) {
4592 case CS_START_COMMITTING:
4593 if (TnoOfOutStanding == 0) {
4594 jam();
4595 diverify010Lab(signal);
4596 return;
4597 } else if (TnoOfOutStanding > 0) {
4598 if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4599 jam();
4600 sendtckeyconf(signal, 0);
4601 return;
4602 }
4603 else if (tc_testbit(regApiPtr.p->m_flags,
4604 ApiConnectRecord::TF_INDEX_OP_RETURN))
4605 {
4606 jam();
4607 sendtckeyconf(signal, 0);
4608 return;
4609 }//if
4610 jam();
4611 return;
4612 } else {
4613 TCKEY_abort(signal, 44);
4614 return;
4615 }//if
4616 return;
4617 case CS_STARTED:
4618 case CS_RECEIVING:
4619 if (TnoOfOutStanding == 0) {
4620 jam();
4621 sendtckeyconf(signal, 2);
4622 return;
4623 } else {
4624 if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4625 jam();
4626 sendtckeyconf(signal, 0);
4627 return;
4628 }
4629 else if (tc_testbit(regApiPtr.p->m_flags,
4630 ApiConnectRecord::TF_INDEX_OP_RETURN))
4631 {
4632 jam();
4633 sendtckeyconf(signal, 0);
4634 return;
4635 }//if
4636 jam();
4637 }//if
4638 return;
4639 case CS_REC_COMMITTING:
4640 if (TnoOfOutStanding > 0) {
4641 if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4642 jam();
4643 sendtckeyconf(signal, 0);
4644 return;
4645 }
4646 else if (tc_testbit(regApiPtr.p->m_flags,
4647 ApiConnectRecord::TF_INDEX_OP_RETURN))
4648 {
4649 jam();
4650 sendtckeyconf(signal, 0);
4651 return;
4652 }//if
4653 jam();
4654 return;
4655 }//if
4656 TCKEY_abort(signal, 45);
4657 return;
4658 case CS_CONNECTED:
4659 jam();
4660 /*---------------------------------------------------------------*/
4661 /* WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY */
4662 /* CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE */
4663 /* COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS. */
4664 /*---------------------------------------------------------------*/
4665 regApiPtr.p->tckeyrec = 0;
4666 return;
4667 case CS_SEND_FIRE_TRIG_REQ:
4668 return;
4669 case CS_WAIT_FIRE_TRIG_REQ:
4670 if (TnoOfOutStanding == 0 && regApiPtr.p->pendingTriggers == 0)
4671 {
4672 jam();
4673 regApiPtr.p->apiConnectstate = CS_START_COMMITTING;
4674 diverify010Lab(signal);
4675 return;
4676 }
4677 return;
4678 default:
4679 TCKEY_abort(signal, 46);
4680 return;
4681 }//switch
4682 }//Dbtc::lqhKeyConf_checkTransactionState()
4683
sendtckeyconf(Signal * signal,UintR TcommitFlag)4684 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
4685 {
4686 if(ERROR_INSERTED(8049)){
4687 CLEAR_ERROR_INSERT_VALUE;
4688 signal->theData[0] = TcContinueB::DelayTCKEYCONF;
4689 signal->theData[1] = apiConnectptr.i;
4690 signal->theData[2] = TcommitFlag;
4691 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
4692 return;
4693 }
4694
4695 HostRecordPtr localHostptr;
4696 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4697 const UintR TopWords = (UintR)regApiPtr->tckeyrec;
4698 localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
4699 const Uint32 type = getNodeInfo(localHostptr.i).m_type;
4700 const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
4701 const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
4702 const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
4703 ptrAss(localHostptr, hostRecord);
4704 UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
4705 UintR confInfo = 0;
4706 TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
4707 TcKeyConf::setMarkerFlag(confInfo, Tmarker);
4708 const UintR TpacketLen = 6 + TopWords;
4709 regApiPtr->tckeyrec = 0;
4710
4711 if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN))
4712 {
4713 jam();
4714 // Return internally generated TCKEY
4715 TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4716 TcKeyConf::setNoOfOperations(confInfo, 1);
4717 tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
4718 tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
4719 Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[1];
4720 * gci_lo = Uint32(regApiPtr->globalcheckpointid);
4721 tcKeyConf->confInfo = confInfo;
4722 tcKeyConf->transId1 = regApiPtr->transid[0];
4723 tcKeyConf->transId2 = regApiPtr->transid[1];
4724 tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
4725 tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
4726 Uint32 sigLen = 1 /** gci_lo */ +
4727 TcKeyConf::StaticLength + TcKeyConf::OperationLength;
4728 EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
4729 tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN);
4730 if (TopWords == 0) {
4731 jam();
4732 return; // No queued TcKeyConf
4733 }//if
4734 }//if
4735 if(TcommitFlag){
4736 jam();
4737 tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
4738 }
4739 TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
4740 if ((TpacketLen + 1 /** gci_lo */ > 25) || !is_api){
4741 TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4742
4743 jam();
4744 tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4745 tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
4746 Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[TopWords >> 1];
4747 tcKeyConf->confInfo = confInfo;
4748 tcKeyConf->transId1 = regApiPtr->transid[0];
4749 tcKeyConf->transId2 = regApiPtr->transid[1];
4750 copyFromToLen(®ApiPtr->tcSendArray[0],
4751 (UintR*)&tcKeyConf->operations,
4752 (UintR)ZTCOPCONF_SIZE);
4753 * gci_lo = Uint32(regApiPtr->globalcheckpointid);
4754 sendSignal(regApiPtr->ndbapiBlockref,
4755 GSN_TCKEYCONF, signal, (TpacketLen - 1) + 1 /** gci_lo */, JBB);
4756 return;
4757 } else if (((TcurrLen + TpacketLen + 1 /** gci_lo */) > 25) &&
4758 (TcurrLen > 0)) {
4759 jam();
4760 sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
4761 TcurrLen = 0;
4762 } else {
4763 jam();
4764 updatePackedList(signal, localHostptr.p, localHostptr.i);
4765 }//if
4766 // -------------------------------------------------------------------------
4767 // The header contains the block reference of receiver plus the real signal
4768 // length - 3, since we have the real signal length plus one additional word
4769 // for the header we have to do - 4.
4770 // -------------------------------------------------------------------------
4771 UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4 + 1 /** gci_lo */);
4772 UintR Tpack1 = regApiPtr->ndbapiConnect;
4773 UintR Tpack2 = Uint32(regApiPtr->globalcheckpointid >> 32);
4774 UintR Tpack3 = confInfo;
4775 UintR Tpack4 = regApiPtr->transid[0];
4776 UintR Tpack5 = regApiPtr->transid[1];
4777 UintR Tpack6 = Uint32(regApiPtr->globalcheckpointid);
4778
4779 localHostptr.p->noOfWordsTCKEYCONF = TcurrLen + TpacketLen + 1 /** gci_lo */;
4780
4781 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 0] = Tpack0;
4782 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 1] = Tpack1;
4783 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 2] = Tpack2;
4784 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 3] = Tpack3;
4785 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 4] = Tpack4;
4786 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 5] = Tpack5;
4787
4788 UintR Ti;
4789 for (Ti = 6; Ti < TpacketLen; Ti++) {
4790 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + Ti] =
4791 regApiPtr->tcSendArray[Ti - 6];
4792 }//for
4793 localHostptr.p->packedWordsTCKEYCONF[TcurrLen + TpacketLen] = Tpack6;
4794
4795 if (unlikely(!ndb_check_micro_gcp(getNodeInfo(localHostptr.i).m_version)))
4796 {
4797 jam();
4798 ndbassert(Tpack6 == 0 ||
4799 getNodeInfo(localHostptr.i).m_version == 0); // Disconnected
4800 }
4801 }//Dbtc::sendtckeyconf()
4802
copyFromToLen(UintR * sourceBuffer,UintR * destBuffer,UintR Tlen)4803 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
4804 {
4805 UintR Tindex = 0;
4806 UintR Ti;
4807 while (Tlen >= 4) {
4808 UintR Tdata0 = sourceBuffer[Tindex + 0];
4809 UintR Tdata1 = sourceBuffer[Tindex + 1];
4810 UintR Tdata2 = sourceBuffer[Tindex + 2];
4811 UintR Tdata3 = sourceBuffer[Tindex + 3];
4812 Tlen -= 4;
4813 destBuffer[Tindex + 0] = Tdata0;
4814 destBuffer[Tindex + 1] = Tdata1;
4815 destBuffer[Tindex + 2] = Tdata2;
4816 destBuffer[Tindex + 3] = Tdata3;
4817 Tindex += 4;
4818 }//while
4819 for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
4820 destBuffer[Tindex] = sourceBuffer[Tindex];
4821 }//for
4822 }//Dbtc::copyFromToLen()
4823
execSEND_PACKED(Signal * signal)4824 void Dbtc::execSEND_PACKED(Signal* signal)
4825 {
4826 HostRecordPtr Thostptr;
4827 HostRecord *localHostRecord = hostRecord;
4828 UintR i;
4829 UintR TpackedListIndex = cpackedListIndex;
4830 jamEntry();
4831 for (i = 0; i < TpackedListIndex; i++) {
4832 Thostptr.i = cpackedList[i];
4833 ptrAss(Thostptr, localHostRecord);
4834 arrGuard(Thostptr.i - 1, MAX_NODES - 1);
4835 UintR TnoOfPackedWordsLqh = Thostptr.p->noOfPackedWordsLqh;
4836 UintR TnoOfWordsTCKEYCONF = Thostptr.p->noOfWordsTCKEYCONF;
4837 jam();
4838 if (TnoOfPackedWordsLqh > 0) {
4839 jam();
4840 sendPackedSignalLqh(signal, Thostptr.p);
4841 }//if
4842 if (TnoOfWordsTCKEYCONF > 0) {
4843 jam();
4844 sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4845 }//if
4846 Thostptr.p->inPackedList = false;
4847 }//for
4848 cpackedListIndex = 0;
4849 return;
4850 }//Dbtc::execSEND_PACKED()
4851
4852 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 ahostIndex)4853 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
4854 {
4855 if (ahostptr->inPackedList == false) {
4856 UintR TpackedListIndex = cpackedListIndex;
4857 jam();
4858 ahostptr->inPackedList = true;
4859 cpackedList[TpackedListIndex] = ahostIndex;
4860 cpackedListIndex = TpackedListIndex + 1;
4861 }//if
4862 }//Dbtc::updatePackedList()
4863
sendPackedSignalLqh(Signal * signal,HostRecord * ahostptr)4864 void Dbtc::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
4865 {
4866 UintR Tj;
4867 UintR TnoOfWords = ahostptr->noOfPackedWordsLqh;
4868 for (Tj = 0; Tj < TnoOfWords; Tj += 4) {
4869 UintR sig0 = ahostptr->packedWordsLqh[Tj + 0];
4870 UintR sig1 = ahostptr->packedWordsLqh[Tj + 1];
4871 UintR sig2 = ahostptr->packedWordsLqh[Tj + 2];
4872 UintR sig3 = ahostptr->packedWordsLqh[Tj + 3];
4873 signal->theData[Tj + 0] = sig0;
4874 signal->theData[Tj + 1] = sig1;
4875 signal->theData[Tj + 2] = sig2;
4876 signal->theData[Tj + 3] = sig3;
4877 }//for
4878 ahostptr->noOfPackedWordsLqh = 0;
4879 sendSignal(ahostptr->hostLqhBlockRef,
4880 GSN_PACKED_SIGNAL,
4881 signal,
4882 TnoOfWords,
4883 JBB);
4884 }//Dbtc::sendPackedSignalLqh()
4885
sendPackedTCKEYCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)4886 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
4887 HostRecord * ahostptr,
4888 UintR hostId)
4889 {
4890 UintR Tj;
4891 UintR TnoOfWords = ahostptr->noOfWordsTCKEYCONF;
4892 BlockReference TBref = numberToRef(API_PACKED, hostId);
4893 for (Tj = 0; Tj < ahostptr->noOfWordsTCKEYCONF; Tj += 4) {
4894 UintR sig0 = ahostptr->packedWordsTCKEYCONF[Tj + 0];
4895 UintR sig1 = ahostptr->packedWordsTCKEYCONF[Tj + 1];
4896 UintR sig2 = ahostptr->packedWordsTCKEYCONF[Tj + 2];
4897 UintR sig3 = ahostptr->packedWordsTCKEYCONF[Tj + 3];
4898 signal->theData[Tj + 0] = sig0;
4899 signal->theData[Tj + 1] = sig1;
4900 signal->theData[Tj + 2] = sig2;
4901 signal->theData[Tj + 3] = sig3;
4902 }//for
4903 ahostptr->noOfWordsTCKEYCONF = 0;
4904 sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
4905 }//Dbtc::sendPackedTCKEYCONF()
4906
4907 /*
4908 4.3.11 DIVERIFY
4909 ---------------
4910 */
4911 /*****************************************************************************/
4912 /* D I V E R I F Y */
4913 /* */
4914 /*****************************************************************************/
diverify010Lab(Signal * signal)4915 void Dbtc::diverify010Lab(Signal* signal)
4916 {
4917 UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
4918 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4919 signal->theData[0] = apiConnectptr.i;
4920 signal->theData[1] = instance() ? instance() - 1 : 0;
4921 if (ERROR_INSERTED(8022)) {
4922 jam();
4923 systemErrorLab(signal, __LINE__);
4924 }//if
4925
4926 if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS))
4927 {
4928 jam();
4929 /**
4930 * If trans has deferred triggers, let them fire just before
4931 * transaction starts to commit
4932 */
4933 regApiPtr->pendingTriggers = 0;
4934 tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS);
4935 sendFireTrigReq(signal, apiConnectptr, regApiPtr->firstTcConnect);
4936 return;
4937 }
4938
4939 if (regApiPtr->lqhkeyreqrec)
4940 {
4941 if (TfirstfreeApiConnectCopy != RNIL) {
4942 seizeApiConnectCopy(signal);
4943 regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
4944 /*-----------------------------------------------------------------------
4945 * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
4946 * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
4947 * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
4948 * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
4949 *---------------------------------------------------------------------*/
4950 * (EmulatedJamBuffer**)(signal->theData+2) = jamBuffer();
4951 EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal,
4952 2 + sizeof(void*)/sizeof(Uint32), 0);
4953 if (signal->theData[3] == 0) {
4954 execDIVERIFYCONF(signal);
4955 }
4956 return;
4957 } else {
4958 /*-----------------------------------------------------------------------
4959 * There were no free copy connections available. We must abort the
4960 * transaction since otherwise we will have a problem with the report
4961 * to the application.
4962 * This should more or less not happen but if it happens we do
4963 * not want to crash and we do not want to create code to handle it
4964 * properly since it is difficult to test it and will be complex to
4965 * handle a problem more or less not occurring.
4966 *---------------------------------------------------------------------*/
4967 terrorCode = ZSEIZE_API_COPY_ERROR;
4968 abortErrorLab(signal);
4969 return;
4970 }
4971 }
4972 else
4973 {
4974 jam();
4975 sendtckeyconf(signal, 1);
4976 regApiPtr->apiConnectstate = CS_CONNECTED;
4977 regApiPtr->m_transaction_nodes.clear();
4978 setApiConTimer(apiConnectptr.i, 0,__LINE__);
4979 }
4980 }//Dbtc::diverify010Lab()
4981
4982 /* ------------------------------------------------------------------------- */
4983 /* ------- SEIZE_API_CONNECT ------- */
4984 /* SEIZE CONNECT RECORD FOR A REQUEST */
4985 /* ------------------------------------------------------------------------- */
seizeApiConnectCopy(Signal * signal)4986 void Dbtc::seizeApiConnectCopy(Signal* signal)
4987 {
4988 ApiConnectRecordPtr locApiConnectptr;
4989
4990 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4991 UintR TapiConnectFilesize = capiConnectFilesize;
4992 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4993
4994 locApiConnectptr.i = cfirstfreeApiConnectCopy;
4995 ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4996 cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
4997 locApiConnectptr.p->nextApiConnect = RNIL;
4998 regApiPtr->apiCopyRecord = locApiConnectptr.i;
4999 tc_clearbit(regApiPtr->m_flags,
5000 ApiConnectRecord::TF_TRIGGER_PENDING);
5001 regApiPtr->m_special_op_flags = 0;
5002 }//Dbtc::seizeApiConnectCopy()
5003
execDIVERIFYCONF(Signal * signal)5004 void Dbtc::execDIVERIFYCONF(Signal* signal)
5005 {
5006 UintR TapiConnectptrIndex = signal->theData[0];
5007 UintR TapiConnectFilesize = capiConnectFilesize;
5008 UintR Tgci_hi = signal->theData[1];
5009 UintR Tgci_lo = signal->theData[2];
5010 Uint64 Tgci = Tgci_lo | (Uint64(Tgci_hi) << 32);
5011 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5012
5013 jamEntry();
5014 if (ERROR_INSERTED(8017)) {
5015 CLEAR_ERROR_INSERT_VALUE;
5016 return;
5017 }//if
5018 if (TapiConnectptrIndex >= TapiConnectFilesize) {
5019 TCKEY_abort(signal, 31);
5020 return;
5021 }//if
5022 ApiConnectRecord * const regApiPtr =
5023 &localApiConnectRecord[TapiConnectptrIndex];
5024 ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
5025 UintR TApifailureNr = regApiPtr->failureNr;
5026 UintR Tfailure_nr = cfailure_nr;
5027 apiConnectptr.i = TapiConnectptrIndex;
5028 apiConnectptr.p = regApiPtr;
5029 if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
5030 TCKEY_abort(signal, 32);
5031 return;
5032 }//if
5033 /*--------------------------------------------------------------------------
5034 * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
5035 * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
5036 * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
5037 * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
5038 * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
5039 *-------------------------------------------------------------------------*/
5040 if (TApifailureNr != Tfailure_nr) {
5041 DIVER_node_fail_handling(signal, Tgci);
5042 return;
5043 }//if
5044 commitGciHandling(signal, Tgci);
5045
5046 /**************************************************************************
5047 * C O M M I T
5048 * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
5049 **************************************************************************/
5050
5051 UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
5052 UintR TtcConnectFilesize = ctcConnectFilesize;
5053 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5054
5055 regApiPtr->counter = regApiPtr->lqhkeyconfrec;
5056 regApiPtr->apiConnectstate = CS_COMMITTING;
5057 if (TtcConnectptrIndex >= TtcConnectFilesize) {
5058 TCKEY_abort(signal, 33);
5059 return;
5060 }//if
5061 TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
5062 tcConnectptr.i = TtcConnectptrIndex;
5063 tcConnectptr.p = regTcPtr;
5064 commit020Lab(signal);
5065 }//Dbtc::execDIVERIFYCONF()
5066
5067 /*--------------------------------------------------------------------------*/
5068 /* COMMIT_GCI_HANDLING */
5069 /* SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT. */
5070 /*--------------------------------------------------------------------------*/
commitGciHandling(Signal * signal,Uint64 Tgci)5071 void Dbtc::commitGciHandling(Signal* signal, Uint64 Tgci)
5072 {
5073 GcpRecordPtr localGcpPointer;
5074
5075 UintR TgcpFilesize = cgcpFilesize;
5076 UintR Tfirstgcp = cfirstgcp;
5077 Ptr<ApiConnectRecord> regApiPtr = apiConnectptr;
5078 GcpRecord *localGcpRecord = gcpRecord;
5079
5080 regApiPtr.p->globalcheckpointid = Tgci;
5081 if (Tfirstgcp != RNIL) {
5082 /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
5083 localGcpPointer.i = Tfirstgcp;
5084 ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5085 do {
5086 if (regApiPtr.p->globalcheckpointid == localGcpPointer.p->gcpId) {
5087 jam();
5088 linkApiToGcp(localGcpPointer, regApiPtr);
5089 return;
5090 } else {
5091 if (unlikely(! (regApiPtr.p->globalcheckpointid > localGcpPointer.p->gcpId)))
5092 {
5093 ndbout_c("%u/%u %u/%u",
5094 Uint32(regApiPtr.p->globalcheckpointid >> 32),
5095 Uint32(regApiPtr.p->globalcheckpointid),
5096 Uint32(localGcpPointer.p->gcpId >> 32),
5097 Uint32(localGcpPointer.p->gcpId));
5098 crash_gcp(__LINE__);
5099 }
5100 localGcpPointer.i = localGcpPointer.p->nextGcp;
5101 jam();
5102 if (localGcpPointer.i != RNIL) {
5103 jam();
5104 ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5105 continue;
5106 }//if
5107 }//if
5108 seizeGcp(localGcpPointer, Tgci);
5109 linkApiToGcp(localGcpPointer, regApiPtr);
5110 return;
5111 } while (1);
5112 } else {
5113 jam();
5114 seizeGcp(localGcpPointer, Tgci);
5115 linkApiToGcp(localGcpPointer, regApiPtr);
5116 }//if
5117 }//Dbtc::commitGciHandling()
5118
5119 /* --------------------------------------------------------------------------*/
5120 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
5121 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS */
5122 /* LINKED OUT OF THE LIST. */
5123 /*---------------------------------------------------------------------------*/
linkApiToGcp(Ptr<GcpRecord> regGcpPtr,Ptr<ApiConnectRecord> regApiPtr)5124 void Dbtc::linkApiToGcp(Ptr<GcpRecord> regGcpPtr,
5125 Ptr<ApiConnectRecord> regApiPtr)
5126 {
5127 ApiConnectRecordPtr localApiConnectptr;
5128 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5129
5130 regApiPtr.p->nextGcpConnect = RNIL;
5131 if (regGcpPtr.p->firstApiConnect == RNIL) {
5132 regGcpPtr.p->firstApiConnect = regApiPtr.i;
5133 jam();
5134 } else {
5135 UintR TapiConnectFilesize = capiConnectFilesize;
5136 localApiConnectptr.i = regGcpPtr.p->lastApiConnect;
5137 jam();
5138 ptrCheckGuard(localApiConnectptr,
5139 TapiConnectFilesize, localApiConnectRecord);
5140 localApiConnectptr.p->nextGcpConnect = regApiPtr.i;
5141 }//if
5142 UintR TlastApiConnect = regGcpPtr.p->lastApiConnect;
5143 regApiPtr.p->gcpPointer = regGcpPtr.i;
5144 regApiPtr.p->prevGcpConnect = TlastApiConnect;
5145 regGcpPtr.p->lastApiConnect = regApiPtr.i;
5146 }//Dbtc::linkApiToGcp()
5147
5148 void
crash_gcp(Uint32 line)5149 Dbtc::crash_gcp(Uint32 line)
5150 {
5151 GcpRecordPtr localGcpPointer;
5152
5153 localGcpPointer.i = cfirstgcp;
5154
5155 while (localGcpPointer.i != RNIL)
5156 {
5157 ptrCheckGuard(localGcpPointer, cgcpFilesize, gcpRecord);
5158 ndbout_c("%u : %u/%u nomoretrans: %u api %u %u next: %u",
5159 localGcpPointer.i,
5160 Uint32(localGcpPointer.p->gcpId >> 32),
5161 Uint32(localGcpPointer.p->gcpId),
5162 localGcpPointer.p->gcpNomoretransRec,
5163 localGcpPointer.p->firstApiConnect,
5164 localGcpPointer.p->lastApiConnect,
5165 localGcpPointer.p->nextGcp);
5166 localGcpPointer.i = localGcpPointer.p->nextGcp;
5167 }
5168 progError(line, NDBD_EXIT_NDBREQUIRE);
5169 ndbrequire(false);
5170 }
5171
seizeGcp(Ptr<GcpRecord> & dst,Uint64 Tgci)5172 void Dbtc::seizeGcp(Ptr<GcpRecord> & dst, Uint64 Tgci)
5173 {
5174 GcpRecordPtr tmpGcpPointer;
5175 GcpRecordPtr localGcpPointer;
5176
5177 UintR Tfirstgcp = cfirstgcp;
5178 UintR TgcpFilesize = cgcpFilesize;
5179 GcpRecord *localGcpRecord = gcpRecord;
5180
5181 localGcpPointer.i = cfirstfreeGcp;
5182 if (unlikely(localGcpPointer.i > TgcpFilesize))
5183 {
5184 ndbout_c("%u/%u", Uint32(Tgci >> 32), Uint32(Tgci));
5185 crash_gcp(__LINE__);
5186 }
5187 ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5188 UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
5189 localGcpPointer.p->gcpId = Tgci;
5190 localGcpPointer.p->nextGcp = RNIL;
5191 localGcpPointer.p->firstApiConnect = RNIL;
5192 localGcpPointer.p->lastApiConnect = RNIL;
5193 localGcpPointer.p->gcpNomoretransRec = ZFALSE;
5194 cfirstfreeGcp = TfirstfreeGcp;
5195
5196 if (Tfirstgcp == RNIL) {
5197 jam();
5198 cfirstgcp = localGcpPointer.i;
5199 } else {
5200 tmpGcpPointer.i = clastgcp;
5201 jam();
5202 ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
5203 tmpGcpPointer.p->nextGcp = localGcpPointer.i;
5204 }//if
5205 clastgcp = localGcpPointer.i;
5206 dst = localGcpPointer;
5207 }//Dbtc::seizeGcp()
5208
5209 /*---------------------------------------------------------------------------*/
5210 // Send COMMIT messages to all LQH operations involved in the transaction.
5211 /*---------------------------------------------------------------------------*/
commit020Lab(Signal * signal)5212 void Dbtc::commit020Lab(Signal* signal)
5213 {
5214 TcConnectRecordPtr localTcConnectptr;
5215 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5216 UintR TtcConnectFilesize = ctcConnectFilesize;
5217 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5218
5219 localTcConnectptr.p = tcConnectptr.p;
5220 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5221 UintR Tcount = 0;
5222 do {
5223 /*-----------------------------------------------------------------------
5224 * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
5225 *-----------------------------------------------------------------------*/
5226 /* *********< */
5227 /* COMMIT < */
5228 /* *********< */
5229 localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
5230 localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
5231 Tcount += sendCommitLqh(signal, localTcConnectptr.p);
5232
5233 if (localTcConnectptr.i != RNIL) {
5234 if (Tcount < 16 &&
5235 ! (ERROR_INSERTED(8057) ||
5236 ERROR_INSERTED(8073) ||
5237 ERROR_INSERTED(8089)))
5238 {
5239 ptrCheckGuard(localTcConnectptr,
5240 TtcConnectFilesize, localTcConnectRecord);
5241 jam();
5242 continue;
5243 } else {
5244 jam();
5245 if (ERROR_INSERTED(8014)) {
5246 CLEAR_ERROR_INSERT_VALUE;
5247 return;
5248 }//if
5249
5250 if (ERROR_INSERTED(8073))
5251 {
5252 execSEND_PACKED(signal);
5253 signal->theData[0] = 9999;
5254 sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
5255 return;
5256 }
5257 signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
5258 signal->theData[1] = apiConnectptr.i;
5259 signal->theData[2] = localTcConnectptr.i;
5260 if (ERROR_INSERTED(8089))
5261 {
5262 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
5263 return;
5264 }
5265 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5266 return;
5267 }//if
5268 } else {
5269 jam();
5270 if (ERROR_INSERTED(8057))
5271 CLEAR_ERROR_INSERT_VALUE;
5272
5273 if (ERROR_INSERTED(8089))
5274 CLEAR_ERROR_INSERT_VALUE;
5275
5276 regApiPtr->apiConnectstate = CS_COMMIT_SENT;
5277 return;
5278 }//if
5279 } while (1);
5280 }//Dbtc::commit020Lab()
5281
5282 Uint32
sendCommitLqh(Signal * signal,TcConnectRecord * const regTcPtr)5283 Dbtc::sendCommitLqh(Signal* signal,
5284 TcConnectRecord * const regTcPtr)
5285 {
5286 HostRecordPtr Thostptr;
5287 UintR ThostFilesize = chostFilesize;
5288 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5289 Thostptr.i = regTcPtr->lastLqhNodeId;
5290 ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5291
5292 Uint32 Tnode = Thostptr.i;
5293 Uint32 self = getOwnNodeId();
5294 Uint32 ret = (Tnode == self) ? 4 : 1;
5295
5296 Uint32 Tdata[5];
5297 Tdata[0] = regTcPtr->lastLqhCon;
5298 Tdata[1] = Uint32(regApiPtr->globalcheckpointid >> 32);
5299 Tdata[2] = regApiPtr->transid[0];
5300 Tdata[3] = regApiPtr->transid[1];
5301 Tdata[4] = Uint32(regApiPtr->globalcheckpointid);
5302 Uint32 len = 5;
5303
5304 if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
5305 {
5306 jam();
5307 ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
5308 len = 4;
5309 }
5310
5311 // currently packed signal cannot address specific instance
5312 const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5313 if (send_unpacked) {
5314 memcpy(&signal->theData[0], &Tdata[0], len << 2);
5315 Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5316 BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5317 sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
5318 return ret;
5319 }
5320
5321 if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
5322 jam();
5323 sendPackedSignalLqh(signal, Thostptr.p);
5324 } else {
5325 jam();
5326 ret = 1;
5327 updatePackedList(signal, Thostptr.p, Thostptr.i);
5328 }
5329
5330 Tdata[0] |= (ZCOMMIT << 28);
5331 UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5332 UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5333 memcpy(TDataPtr, &Tdata[0], len << 2);
5334 Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5335 return ret;
5336 }
5337
5338 void
DIVER_node_fail_handling(Signal * signal,Uint64 Tgci)5339 Dbtc::DIVER_node_fail_handling(Signal* signal, Uint64 Tgci)
5340 {
5341 /*------------------------------------------------------------------------
5342 * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
5343 * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
5344 * ABORT AND THE COMMIT CASES WE NEED TO SET-UP THE DATA FOR THE
5345 * ABORT/COMMIT/COMPLETE HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
5346 *------------------------------------------------------------------------*/
5347 tabortInd = ZFALSE;
5348 setupFailData(signal);
5349 if (false && tabortInd == ZFALSE) {
5350 jam();
5351 commitGciHandling(signal, Tgci);
5352 toCommitHandlingLab(signal);
5353 } else {
5354 jam();
5355 apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
5356 apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
5357 toAbortHandlingLab(signal);
5358 }//if
5359 return;
5360 }//Dbtc::DIVER_node_fail_handling()
5361
5362
5363 /* ------------------------------------------------------------------------- */
5364 /* ------- ENTER COMMITTED ------- */
5365 /* */
5366 /* ------------------------------------------------------------------------- */
execCOMMITTED(Signal * signal)5367 void Dbtc::execCOMMITTED(Signal* signal)
5368 {
5369 TcConnectRecordPtr localTcConnectptr;
5370 ApiConnectRecordPtr localApiConnectptr;
5371 ApiConnectRecordPtr localCopyPtr;
5372
5373 UintR TtcConnectFilesize = ctcConnectFilesize;
5374 UintR TapiConnectFilesize = capiConnectFilesize;
5375 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5376 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5377
5378 #ifdef ERROR_INSERT
5379 if (ERROR_INSERTED(8018)) {
5380 CLEAR_ERROR_INSERT_VALUE;
5381 return;
5382 }//if
5383 CRASH_INSERTION(8030);
5384 if (ERROR_INSERTED(8025)) {
5385 SET_ERROR_INSERT_VALUE(8026);
5386 return;
5387 }//if
5388 if (ERROR_INSERTED(8041)) {
5389 CLEAR_ERROR_INSERT_VALUE;
5390 sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
5391 return;
5392 }//if
5393 if (ERROR_INSERTED(8042)) {
5394 SET_ERROR_INSERT_VALUE(8046);
5395 sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
5396 return;
5397 }//if
5398 #endif
5399 localTcConnectptr.i = signal->theData[0];
5400 jamEntry();
5401 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5402 localApiConnectptr.i = localTcConnectptr.p->apiConnect;
5403 if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
5404 warningReport(signal, 4);
5405 return;
5406 }//if
5407 ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
5408 localApiConnectRecord);
5409 UintR Tcounter = localApiConnectptr.p->counter - 1;
5410 ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
5411 UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
5412 UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
5413 Tdata1 = Tdata1 | Tdata2;
5414 bool TcheckCondition =
5415 (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
5416
5417 setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
5418 localApiConnectptr.p->counter = Tcounter;
5419 localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
5420 if (Tdata1 != 0) {
5421 warningReport(signal, 5);
5422 return;
5423 }//if
5424 if (TcheckCondition) {
5425 jam();
5426 /*-------------------------------------------------------*/
5427 // We have not sent all COMMIT requests yet. We could be
5428 // in the state that all sent are COMMITTED but we are
5429 // still waiting for a CONTINUEB to send the rest of the
5430 // COMMIT requests.
5431 /*-------------------------------------------------------*/
5432 return;
5433 }//if
5434 if (ERROR_INSERTED(8020)) {
5435 jam();
5436 systemErrorLab(signal, __LINE__);
5437 }//if
5438 /*-------------------------------------------------------*/
5439 /* THE ENTIRE TRANSACTION IS NOW COMMITED */
5440 /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION. */
5441 /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
5442 /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A */
5443 /* NEW API CONNECT RECORD. */
5444 /*-------------------------------------------------------*/
5445
5446 apiConnectptr = localApiConnectptr;
5447 localCopyPtr = sendApiCommit(signal);
5448
5449 localTcConnectptr.i = localCopyPtr.p->firstTcConnect;
5450 UintR Tlqhkeyconfrec = localCopyPtr.p->lqhkeyconfrec;
5451 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5452 localCopyPtr.p->counter = Tlqhkeyconfrec;
5453
5454 apiConnectptr = localCopyPtr;
5455 tcConnectptr = localTcConnectptr;
5456 complete010Lab(signal);
5457 return;
5458
5459 }//Dbtc::execCOMMITTED()
5460
5461 /*-------------------------------------------------------*/
5462 /* SEND_API_COMMIT */
5463 /* SEND COMMIT DECISION TO THE API. */
5464 /*-------------------------------------------------------*/
5465 Ptr<Dbtc::ApiConnectRecord>
sendApiCommit(Signal * signal)5466 Dbtc::sendApiCommit(Signal* signal)
5467 {
5468 ApiConnectRecordPtr regApiPtr = apiConnectptr;
5469
5470 if (ERROR_INSERTED(8055))
5471 {
5472 /**
5473 * 1) Kill self
5474 * 2) Disconnect API
5475 * 3) Prevent execAPI_FAILREQ from handling trans...
5476 */
5477 signal->theData[0] = 9999;
5478 sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
5479 Uint32 node = refToNode(regApiPtr.p->ndbapiBlockref);
5480 signal->theData[0] = node;
5481 sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
5482
5483 SET_ERROR_INSERT_VALUE(8056);
5484
5485 goto err8055;
5486 }
5487
5488 if (regApiPtr.p->returnsignal == RS_TCKEYCONF)
5489 {
5490 if (ERROR_INSERTED(8054))
5491 {
5492 CLEAR_ERROR_INSERT_VALUE;
5493 signal->theData[0] = 9999;
5494 sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 5000, 1);
5495 }
5496 else
5497 {
5498 sendtckeyconf(signal, 1);
5499 }
5500 }
5501 else if (regApiPtr.p->returnsignal == RS_TC_COMMITCONF)
5502 {
5503 jam();
5504 TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
5505 if(regApiPtr.p->commitAckMarker == RNIL)
5506 {
5507 jam();
5508 commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect;
5509 }
5510 else
5511 {
5512 jam();
5513 commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect | 1;
5514 }
5515 commitConf->transId1 = regApiPtr.p->transid[0];
5516 commitConf->transId2 = regApiPtr.p->transid[1];
5517 commitConf->gci_hi = Uint32(regApiPtr.p->globalcheckpointid >> 32);
5518 commitConf->gci_lo = Uint32(regApiPtr.p->globalcheckpointid);
5519
5520 sendSignal(regApiPtr.p->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
5521 TcCommitConf::SignalLength, JBB);
5522 }
5523 else if (regApiPtr.p->returnsignal == RS_NO_RETURN)
5524 {
5525 jam();
5526 }
5527 else
5528 {
5529 TCKEY_abort(signal, 37);
5530 return regApiPtr;
5531 }//if
5532
5533 err8055:
5534 Ptr<ApiConnectRecord> copyPtr;
5535 UintR TapiConnectFilesize = capiConnectFilesize;
5536 copyPtr.i = regApiPtr.p->apiCopyRecord;
5537 UintR TapiFailState = regApiPtr.p->apiFailState;
5538 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5539
5540 c_counters.ccommitCount++;
5541 ptrCheckGuard(copyPtr, TapiConnectFilesize, localApiConnectRecord);
5542 copyApi(copyPtr, regApiPtr);
5543 if (TapiFailState != ZTRUE) {
5544 return copyPtr;
5545 } else {
5546 jam();
5547 handleApiFailState(signal, regApiPtr.i);
5548 return copyPtr;
5549 }//if
5550 }//Dbtc::sendApiCommit()
5551
5552 /* ========================================================================= */
5553 /* ======= COPY_API ======= */
5554 /* COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT */
5555 /* IS PREPARED TO RECEIVE A NEW TRANSACTION. */
5556 /*===========================================================================*/
copyApi(ApiConnectRecordPtr copyPtr,ApiConnectRecordPtr regApiPtr)5557 void Dbtc::copyApi(ApiConnectRecordPtr copyPtr, ApiConnectRecordPtr regApiPtr)
5558 {
5559 UintR TndbapiConnect = regApiPtr.p->ndbapiConnect;
5560 UintR TfirstTcConnect = regApiPtr.p->firstTcConnect;
5561 UintR Ttransid1 = regApiPtr.p->transid[0];
5562 UintR Ttransid2 = regApiPtr.p->transid[1];
5563 UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
5564 UintR TgcpPointer = regApiPtr.p->gcpPointer;
5565 UintR TgcpFilesize = cgcpFilesize;
5566 NdbNodeBitmask Tnodes = regApiPtr.p->m_transaction_nodes;
5567 GcpRecord *localGcpRecord = gcpRecord;
5568
5569 copyPtr.p->ndbapiBlockref = regApiPtr.p->ndbapiBlockref;
5570 copyPtr.p->ndbapiConnect = TndbapiConnect;
5571 copyPtr.p->firstTcConnect = TfirstTcConnect;
5572 copyPtr.p->apiConnectstate = CS_COMPLETING;
5573 copyPtr.p->transid[0] = Ttransid1;
5574 copyPtr.p->transid[1] = Ttransid2;
5575 copyPtr.p->lqhkeyconfrec = Tlqhkeyconfrec;
5576 copyPtr.p->commitAckMarker = RNIL;
5577 copyPtr.p->m_transaction_nodes = Tnodes;
5578 copyPtr.p->singleUserMode = 0;
5579
5580 Ptr<GcpRecord> gcpPtr;
5581 gcpPtr.i = TgcpPointer;
5582 ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
5583 unlinkApiConnect(gcpPtr, regApiPtr);
5584 linkApiToGcp(gcpPtr, copyPtr);
5585 setApiConTimer(regApiPtr.i, 0, __LINE__);
5586 regApiPtr.p->apiConnectstate = CS_CONNECTED;
5587 regApiPtr.p->commitAckMarker = RNIL;
5588 regApiPtr.p->firstTcConnect = RNIL;
5589 regApiPtr.p->lastTcConnect = RNIL;
5590 regApiPtr.p->m_transaction_nodes.clear();
5591 regApiPtr.p->singleUserMode = 0;
5592 releaseAllSeizedIndexOperations(regApiPtr.p);
5593 }//Dbtc::copyApi()
5594
unlinkApiConnect(Ptr<GcpRecord> gcpPtr,Ptr<ApiConnectRecord> regApiPtr)5595 void Dbtc::unlinkApiConnect(Ptr<GcpRecord> gcpPtr,
5596 Ptr<ApiConnectRecord> regApiPtr)
5597 {
5598 ApiConnectRecordPtr localApiConnectptr;
5599 UintR TapiConnectFilesize = capiConnectFilesize;
5600 UintR TprevGcpConnect = regApiPtr.p->prevGcpConnect;
5601 UintR TnextGcpConnect = regApiPtr.p->nextGcpConnect;
5602 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5603
5604 if (TprevGcpConnect == RNIL) {
5605 gcpPtr.p->firstApiConnect = TnextGcpConnect;
5606 jam();
5607 } else {
5608 localApiConnectptr.i = TprevGcpConnect;
5609 jam();
5610 ptrCheckGuard(localApiConnectptr,
5611 TapiConnectFilesize, localApiConnectRecord);
5612 localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
5613 }//if
5614 if (TnextGcpConnect == RNIL) {
5615 gcpPtr.p->lastApiConnect = TprevGcpConnect;
5616 jam();
5617 } else {
5618 localApiConnectptr.i = TnextGcpConnect;
5619 jam();
5620 ptrCheckGuard(localApiConnectptr,
5621 TapiConnectFilesize, localApiConnectRecord);
5622 localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
5623 }//if
5624 }//Dbtc::unlinkApiConnect()
5625
complete010Lab(Signal * signal)5626 void Dbtc::complete010Lab(Signal* signal)
5627 {
5628 TcConnectRecordPtr localTcConnectptr;
5629 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5630 UintR TtcConnectFilesize = ctcConnectFilesize;
5631 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5632
5633 localTcConnectptr.p = tcConnectptr.p;
5634 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5635 UintR TapiConnectptrIndex = apiConnectptr.i;
5636 UintR Tcount = 0;
5637 do {
5638 localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
5639 localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
5640
5641 /* ************ */
5642 /* COMPLETE < */
5643 /* ************ */
5644 const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
5645 Tcount += sendCompleteLqh(signal, localTcConnectptr.p);
5646 localTcConnectptr.i = nextTcConnect;
5647 if (localTcConnectptr.i != RNIL) {
5648 if (Tcount < 16) {
5649 ptrCheckGuard(localTcConnectptr,
5650 TtcConnectFilesize, localTcConnectRecord);
5651 jam();
5652 continue;
5653 } else {
5654 jam();
5655 if (ERROR_INSERTED(8013)) {
5656 CLEAR_ERROR_INSERT_VALUE;
5657 return;
5658 }//if
5659 signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
5660 signal->theData[1] = apiConnectptr.i;
5661 signal->theData[2] = localTcConnectptr.i;
5662 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5663 return;
5664 }//if
5665 } else {
5666 jam();
5667 regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
5668 return;
5669 }//if
5670 } while (1);
5671 }//Dbtc::complete010Lab()
5672
5673 Uint32
sendCompleteLqh(Signal * signal,TcConnectRecord * const regTcPtr)5674 Dbtc::sendCompleteLqh(Signal* signal,
5675 TcConnectRecord * const regTcPtr)
5676 {
5677 HostRecordPtr Thostptr;
5678 UintR ThostFilesize = chostFilesize;
5679 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5680 Thostptr.i = regTcPtr->lastLqhNodeId; //last???
5681 ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5682
5683 Uint32 Tnode = Thostptr.i;
5684 Uint32 self = getOwnNodeId();
5685 Uint32 ret = (Tnode == self) ? 4 : 1;
5686
5687 Uint32 Tdata[3];
5688 Tdata[0] = regTcPtr->lastLqhCon;
5689 Tdata[1] = regApiPtr->transid[0];
5690 Tdata[2] = regApiPtr->transid[1];
5691 Uint32 len = 3;
5692
5693 // currently packed signal cannot address specific instance
5694 const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5695 if (send_unpacked) {
5696 memcpy(&signal->theData[0], &Tdata[0], len << 2);
5697 Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5698 BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5699 sendSignal(lqhRef, GSN_COMPLETE, signal, 3, JBB);
5700 return ret;
5701 }
5702
5703 if (Thostptr.p->noOfPackedWordsLqh > 22) {
5704 jam();
5705 sendPackedSignalLqh(signal, Thostptr.p);
5706 } else {
5707 jam();
5708 ret = 1;
5709 updatePackedList(signal, Thostptr.p, Thostptr.i);
5710 }
5711
5712 Tdata[0] |= (ZCOMPLETE << 28);
5713 UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5714 UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5715 memcpy(TDataPtr, &Tdata[0], len << 2);
5716 Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5717
5718 return ret;
5719 }
5720
5721 void
sendFireTrigReq(Signal * signal,Ptr<ApiConnectRecord> regApiPtr,Uint32 TopPtrI)5722 Dbtc::sendFireTrigReq(Signal* signal,
5723 Ptr<ApiConnectRecord> regApiPtr,
5724 Uint32 TopPtrI)
5725 {
5726 UintR TtcConnectFilesize = ctcConnectFilesize;
5727 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5728 TcConnectRecordPtr localTcConnectptr;
5729
5730 setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
5731 regApiPtr.p->apiConnectstate = CS_SEND_FIRE_TRIG_REQ;
5732
5733 localTcConnectptr.i = TopPtrI;
5734 ndbassert(TopPtrI != RNIL);
5735 Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5736 Uint32 pass = regApiPtr.p->m_pre_commit_pass;
5737 for (Uint32 i = 0; localTcConnectptr.i != RNIL && i < 16; i++)
5738 {
5739 ptrCheckGuard(localTcConnectptr,
5740 TtcConnectFilesize, localTcConnectRecord);
5741
5742 const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
5743 Uint32 flags = localTcConnectptr.p->m_special_op_flags;
5744 if (flags & TcConnectRecord::SOF_DEFERRED_TRIGGER)
5745 {
5746 jam();
5747 tc_clearbit(flags, TcConnectRecord::SOF_DEFERRED_TRIGGER);
5748 ndbrequire(localTcConnectptr.p->tcConnectstate == OS_PREPARED);
5749 localTcConnectptr.p->tcConnectstate = OS_FIRE_TRIG_REQ;
5750 localTcConnectptr.p->m_special_op_flags = flags;
5751 i += sendFireTrigReqLqh(signal, localTcConnectptr, pass);
5752 Tlqhkeyreqrec++;
5753 }
5754 localTcConnectptr.i = nextTcConnect;
5755 }
5756
5757 regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec;
5758 if (localTcConnectptr.i == RNIL)
5759 {
5760 /**
5761 * Now wait for FIRE_TRIG_CONF
5762 */
5763 jam();
5764 regApiPtr.p->apiConnectstate = CS_WAIT_FIRE_TRIG_REQ;
5765 ndbrequire(pass < 255);
5766 regApiPtr.p->m_pre_commit_pass = (Uint8)(pass + 1);
5767 return;
5768 }
5769 else
5770 {
5771 jam();
5772 signal->theData[0] = TcContinueB::ZSEND_FIRE_TRIG_REQ;
5773 signal->theData[1] = regApiPtr.i;
5774 signal->theData[2] = regApiPtr.p->transid[0];
5775 signal->theData[3] = regApiPtr.p->transid[1];
5776 signal->theData[4] = localTcConnectptr.i;
5777 if (ERROR_INSERTED_CLEAR(8090))
5778 {
5779 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 5);
5780 }
5781 else
5782 {
5783 sendSignal(cownref, GSN_CONTINUEB, signal, 5, JBB);
5784 }
5785 }
5786 }
5787
5788 Uint32
sendFireTrigReqLqh(Signal * signal,Ptr<TcConnectRecord> regTcPtr,Uint32 pass)5789 Dbtc::sendFireTrigReqLqh(Signal* signal,
5790 Ptr<TcConnectRecord> regTcPtr,
5791 Uint32 pass)
5792 {
5793 HostRecordPtr Thostptr;
5794 UintR ThostFilesize = chostFilesize;
5795 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5796 Thostptr.i = regTcPtr.p->tcNodedata[0];
5797 ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5798
5799 Uint32 Tnode = Thostptr.i;
5800 Uint32 self = getOwnNodeId();
5801 Uint32 ret = (Tnode == self) ? 4 : 1;
5802
5803 Uint32 Tdata[FireTrigReq::SignalLength];
5804 FireTrigReq * req = CAST_PTR(FireTrigReq, Tdata);
5805 req->tcOpRec = regTcPtr.i;
5806 req->transId[0] = regApiPtr->transid[0];
5807 req->transId[1] = regApiPtr->transid[1];
5808 req->pass = pass;
5809 Uint32 len = FireTrigReq::SignalLength;
5810
5811 // currently packed signal cannot address specific instance
5812 const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5813 if (send_unpacked) {
5814 memcpy(signal->theData, Tdata, len << 2);
5815 Uint32 instanceKey = regTcPtr.p->lqhInstanceKey;
5816 BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5817 sendSignal(lqhRef, GSN_FIRE_TRIG_REQ, signal, len, JBB);
5818 return ret;
5819 }
5820
5821 if (Thostptr.p->noOfPackedWordsLqh > 25 - len) {
5822 jam();
5823 sendPackedSignalLqh(signal, Thostptr.p);
5824 } else {
5825 jam();
5826 ret = 1;
5827 updatePackedList(signal, Thostptr.p, Thostptr.i);
5828 }
5829
5830 Tdata[0] |= (ZFIRE_TRIG_REQ << 28);
5831 UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5832 UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5833 memcpy(TDataPtr, Tdata, len << 2);
5834 Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5835 return ret;
5836 }
5837
5838 void
execFIRE_TRIG_CONF(Signal * signal)5839 Dbtc::execFIRE_TRIG_CONF(Signal* signal)
5840 {
5841 TcConnectRecordPtr localTcConnectptr;
5842 ApiConnectRecordPtr regApiPtr;
5843
5844 UintR TtcConnectFilesize = ctcConnectFilesize;
5845 UintR TapiConnectFilesize = capiConnectFilesize;
5846 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5847 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5848
5849 const FireTrigConf * conf = CAST_CONSTPTR(FireTrigConf, signal->theData);
5850 localTcConnectptr.i = conf->tcOpRec;
5851 jamEntry();
5852 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5853 regApiPtr.i = localTcConnectptr.p->apiConnect;
5854 if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
5855 {
5856 warningReport(signal, 28);
5857 return;
5858 }//if
5859 ptrCheckGuard(regApiPtr, TapiConnectFilesize,
5860 localApiConnectRecord);
5861
5862 Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5863 Uint32 TapiConnectstate = regApiPtr.p->apiConnectstate;
5864 UintR Tdata1 = regApiPtr.p->transid[0] - conf->transId[0];
5865 UintR Tdata2 = regApiPtr.p->transid[1] - conf->transId[1];
5866 Uint32 TcheckCondition =
5867 (TapiConnectstate != CS_SEND_FIRE_TRIG_REQ) &&
5868 (TapiConnectstate != CS_WAIT_FIRE_TRIG_REQ);
5869
5870 Tdata1 = Tdata1 | Tdata2 | TcheckCondition;
5871
5872 if (Tdata1 != 0) {
5873 warningReport(signal, 28);
5874 return;
5875 }//if
5876
5877 if (ERROR_INSERTED_CLEAR(8091))
5878 {
5879 jam();
5880 return;
5881 }
5882
5883 CRASH_INSERTION(8092);
5884
5885 setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
5886 ndbassert(Tlqhkeyreqrec > 0);
5887 regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
5888 localTcConnectptr.p->tcConnectstate = OS_PREPARED;
5889
5890 Uint32 noFired = FireTrigConf::getFiredCount(conf->noFiredTriggers);
5891 Uint32 deferred = FireTrigConf::getDeferredBit(conf->noFiredTriggers);
5892
5893 regApiPtr.p->pendingTriggers += noFired;
5894 regApiPtr.p->m_flags |= (deferred) ?
5895 ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
5896 localTcConnectptr.p->m_special_op_flags |= (deferred) ?
5897 TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
5898
5899 if (regApiPtr.p->pendingTriggers == 0)
5900 {
5901 jam();
5902 lqhKeyConf_checkTransactionState(signal, regApiPtr);
5903 }
5904 }
5905
5906 void
execFIRE_TRIG_REF(Signal * signal)5907 Dbtc::execFIRE_TRIG_REF(Signal* signal)
5908 {
5909 TcConnectRecordPtr localTcConnectptr;
5910 ApiConnectRecordPtr regApiPtr;
5911
5912 UintR TtcConnectFilesize = ctcConnectFilesize;
5913 UintR TapiConnectFilesize = capiConnectFilesize;
5914 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5915 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5916
5917 const FireTrigRef * ref = CAST_CONSTPTR(FireTrigRef, signal->theData);
5918 localTcConnectptr.i = ref->tcOpRec;
5919 jamEntry();
5920 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5921 regApiPtr.i = localTcConnectptr.p->apiConnect;
5922 if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
5923 {
5924 warningReport(signal, 28);
5925 return;
5926 }//if
5927 ptrCheckGuard(regApiPtr, TapiConnectFilesize,
5928 localApiConnectRecord);
5929
5930 apiConnectptr = regApiPtr;
5931
5932 UintR Tdata1 = regApiPtr.p->transid[0] - ref->transId[0];
5933 UintR Tdata2 = regApiPtr.p->transid[1] - ref->transId[1];
5934 Tdata1 = Tdata1 | Tdata2;
5935 if (Tdata1 != 0) {
5936 warningReport(signal, 28);
5937 return;
5938 }//if
5939
5940 if (regApiPtr.p->apiConnectstate != CS_SEND_FIRE_TRIG_REQ &&
5941 regApiPtr.p->apiConnectstate != CS_WAIT_FIRE_TRIG_REQ)
5942 {
5943 jam();
5944 warningReport(signal, 28);
5945 return;
5946 }
5947
5948 terrorCode = ref->errCode;
5949 abortErrorLab(signal);
5950 }
5951
5952 void
execTC_COMMIT_ACK(Signal * signal)5953 Dbtc::execTC_COMMIT_ACK(Signal* signal){
5954 jamEntry();
5955
5956 CommitAckMarker key;
5957 key.transid1 = signal->theData[0];
5958 key.transid2 = signal->theData[1];
5959
5960 CommitAckMarkerPtr removedMarker;
5961 m_commitAckMarkerHash.remove(removedMarker, key);
5962 if (removedMarker.i == RNIL) {
5963 jam();
5964 warningHandlerLab(signal, __LINE__);
5965 return;
5966 }//if
5967 sendRemoveMarkers(signal, removedMarker.p);
5968 m_commitAckMarkerPool.release(removedMarker);
5969 }
5970
5971 void
sendRemoveMarkers(Signal * signal,const CommitAckMarker * marker)5972 Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker)
5973 {
5974 jam();
5975 const Uint32 transId1 = marker->transid1;
5976 const Uint32 transId2 = marker->transid2;
5977
5978 for(Uint32 node_id = 1; node_id < MAX_NDB_NODES; node_id++)
5979 {
5980 jam();
5981 if (marker->m_commit_ack_marker_nodes.get(node_id))
5982 sendRemoveMarker(signal, node_id, transId1, transId2);
5983 }
5984 }
5985
5986 void
sendRemoveMarker(Signal * signal,NodeId nodeId,Uint32 transid1,Uint32 transid2)5987 Dbtc::sendRemoveMarker(Signal* signal,
5988 NodeId nodeId,
5989 Uint32 transid1,
5990 Uint32 transid2){
5991 /**
5992 * Seize host ptr
5993 */
5994 HostRecordPtr hostPtr;
5995 const UintR ThostFilesize = chostFilesize;
5996 hostPtr.i = nodeId;
5997 ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
5998
5999 Uint32 Tdata[3];
6000 Tdata[0] = 0;
6001 Tdata[1] = transid1;
6002 Tdata[2] = transid2;
6003 Uint32 len = 3;
6004
6005 // currently packed signals can not address specific instance
6006 bool send_unpacked = getNodeInfo(hostPtr.i).m_lqh_workers > 1;
6007 if (send_unpacked) {
6008 jam();
6009 // first word omitted
6010 memcpy(&signal->theData[0], &Tdata[1], (len - 1) << 2);
6011 Uint32 Tnode = hostPtr.i;
6012 Uint32 i;
6013 for (i = 0; i < MAX_NDBMT_LQH_WORKERS; i++) {
6014 // wl4391_todo skip workers not part of tx
6015 Uint32 instanceKey = 1 + i;
6016 BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
6017 sendSignal(ref, GSN_REMOVE_MARKER_ORD, signal, len - 1, JBB);
6018 }
6019 return;
6020 }
6021
6022 if (hostPtr.p->noOfPackedWordsLqh > (25 - 3)){
6023 jam();
6024 sendPackedSignalLqh(signal, hostPtr.p);
6025 } else {
6026 jam();
6027 updatePackedList(signal, hostPtr.p, hostPtr.i);
6028 }
6029
6030 UintR numWord = hostPtr.p->noOfPackedWordsLqh;
6031 UintR* dataPtr = &hostPtr.p->packedWordsLqh[numWord];
6032
6033 Tdata[0] |= (ZREMOVE_MARKER << 28);
6034 memcpy(dataPtr, &Tdata[0], len << 2);
6035 hostPtr.p->noOfPackedWordsLqh = numWord + 3;
6036 }
6037
execCOMPLETED(Signal * signal)6038 void Dbtc::execCOMPLETED(Signal* signal)
6039 {
6040 TcConnectRecordPtr localTcConnectptr;
6041 ApiConnectRecordPtr localApiConnectptr;
6042
6043 UintR TtcConnectFilesize = ctcConnectFilesize;
6044 UintR TapiConnectFilesize = capiConnectFilesize;
6045 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6046 ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6047
6048 #ifdef ERROR_INSERT
6049 if (ERROR_INSERTED(8031)) {
6050 systemErrorLab(signal, __LINE__);
6051 }//if
6052 if (ERROR_INSERTED(8019)) {
6053 CLEAR_ERROR_INSERT_VALUE;
6054 return;
6055 }//if
6056 if (ERROR_INSERTED(8027)) {
6057 SET_ERROR_INSERT_VALUE(8028);
6058 return;
6059 }//if
6060 if (ERROR_INSERTED(8043)) {
6061 CLEAR_ERROR_INSERT_VALUE;
6062 sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6063 return;
6064 }//if
6065 if (ERROR_INSERTED(8044)) {
6066 SET_ERROR_INSERT_VALUE(8047);
6067 sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6068 return;
6069 }//if
6070 #endif
6071 localTcConnectptr.i = signal->theData[0];
6072 jamEntry();
6073 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6074 bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
6075 localApiConnectptr.i = localTcConnectptr.p->apiConnect;
6076 if (Tcond1) {
6077 warningReport(signal, 6);
6078 return;
6079 }//if
6080 ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
6081 localApiConnectRecord);
6082 UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
6083 UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
6084 UintR Tcounter = localApiConnectptr.p->counter - 1;
6085 ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
6086 Tdata1 = Tdata1 | Tdata2;
6087 bool TcheckCondition =
6088 (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
6089 if (Tdata1 != 0) {
6090 warningReport(signal, 7);
6091 return;
6092 }//if
6093 setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
6094 localApiConnectptr.p->counter = Tcounter;
6095 localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
6096 localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
6097 if (TcheckCondition) {
6098 jam();
6099 /*-------------------------------------------------------*/
6100 // We have not sent all COMPLETE requests yet. We could be
6101 // in the state that all sent are COMPLETED but we are
6102 // still waiting for a CONTINUEB to send the rest of the
6103 // COMPLETE requests.
6104 /*-------------------------------------------------------*/
6105 return;
6106 }//if
6107 if (ERROR_INSERTED(8021)) {
6108 jam();
6109 systemErrorLab(signal, __LINE__);
6110 }//if
6111 apiConnectptr = localApiConnectptr;
6112 releaseTransResources(signal);
6113 }//Dbtc::execCOMPLETED()
6114
6115 /*---------------------------------------------------------------------------*/
6116 /* RELEASE_TRANS_RESOURCES */
6117 /* RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION. */
6118 /*---------------------------------------------------------------------------*/
releaseTransResources(Signal * signal)6119 void Dbtc::releaseTransResources(Signal* signal)
6120 {
6121 TcConnectRecordPtr localTcConnectptr;
6122 UintR TtcConnectFilesize = ctcConnectFilesize;
6123 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6124 apiConnectptr.p->m_transaction_nodes.clear();
6125 localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
6126 do {
6127 jam();
6128 ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6129 UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
6130 tcConnectptr.i = localTcConnectptr.i;
6131 tcConnectptr.p = localTcConnectptr.p;
6132 localTcConnectptr.i = rtrTcConnectptrIndex;
6133 releaseTcCon();
6134 } while (localTcConnectptr.i != RNIL);
6135 handleGcp(signal, apiConnectptr);
6136 releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
6137 releaseAllSeizedIndexOperations(apiConnectptr.p);
6138 releaseApiConCopy(signal);
6139 }//Dbtc::releaseTransResources()
6140
6141 /* *********************************************************************>> */
6142 /* MODULE: HANDLE_GCP */
6143 /* DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
6144 /* OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC */
6145 /* SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
6146 /* GLOBAL CHECKPOINT HAVE COMPLETED. */
6147 /* *********************************************************************>> */
handleGcp(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)6148 void Dbtc::handleGcp(Signal* signal, Ptr<ApiConnectRecord> regApiPtr)
6149 {
6150 GcpRecord *localGcpRecord = gcpRecord;
6151 GcpRecordPtr localGcpPtr;
6152 UintR TgcpFilesize = cgcpFilesize;
6153 localGcpPtr.i = apiConnectptr.p->gcpPointer;
6154 ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
6155 unlinkApiConnect(localGcpPtr, regApiPtr);
6156 if (localGcpPtr.p->firstApiConnect == RNIL) {
6157 if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
6158 if (c_ongoing_take_over_cnt == 0)
6159 {
6160 jam();
6161 gcpTcfinished(signal, localGcpPtr.p->gcpId);
6162 unlinkGcp(localGcpPtr);
6163 }
6164 }//if
6165 }
6166 }//Dbtc::handleGcp()
6167
releaseApiConCopy(Signal * signal)6168 void Dbtc::releaseApiConCopy(Signal* signal)
6169 {
6170 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6171 UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
6172 cfirstfreeApiConnectCopy = apiConnectptr.i;
6173 regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
6174 setApiConTimer(apiConnectptr.i, 0, __LINE__);
6175 regApiPtr->apiConnectstate = CS_RESTART;
6176 ndbrequire(regApiPtr->commitAckMarker == RNIL);
6177 }//Dbtc::releaseApiConCopy()
6178
6179 /* ========================================================================= */
6180 /* ------- RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
6181 /* ========================================================================= */
releaseDirtyWrite(Signal * signal)6182 void Dbtc::releaseDirtyWrite(Signal* signal)
6183 {
6184 unlinkReadyTcCon(signal);
6185 releaseTcCon();
6186 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6187 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6188 if (regApiPtr->firstTcConnect == RNIL) {
6189 jam();
6190 regApiPtr->apiConnectstate = CS_CONNECTED;
6191 setApiConTimer(apiConnectptr.i, 0, __LINE__);
6192 sendtckeyconf(signal, 1);
6193 }//if
6194 }//if
6195 }//Dbtc::releaseDirtyWrite()
6196
6197 /*****************************************************************************
6198 * L Q H K E Y R E F
6199 * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
6200 * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
6201 * TCROLLBACKREP WILL BE SENT TO THE API.
6202 *
6203 * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
6204 * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
6205 * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
6206 * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
6207 * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
6208 * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
6209 * "REC_LQHREFUSE",
6210 * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
6211 * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
6212 *****************************************************************************/
execLQHKEYREF(Signal * signal)6213 void Dbtc::execLQHKEYREF(Signal* signal)
6214 {
6215 const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
6216 Uint32 indexId = 0;
6217 jamEntry();
6218
6219 UintR compare_transid1, compare_transid2;
6220 UintR TtcConnectFilesize = ctcConnectFilesize;
6221 /*-------------------------------------------------------------------------
6222 *
6223 * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
6224 * TRANSACTION PARTS ACTIVE ANYMORE.
6225 * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
6226 *-------------------------------------------------------------------------*/
6227 if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
6228 /*-----------------------------------------------------------------------
6229 * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
6230 * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
6231 * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
6232 * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
6233 * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
6234 * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
6235 * ALREADY COMPLETED (ABORTED).
6236 *-----------------------------------------------------------------------*/
6237 tcConnectptr.i = lqhKeyRef->connectPtr;
6238 Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
6239 ptrAss(tcConnectptr, tcConnectRecord);
6240 TcConnectRecord * const regTcPtr = tcConnectptr.p;
6241 if (regTcPtr->tcConnectstate == OS_OPERATING) {
6242 Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
6243 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6244 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6245 compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
6246 compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
6247 compare_transid1 = compare_transid1 | compare_transid2;
6248 if (compare_transid1 != 0) {
6249 warningReport(signal, 25);
6250 return;
6251 }//if
6252
6253 const Uint32 triggeringOp = regTcPtr->triggeringOperation;
6254 if (triggeringOp != RNIL) {
6255 jam();
6256 // This operation was created by a trigger execting operation
6257 TcConnectRecordPtr opPtr;
6258 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6259
6260 opPtr.i = triggeringOp;
6261 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
6262
6263 const Uint32 opType = regTcPtr->operation;
6264 Ptr<TcDefinedTriggerData> trigPtr;
6265 c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
6266 switch(trigPtr.p->triggerType){
6267 case TriggerType::SECONDARY_INDEX:{
6268 jam();
6269
6270 // The operation executed an index trigger
6271 TcIndexData* indexData = c_theIndexes.getPtr(trigPtr.p->indexId);
6272 indexId = indexData->indexId;
6273 regApiPtr->errorData = indexId;
6274 if (errCode == ZALREADYEXIST)
6275 {
6276 jam();
6277 errCode = terrorCode = ZNOTUNIQUE;
6278 goto do_abort;
6279 }
6280 else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
6281 jam();
6282 /**
6283 * "Normal path"
6284 */
6285 goto do_abort;
6286 }
6287 else
6288 {
6289 jam();
6290 /** ZDELETE && NOT_FOUND */
6291 if (indexData->indexState != IS_BUILDING)
6292 {
6293 jam();
6294 goto do_abort;
6295 }
6296 }
6297 goto do_ignore;
6298 }
6299 case TriggerType::REORG_TRIGGER:
6300 jam();
6301 if (opType == ZINSERT && errCode == ZALREADYEXIST)
6302 {
6303 jam();
6304 ndbout_c("reorg, ignore ZALREADYEXIST");
6305 goto do_ignore;
6306 }
6307 else if (errCode == ZNOT_FOUND)
6308 {
6309 jam();
6310 ndbout_c("reorg, ignore ZNOT_FOUND");
6311 goto do_ignore;
6312 }
6313 else if (errCode == 839)
6314 {
6315 jam();
6316 ndbout_c("reorg, ignore 839");
6317 goto do_ignore;
6318 }
6319 else
6320 {
6321 ndbout_c("reorg: opType: %u errCode: %u", opType, errCode);
6322 }
6323 // fall-through
6324 default:
6325 jam();
6326 goto do_abort;
6327 }
6328
6329 do_ignore:
6330 jam();
6331 /**
6332 * Ignore error
6333 */
6334 regApiPtr->lqhkeyreqrec--;
6335
6336 /**
6337 * An failing op in LQH, never leaves the commit ack marker around
6338 * TODO: This can be bug in ordinary code too!!!
6339 */
6340 clearCommitAckMarker(regApiPtr, regTcPtr);
6341
6342 unlinkReadyTcCon(signal);
6343 releaseTcCon();
6344
6345 trigger_op_finished(signal, apiConnectptr, opPtr.p);
6346 return;
6347 }
6348
6349 do_abort:
6350 markOperationAborted(regApiPtr, regTcPtr);
6351
6352 if(regApiPtr->apiConnectstate == CS_ABORTING){
6353 /**
6354 * We're already aborting' so don't send an "extra" TCKEYREF
6355 */
6356 jam();
6357 return;
6358 }
6359
6360 const Uint32 abort = regTcPtr->m_execAbortOption;
6361 if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
6362 /**
6363 * No error is allowed on this operation
6364 */
6365 TCKEY_abort(signal, 49);
6366 return;
6367 }//if
6368
6369 /* *************** */
6370 /* TCKEYREF < */
6371 /* *************** */
6372 TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
6373 tcKeyRef->transId[0] = regApiPtr->transid[0];
6374 tcKeyRef->transId[1] = regApiPtr->transid[1];
6375 tcKeyRef->errorCode = terrorCode;
6376 bool isIndexOp = regTcPtr->isIndexOp(regTcPtr->m_special_op_flags);
6377 Uint32 indexOp = tcConnectptr.p->indexOp;
6378 Uint32 clientData = regTcPtr->clientData;
6379 unlinkReadyTcCon(signal); /* LINK TC CONNECT RECORD OUT OF */
6380 releaseTcCon(); /* RELEASE THE TC CONNECT RECORD */
6381 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6382 if (isIndexOp) {
6383 jam();
6384 regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
6385 tcKeyRef->connectPtr = indexOp;
6386 tcKeyRef->errorData = indexId;
6387 EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
6388 apiConnectptr.i = save;
6389 apiConnectptr.p = regApiPtr;
6390 } else {
6391 jam();
6392 tcKeyRef->connectPtr = clientData;
6393 tcKeyRef->errorData = indexId;
6394 sendSignal(regApiPtr->ndbapiBlockref,
6395 GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
6396 }//if
6397
6398 /*---------------------------------------------------------------------
6399 * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
6400 * LQHKEYREQ THAT HAVE RETURNED.
6401 * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
6402 * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
6403 *---------------------------------------------------------------------*/
6404 regApiPtr->lqhkeyreqrec--;
6405 if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
6406 if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6407 jam();
6408 diverify010Lab(signal);
6409 return;
6410 }
6411 else if (regApiPtr->tckeyrec > 0 ||
6412 tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG))
6413 {
6414 jam();
6415 sendtckeyconf(signal, 2);
6416 return;
6417 }
6418 }//if
6419 return;
6420
6421 } else {
6422 warningReport(signal, 26);
6423 }//if
6424 } else {
6425 errorReport(signal, 6);
6426 }//if
6427 return;
6428 }//Dbtc::execLQHKEYREF()
6429
clearCommitAckMarker(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)6430 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
6431 TcConnectRecord * const regTcPtr)
6432 {
6433 const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
6434 if (regApiPtr->commitAckMarker == RNIL)
6435 {
6436 ndbassert(commitAckMarker == RNIL);
6437 }
6438
6439 if(commitAckMarker != RNIL)
6440 {
6441 jam();
6442 ndbassert(regApiPtr->commitAckMarker == commitAckMarker);
6443 ndbrequire(regApiPtr->no_commit_ack_markers > 0);
6444 regApiPtr->no_commit_ack_markers--;
6445 regTcPtr->commitAckMarker = RNIL;
6446 if (regApiPtr->no_commit_ack_markers == 0)
6447 {
6448 regApiPtr->commitAckMarker = RNIL;
6449 tc_clearbit(regApiPtr->m_flags,
6450 ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
6451 m_commitAckMarkerHash.release(commitAckMarker);
6452 }
6453 }
6454 }
6455
markOperationAborted(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)6456 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
6457 TcConnectRecord * const regTcPtr)
6458 {
6459 /*------------------------------------------------------------------------
6460 * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
6461 * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
6462 * ALREADY COMPLETED.
6463 *------------------------------------------------------------------------*/
6464 regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
6465 regTcPtr->tcConnectstate = OS_ABORTING;
6466 clearCommitAckMarker(regApiPtr, regTcPtr);
6467 }
6468
6469 /*--------------------------------------*/
6470 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ */
6471 /* OR TCROLLBACKREQ FROM THE USER TO */
6472 /* CONTINUE THE TRANSACTION */
6473 /*--------------------------------------*/
execTC_COMMITREQ(Signal * signal)6474 void Dbtc::execTC_COMMITREQ(Signal* signal)
6475 {
6476 UintR compare_transid1, compare_transid2;
6477
6478 jamEntry();
6479 apiConnectptr.i = signal->theData[0];
6480 if (apiConnectptr.i < capiConnectFilesize) {
6481 ptrAss(apiConnectptr, apiConnectRecord);
6482 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
6483 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
6484 compare_transid1 = compare_transid1 | compare_transid2;
6485 if (compare_transid1 != 0) {
6486 jam();
6487 return;
6488 }//if
6489
6490 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6491
6492 const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
6493 const Uint32 apiBlockRef = regApiPtr->ndbapiBlockref;
6494 const Uint32 transId1 = regApiPtr->transid[0];
6495 const Uint32 transId2 = regApiPtr->transid[1];
6496 Uint32 errorCode = 0;
6497
6498 regApiPtr->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
6499 switch (regApiPtr->apiConnectstate) {
6500 case CS_STARTED:
6501 tcConnectptr.i = regApiPtr->firstTcConnect;
6502 if (tcConnectptr.i != RNIL) {
6503 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6504 if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
6505 jam();
6506 /*******************************************************************/
6507 // The proper case where the application is waiting for commit or
6508 // abort order.
6509 // Start the commit order.
6510 /*******************************************************************/
6511 regApiPtr->returnsignal = RS_TC_COMMITCONF;
6512 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6513 diverify010Lab(signal);
6514 return;
6515 } else {
6516 jam();
6517 /*******************************************************************/
6518 // The transaction is started but not all operations are completed.
6519 // It is not possible to commit the transaction in this state.
6520 // We will abort it instead.
6521 /*******************************************************************/
6522 regApiPtr->returnsignal = RS_NO_RETURN;
6523 errorCode = ZTRANS_STATUS_ERROR;
6524 abort010Lab(signal);
6525 }//if
6526 } else {
6527 jam();
6528 /**
6529 * No operations, accept commit
6530 */
6531 TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
6532 commitConf->apiConnectPtr = apiConnectPtr;
6533 commitConf->transId1 = transId1;
6534 commitConf->transId2 = transId2;
6535 commitConf->gci_hi = 0;
6536 commitConf->gci_lo = 0;
6537 sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
6538 TcCommitConf::SignalLength, JBB);
6539
6540 regApiPtr->returnsignal = RS_NO_RETURN;
6541 releaseAbortResources(signal);
6542 return;
6543 }//if
6544 break;
6545 case CS_RECEIVING:
6546 jam();
6547 /***********************************************************************/
6548 // A transaction is still receiving data. We cannot commit an unfinished
6549 // transaction. We will abort it instead.
6550 /***********************************************************************/
6551 regApiPtr->returnsignal = RS_NO_RETURN;
6552 errorCode = ZPREPAREINPROGRESS;
6553 abort010Lab(signal);
6554 break;
6555
6556 case CS_START_COMMITTING:
6557 case CS_COMMITTING:
6558 case CS_COMMIT_SENT:
6559 case CS_COMPLETING:
6560 case CS_COMPLETE_SENT:
6561 case CS_REC_COMMITTING:
6562 case CS_PREPARE_TO_COMMIT:
6563 jam();
6564 /***********************************************************************/
6565 // The transaction is already performing a commit but it is not concluded
6566 // yet.
6567 /***********************************************************************/
6568 errorCode = ZCOMMITINPROGRESS;
6569 break;
6570 case CS_ABORTING:
6571 jam();
6572 errorCode = regApiPtr->returncode ?
6573 regApiPtr->returncode : ZABORTINPROGRESS;
6574 break;
6575 case CS_START_SCAN:
6576 jam();
6577 /***********************************************************************/
6578 // The transaction is a scan. Scans cannot commit
6579 /***********************************************************************/
6580 errorCode = ZSCANINPROGRESS;
6581 break;
6582 case CS_PREPARED:
6583 jam();
6584 return;
6585 case CS_START_PREPARING:
6586 jam();
6587 return;
6588 case CS_REC_PREPARING:
6589 jam();
6590 return;
6591 break;
6592 default:
6593 warningHandlerLab(signal, __LINE__);
6594 return;
6595 }//switch
6596 TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
6597 commitRef->apiConnectPtr = apiConnectPtr;
6598 commitRef->transId1 = transId1;
6599 commitRef->transId2 = transId2;
6600 commitRef->errorCode = errorCode;
6601 sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
6602 TcCommitRef::SignalLength, JBB);
6603 return;
6604 } else /** apiConnectptr.i < capiConnectFilesize */ {
6605 jam();
6606 warningHandlerLab(signal, __LINE__);
6607 return;
6608 }
6609 }//Dbtc::execTC_COMMITREQ()
6610
6611 /**
6612 * TCROLLBACKREQ
6613 *
6614 * Format is:
6615 *
6616 * thedata[0] = apiconnectptr
6617 * thedata[1] = transid[0]
6618 * thedata[2] = transid[1]
6619 * OPTIONAL thedata[3] = flags
6620 *
6621 * Flags:
6622 * 0x1 = potentiallyBad data from API (try not to assert)
6623 */
execTCROLLBACKREQ(Signal * signal)6624 void Dbtc::execTCROLLBACKREQ(Signal* signal)
6625 {
6626 bool potentiallyBad= false;
6627 UintR compare_transid1, compare_transid2;
6628
6629 jamEntry();
6630
6631 if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
6632 {
6633 ndbout_c("Trying to roll back potentially bad txn\n");
6634 potentiallyBad= true;
6635 }
6636
6637 apiConnectptr.i = signal->theData[0];
6638 if (apiConnectptr.i >= capiConnectFilesize) {
6639 goto TC_ROLL_warning;
6640 }//if
6641 ptrAss(apiConnectptr, apiConnectRecord);
6642 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
6643 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
6644 compare_transid1 = compare_transid1 | compare_transid2;
6645 if (compare_transid1 != 0) {
6646 jam();
6647 return;
6648 }//if
6649
6650 apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
6651 switch (apiConnectptr.p->apiConnectstate) {
6652 case CS_STARTED:
6653 case CS_RECEIVING:
6654 jam();
6655 apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6656 abort010Lab(signal);
6657 return;
6658 case CS_CONNECTED:
6659 jam();
6660 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6661 signal->theData[1] = apiConnectptr.p->transid[0];
6662 signal->theData[2] = apiConnectptr.p->transid[1];
6663 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
6664 signal, 3, JBB);
6665 break;
6666 case CS_START_SCAN:
6667 case CS_PREPARE_TO_COMMIT:
6668 case CS_COMMITTING:
6669 case CS_COMMIT_SENT:
6670 case CS_COMPLETING:
6671 case CS_COMPLETE_SENT:
6672 case CS_WAIT_COMMIT_CONF:
6673 case CS_WAIT_COMPLETE_CONF:
6674 case CS_RESTART:
6675 case CS_DISCONNECTED:
6676 case CS_START_COMMITTING:
6677 case CS_REC_COMMITTING:
6678 jam();
6679 /* ***************< */
6680 /* TC_ROLLBACKREF < */
6681 /* ***************< */
6682 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6683 signal->theData[1] = apiConnectptr.p->transid[0];
6684 signal->theData[2] = apiConnectptr.p->transid[1];
6685 signal->theData[3] = ZROLLBACKNOTALLOWED;
6686 signal->theData[4] = apiConnectptr.p->apiConnectstate;
6687 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
6688 signal, 5, JBB);
6689 break;
6690 /* SEND A REFUSAL SIGNAL*/
6691 case CS_ABORTING:
6692 jam();
6693 if (apiConnectptr.p->abortState == AS_IDLE) {
6694 jam();
6695 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6696 signal->theData[1] = apiConnectptr.p->transid[0];
6697 signal->theData[2] = apiConnectptr.p->transid[1];
6698 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
6699 signal, 3, JBB);
6700 } else {
6701 jam();
6702 apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6703 }//if
6704 break;
6705 case CS_WAIT_ABORT_CONF:
6706 jam();
6707 apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6708 break;
6709 case CS_START_PREPARING:
6710 jam();
6711 case CS_PREPARED:
6712 jam();
6713 case CS_REC_PREPARING:
6714 jam();
6715 default:
6716 goto TC_ROLL_system_error;
6717 break;
6718 }//switch
6719 return;
6720
6721 TC_ROLL_warning:
6722 jam();
6723 if(likely(potentiallyBad==false))
6724 warningHandlerLab(signal, __LINE__);
6725 return;
6726
6727 TC_ROLL_system_error:
6728 jam();
6729 if(likely(potentiallyBad==false))
6730 systemErrorLab(signal, __LINE__);
6731 return;
6732 }//Dbtc::execTCROLLBACKREQ()
6733
execTC_HBREP(Signal * signal)6734 void Dbtc::execTC_HBREP(Signal* signal)
6735 {
6736 const TcHbRep * const tcHbRep =
6737 (TcHbRep *)signal->getDataPtr();
6738
6739 jamEntry();
6740 apiConnectptr.i = tcHbRep->apiConnectPtr;
6741 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6742
6743 if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
6744 apiConnectptr.p->transid[1] == tcHbRep->transId2){
6745
6746 if (getApiConTimer(apiConnectptr.i) != 0){
6747 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6748 } else {
6749 DEBUG("TCHBREP received when timer was off apiConnectptr.i="
6750 << apiConnectptr.i);
6751 }
6752 }
6753 }//Dbtc::execTCHBREP()
6754
6755 /*
6756 4.3.15 ABORT
6757 -----------
6758 */
6759 /*****************************************************************************/
6760 /* A B O R T */
6761 /* */
6762 /*****************************************************************************/
warningReport(Signal * signal,int place)6763 void Dbtc::warningReport(Signal* signal, int place)
6764 {
6765 switch (place) {
6766 case 0:
6767 jam();
6768 #ifdef ABORT_TRACE
6769 ndbout << "ABORTED to not active TC record" << endl;
6770 #endif
6771 break;
6772 case 1:
6773 jam();
6774 #ifdef ABORT_TRACE
6775 ndbout << "ABORTED to TC record active with new transaction" << endl;
6776 #endif
6777 break;
6778 case 2:
6779 jam();
6780 #ifdef ABORT_TRACE
6781 ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
6782 #endif
6783 break;
6784 case 3:
6785 jam();
6786 #ifdef ABORT_TRACE
6787 ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
6788 ndbout << "This is ok when aborting in node failure situations" << endl;
6789 #endif
6790 break;
6791 case 4:
6792 jam();
6793 #ifdef ABORT_TRACE
6794 ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
6795 #endif
6796 break;
6797 case 5:
6798 jam();
6799 #ifdef ABORT_TRACE
6800 ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
6801 #endif
6802 break;
6803 case 6:
6804 jam();
6805 #ifdef ABORT_TRACE
6806 ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
6807 #endif
6808 break;
6809 case 7:
6810 jam();
6811 #ifdef ABORT_TRACE
6812 ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
6813 #endif
6814 break;
6815 case 8:
6816 jam();
6817 #ifdef ABORT_TRACE
6818 ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
6819 #endif
6820 break;
6821 case 9:
6822 jam();
6823 #ifdef ABORT_TRACE
6824 ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
6825 #endif
6826 break;
6827 case 10:
6828 jam();
6829 #ifdef ABORT_TRACE
6830 ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
6831 #endif
6832 break;
6833 case 11:
6834 jam();
6835 #ifdef ABORT_TRACE
6836 ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
6837 #endif
6838 break;
6839 case 12:
6840 jam();
6841 #ifdef ABORT_TRACE
6842 ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
6843 #endif
6844 break;
6845 case 13:
6846 jam();
6847 #ifdef ABORT_TRACE
6848 ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
6849 #endif
6850 break;
6851 case 14:
6852 jam();
6853 #ifdef ABORT_TRACE
6854 ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
6855 #endif
6856 break;
6857 case 15:
6858 jam();
6859 #ifdef ABORT_TRACE
6860 ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
6861 #endif
6862 break;
6863 case 16:
6864 jam();
6865 #ifdef ABORT_TRACE
6866 ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
6867 #endif
6868 break;
6869 case 17:
6870 jam();
6871 #ifdef ABORT_TRACE
6872 ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
6873 #endif
6874 break;
6875 case 18:
6876 jam();
6877 #ifdef ABORT_TRACE
6878 ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
6879 #endif
6880 break;
6881 case 19:
6882 jam();
6883 #ifdef ABORT_TRACE
6884 ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
6885 #endif
6886 break;
6887 case 20:
6888 jam();
6889 #ifdef ABORT_TRACE
6890 ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
6891 #endif
6892 break;
6893 case 21:
6894 jam();
6895 #ifdef ABORT_TRACE
6896 ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
6897 #endif
6898 break;
6899 case 22:
6900 jam();
6901 #ifdef ABORT_TRACE
6902 ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
6903 #endif
6904 break;
6905 case 23:
6906 jam();
6907 #ifdef ABORT_TRACE
6908 ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
6909 #endif
6910 break;
6911 case 24:
6912 jam();
6913 #ifdef ABORT_TRACE
6914 ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
6915 #endif
6916 break;
6917 case 25:
6918 jam();
6919 #ifdef ABORT_TRACE
6920 ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
6921 #endif
6922 break;
6923 case 26:
6924 jam();
6925 #ifdef ABORT_TRACE
6926 ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
6927 #endif
6928 break;
6929 case 27:
6930 jam();
6931 // printState(signal, 27);
6932 #ifdef ABORT_TRACE
6933 ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
6934 #endif
6935 break;
6936 case 28:
6937 jam();
6938 #ifdef ABORT_TRACE
6939 ndbout << "Discarding FIRE_TRIG_REF/CONF in Dbtc" << endl;
6940 #endif
6941 break;
6942 case 29:
6943 jam();
6944 #ifdef ABORT_TRACE
6945 ndbout << "Discarding TcContinueB::ZSEND_FIRE_TRIG_REQ in Dbtc" << endl;
6946 #endif
6947 break;
6948 default:
6949 jam();
6950 break;
6951 }//switch
6952 return;
6953 }//Dbtc::warningReport()
6954
errorReport(Signal * signal,int place)6955 void Dbtc::errorReport(Signal* signal, int place)
6956 {
6957 switch (place) {
6958 case 0:
6959 jam();
6960 break;
6961 case 1:
6962 jam();
6963 break;
6964 case 2:
6965 jam();
6966 break;
6967 case 3:
6968 jam();
6969 break;
6970 case 4:
6971 jam();
6972 break;
6973 case 5:
6974 jam();
6975 break;
6976 case 6:
6977 jam();
6978 break;
6979 default:
6980 jam();
6981 break;
6982 }//switch
6983 systemErrorLab(signal, __LINE__);
6984 return;
6985 }//Dbtc::errorReport()
6986
6987 /* ------------------------------------------------------------------------- */
6988 /* ------- ENTER ABORTED ------- */
6989 /* */
6990 /*-------------------------------------------------------------------------- */
execABORTED(Signal * signal)6991 void Dbtc::execABORTED(Signal* signal)
6992 {
6993 UintR compare_transid1, compare_transid2;
6994
6995 jamEntry();
6996 tcConnectptr.i = signal->theData[0];
6997 UintR Tnodeid = signal->theData[3];
6998 UintR TlastLqhInd = signal->theData[4];
6999
7000 if (ERROR_INSERTED(8040)) {
7001 CLEAR_ERROR_INSERT_VALUE;
7002 sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
7003 return;
7004 }//if
7005 /*------------------------------------------------------------------------
7006 * ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
7007 *------------------------------------------------------------------------*/
7008 if (tcConnectptr.i >= ctcConnectFilesize) {
7009 errorReport(signal, 0);
7010 return;
7011 }//if
7012 /*-------------------------------------------------------------------------
7013 * WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
7014 * TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
7015 * IN TC WAITING FOR ABORTED.
7016 *-------------------------------------------------------------------------*/
7017 ptrAss(tcConnectptr, tcConnectRecord);
7018 if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
7019 warningReport(signal, 2);
7020 return;
7021 /*-----------------------------------------------------------------------*/
7022 // ABORTED reported on an operation not expecting ABORT.
7023 /*-----------------------------------------------------------------------*/
7024 }//if
7025 apiConnectptr.i = tcConnectptr.p->apiConnect;
7026 if (apiConnectptr.i >= capiConnectFilesize) {
7027 warningReport(signal, 0);
7028 return;
7029 }//if
7030 ptrAss(apiConnectptr, apiConnectRecord);
7031 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
7032 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
7033 compare_transid1 = compare_transid1 | compare_transid2;
7034 if (compare_transid1 != 0) {
7035 warningReport(signal, 1);
7036 return;
7037 }//if
7038 if (ERROR_INSERTED(8024)) {
7039 jam();
7040 systemErrorLab(signal, __LINE__);
7041 }//if
7042
7043 /**
7044 * Release marker
7045 */
7046 clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
7047
7048 Uint32 i;
7049 Uint32 Tfound = 0;
7050 for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7051 jam();
7052 if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
7053 /*---------------------------------------------------------------------
7054 * We have received ABORTED from one of the participants in this
7055 * operation in this aborted transaction.
7056 * Record all nodes that have completed abort.
7057 * If last indicator is set it means that no more replica has
7058 * heard of the operation and are thus also aborted.
7059 *---------------------------------------------------------------------*/
7060 jam();
7061 Tfound = 1;
7062 clearTcNodeData(signal, TlastLqhInd, i);
7063 }//if
7064 }//for
7065 if (Tfound == 0) {
7066 warningReport(signal, 3);
7067 return;
7068 }
7069 for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7070 if (tcConnectptr.p->tcNodedata[i] != 0) {
7071 /*--------------------------------------------------------------------
7072 * There are still outstanding ABORTED's to wait for.
7073 *--------------------------------------------------------------------*/
7074 jam();
7075 return;
7076 }//if
7077 }//for
7078 tcConnectptr.p->noOfNodes = 0;
7079 tcConnectptr.p->tcConnectstate = OS_ABORTING;
7080 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7081 apiConnectptr.p->counter--;
7082 if (apiConnectptr.p->counter > 0) {
7083 jam();
7084 /*----------------------------------------------------------------------
7085 * WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
7086 *----------------------------------------------------------------------*/
7087 return;
7088 }//if
7089 /*------------------------------------------------------------------------*/
7090 /* */
7091 /* WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED */
7092 /* FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL */
7093 /* RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
7094 /*------------------------------------------------------------------------*/
7095 releaseAbortResources(signal);
7096 }//Dbtc::execABORTED()
7097
clearTcNodeData(Signal * signal,UintR TLastLqhIndicator,UintR Tstart)7098 void Dbtc::clearTcNodeData(Signal* signal,
7099 UintR TLastLqhIndicator,
7100 UintR Tstart)
7101 {
7102 UintR Ti;
7103 if (TLastLqhIndicator == ZTRUE) {
7104 for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7105 jam();
7106 tcConnectptr.p->tcNodedata[Ti] = 0;
7107 }//for
7108 } else {
7109 jam();
7110 tcConnectptr.p->tcNodedata[Tstart] = 0;
7111 }//for
7112 }//clearTcNodeData()
7113
abortErrorLab(Signal * signal)7114 void Dbtc::abortErrorLab(Signal* signal)
7115 {
7116 ptrGuard(apiConnectptr);
7117 ApiConnectRecord * transP = apiConnectptr.p;
7118 if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7119 jam();
7120 return;
7121 }
7122 transP->returnsignal = RS_TCROLLBACKREP;
7123 if(transP->returncode == 0){
7124 jam();
7125 transP->returncode = terrorCode;
7126 }
7127 abort010Lab(signal);
7128 }//Dbtc::abortErrorLab()
7129
abort010Lab(Signal * signal)7130 void Dbtc::abort010Lab(Signal* signal)
7131 {
7132 ApiConnectRecord * transP = apiConnectptr.p;
7133 if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7134 jam();
7135 return;
7136 }
7137 transP->apiConnectstate = CS_ABORTING;
7138 /*------------------------------------------------------------------------*/
7139 /* AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
7140 /* ALL PARTICIPANTS IN THE TRANSACTION. */
7141 /*------------------------------------------------------------------------*/
7142 transP->abortState = AS_ACTIVE;
7143 transP->counter = 0;
7144
7145 if (transP->firstTcConnect == RNIL) {
7146 jam();
7147 /*--------------------------------------------------------------------*/
7148 /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION. */
7149 /*--------------------------------------------------------------------*/
7150 releaseAbortResources(signal);
7151 return;
7152 }//if
7153 tcConnectptr.i = transP->firstTcConnect;
7154 abort015Lab(signal);
7155 }//Dbtc::abort010Lab()
7156
7157 /*--------------------------------------------------------------------------*/
7158 /* */
7159 /* WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP */
7160 /* ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE. */
7161 /* EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE */
7162 /* MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES */
7163 /* NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
7164 /* WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
7165 /*--------------------------------------------------------------------------*/
abort015Lab(Signal * signal)7166 void Dbtc::abort015Lab(Signal* signal)
7167 {
7168 Uint32 TloopCount = 0;
7169 ABORT020:
7170 jam();
7171 TloopCount++;
7172 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7173 switch (tcConnectptr.p->tcConnectstate) {
7174 case OS_WAIT_DIH:
7175 case OS_WAIT_KEYINFO:
7176 case OS_WAIT_ATTR:
7177 jam();
7178 /*----------------------------------------------------------------------*/
7179 /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
7180 /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING. */
7181 /*----------------------------------------------------------------------*/
7182 tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7183 tcConnectptr.p->tcConnectstate = OS_ABORTING;
7184 break;
7185 case OS_CONNECTED:
7186 jam();
7187 /*-----------------------------------------------------------------------
7188 * WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
7189 * NEED NOT BOTHER ABOUT ANY LQH ABORTS.
7190 *-----------------------------------------------------------------------*/
7191 tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7192 tcConnectptr.p->tcConnectstate = OS_ABORTING;
7193 break;
7194 case OS_PREPARED:
7195 jam();
7196 case OS_OPERATING:
7197 jam();
7198 case OS_FIRE_TRIG_REQ:
7199 jam();
7200 /*----------------------------------------------------------------------
7201 * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
7202 * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
7203 * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
7204 *----------------------------------------------------------------------*/
7205 releaseAndAbort(signal);
7206 tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
7207 TloopCount += 127;
7208 break;
7209 case OS_ABORTING:
7210 jam();
7211 break;
7212 case OS_ABORT_SENT:
7213 jam();
7214 DEBUG("ABORT_SENT state in abort015Lab(), not expected");
7215 systemErrorLab(signal, __LINE__);
7216 return;
7217 default:
7218 jam();
7219 DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
7220 systemErrorLab(signal, __LINE__);
7221 return;
7222 }//switch
7223
7224 if (tcConnectptr.p->nextTcConnect != RNIL) {
7225 jam();
7226 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7227 if (TloopCount < 1024 && !
7228 (ERROR_INSERTED(8089)))
7229 {
7230 goto ABORT020;
7231 }
7232 else
7233 {
7234 jam();
7235 /*---------------------------------------------------------------------
7236 * Reset timer to avoid time-out in real-time break.
7237 * Increase counter to ensure that we don't think that all ABORTED have
7238 * been received before all have been sent.
7239 *---------------------------------------------------------------------*/
7240 apiConnectptr.p->counter++;
7241 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7242 signal->theData[0] = TcContinueB::ZABORT_BREAK;
7243 signal->theData[1] = tcConnectptr.i;
7244 signal->theData[2] = apiConnectptr.i;
7245 if (ERROR_INSERTED(8089))
7246 {
7247 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
7248 return;
7249 }
7250 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7251 return;
7252 }//if
7253 }//if
7254
7255 if (ERROR_INSERTED(8089))
7256 {
7257 CLEAR_ERROR_INSERT_VALUE;
7258 }
7259
7260 if (apiConnectptr.p->counter > 0) {
7261 jam();
7262 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7263 return;
7264 }//if
7265 /*-----------------------------------------------------------------------
7266 * WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
7267 * FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
7268 * RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
7269 *------------------------------------------------------------------------*/
7270 releaseAbortResources(signal);
7271 }//Dbtc::abort015Lab()
7272
7273 /*--------------------------------------------------------------------------*/
7274 /* RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK. */
7275 /*--------------------------------------------------------------------------*/
releaseAndAbort(Signal * signal)7276 int Dbtc::releaseAndAbort(Signal* signal)
7277 {
7278 HostRecordPtr localHostptr;
7279 UintR TnoLoops = tcConnectptr.p->noOfNodes;
7280
7281 apiConnectptr.p->counter++;
7282 bool prevAlive = false;
7283 for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
7284 localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
7285 ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
7286 if (localHostptr.p->hostStatus == HS_ALIVE) {
7287 jam();
7288 if (prevAlive) {
7289 // if previous is alive, its LQH forwards abort to this node
7290 jam();
7291 continue;
7292 }
7293 /* ************< */
7294 /* ABORT < */
7295 /* ************< */
7296 Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7297 tblockref = numberToRef(DBLQH, instanceKey, localHostptr.i);
7298 signal->theData[0] = tcConnectptr.i;
7299 signal->theData[1] = cownref;
7300 signal->theData[2] = apiConnectptr.p->transid[0];
7301 signal->theData[3] = apiConnectptr.p->transid[1];
7302 sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
7303 prevAlive = true;
7304 } else {
7305 jam();
7306 signal->theData[0] = tcConnectptr.i;
7307 signal->theData[1] = apiConnectptr.p->transid[0];
7308 signal->theData[2] = apiConnectptr.p->transid[1];
7309 signal->theData[3] = localHostptr.i;
7310 signal->theData[4] = ZFALSE;
7311 sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7312 prevAlive = false;
7313 }//if
7314 }//for
7315 return 1;
7316 }//Dbtc::releaseAndAbort()
7317
7318 /* ------------------------------------------------------------------------- */
7319 /* ------- ENTER TIME_SIGNAL ------- */
7320 /* */
7321 /* ------------------------------------------------------------------------- */
execTIME_SIGNAL(Signal * signal)7322 void Dbtc::execTIME_SIGNAL(Signal* signal)
7323 {
7324
7325 jamEntry();
7326 ctcTimer++;
7327 if (csystemStart != SSS_TRUE) {
7328 jam();
7329 return;
7330 }//if
7331 checkStartTimeout(signal);
7332 checkStartFragTimeout(signal);
7333 }//Dbtc::execTIME_SIGNAL()
7334
7335 /*------------------------------------------------*/
7336 /* Start timeout handling if not already going on */
7337 /*------------------------------------------------*/
checkStartTimeout(Signal * signal)7338 void Dbtc::checkStartTimeout(Signal* signal)
7339 {
7340 ctimeOutCheckCounter++;
7341 if (ctimeOutCheckActive == TOCS_TRUE) {
7342 jam();
7343 // Check heartbeat of timeout loop
7344 if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
7345 jam();
7346 ctimeOutMissedHeartbeats = 0;
7347 }else{
7348 jam();
7349 ctimeOutMissedHeartbeats++;
7350 if (ctimeOutMissedHeartbeats > 100){
7351 jam();
7352 systemErrorLab(signal, __LINE__);
7353 }
7354 }
7355 ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
7356 return;
7357 }//if
7358 if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
7359 jam();
7360 /*------------------------------------------------------------------*/
7361 /* */
7362 /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
7363 /*------------------------------------------------------------------*/
7364 return;
7365 }//if
7366 ctimeOutCheckActive = TOCS_TRUE;
7367 ctimeOutCheckCounter = 0;
7368 timeOutLoopStartLab(signal, 0); // 0 is first api connect record
7369 return;
7370 }//Dbtc::execTIME_SIGNAL()
7371
7372 /*----------------------------------------------------------------*/
7373 /* Start fragment (scan) timeout handling if not already going on */
7374 /*----------------------------------------------------------------*/
checkStartFragTimeout(Signal * signal)7375 void Dbtc::checkStartFragTimeout(Signal* signal)
7376 {
7377 ctimeOutCheckFragCounter++;
7378 if (ctimeOutCheckFragActive == TOCS_TRUE) {
7379 jam();
7380 return;
7381 }//if
7382 if (ctimeOutCheckFragCounter < ctimeOutCheckDelay) {
7383 jam();
7384 /*------------------------------------------------------------------*/
7385 /* NO TIME-OUT CHECKED THIS TIME. WAIT MORE. */
7386 /*------------------------------------------------------------------*/
7387 return;
7388 }//if
7389
7390 // Go through the fragment records and look for timeout in a scan.
7391 ctimeOutCheckFragActive = TOCS_TRUE;
7392 ctimeOutCheckFragCounter = 0;
7393 timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
7394 }//checkStartFragTimeout()
7395
7396 /*------------------------------------------------------------------*/
7397 /* IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE */
7398 /* BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM */
7399 /* SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM */
7400 /* THE WAITING PART OF A PROTOCOL. */
7401 /*
7402 The algorithm used here is to check 1024 transactions at a time before
7403 doing a real-time break.
7404 To avoid aborting both transactions in a deadlock detected by time-out
7405 we insert a random extra time-out of upto 630 ms by using the lowest
7406 six bits of the api connect reference.
7407 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
7408 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
7409 and otherwise we spread it out 310 ms.
7410 */
7411 /*------------------------------------------------------------------*/
timeOutLoopStartLab(Signal * signal,Uint32 api_con_ptr)7412 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
7413 {
7414 Uint32 end_ptr, time_passed, time_out_value, mask_value;
7415 Uint32 old_mask_value= 0;
7416 const Uint32 api_con_sz= capiConnectFilesize;
7417 const Uint32 tc_timer= ctcTimer;
7418 const Uint32 time_out_param= ctimeOutValue;
7419 const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
7420
7421 ctimeOutCheckHeartbeat = tc_timer;
7422
7423 if (api_con_ptr + 1024 < api_con_sz) {
7424 jam();
7425 end_ptr= api_con_ptr + 1024;
7426 } else {
7427 jam();
7428 end_ptr= api_con_sz;
7429 }
7430 if (time_out_param > 300) {
7431 jam();
7432 mask_value= 63;
7433 } else if (time_out_param < 30) {
7434 jam();
7435 mask_value= 7;
7436 } else {
7437 jam();
7438 mask_value= 31;
7439 }
7440 if (time_out_param != old_time_out_param &&
7441 getNodeState().getSingleUserMode())
7442 {
7443 // abort during single user mode, use old_mask_value as flag
7444 // and calculate value to be used for connections with allowed api
7445 if (old_time_out_param > 300) {
7446 jam();
7447 old_mask_value= 63;
7448 } else if (old_time_out_param < 30) {
7449 jam();
7450 old_mask_value= 7;
7451 } else {
7452 jam();
7453 old_mask_value= 31;
7454 }
7455 }
7456 for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
7457 Uint32 api_timer= getApiConTimer(api_con_ptr);
7458 jam();
7459 if (api_timer != 0) {
7460 Uint32 error= ZTIME_OUT_ERROR;
7461 time_out_value= time_out_param + (ndb_rand() & mask_value);
7462 if (unlikely(old_mask_value)) // abort during single user mode
7463 {
7464 apiConnectptr.i = api_con_ptr;
7465 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7466 if ((getNodeState().getSingleUserApi() ==
7467 refToNode(apiConnectptr.p->ndbapiBlockref)) ||
7468 !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
7469 {
7470 // api allowed during single user, use original timeout
7471 time_out_value=
7472 old_time_out_param + (api_con_ptr & old_mask_value);
7473 }
7474 else
7475 {
7476 error= ZCLUSTER_IN_SINGLEUSER_MODE;
7477 }
7478 }
7479 time_passed= tc_timer - api_timer;
7480 if (time_passed > time_out_value)
7481 {
7482 jam();
7483 timeOutFoundLab(signal, api_con_ptr, error);
7484 api_con_ptr++;
7485 break;
7486 }
7487 }
7488 }
7489 if (api_con_ptr == api_con_sz) {
7490 jam();
7491 /*------------------------------------------------------------------*/
7492 /* */
7493 /* WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
7494 /* STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW */
7495 /* READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK. */
7496 /*------------------------------------------------------------------*/
7497 ctimeOutCheckActive = TOCS_FALSE;
7498 } else {
7499 jam();
7500 sendContinueTimeOutControl(signal, api_con_ptr);
7501 }
7502 return;
7503 }//Dbtc::timeOutLoopStartLab()
7504
timeOutFoundLab(Signal * signal,Uint32 TapiConPtr,Uint32 errCode)7505 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
7506 {
7507 apiConnectptr.i = TapiConPtr;
7508 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7509 /*------------------------------------------------------------------*/
7510 /* */
7511 /* THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
7512 /* FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
7513 /*------------------------------------------------------------------*/
7514 DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
7515 << " H'" << apiConnectptr.p->transid[1] << "] " << dec
7516 << "Time-out in state = " << apiConnectptr.p->apiConnectstate
7517 << " apiConnectptr.i = " << apiConnectptr.i
7518 << " - exec: "
7519 << tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG)
7520 << " - place: " << c_apiConTimer_line[apiConnectptr.i]
7521 << " code: " << errCode);
7522 switch (apiConnectptr.p->apiConnectstate) {
7523 case CS_STARTED:
7524 if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
7525 errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
7526 jam();
7527 /*
7528 We are waiting for application to continue the transaction. In this
7529 particular state we will use the application timeout parameter rather
7530 than the shorter Deadlock detection timeout.
7531 */
7532 if (c_appl_timeout_value == 0 ||
7533 (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
7534 jam();
7535 return;
7536 }//if
7537 }
7538 apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
7539 apiConnectptr.p->returncode = errCode;
7540 abort010Lab(signal);
7541 return;
7542 case CS_RECEIVING:
7543 case CS_REC_COMMITTING:
7544 case CS_START_COMMITTING:
7545 case CS_WAIT_FIRE_TRIG_REQ:
7546 case CS_SEND_FIRE_TRIG_REQ:
7547 jam();
7548 /*------------------------------------------------------------------*/
7549 /* WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS */
7550 /* NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO */
7551 /* START ABORTING THE TRANSACTION. ALSO START CHECKING THE */
7552 /* REMAINING TRANSACTIONS. */
7553 /*------------------------------------------------------------------*/
7554 terrorCode = errCode;
7555 abortErrorLab(signal);
7556 return;
7557 case CS_COMMITTING:
7558 jam();
7559 /*------------------------------------------------------------------*/
7560 // We are simply waiting for a signal in the job buffer. Only extreme
7561 // conditions should get us here. We ignore it.
7562 /*------------------------------------------------------------------*/
7563 case CS_COMPLETING:
7564 jam();
7565 /*------------------------------------------------------------------*/
7566 // We are simply waiting for a signal in the job buffer. Only extreme
7567 // conditions should get us here. We ignore it.
7568 /*------------------------------------------------------------------*/
7569 case CS_PREPARE_TO_COMMIT:
7570 {
7571 jam();
7572 /*------------------------------------------------------------------*/
7573 /* WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
7574 /* KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO. */
7575 /* IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE. */
7576 // To ensure against strange bugs we crash the system if we have passed
7577 // time-out period by a factor of 10 and it is also at least 5 seconds.
7578 /*------------------------------------------------------------------*/
7579 Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
7580 if (time_passed > 500 &&
7581 time_passed > (5 * cDbHbInterval) &&
7582 time_passed > (10 * ctimeOutValue))
7583 {
7584 jam();
7585 ndbout_c("timeOutFoundLab trans: 0x%x 0x%x state: %u",
7586 apiConnectptr.p->transid[0],
7587 apiConnectptr.p->transid[1],
7588 (Uint32)apiConnectptr.p->apiConnectstate);
7589
7590 // Reset timeout to not flood log...
7591 setApiConTimer(apiConnectptr.i, 0, __LINE__);
7592 }//if
7593 break;
7594 }
7595 case CS_COMMIT_SENT:
7596 jam();
7597 /*------------------------------------------------------------------*/
7598 /* WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
7599 /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
7600 /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL */
7601 /* TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO */
7602 /* A NODE FAILURE. */
7603 /*------------------------------------------------------------------*/
7604 tabortInd = ZCOMMIT_SETUP;
7605 setupFailData(signal);
7606 toCommitHandlingLab(signal);
7607 return;
7608 case CS_COMPLETE_SENT:
7609 jam();
7610 /*--------------------------------------------------------------------*/
7611 /* WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
7612 /* WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE */
7613 /* WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL */
7614 /* TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO */
7615 /* A NODE FAILURE. */
7616 /*--------------------------------------------------------------------*/
7617 tabortInd = ZCOMMIT_SETUP;
7618 setupFailData(signal);
7619 toCompleteHandlingLab(signal);
7620 return;
7621 case CS_ABORTING:
7622 jam();
7623 /*------------------------------------------------------------------*/
7624 /* TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL */
7625 /* NODES THAT HAVE FAILED BEFORE SENDING ABORTED. */
7626 /*------------------------------------------------------------------*/
7627 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7628 sendAbortedAfterTimeout(signal, 0);
7629 break;
7630 case CS_START_SCAN:{
7631 jam();
7632
7633 /*
7634 We are waiting for application to continue the transaction. In this
7635 particular state we will use the application timeout parameter rather
7636 than the shorter Deadlock detection timeout.
7637 */
7638 if (c_appl_timeout_value == 0 ||
7639 (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
7640 jam();
7641 return;
7642 }//if
7643
7644 ScanRecordPtr scanPtr;
7645 scanPtr.i = apiConnectptr.p->apiScanRec;
7646 ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
7647 scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
7648 break;
7649 }
7650 case CS_WAIT_ABORT_CONF:
7651 jam();
7652 tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7653 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7654 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7655 hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7656 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7657 if (hostptr.p->hostStatus == HS_ALIVE) {
7658 /*------------------------------------------------------------------*/
7659 // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
7660 // case.
7661 /*------------------------------------------------------------------*/
7662 warningReport(signal, 20);
7663 apiConnectptr.p->timeOutCounter++;
7664 if (apiConnectptr.p->timeOutCounter > 3) {
7665 /*------------------------------------------------------------------*/
7666 // 100 time-outs are not acceptable. We will shoot down the node
7667 // not responding.
7668 /*------------------------------------------------------------------*/
7669 reportNodeFailed(signal, hostptr.i);
7670 }//if
7671 apiConnectptr.p->currentReplicaNo++;
7672 }//if
7673 tcurrentReplicaNo = (Uint8)Z8NIL;
7674 toAbortHandlingLab(signal);
7675 return;
7676 case CS_WAIT_COMMIT_CONF:
7677 jam();
7678 CRASH_INSERTION(8053);
7679 tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7680 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7681 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7682 hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7683 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7684 if (hostptr.p->hostStatus == HS_ALIVE) {
7685 /*------------------------------------------------------------------*/
7686 // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
7687 // case.
7688 /*------------------------------------------------------------------*/
7689 warningReport(signal, 21);
7690 apiConnectptr.p->timeOutCounter++;
7691 if (apiConnectptr.p->timeOutCounter > 3) {
7692 /*------------------------------------------------------------------*/
7693 // 100 time-outs are not acceptable. We will shoot down the node
7694 // not responding.
7695 /*------------------------------------------------------------------*/
7696 reportNodeFailed(signal, hostptr.i);
7697 }//if
7698 apiConnectptr.p->currentReplicaNo++;
7699 }//if
7700 tcurrentReplicaNo = (Uint8)Z8NIL;
7701 toCommitHandlingLab(signal);
7702 return;
7703 case CS_WAIT_COMPLETE_CONF:
7704 jam();
7705 tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7706 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7707 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7708 hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7709 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7710 if (hostptr.p->hostStatus == HS_ALIVE) {
7711 /*------------------------------------------------------------------*/
7712 // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
7713 // just in case.
7714 /*------------------------------------------------------------------*/
7715 warningReport(signal, 22);
7716 apiConnectptr.p->timeOutCounter++;
7717 if (apiConnectptr.p->timeOutCounter > 100) {
7718 /*------------------------------------------------------------------*/
7719 // 100 time-outs are not acceptable. We will shoot down the node
7720 // not responding.
7721 /*------------------------------------------------------------------*/
7722 reportNodeFailed(signal, hostptr.i);
7723 }//if
7724 apiConnectptr.p->currentReplicaNo++;
7725 }//if
7726 tcurrentReplicaNo = (Uint8)Z8NIL;
7727 toCompleteHandlingLab(signal);
7728 return;
7729 case CS_FAIL_PREPARED:
7730 jam();
7731 case CS_FAIL_COMMITTING:
7732 jam();
7733 case CS_FAIL_COMMITTED:
7734 jam();
7735 case CS_REC_PREPARING:
7736 jam();
7737 case CS_START_PREPARING:
7738 jam();
7739 case CS_PREPARED:
7740 jam();
7741 case CS_RESTART:
7742 jam();
7743 case CS_FAIL_ABORTED:
7744 jam();
7745 case CS_DISCONNECTED:
7746 jam();
7747 default:
7748 jam();
7749 /*------------------------------------------------------------------*/
7750 /* AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM. */
7751 /*------------------------------------------------------------------*/
7752 DEBUG("State = " << apiConnectptr.p->apiConnectstate);
7753 systemErrorLab(signal, __LINE__);
7754 return;
7755 }//switch
7756 return;
7757 }//Dbtc::timeOutFoundLab()
7758
sendAbortedAfterTimeout(Signal * signal,int Tcheck)7759 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
7760 {
7761 ApiConnectRecord * transP = apiConnectptr.p;
7762 if(transP->abortState == AS_IDLE){
7763 jam();
7764 warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
7765 __LINE__,
7766 apiConnectptr.i,
7767 transP->apiConnectstate,
7768 c_apiConTimer_line[apiConnectptr.i],
7769 transP->firstTcConnect,
7770 c_apiConTimer[apiConnectptr.i]
7771 );
7772 ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
7773 __LINE__,
7774 apiConnectptr.i,
7775 transP->apiConnectstate,
7776 c_apiConTimer_line[apiConnectptr.i],
7777 transP->firstTcConnect,
7778 c_apiConTimer[apiConnectptr.i]
7779 );
7780 ndbrequire(false);
7781 setApiConTimer(apiConnectptr.i, 0, __LINE__);
7782 return;
7783 }
7784
7785 bool found = false;
7786 OperationState tmp[16];
7787
7788 Uint32 TloopCount = 0;
7789 do {
7790 jam();
7791 if (tcConnectptr.i == RNIL) {
7792 jam();
7793
7794 #ifdef VM_TRACE
7795 ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
7796 found, Tcheck, apiConnectptr.p->counter);
7797 #endif
7798 if (found || apiConnectptr.p->counter)
7799 {
7800 jam();
7801 /**
7802 * We sent atleast one ABORT/ABORTED
7803 * or ZABORT_TIMEOUT_BREAK is in job buffer
7804 * wait for reception...
7805 */
7806 return;
7807 }
7808
7809 if (Tcheck == 1)
7810 {
7811 jam();
7812 releaseAbortResources(signal);
7813 return;
7814 }
7815
7816 if (Tcheck == 0)
7817 {
7818 jam();
7819 /*------------------------------------------------------------------
7820 * All nodes had already reported ABORTED for all tcConnect records.
7821 * Crash since it is an error situation that we then received a
7822 * time-out.
7823 *------------------------------------------------------------------*/
7824 char buf[96]; buf[0] = 0;
7825 char buf2[96];
7826 BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
7827 __LINE__, apiConnectptr.i,
7828 apiConnectptr.p->counter);
7829 for(Uint32 i = 0; i<TloopCount; i++)
7830 {
7831 BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
7832 BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
7833 }
7834 warningEvent("%s", buf);
7835 ndbout_c("%s", buf);
7836 ndbrequire(false);
7837 releaseAbortResources(signal);
7838 return;
7839 }
7840
7841 return;
7842 }//if
7843 TloopCount++;
7844 if (TloopCount >= 1024) {
7845 jam();
7846 /*------------------------------------------------------------------*/
7847 // Insert a real-time break for large transactions to avoid blowing
7848 // away the job buffer.
7849 /*------------------------------------------------------------------*/
7850 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7851 apiConnectptr.p->counter++;
7852 signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
7853 signal->theData[1] = tcConnectptr.i;
7854 signal->theData[2] = apiConnectptr.i;
7855 if (ERROR_INSERTED(8080))
7856 {
7857 ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
7858 Tcheck, apiConnectptr.p->counter);
7859 sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
7860 }
7861 else
7862 {
7863 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7864 }
7865 return;
7866 }//if
7867 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7868 if(TloopCount < 16){
7869 jam();
7870 tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
7871 }
7872
7873 if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
7874 jam();
7875 /*------------------------------------------------------------------*/
7876 // We have sent an ABORT signal to this node but not yet received any
7877 // reply. We have to send an ABORTED signal on our own in some cases.
7878 // If the node is declared as up and running and still do not respond
7879 // in time to the ABORT signal we will declare it as dead.
7880 /*------------------------------------------------------------------*/
7881 UintR Ti = 0;
7882 arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
7883 for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7884 jam();
7885 if (tcConnectptr.p->tcNodedata[Ti] != 0) {
7886 TloopCount += 31;
7887 found = true;
7888 hostptr.i = tcConnectptr.p->tcNodedata[Ti];
7889 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7890 if (hostptr.p->hostStatus == HS_ALIVE) {
7891 jam();
7892 /*---------------------------------------------------------------
7893 * A backup replica has not sent ABORTED.
7894 * Could be that a node before him has crashed.
7895 * Send an ABORT signal specifically to this node.
7896 * We will not send to any more nodes after this
7897 * to avoid race problems.
7898 * To also ensure that we use this message also as a heartbeat
7899 * we will move this node to the primary replica seat.
7900 * The primary replica and any failed node after it will
7901 * be removed from the node list. Update also number of nodes.
7902 * Finally break the loop to ensure we don't mess
7903 * things up by executing another loop.
7904 * We also update the timer to ensure we don't get time-out
7905 * too early.
7906 *--------------------------------------------------------------*/
7907 Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7908 BlockReference TBRef = numberToRef(DBLQH, instanceKey, hostptr.i);
7909 signal->theData[0] = tcConnectptr.i;
7910 signal->theData[1] = cownref;
7911 signal->theData[2] = apiConnectptr.p->transid[0];
7912 signal->theData[3] = apiConnectptr.p->transid[1];
7913 sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
7914 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7915 break;
7916 } else {
7917 jam();
7918 /*--------------------------------------------------------------
7919 * The node we are waiting for is dead. We will send ABORTED to
7920 * ourselves vicarious for the failed node.
7921 *--------------------------------------------------------------*/
7922 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7923 signal->theData[0] = tcConnectptr.i;
7924 signal->theData[1] = apiConnectptr.p->transid[0];
7925 signal->theData[2] = apiConnectptr.p->transid[1];
7926 signal->theData[3] = hostptr.i;
7927 signal->theData[4] = ZFALSE;
7928 sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7929 }//if
7930 }//if
7931 }//for
7932 }//if
7933 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7934 } while (1);
7935 }//Dbtc::sendAbortedAfterTimeout()
7936
reportNodeFailed(Signal * signal,Uint32 nodeId)7937 void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
7938 {
7939 DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
7940 rep->nodeId = nodeId;
7941 rep->err = DisconnectRep::TcReportNodeFailed;
7942 sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
7943 DisconnectRep::SignalLength, JBB);
7944 }//Dbtc::reportNodeFailed()
7945
7946 /*-------------------------------------------------*/
7947 /* Timeout-loop for scanned fragments. */
7948 /*-------------------------------------------------*/
timeOutLoopStartFragLab(Signal * signal,Uint32 TscanConPtr)7949 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
7950 {
7951 ScanFragRecPtr timeOutPtr[8];
7952 UintR tfragTimer[8];
7953 UintR texpiredTime[8];
7954 UintR TloopCount = 0;
7955 Uint32 TtcTimer = ctcTimer;
7956
7957 while ((TscanConPtr + 8) < cscanFragrecFileSize) {
7958 jam();
7959 timeOutPtr[0].i = TscanConPtr + 0;
7960 timeOutPtr[1].i = TscanConPtr + 1;
7961 timeOutPtr[2].i = TscanConPtr + 2;
7962 timeOutPtr[3].i = TscanConPtr + 3;
7963 timeOutPtr[4].i = TscanConPtr + 4;
7964 timeOutPtr[5].i = TscanConPtr + 5;
7965 timeOutPtr[6].i = TscanConPtr + 6;
7966 timeOutPtr[7].i = TscanConPtr + 7;
7967
7968 c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
7969 c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
7970 c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
7971 c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
7972 c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
7973 c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
7974 c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
7975 c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
7976
7977 tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
7978 tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
7979 tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
7980 tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
7981 tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
7982 tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
7983 tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
7984 tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
7985
7986 texpiredTime[0] = TtcTimer - tfragTimer[0];
7987 texpiredTime[1] = TtcTimer - tfragTimer[1];
7988 texpiredTime[2] = TtcTimer - tfragTimer[2];
7989 texpiredTime[3] = TtcTimer - tfragTimer[3];
7990 texpiredTime[4] = TtcTimer - tfragTimer[4];
7991 texpiredTime[5] = TtcTimer - tfragTimer[5];
7992 texpiredTime[6] = TtcTimer - tfragTimer[6];
7993 texpiredTime[7] = TtcTimer - tfragTimer[7];
7994
7995 for (Uint32 Ti = 0; Ti < 8; Ti++) {
7996 jam();
7997 if (tfragTimer[Ti] != 0) {
7998
7999 if (texpiredTime[Ti] > ctimeOutValue) {
8000 jam();
8001 DEBUG("Fragment timeout found:"<<
8002 " ctimeOutValue=" <<ctimeOutValue
8003 <<", texpiredTime="<<texpiredTime[Ti]<<endl
8004 <<" tfragTimer="<<tfragTimer[Ti]
8005 <<", ctcTimer="<<ctcTimer);
8006 timeOutFoundFragLab(signal, TscanConPtr + Ti);
8007 return;
8008 }//if
8009 }//if
8010 }//for
8011 TscanConPtr += 8;
8012 /*----------------------------------------------------------------*/
8013 /* We split the process up checking 1024 fragmentrecords at a time*/
8014 /* to maintain real time behaviour. */
8015 /*----------------------------------------------------------------*/
8016 if (TloopCount++ > 128 ) {
8017 jam();
8018 signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8019 signal->theData[1] = TscanConPtr;
8020 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8021 return;
8022 }//if
8023 }//while
8024 for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
8025 jam();
8026 timeOutPtr[0].i = TscanConPtr;
8027 c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
8028 if (timeOutPtr[0].p->scanFragTimer != 0) {
8029 texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
8030 if (texpiredTime[0] > ctimeOutValue) {
8031 jam();
8032 DEBUG("Fragment timeout found:"<<
8033 " ctimeOutValue=" <<ctimeOutValue
8034 <<", texpiredTime="<<texpiredTime[0]<<endl
8035 <<" tfragTimer="<<tfragTimer[0]
8036 <<", ctcTimer="<<ctcTimer);
8037 timeOutFoundFragLab(signal, TscanConPtr);
8038 return;
8039 }//if
8040 }//if
8041 }//for
8042 ctimeOutCheckFragActive = TOCS_FALSE;
8043
8044 return;
8045 }//timeOutLoopStartFragLab()
8046
8047 /*--------------------------------------------------------------------------*/
8048 /*Handle the heartbeat signal from LQH in a scan process */
8049 // (Set timer on fragrec.)
8050 /*--------------------------------------------------------------------------*/
execSCAN_HBREP(Signal * signal)8051 void Dbtc::execSCAN_HBREP(Signal* signal)
8052 {
8053 jamEntry();
8054
8055 scanFragptr.i = signal->theData[0];
8056 c_scan_frag_pool.getPtr(scanFragptr);
8057 switch (scanFragptr.p->scanFragState){
8058 case ScanFragRec::LQH_ACTIVE:
8059 break;
8060 default:
8061 DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
8062 systemErrorLab(signal, __LINE__);
8063 break;
8064 }
8065
8066 ScanRecordPtr scanptr;
8067 scanptr.i = scanFragptr.p->scanRec;
8068 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8069
8070 apiConnectptr.i = scanptr.p->scanApiRec;
8071 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8072
8073 if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
8074 apiConnectptr.p->transid[1] == signal->theData[2])){
8075 jam();
8076 /**
8077 * Send signal back to sender so that the crash occurs there
8078 */
8079 // Save original transid
8080 signal->theData[3] = signal->theData[0];
8081 signal->theData[4] = signal->theData[1];
8082 // Set transid to illegal values
8083 signal->theData[1] = RNIL;
8084 signal->theData[2] = RNIL;
8085
8086 sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
8087 DEBUG("SCAN_HBREP with wrong transid("
8088 <<signal->theData[3]<<", "<<signal->theData[4]<<")");
8089 return;
8090 }//if
8091
8092 // Update timer on ScanFragRec
8093 if (scanFragptr.p->scanFragTimer != 0){
8094 updateBuddyTimer(apiConnectptr);
8095 scanFragptr.p->startFragTimer(ctcTimer);
8096 } else {
8097 ndbassert(false);
8098 DEBUG("SCAN_HBREP when scanFragTimer was turned off");
8099 }
8100 }//execSCAN_HBREP()
8101
8102 /*--------------------------------------------------------------------------*/
8103 /* Timeout has occured on a fragment which means a scan has timed out. */
8104 /* If this is true we have an error in LQH/ACC. */
8105 /*--------------------------------------------------------------------------*/
timeOutFoundFragLab(Signal * signal,UintR TscanConPtr)8106 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
8107 {
8108 ScanFragRecPtr ptr;
8109 c_scan_frag_pool.getPtr(ptr, TscanConPtr);
8110 #ifdef VM_TRACE
8111 {
8112 ScanRecordPtr scanptr;
8113 scanptr.i = ptr.p->scanRec;
8114 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8115 ApiConnectRecordPtr TlocalApiConnectptr;
8116 TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8117 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8118
8119 DEBUG("[ H'" << hex << TlocalApiConnectptr.p->transid[0]
8120 << " H'" << TlocalApiConnectptr.p->transid[1] << "] "
8121 << TscanConPtr << " timeOutFoundFragLab: scanFragState = "
8122 << ptr.p->scanFragState);
8123 }
8124 #endif
8125
8126 const Uint32 time_out_param= ctimeOutValue;
8127 const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
8128
8129 if (unlikely(time_out_param != old_time_out_param &&
8130 getNodeState().getSingleUserMode()))
8131 {
8132 jam();
8133 ScanRecordPtr scanptr;
8134 scanptr.i = ptr.p->scanRec;
8135 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8136 ApiConnectRecordPtr TlocalApiConnectptr;
8137 TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8138 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8139
8140 if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
8141 getNodeState().getSingleUserApi())
8142 {
8143 jam();
8144 Uint32 val = ctcTimer - ptr.p->scanFragTimer;
8145 if (val <= old_time_out_param)
8146 {
8147 jam();
8148 goto next;
8149 }
8150 }
8151 }
8152
8153 /*-------------------------------------------------------------------------*/
8154 // The scan fragment has expired its timeout. Check its state to decide
8155 // what to do.
8156 /*-------------------------------------------------------------------------*/
8157 switch (ptr.p->scanFragState) {
8158 case ScanFragRec::WAIT_GET_PRIMCONF:
8159 jam();
8160 ndbrequire(false);
8161 break;
8162 case ScanFragRec::LQH_ACTIVE:{
8163 jam();
8164
8165 /**
8166 * The LQH expired it's timeout, try to close it
8167 */
8168 Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
8169 Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
8170 ScanRecordPtr scanptr;
8171 scanptr.i = ptr.p->scanRec;
8172 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8173
8174 if(connectCount != ptr.p->m_connectCount){
8175 jam();
8176 /**
8177 * The node has died
8178 */
8179 ptr.p->scanFragState = ScanFragRec::COMPLETED;
8180 ptr.p->stopFragTimer();
8181 {
8182 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8183 run.release(ptr);
8184 }
8185 }
8186
8187 scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
8188 break;
8189 }
8190 case ScanFragRec::DELIVERED:
8191 jam();
8192 case ScanFragRec::IDLE:
8193 jam();
8194 case ScanFragRec::QUEUED_FOR_DELIVERY:
8195 jam();
8196 /*-----------------------------------------------------------------------
8197 * Should never occur. We will simply report set the timer to zero and
8198 * continue. In a debug version we should crash here but not in a release
8199 * version. In a release version we will simply set the time-out to zero.
8200 *-----------------------------------------------------------------------*/
8201 #ifdef VM_TRACE
8202 systemErrorLab(signal, __LINE__);
8203 #endif
8204 scanFragptr.p->stopFragTimer();
8205 break;
8206 default:
8207 jam();
8208 /*-----------------------------------------------------------------------
8209 * Non-existent state. Crash.
8210 *-----------------------------------------------------------------------*/
8211 systemErrorLab(signal, __LINE__);
8212 break;
8213 }//switch
8214
8215 next:
8216 signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8217 signal->theData[1] = TscanConPtr + 1;
8218 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8219 return;
8220 }//timeOutFoundFragLab()
8221
8222
8223 /*
8224 4.3.16 GCP_NOMORETRANS
8225 ----------------------
8226 */
8227 /*****************************************************************************
8228 * G C P _ N O M O R E T R A N S
8229 *
8230 * WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
8231 * THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
8232 * SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
8233 * CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
8234 * FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
8235 * COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
8236 * THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
8237 * THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
8238 * TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
8239 *****************************************************************************/
execGCP_NOMORETRANS(Signal * signal)8240 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
8241 {
8242 jamEntry();
8243 GCPNoMoreTrans* req = (GCPNoMoreTrans*)signal->getDataPtr();
8244 c_gcp_ref = req->senderRef;
8245 c_gcp_data = req->senderData;
8246 Uint32 gci_lo = req->gci_lo;
8247 Uint32 gci_hi = req->gci_hi;
8248 tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32);
8249
8250 Ptr<GcpRecord> gcpPtr;
8251 if (cfirstgcp != RNIL) {
8252 jam();
8253 /* A GLOBAL CHECKPOINT IS GOING ON */
8254 gcpPtr.i = cfirstgcp; /* SET POINTER TO FIRST GCP IN QUEUE*/
8255 ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8256 if (gcpPtr.p->gcpId == tcheckGcpId)
8257 {
8258 jam();
8259 bool empty = gcpPtr.p->firstApiConnect == RNIL;
8260 bool nfhandling = c_ongoing_take_over_cnt;
8261
8262 if (empty && nfhandling)
8263 {
8264 jam();
8265 ndbout_c("NOT returning gcpTcfinished due to nfhandling %u/%u",
8266 gci_hi, gci_lo);
8267 }
8268
8269 if (!empty || c_ongoing_take_over_cnt)
8270 {
8271 jam();
8272 gcpPtr.p->gcpNomoretransRec = ZTRUE;
8273 } else {
8274 jam();
8275 gcpTcfinished(signal, tcheckGcpId);
8276 unlinkGcp(gcpPtr);
8277 }//if
8278 }
8279 else if (c_ongoing_take_over_cnt == 0)
8280 {
8281 jam();
8282 /*------------------------------------------------------------*/
8283 /* IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO */
8284 /* RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE */
8285 /* THE GLOBAL CHECKPOINTS IN ORDER. */
8286 /*------------------------------------------------------------*/
8287 gcpTcfinished(signal, tcheckGcpId);
8288 }
8289 else
8290 {
8291 jam();
8292 goto outoforder;
8293 }
8294 }
8295 else if (c_ongoing_take_over_cnt == 0)
8296 {
8297 jam();
8298 gcpTcfinished(signal, tcheckGcpId);
8299 }
8300 else
8301 {
8302 seize:
8303 jam();
8304 ndbout_c("execGCP_NOMORETRANS(%u/%u) c_ongoing_take_over_cnt -> seize",
8305 gci_hi, gci_lo);
8306 seizeGcp(gcpPtr, tcheckGcpId);
8307 gcpPtr.p->gcpNomoretransRec = ZTRUE;
8308 }
8309 return;
8310
8311 outoforder:
8312 printf("ooo: execGCP_NOMORETRANS tcheckGcpId: %u/%u cfirstgcp: %u/%u",
8313 gci_hi, gci_lo,
8314 Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8315
8316 if (tcheckGcpId < gcpPtr.p->gcpId)
8317 {
8318 jam();
8319
8320 Ptr<GcpRecord> tmp;
8321 tmp.i = cfirstfreeGcp;
8322 ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8323 cfirstfreeGcp = tmp.p->nextGcp;
8324
8325 tmp.p->gcpId = tcheckGcpId;
8326 tmp.p->nextGcp = cfirstgcp;
8327 tmp.p->firstApiConnect = RNIL;
8328 tmp.p->lastApiConnect = RNIL;
8329 tmp.p->gcpNomoretransRec = ZTRUE;
8330 cfirstgcp = tmp.i;
8331 ndbout_c("LINK FIRST");
8332 return;
8333 }
8334 else
8335 {
8336 Ptr<GcpRecord> prev = gcpPtr;
8337 while (tcheckGcpId > gcpPtr.p->gcpId)
8338 {
8339 jam();
8340 if (gcpPtr.p->nextGcp == RNIL)
8341 {
8342 printf("nextGcp == RNIL -> ");
8343 goto seize;
8344 }
8345
8346 prev = gcpPtr;
8347 gcpPtr.i = gcpPtr.p->nextGcp;
8348 ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8349 }
8350
8351 if (tcheckGcpId == gcpPtr.p->gcpId)
8352 {
8353 jam();
8354 gcpPtr.p->gcpNomoretransRec = ZTRUE;
8355 ndbout_c("found");
8356 return;
8357 }
8358 ndbrequire(prev.i != gcpPtr.i); // checked earlier with initial "<"
8359 ndbrequire(prev.p->gcpId < tcheckGcpId);
8360 ndbrequire(gcpPtr.p->gcpId > tcheckGcpId);
8361
8362 Ptr<GcpRecord> tmp;
8363 tmp.i = cfirstfreeGcp;
8364 ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8365 cfirstfreeGcp = tmp.p->nextGcp;
8366
8367 tmp.p->gcpId = tcheckGcpId;
8368 tmp.p->nextGcp = gcpPtr.i;
8369 tmp.p->firstApiConnect = RNIL;
8370 tmp.p->lastApiConnect = RNIL;
8371 tmp.p->gcpNomoretransRec = ZTRUE;
8372 prev.p->nextGcp = tmp.i;
8373 ndbout_c("link middle %u/%u < %u/%u < %u/%u",
8374 Uint32(prev.p->gcpId >> 32), Uint32(prev.p->gcpId),
8375 gci_hi, gci_lo,
8376 Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8377 return;
8378 }
8379 }//Dbtc::execGCP_NOMORETRANS()
8380
8381 /*****************************************************************************/
8382 /* */
8383 /* TAKE OVER MODULE */
8384 /* */
8385 /*****************************************************************************/
8386 /* */
8387 /* THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE */
8388 /* NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT */
8389 /* ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE */
8390 /* FAILED. */
8391 /* */
8392 /* AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
8393 /* CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
8394 /* COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED. */
8395 /* IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO */
8396 /* WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT. */
8397 /*****************************************************************************/
execNODE_FAILREP(Signal * signal)8398 void Dbtc::execNODE_FAILREP(Signal* signal)
8399 {
8400 jamEntry();
8401
8402 NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
8403
8404 cfailure_nr = nodeFail->failNo;
8405 const Uint32 tnoOfNodes = nodeFail->noOfNodes;
8406 const Uint32 tnewMasterId = nodeFail->masterNodeId;
8407
8408 arrGuard(tnoOfNodes, MAX_NDB_NODES);
8409 Uint32 i;
8410 int index = 0;
8411 for (i = 1; i< MAX_NDB_NODES; i++)
8412 {
8413 if(NdbNodeBitmask::get(nodeFail->theNodes, i))
8414 {
8415 cdata[index] = i;
8416 index++;
8417 }//if
8418 }//for
8419
8420 cmasterNodeId = tnewMasterId;
8421
8422 HostRecordPtr myHostPtr;
8423
8424 tcNodeFailptr.i = 0;
8425 ptrAss(tcNodeFailptr, tcFailRecord);
8426 for (i = 0; i < tnoOfNodes; i++)
8427 {
8428 jam();
8429 myHostPtr.i = cdata[i];
8430 ptrCheckGuard(myHostPtr, chostFilesize, hostRecord);
8431
8432 /*------------------------------------------------------------*/
8433 /* SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS */
8434 /* FAILED. */
8435 /*------------------------------------------------------------*/
8436 myHostPtr.p->hostStatus = HS_DEAD;
8437 myHostPtr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
8438 c_ongoing_take_over_cnt++;
8439 c_alive_nodes.clear(myHostPtr.i);
8440
8441 if (tcNodeFailptr.p->failStatus == FS_LISTENING)
8442 {
8443 jam();
8444 /*------------------------------------------------------------*/
8445 /* THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE */
8446 /* FAILURE. */
8447 /*------------------------------------------------------------*/
8448 if (myHostPtr.p->lqhTransStatus == LTS_ACTIVE)
8449 {
8450 jam();
8451 /*------------------------------------------------------------*/
8452 /* WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
8453 /* PROTOCOL FOR TC. */
8454 /*------------------------------------------------------------*/
8455 signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
8456 signal->theData[1] = myHostPtr.i;
8457 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8458 }//if
8459 }//if
8460
8461 jam();
8462 signal->theData[0] = myHostPtr.i;
8463 sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
8464
8465 checkScanActiveInFailedLqh(signal, 0, myHostPtr.i);
8466 nodeFailCheckTransactions(signal, 0, myHostPtr.i);
8467 Callback cb = {safe_cast(&Dbtc::ndbdFailBlockCleanupCallback),
8468 myHostPtr.i};
8469 simBlockNodeFailure(signal, myHostPtr.i, cb);
8470 }
8471
8472 if (m_deferred_enabled == 0)
8473 {
8474 jam();
8475 Uint32 ok = 1;
8476 for(Uint32 n = c_alive_nodes.find_first();
8477 n != c_alive_nodes.NotFound;
8478 n = c_alive_nodes.find_next(n+1))
8479 {
8480 if (!ndbd_deferred_unique_constraints(getNodeInfo(n).m_version))
8481 {
8482 jam();
8483 ok = 0;
8484 break;
8485 }
8486 }
8487 if (ok)
8488 {
8489 jam();
8490 m_deferred_enabled = ~Uint32(0);
8491 }
8492 }
8493 }//Dbtc::execNODE_FAILREP()
8494
8495 void
checkNodeFailComplete(Signal * signal,Uint32 failedNodeId,Uint32 bit)8496 Dbtc::checkNodeFailComplete(Signal* signal,
8497 Uint32 failedNodeId,
8498 Uint32 bit)
8499 {
8500 hostptr.i = failedNodeId;
8501 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8502 hostptr.p->m_nf_bits &= ~bit;
8503 if (hostptr.p->m_nf_bits == 0)
8504 {
8505 NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
8506 nfRep->blockNo = DBTC;
8507 nfRep->nodeId = cownNodeid;
8508 nfRep->failedNodeId = hostptr.i;
8509
8510 if (instance() == 0)
8511 {
8512 jam();
8513 sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
8514 NFCompleteRep::SignalLength, JBB);
8515 sendSignal(QMGR_REF, GSN_NF_COMPLETEREP, signal,
8516 NFCompleteRep::SignalLength, JBB);
8517 }
8518 else
8519 {
8520 /**
8521 * Send to proxy
8522 */
8523 sendSignal(DBTC_REF, GSN_NF_COMPLETEREP, signal,
8524 NFCompleteRep::SignalLength, JBB);
8525 }
8526 }
8527
8528 CRASH_INSERTION(8058);
8529 if (ERROR_INSERTED(8059))
8530 {
8531 signal->theData[0] = 9999;
8532 sendSignalWithDelay(numberToRef(CMVMI, hostptr.i),
8533 GSN_NDB_TAMPER, signal, 100, 1);
8534 }
8535 }
8536
checkScanActiveInFailedLqh(Signal * signal,Uint32 scanPtrI,Uint32 failedNodeId)8537 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
8538 Uint32 scanPtrI,
8539 Uint32 failedNodeId){
8540
8541 ScanRecordPtr scanptr;
8542 for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
8543 jam();
8544 ptrAss(scanptr, scanRecord);
8545 bool found = false;
8546 if (scanptr.p->scanState != ScanRecord::IDLE){
8547 jam();
8548 ScanFragRecPtr ptr;
8549 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8550
8551 for(run.first(ptr); !ptr.isNull(); ){
8552 jam();
8553 ScanFragRecPtr curr = ptr;
8554 run.next(ptr);
8555 if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
8556 refToNode(curr.p->lqhBlockref) == failedNodeId){
8557 jam();
8558
8559 run.release(curr);
8560 curr.p->scanFragState = ScanFragRec::COMPLETED;
8561 curr.p->stopFragTimer();
8562 found = true;
8563 }
8564 }
8565
8566 ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
8567 for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
8568 {
8569 jam();
8570 if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
8571 {
8572 jam();
8573 found = true;
8574 break;
8575 }
8576 }
8577 }
8578 if(found){
8579 jam();
8580 scanError(signal, scanptr, ZSCAN_LQH_ERROR);
8581 }
8582
8583 // Send CONTINUEB to continue later
8584 signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
8585 signal->theData[1] = scanptr.i + 1; // Check next scanptr
8586 signal->theData[2] = failedNodeId;
8587 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8588 return;
8589 }//for
8590
8591 checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
8592 }
8593
8594 void
nodeFailCheckTransactions(Signal * signal,Uint32 transPtrI,Uint32 failedNodeId)8595 Dbtc::nodeFailCheckTransactions(Signal* signal,
8596 Uint32 transPtrI,
8597 Uint32 failedNodeId)
8598 {
8599 jam();
8600 Ptr<ApiConnectRecord> transPtr;
8601 Uint32 TtcTimer = ctcTimer;
8602 Uint32 TapplTimeout = c_appl_timeout_value;
8603 Uint32 RT_BREAK = 64;
8604 Uint32 endPtrI = transPtrI + RT_BREAK;
8605 if (endPtrI > capiConnectFilesize)
8606 {
8607 endPtrI = capiConnectFilesize;
8608 }
8609
8610 for (transPtr.i = transPtrI; transPtr.i < endPtrI; transPtr.i++)
8611 {
8612 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
8613 if (transPtr.p->m_transaction_nodes.get(failedNodeId))
8614 {
8615 jam();
8616
8617 // Force timeout regardless of state
8618 c_appl_timeout_value = 1;
8619 setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
8620 timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
8621 c_appl_timeout_value = TapplTimeout;
8622
8623 transPtr.i++;
8624 break;
8625 }
8626 }
8627
8628 if (transPtr.i == capiConnectFilesize)
8629 {
8630 jam();
8631 checkNodeFailComplete(signal, failedNodeId,
8632 HostRecord::NF_CHECK_TRANSACTION);
8633 }
8634 else
8635 {
8636 signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
8637 signal->theData[1] = transPtr.i;
8638 signal->theData[2] = failedNodeId;
8639 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8640 }
8641 }
8642
8643 void
ndbdFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)8644 Dbtc::ndbdFailBlockCleanupCallback(Signal* signal,
8645 Uint32 failedNodeId,
8646 Uint32 ignoredRc)
8647 {
8648 jamEntry();
8649
8650 checkNodeFailComplete(signal, failedNodeId,
8651 HostRecord::NF_BLOCK_HANDLE);
8652 }
8653
8654 void
apiFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)8655 Dbtc::apiFailBlockCleanupCallback(Signal* signal,
8656 Uint32 failedNodeId,
8657 Uint32 ignoredRc)
8658 {
8659 jamEntry();
8660
8661 signal->theData[0] = failedNodeId;
8662 signal->theData[1] = reference();
8663 sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
8664 }
8665
8666 void
checkScanFragList(Signal * signal,Uint32 failedNodeId,ScanRecord * scanP,ScanFragList::Head & head)8667 Dbtc::checkScanFragList(Signal* signal,
8668 Uint32 failedNodeId,
8669 ScanRecord * scanP,
8670 ScanFragList::Head & head){
8671
8672 DEBUG("checkScanActiveInFailedLqh: scanFragError");
8673 }
8674
execTAKE_OVERTCCONF(Signal * signal)8675 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
8676 {
8677 jamEntry();
8678
8679 if (!checkNodeFailSequence(signal))
8680 {
8681 jam();
8682 return;
8683 }
8684
8685 tfailedNodeId = signal->theData[0];
8686 hostptr.i = tfailedNodeId;
8687 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8688
8689 Uint32 senderRef = signal->theData[1];
8690 if (signal->getLength() < 2)
8691 {
8692 jam();
8693 senderRef = 0; // currently only used to see if it's from self
8694 }
8695
8696 if (senderRef != reference())
8697 {
8698 jam();
8699
8700 tcNodeFailptr.i = 0;
8701 ptrAss(tcNodeFailptr, tcFailRecord);
8702
8703 /**
8704 * Node should be in queue
8705 */
8706 Uint32 i = 0;
8707 Uint32 end = tcNodeFailptr.p->queueIndex;
8708 for (; i<end; i++)
8709 {
8710 jam();
8711 if (tcNodeFailptr.p->queueList[i] == hostptr.i)
8712 {
8713 jam();
8714 break;
8715 }
8716 }
8717 ndbrequire(i != end);
8718 tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[end-1];
8719 tcNodeFailptr.p->queueIndex = end - 1;
8720 }
8721
8722 Uint32 cnt = c_ongoing_take_over_cnt;
8723 ndbrequire(cnt);
8724 c_ongoing_take_over_cnt = cnt - 1;
8725 checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
8726
8727 if (cnt == 1 && cfirstgcp != RNIL)
8728 {
8729 /**
8730 * Check if there are any hanging GCP_NOMORETRANS
8731 */
8732 GcpRecordPtr tmpGcpPointer;
8733 tmpGcpPointer.i = cfirstgcp;
8734 ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
8735 if (tmpGcpPointer.p->gcpNomoretransRec &&
8736 tmpGcpPointer.p->firstApiConnect == RNIL)
8737 {
8738 jam();
8739 ndbout_c("completing gcp %u/%u in execTAKE_OVERTCCONF",
8740 Uint32(tmpGcpPointer.p->gcpId >> 32),
8741 Uint32(tmpGcpPointer.p->gcpId));
8742 gcpTcfinished(signal, tmpGcpPointer.p->gcpId);
8743 unlinkGcp(tmpGcpPointer);
8744 }
8745 }
8746 }//Dbtc::execTAKE_OVERTCCONF()
8747
execTAKE_OVERTCREQ(Signal * signal)8748 void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
8749 {
8750 jamEntry();
8751 tfailedNodeId = signal->theData[0];
8752 tcNodeFailptr.i = 0;
8753 ptrAss(tcNodeFailptr, tcFailRecord);
8754 if (tcNodeFailptr.p->failStatus != FS_IDLE ||
8755 cmasterNodeId != getOwnNodeId() ||
8756 (! (instance() == 0 /* single TC */ ||
8757 instance() == TAKE_OVER_INSTANCE))) /* in mt-TC case let 1 instance
8758 do take-over */
8759 {
8760 jam();
8761 /*------------------------------------------------------------*/
8762 /* WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
8763 /*------------------------------------------------------------*/
8764 /* IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL */
8765 /* QUEUE THE TAKE OVER AND START IT AS SOON AS THE */
8766 /* PREVIOUS ARE COMPLETED. */
8767 /*------------------------------------------------------------*/
8768 arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
8769 tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
8770 tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
8771 return;
8772 }//if
8773 ndbrequire(instance() == 0 || instance() == TAKE_OVER_INSTANCE);
8774 startTakeOverLab(signal);
8775 }//Dbtc::execTAKE_OVERTCREQ()
8776
8777 /*------------------------------------------------------------*/
8778 /* INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS */
8779 /* AND OPERATIONS DURING TC TAKE OVER. */
8780 /*------------------------------------------------------------*/
startTakeOverLab(Signal * signal)8781 void Dbtc::startTakeOverLab(Signal* signal)
8782 {
8783 for (tindex = 0; tindex <= 511; tindex++) {
8784 ctransidFailHash[tindex] = RNIL;
8785 }//for
8786 for (tindex = 0; tindex <= 1023; tindex++) {
8787 ctcConnectFailHash[tindex] = RNIL;
8788 }//for
8789 tcNodeFailptr.p->failStatus = FS_LISTENING;
8790 tcNodeFailptr.p->takeOverNode = tfailedNodeId;
8791 for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
8792 jam();
8793 ptrAss(hostptr, hostRecord);
8794 if (hostptr.p->hostStatus == HS_ALIVE) {
8795 jam();
8796 tblockref = calcLqhBlockRef(hostptr.i);
8797 hostptr.p->lqhTransStatus = LTS_ACTIVE;
8798 signal->theData[0] = tcNodeFailptr.i;
8799 signal->theData[1] = cownref;
8800 signal->theData[2] = tfailedNodeId;
8801 if (ERROR_INSERTED(8064) && hostptr.i == getOwnNodeId())
8802 {
8803 ndbout_c("sending delayed GSN_LQH_TRANSREQ to self");
8804 sendSignalWithDelay(tblockref, GSN_LQH_TRANSREQ, signal, 100, 3);
8805 CLEAR_ERROR_INSERT_VALUE;
8806 }
8807 else
8808 {
8809 sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
8810 }
8811 }//if
8812 }//for
8813 }//Dbtc::startTakeOverLab()
8814
8815 /*------------------------------------------------------------*/
8816 /* A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
8817 /*------------------------------------------------------------*/
execLQH_TRANSCONF(Signal * signal)8818 void Dbtc::execLQH_TRANSCONF(Signal* signal)
8819 {
8820 jamEntry();
8821 LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
8822
8823 CRASH_INSERTION(8060);
8824
8825 tcNodeFailptr.i = lqhTransConf->tcRef;
8826 ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
8827 tnodeid = lqhTransConf->lqhNodeId;
8828 ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
8829 ttransid1 = lqhTransConf->transId1;
8830 ttransid2 = lqhTransConf->transId2;
8831 ttcOprec = lqhTransConf->oldTcOpRec;
8832 treqinfo = lqhTransConf->requestInfo;
8833 tgci = Uint64(lqhTransConf->gci_hi) << 32;
8834 cnodes[0] = lqhTransConf->nextNodeId1;
8835 cnodes[1] = lqhTransConf->nextNodeId2;
8836 cnodes[2] = lqhTransConf->nextNodeId3;
8837 const Uint32 ref = tapplRef = lqhTransConf->apiRef;
8838 tapplOprec = lqhTransConf->apiOpRec;
8839 const Uint32 tableId = lqhTransConf->tableId;
8840 Uint32 gci_lo = lqhTransConf->gci_lo;
8841 Uint32 fragId = lqhTransConf->fragId;
8842 if (ttransStatus == LqhTransConf::Committed &&
8843 unlikely(signal->getLength() < LqhTransConf::SignalLength_GCI_LO))
8844 {
8845 jam();
8846 gci_lo = 0;
8847 ndbassert(!ndb_check_micro_gcp(getNodeInfo(tnodeid).m_version));
8848 }
8849 tgci |= gci_lo;
8850
8851 if (ttransStatus == LqhTransConf::LastTransConf){
8852 jam();
8853 /*------------------------------------------------------------*/
8854 /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
8855 /*------------------------------------------------------------*/
8856 nodeTakeOverCompletedLab(signal);
8857 return;
8858 }//if
8859 if (ttransStatus == LqhTransConf::Marker){
8860 jam();
8861 treqinfo = 0;
8862 LqhTransConf::setMarkerFlag(treqinfo, 1);
8863 } else {
8864 TableRecordPtr tabPtr;
8865 tabPtr.i = tableId;
8866 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
8867 switch((DictTabInfo::TableType)tabPtr.p->tableType){
8868 case DictTabInfo::SystemTable:
8869 case DictTabInfo::UserTable:
8870 break;
8871 default:
8872 tapplRef = 0;
8873 tapplOprec = 0;
8874 }
8875 }
8876
8877 findApiConnectFail(signal);
8878
8879 if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
8880 apiConnectptr.p->ndbapiBlockref = ref;
8881 apiConnectptr.p->ndbapiConnect = tapplOprec;
8882 }
8883
8884 if (ttransStatus != LqhTransConf::Marker)
8885 {
8886 jam();
8887
8888 Uint32 instanceKey;
8889
8890 if (unlikely(signal->getLength() < LqhTransConf::SignalLength_FRAG_ID))
8891 {
8892 jam();
8893 instanceKey = 0;
8894 }
8895 else
8896 {
8897 jam();
8898 instanceKey = getInstanceKey(tableId, fragId);
8899 }
8900 findTcConnectFail(signal, instanceKey);
8901 }
8902 }//Dbtc::execLQH_TRANSCONF()
8903
8904 /*------------------------------------------------------------*/
8905 /* A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
8906 /*------------------------------------------------------------*/
nodeTakeOverCompletedLab(Signal * signal)8907 void Dbtc::nodeTakeOverCompletedLab(Signal* signal)
8908 {
8909 Uint32 guard0;
8910
8911 CRASH_INSERTION(8061);
8912
8913 hostptr.i = tnodeid;
8914 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8915 hostptr.p->lqhTransStatus = LTS_IDLE;
8916 for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
8917 jam();
8918 ptrAss(hostptr, hostRecord);
8919 if (hostptr.p->hostStatus == HS_ALIVE) {
8920 if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
8921 jam();
8922 /*------------------------------------------------------------*/
8923 /* NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE */
8924 /* TAKE OVER. */
8925 /*------------------------------------------------------------*/
8926 return;
8927 }//if
8928 }//if
8929 }//for
8930 /*------------------------------------------------------------*/
8931 /* ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
8932 /* OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE */
8933 /* ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE */
8934 /* TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN */
8935 /* UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
8936 /* TO THE APPLICATION IF THAT IS STILL ALIVE. */
8937 /*------------------------------------------------------------*/
8938 tcNodeFailptr.p->currentHashIndexTakeOver = 0;
8939 tcNodeFailptr.p->completedTakeOver = 0;
8940 tcNodeFailptr.p->failStatus = FS_COMPLETING;
8941 guard0 = cnoParallelTakeOver - 1;
8942 /*------------------------------------------------------------*/
8943 /* WE WILL COMPLETE THE TRANSACTIONS BY STARTING A */
8944 /* NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL */
8945 /* COMPLETE ONE TRANSACTION AT A TIME AND IN THAT */
8946 /* TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
8947 /* WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
8948 /* IS COMPLETED. */
8949 /*------------------------------------------------------------*/
8950 arrGuard(guard0, MAX_NDB_NODES);
8951 for (tindex = 0; tindex <= guard0; tindex++) {
8952 jam();
8953 tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
8954 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
8955 signal->theData[1] = tcNodeFailptr.i;
8956 signal->theData[2] = tindex;
8957 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8958 }//for
8959 }//Dbtc::nodeTakeOverCompletedLab()
8960
8961 /*------------------------------------------------------------*/
8962 /* COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF */
8963 /* TRANSACTIONS TO COMPLETE. */
8964 /*------------------------------------------------------------*/
completeTransAtTakeOverLab(Signal * signal,UintR TtakeOverInd)8965 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
8966 {
8967 jam();
8968 while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
8969 jam();
8970 apiConnectptr.i =
8971 ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
8972 if (apiConnectptr.i != RNIL) {
8973 jam();
8974 /*------------------------------------------------------------*/
8975 /* WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE */
8976 /* COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT */
8977 /* NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS */
8978 /* TRANSACTION. */
8979 /*------------------------------------------------------------*/
8980 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8981 ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
8982 apiConnectptr.p->nextApiConnect;
8983
8984 completeTransAtTakeOverDoOne(signal, TtakeOverInd);
8985 // One transaction taken care of, return from this function
8986 // and wait for the next CONTINUEB to continue processing
8987 break;
8988
8989 } else {
8990 if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
8991 jam();
8992 tcNodeFailptr.p->currentHashIndexTakeOver++;
8993 } else {
8994 jam();
8995 completeTransAtTakeOverDoLast(signal, TtakeOverInd);
8996 tcNodeFailptr.p->currentHashIndexTakeOver++;
8997 }//if
8998 }//if
8999 }//while
9000 }//Dbtc::completeTransAtTakeOverLab()
9001
9002
9003
9004
completeTransAtTakeOverDoLast(Signal * signal,UintR TtakeOverInd)9005 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
9006 {
9007 Uint32 guard0;
9008 /*------------------------------------------------------------*/
9009 /* THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS */
9010 /* ACTIVITY IS COMPLETED. */
9011 /*------------------------------------------------------------*/
9012 arrGuard(TtakeOverInd, MAX_NDB_NODES);
9013 if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
9014 jam();
9015 systemErrorLab(signal, __LINE__);
9016 return;
9017 }//if
9018 tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
9019 tcNodeFailptr.p->completedTakeOver++;
9020
9021 CRASH_INSERTION(8062);
9022
9023 if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
9024 jam();
9025 /*------------------------------------------------------------*/
9026 /* WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
9027 /* TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL */
9028 /* NODES THAT ARE ALIVE. */
9029 /*------------------------------------------------------------*/
9030 NodeReceiverGroup rg(DBTC, c_alive_nodes);
9031 signal->theData[0] = tcNodeFailptr.p->takeOverNode;
9032 signal->theData[1] = reference();
9033 sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 2, JBB);
9034
9035 if (tcNodeFailptr.p->queueIndex > 0) {
9036 jam();
9037 /*------------------------------------------------------------*/
9038 /* THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START */
9039 /* THE TAKE OVER. */
9040 /*------------------------------------------------------------*/
9041 tfailedNodeId = tcNodeFailptr.p->queueList[0];
9042 guard0 = tcNodeFailptr.p->queueIndex - 1;
9043 arrGuard(guard0 + 1, MAX_NDB_NODES);
9044 for (tindex = 0; tindex <= guard0; tindex++) {
9045 jam();
9046 tcNodeFailptr.p->queueList[tindex] =
9047 tcNodeFailptr.p->queueList[tindex + 1];
9048 }//for
9049 tcNodeFailptr.p->queueIndex--;
9050 startTakeOverLab(signal);
9051 return;
9052 } else {
9053 jam();
9054 tcNodeFailptr.p->failStatus = FS_IDLE;
9055 }//if
9056 }//if
9057 return;
9058 }//Dbtc::completeTransAtTakeOverDoLast()
9059
completeTransAtTakeOverDoOne(Signal * signal,UintR TtakeOverInd)9060 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
9061 {
9062 apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
9063 apiConnectptr.p->takeOverInd = TtakeOverInd;
9064
9065 switch (apiConnectptr.p->apiConnectstate) {
9066 case CS_FAIL_COMMITTED:
9067 jam();
9068 /*------------------------------------------------------------*/
9069 /* ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
9070 /* HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT */
9071 /* COMMITTED TO THE APPLICATION AND CONTINUE WITH THE */
9072 /* COMPLETE PHASE. */
9073 /*------------------------------------------------------------*/
9074 sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9075 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9076 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9077 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9078 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9079 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9080 commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
9081 toCompleteHandlingLab(signal);
9082 return;
9083 case CS_FAIL_COMMITTING:
9084 jam();
9085 /*------------------------------------------------------------*/
9086 /* AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
9087 /* PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
9088 /* THEN CONTINUE AS AFTER COMMITTED. */
9089 /*------------------------------------------------------------*/
9090 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9091 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9092 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9093 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9094 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9095 commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
9096 toCommitHandlingLab(signal);
9097 return;
9098 case CS_FAIL_ABORTING:
9099 case CS_FAIL_PREPARED:
9100 jam();
9101 /*------------------------------------------------------------*/
9102 /* WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
9103 /* STATE IN THIS VERSION. IN LATER VERSIONS WE WILL */
9104 /* HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT */
9105 /* TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
9106 /* HAVE HEARD FROM THE TRANSACTION COORDINATOR. */
9107 /* */
9108 /* IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE */
9109 /* PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL */
9110 /* LATER VERSIONS. */
9111 /*------------------------------------------------------------*/
9112 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9113 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9114 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9115 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9116 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9117 toAbortHandlingLab(signal);
9118 return;
9119 case CS_FAIL_ABORTED:
9120 jam();
9121 sendTCKEY_FAILREF(signal, apiConnectptr.p);
9122
9123 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9124 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9125 signal->theData[2] = apiConnectptr.p->takeOverInd;
9126 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9127 releaseTakeOver(signal);
9128 break;
9129 case CS_FAIL_COMPLETED:
9130 jam();
9131 sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9132
9133 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9134 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9135 signal->theData[2] = apiConnectptr.p->takeOverInd;
9136 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9137 releaseApiConnectFail(signal);
9138 break;
9139 default:
9140 jam();
9141 systemErrorLab(signal, __LINE__);
9142 return;
9143 }//switch
9144 }//Dbtc::completeTransAtTakeOverDoOne()
9145
9146 void
sendTCKEY_FAILREF(Signal * signal,ApiConnectRecord * regApiPtr)9147 Dbtc::sendTCKEY_FAILREF(Signal* signal, ApiConnectRecord * regApiPtr){
9148 jam();
9149
9150 const Uint32 ref = regApiPtr->ndbapiBlockref;
9151 const Uint32 nodeId = refToNode(ref);
9152 if(ref != 0)
9153 {
9154 jam();
9155 bool connectedToNode = getNodeInfo(nodeId).m_connected;
9156 signal->theData[0] = regApiPtr->ndbapiConnect;
9157 signal->theData[1] = regApiPtr->transid[0];
9158 signal->theData[2] = regApiPtr->transid[1];
9159
9160 if (likely(connectedToNode))
9161 {
9162 jam();
9163 sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
9164 }
9165 else
9166 {
9167 routeTCKEY_FAILREFCONF(signal, regApiPtr, GSN_TCKEY_FAILREF, 3);
9168 }
9169 }
9170
9171 const Uint32 marker = regApiPtr->commitAckMarker;
9172 if(marker != RNIL)
9173 {
9174 jam();
9175 m_commitAckMarkerHash.release(marker);
9176 regApiPtr->commitAckMarker = RNIL;
9177 }
9178 }
9179
9180 void
sendTCKEY_FAILCONF(Signal * signal,ApiConnectRecord * regApiPtr)9181 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
9182 jam();
9183 TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
9184
9185 const Uint32 ref = regApiPtr->ndbapiBlockref;
9186 const Uint32 marker = regApiPtr->commitAckMarker;
9187 const Uint32 nodeId = refToNode(ref);
9188 if(ref != 0)
9189 {
9190 jam();
9191 failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
9192 failConf->transId1 = regApiPtr->transid[0];
9193 failConf->transId2 = regApiPtr->transid[1];
9194
9195 bool connectedToNode = getNodeInfo(nodeId).m_connected;
9196 if (likely(connectedToNode))
9197 {
9198 jam();
9199 sendSignal(ref, GSN_TCKEY_FAILCONF, signal,
9200 TcKeyFailConf::SignalLength, JBB);
9201 }
9202 else
9203 {
9204 routeTCKEY_FAILREFCONF(signal, regApiPtr,
9205 GSN_TCKEY_FAILCONF, TcKeyFailConf::SignalLength);
9206 }
9207 }
9208 regApiPtr->commitAckMarker = RNIL;
9209 }
9210
9211 void
routeTCKEY_FAILREFCONF(Signal * signal,const ApiConnectRecord * regApiPtr,Uint32 gsn,Uint32 len)9212 Dbtc::routeTCKEY_FAILREFCONF(Signal* signal, const ApiConnectRecord* regApiPtr,
9213 Uint32 gsn, Uint32 len)
9214 {
9215 jam();
9216
9217 Uint32 ref = regApiPtr->ndbapiBlockref;
9218
9219 /**
9220 * We're not connected
9221 * so we find another node in same node group as died node
9222 * and send to it, so that it can forward
9223 */
9224 tcNodeFailptr.i = regApiPtr->takeOverRec;
9225 ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
9226
9227 /**
9228 * Save signal
9229 */
9230 Uint32 save[25];
9231 ndbrequire(len <= 25);
9232 memcpy(save, signal->theData, 4*len);
9233
9234 Uint32 node = tcNodeFailptr.p->takeOverNode;
9235
9236 CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
9237 sd->blockRef = reference();
9238 sd->requestType =
9239 CheckNodeGroups::Direct |
9240 CheckNodeGroups::GetNodeGroupMembers;
9241 sd->nodeId = node;
9242 EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
9243 CheckNodeGroups::SignalLength);
9244 jamEntry();
9245
9246 NdbNodeBitmask mask;
9247 mask.assign(sd->mask);
9248 mask.clear(getOwnNodeId());
9249 memcpy(signal->theData, save, 4*len);
9250
9251 Uint32 i = 0;
9252 while((i = mask.find(i + 1)) != NdbNodeBitmask::NotFound)
9253 {
9254 jam();
9255 HostRecordPtr localHostptr;
9256 localHostptr.i = i;
9257 ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
9258 if (localHostptr.p->hostStatus == HS_ALIVE)
9259 {
9260 jam();
9261 signal->theData[len] = gsn;
9262 signal->theData[len+1] = ref;
9263 sendSignal(calcTcBlockRef(i), GSN_TCKEY_FAILREFCONF_R,
9264 signal, len+2, JBB);
9265 return;
9266 }
9267 }
9268
9269
9270 /**
9271 * This code was 'unfinished' code for partially connected API's
9272 * it does however not really work...
9273 * and we seriously need to think about semantics for API connect
9274 */
9275 #if 0
9276 ndbrequire(getNodeInfo(refToNode(ref)).m_type == NodeInfo::DB);
9277 #endif
9278 }
9279
9280 void
execTCKEY_FAILREFCONF_R(Signal * signal)9281 Dbtc::execTCKEY_FAILREFCONF_R(Signal* signal)
9282 {
9283 jamEntry();
9284 Uint32 len = signal->getLength();
9285 Uint32 gsn = signal->theData[len-2];
9286 Uint32 ref = signal->theData[len-1];
9287 sendSignal(ref, gsn, signal, len-2, JBB);
9288 }
9289
9290 /*------------------------------------------------------------*/
9291 /* THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A */
9292 /* NODE FAILURE BEFORE THE COMMIT DECISION. */
9293 /*------------------------------------------------------------*/
9294 /* ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
9295 /*------------------------------------------------------------*/
execABORTCONF(Signal * signal)9296 void Dbtc::execABORTCONF(Signal* signal)
9297 {
9298 UintR compare_transid1, compare_transid2;
9299
9300 jamEntry();
9301 tcConnectptr.i = signal->theData[0];
9302 tnodeid = signal->theData[2];
9303 if (ERROR_INSERTED(8045)) {
9304 CLEAR_ERROR_INSERT_VALUE;
9305 sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
9306 return;
9307 }//if
9308 if (tcConnectptr.i >= ctcConnectFilesize) {
9309 errorReport(signal, 5);
9310 return;
9311 }//if
9312 ptrAss(tcConnectptr, tcConnectRecord);
9313 if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
9314 warningReport(signal, 16);
9315 return;
9316 }//if
9317 apiConnectptr.i = tcConnectptr.p->apiConnect;
9318 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9319 if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
9320 warningReport(signal, 17);
9321 return;
9322 }//if
9323 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
9324 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
9325 compare_transid1 = compare_transid1 | compare_transid2;
9326 if (compare_transid1 != 0) {
9327 warningReport(signal, 18);
9328 return;
9329 }//if
9330 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9331 if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9332 tnodeid) {
9333 warningReport(signal, 19);
9334 return;
9335 }//if
9336 tcurrentReplicaNo = (Uint8)Z8NIL;
9337 tcConnectptr.p->tcConnectstate = OS_ABORTING;
9338 toAbortHandlingLab(signal);
9339 }//Dbtc::execABORTCONF()
9340
toAbortHandlingLab(Signal * signal)9341 void Dbtc::toAbortHandlingLab(Signal* signal)
9342 {
9343 do {
9344 if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9345 jam();
9346 arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9347 const LqhTransConf::OperationStatus stat =
9348 (LqhTransConf::OperationStatus)
9349 tcConnectptr.p->failData[tcurrentReplicaNo];
9350 switch(stat){
9351 case LqhTransConf::InvalidStatus:
9352 case LqhTransConf::Aborted:
9353 jam();
9354 /*empty*/;
9355 break;
9356 case LqhTransConf::Prepared:
9357 jam();
9358 hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9359 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9360 if (hostptr.p->hostStatus == HS_ALIVE) {
9361 jam();
9362 Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9363 tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9364 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9365 tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
9366 apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
9367 apiConnectptr.p->timeOutCounter = 0;
9368 signal->theData[0] = tcConnectptr.i;
9369 signal->theData[1] = cownref;
9370 signal->theData[2] = apiConnectptr.p->transid[0];
9371 signal->theData[3] = apiConnectptr.p->transid[1];
9372 signal->theData[4] = apiConnectptr.p->tcBlockref;
9373 signal->theData[5] = tcConnectptr.p->tcOprec;
9374 sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
9375 return;
9376 }//if
9377 break;
9378 default:
9379 jam();
9380 systemErrorLab(signal, __LINE__);
9381 return;
9382 }//switch
9383 }//if
9384 if (apiConnectptr.p->currentReplicaNo > 0) {
9385 jam();
9386 /*------------------------------------------------------------*/
9387 /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
9388 /* ABORTED. */
9389 /*------------------------------------------------------------*/
9390 apiConnectptr.p->currentReplicaNo--;
9391 tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9392 } else {
9393 /*------------------------------------------------------------*/
9394 /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
9395 /*------------------------------------------------------------*/
9396 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9397 if (tcConnectptr.i == RNIL) {
9398 /*------------------------------------------------------------*/
9399 /* WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
9400 /* THE ABORT STATUS TO THE APPLICATION AND CONTINUE */
9401 /* WITH THE NEXT TRANSACTION. */
9402 /*------------------------------------------------------------*/
9403 if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9404 jam();
9405 sendTCKEY_FAILREF(signal, apiConnectptr.p);
9406
9407 /*------------------------------------------------------------*/
9408 /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
9409 /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
9410 /*------------------------------------------------------------*/
9411 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9412 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9413 signal->theData[2] = apiConnectptr.p->takeOverInd;
9414 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9415 releaseTakeOver(signal);
9416 } else {
9417 jam();
9418 releaseAbortResources(signal);
9419 }//if
9420 return;
9421 }//if
9422 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9423 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9424 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9425 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9426 }//if
9427 } while (1);
9428 }//Dbtc::toAbortHandlingLab()
9429
9430 /*------------------------------------------------------------*/
9431 /* THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A */
9432 /* NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE. */
9433 /*------------------------------------------------------------*/
9434 /* COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID */
9435 /*------------------------------------------------------------*/
execCOMMITCONF(Signal * signal)9436 void Dbtc::execCOMMITCONF(Signal* signal)
9437 {
9438 UintR compare_transid1, compare_transid2;
9439
9440 jamEntry();
9441 tcConnectptr.i = signal->theData[0];
9442 tnodeid = signal->theData[1];
9443 if (ERROR_INSERTED(8046)) {
9444 CLEAR_ERROR_INSERT_VALUE;
9445 sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
9446 return;
9447 }//if
9448 if (tcConnectptr.i >= ctcConnectFilesize) {
9449 errorReport(signal, 4);
9450 return;
9451 }//if
9452 ptrAss(tcConnectptr, tcConnectRecord);
9453 if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
9454 warningReport(signal, 8);
9455 return;
9456 }//if
9457 apiConnectptr.i = tcConnectptr.p->apiConnect;
9458 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9459 if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
9460 warningReport(signal, 9);
9461 return;
9462 }//if
9463 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
9464 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
9465 compare_transid1 = compare_transid1 | compare_transid2;
9466 if (compare_transid1 != 0) {
9467 warningReport(signal, 10);
9468 return;
9469 }//if
9470 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9471 if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9472 tnodeid) {
9473 warningReport(signal, 11);
9474 return;
9475 }//if
9476 if (ERROR_INSERTED(8026)) {
9477 jam();
9478 systemErrorLab(signal, __LINE__);
9479 }//if
9480 tcurrentReplicaNo = (Uint8)Z8NIL;
9481 tcConnectptr.p->tcConnectstate = OS_COMMITTED;
9482 toCommitHandlingLab(signal);
9483 }//Dbtc::execCOMMITCONF()
9484
toCommitHandlingLab(Signal * signal)9485 void Dbtc::toCommitHandlingLab(Signal* signal)
9486 {
9487 do {
9488 if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9489 jam();
9490 arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9491 switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
9492 case LqhTransConf::InvalidStatus:
9493 jam();
9494 /*empty*/;
9495 break;
9496 case LqhTransConf::Committed:
9497 jam();
9498 /*empty*/;
9499 break;
9500 case LqhTransConf::Prepared:
9501 jam();
9502 /*------------------------------------------------------------*/
9503 /* THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR */
9504 /* COMMIT REQUEST FROM TC. */
9505 /*------------------------------------------------------------*/
9506 hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9507 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9508 if (hostptr.p->hostStatus == HS_ALIVE) {
9509 jam();
9510 Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9511 tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9512 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9513 apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
9514 apiConnectptr.p->timeOutCounter = 0;
9515 tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
9516 Uint64 gci = apiConnectptr.p->globalcheckpointid;
9517 signal->theData[0] = tcConnectptr.i;
9518 signal->theData[1] = cownref;
9519 signal->theData[2] = Uint32(gci >> 32); // XXX JON
9520 signal->theData[3] = apiConnectptr.p->transid[0];
9521 signal->theData[4] = apiConnectptr.p->transid[1];
9522 signal->theData[5] = apiConnectptr.p->tcBlockref;
9523 signal->theData[6] = tcConnectptr.p->tcOprec;
9524 signal->theData[7] = Uint32(gci);
9525 sendSignal(tblockref, GSN_COMMITREQ, signal, 8, JBB);
9526 return;
9527 }//if
9528 break;
9529 default:
9530 jam();
9531 systemErrorLab(signal, __LINE__);
9532 return;
9533 break;
9534 }//switch
9535 }//if
9536 if (apiConnectptr.p->currentReplicaNo > 0) {
9537 jam();
9538 /*------------------------------------------------------------*/
9539 /* THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE */
9540 /* COMMITTED. */
9541 /*------------------------------------------------------------*/
9542 apiConnectptr.p->currentReplicaNo--;
9543 tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9544 } else {
9545 /*------------------------------------------------------------*/
9546 /* THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED. */
9547 /*------------------------------------------------------------*/
9548 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9549 if (tcConnectptr.i == RNIL) {
9550 /*------------------------------------------------------------*/
9551 /* WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
9552 /* THE COMMIT STATUS TO THE APPLICATION AND CONTINUE */
9553 /* WITH THE COMPLETE PHASE. */
9554 /*------------------------------------------------------------*/
9555 if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9556 jam();
9557 sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9558 } else {
9559 jam();
9560 apiConnectptr = sendApiCommit(signal);
9561 }//if
9562 apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
9563 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9564 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9565 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9566 apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
9567 toCompleteHandlingLab(signal);
9568 return;
9569 }//if
9570 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9571 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9572 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9573 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9574 }//if
9575 } while (1);
9576 }//Dbtc::toCommitHandlingLab()
9577
9578 /*------------------------------------------------------------*/
9579 /* COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE */
9580 /* HAVE FAILED. */
9581 /*------------------------------------------------------------*/
9582 /* THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION */
9583 /*------------------------------------------------------------*/
execCOMPLETECONF(Signal * signal)9584 void Dbtc::execCOMPLETECONF(Signal* signal)
9585 {
9586 UintR compare_transid1, compare_transid2;
9587
9588 jamEntry();
9589 tcConnectptr.i = signal->theData[0];
9590 tnodeid = signal->theData[1];
9591 if (ERROR_INSERTED(8047)) {
9592 CLEAR_ERROR_INSERT_VALUE;
9593 sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
9594 return;
9595 }//if
9596 if (tcConnectptr.i >= ctcConnectFilesize) {
9597 errorReport(signal, 3);
9598 return;
9599 }//if
9600 ptrAss(tcConnectptr, tcConnectRecord);
9601 if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
9602 warningReport(signal, 12);
9603 return;
9604 }//if
9605 apiConnectptr.i = tcConnectptr.p->apiConnect;
9606 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9607 if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
9608 warningReport(signal, 13);
9609 return;
9610 }//if
9611 compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
9612 compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
9613 compare_transid1 = compare_transid1 | compare_transid2;
9614 if (compare_transid1 != 0) {
9615 warningReport(signal, 14);
9616 return;
9617 }//if
9618 arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9619 if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9620 tnodeid) {
9621 warningReport(signal, 15);
9622 return;
9623 }//if
9624 if (ERROR_INSERTED(8028)) {
9625 jam();
9626 systemErrorLab(signal, __LINE__);
9627 }//if
9628 tcConnectptr.p->tcConnectstate = OS_COMPLETED;
9629 tcurrentReplicaNo = (Uint8)Z8NIL;
9630 toCompleteHandlingLab(signal);
9631 }//Dbtc::execCOMPLETECONF()
9632
toCompleteHandlingLab(Signal * signal)9633 void Dbtc::toCompleteHandlingLab(Signal* signal)
9634 {
9635 do {
9636 if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9637 jam();
9638 arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9639 switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
9640 case LqhTransConf::InvalidStatus:
9641 jam();
9642 /*empty*/;
9643 break;
9644 default:
9645 jam();
9646 /*------------------------------------------------------------*/
9647 /* THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
9648 /* IT MUST HAVE FAILED. */
9649 /*------------------------------------------------------------*/
9650 /*------------------------------------------------------------*/
9651 /* SEND COMPLETEREQ TO THE NEXT REPLICA. */
9652 /*------------------------------------------------------------*/
9653 hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9654 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9655 if (hostptr.p->hostStatus == HS_ALIVE) {
9656 jam();
9657 Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9658 tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9659 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9660 tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
9661 apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
9662 apiConnectptr.p->timeOutCounter = 0;
9663 tcConnectptr.p->apiConnect = apiConnectptr.i;
9664 signal->theData[0] = tcConnectptr.i;
9665 signal->theData[1] = cownref;
9666 signal->theData[2] = apiConnectptr.p->transid[0];
9667 signal->theData[3] = apiConnectptr.p->transid[1];
9668 signal->theData[4] = apiConnectptr.p->tcBlockref;
9669 signal->theData[5] = tcConnectptr.p->tcOprec;
9670 sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
9671 return;
9672 }//if
9673 break;
9674 }//switch
9675 }//if
9676 if (apiConnectptr.p->currentReplicaNo != 0) {
9677 jam();
9678 /*------------------------------------------------------------*/
9679 /* THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE */
9680 /* NEED TO CONTINUE WITH THOSE REPLICAS. */
9681 /*------------------------------------------------------------*/
9682 apiConnectptr.p->currentReplicaNo--;
9683 tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9684 } else {
9685 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9686 if (tcConnectptr.i == RNIL) {
9687 /*------------------------------------------------------------*/
9688 /* WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN */
9689 /* CONTINUE THE PROCESS WITH THE NEXT TRANSACTION. */
9690 /*------------------------------------------------------------*/
9691 if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9692 jam();
9693 signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9694 signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9695 signal->theData[2] = apiConnectptr.p->takeOverInd;
9696 sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9697 handleGcp(signal, apiConnectptr);
9698 releaseTakeOver(signal);
9699 } else {
9700 jam();
9701 releaseTransResources(signal);
9702 }//if
9703 return;
9704 }//if
9705 /*------------------------------------------------------------*/
9706 /* WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
9707 /* COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
9708 /* FIRST REPLICA SINCE IT IS THE COMPLETE PHASE. */
9709 /*------------------------------------------------------------*/
9710 apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9711 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9712 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9713 apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
9714 }//if
9715 } while (1);
9716 }//Dbtc::toCompleteHandlingLab()
9717
9718 /*------------------------------------------------------------*/
9719 /* */
9720 /* FIND THE API CONNECT RECORD FOR THIS TRANSACTION */
9721 /* DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS */
9722 /* YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT */
9723 /* INTO THE HASH TABLE. */
9724 /*------------------------------------------------------------*/
findApiConnectFail(Signal * signal)9725 void Dbtc::findApiConnectFail(Signal* signal)
9726 {
9727 ApiConnectRecordPtr fafPrevApiConnectptr;
9728 ApiConnectRecordPtr fafNextApiConnectptr;
9729 UintR tfafHashNumber;
9730
9731 tfafHashNumber = ttransid1 & 511;
9732 fafPrevApiConnectptr.i = RNIL;
9733 ptrNull(fafPrevApiConnectptr);
9734 arrGuard(tfafHashNumber, 512);
9735 fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
9736 ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
9737 FAF_LOOP:
9738 jam();
9739 if (fafNextApiConnectptr.i == RNIL) {
9740 jam();
9741 if (cfirstfreeApiConnectFail == RNIL) {
9742 jam();
9743 systemErrorLab(signal, __LINE__);
9744 return;
9745 }//if
9746 seizeApiConnectFail(signal);
9747 if (fafPrevApiConnectptr.i == RNIL) {
9748 jam();
9749 ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
9750 } else {
9751 jam();
9752 ptrGuard(fafPrevApiConnectptr);
9753 fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
9754 }//if
9755 apiConnectptr.p->nextApiConnect = RNIL;
9756 initApiConnectFail(signal);
9757 } else {
9758 jam();
9759 fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
9760 fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
9761 apiConnectptr.i = fafNextApiConnectptr.i;
9762 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9763 fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
9764 ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
9765 if ((apiConnectptr.p->transid[1] != ttransid2) ||
9766 (apiConnectptr.p->transid[0] != ttransid1)) {
9767 goto FAF_LOOP;
9768 }//if
9769 updateApiStateFail(signal);
9770 }//if
9771 }//Dbtc::findApiConnectFail()
9772
9773 /*----------------------------------------------------------*/
9774 /* FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW */
9775 /*----------------------------------------------------------*/
findTcConnectFail(Signal * signal,Uint32 instanceKey)9776 void Dbtc::findTcConnectFail(Signal* signal, Uint32 instanceKey)
9777 {
9778 UintR tftfHashNumber;
9779
9780 tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
9781 tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
9782 do {
9783 if (tcConnectptr.i == RNIL) {
9784 jam();
9785 if (cfirstfreeTcConnectFail == RNIL) {
9786 jam();
9787 systemErrorLab(signal, __LINE__);
9788 return;
9789 }//if
9790 seizeTcConnectFail(signal);
9791 linkTcInConnectionlist(signal);
9792 tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
9793 ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
9794 initTcConnectFail(signal, instanceKey);
9795 return;
9796 } else {
9797 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9798 if (tcConnectptr.p->tcOprec != ttcOprec) {
9799 jam(); /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
9800 tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
9801 } else {
9802 updateTcStateFail(signal, instanceKey);
9803 return;
9804 }//if
9805 }//if
9806 } while (1);
9807 }//Dbtc::findTcConnectFail()
9808
9809 /*----------------------------------------------------------*/
9810 /* INITIALISE AN API CONNECT FAIL RECORD */
9811 /*----------------------------------------------------------*/
initApiConnectFail(Signal * signal)9812 void Dbtc::initApiConnectFail(Signal* signal)
9813 {
9814 apiConnectptr.p->transid[0] = ttransid1;
9815 apiConnectptr.p->transid[1] = ttransid2;
9816 apiConnectptr.p->firstTcConnect = RNIL;
9817 apiConnectptr.p->currSavePointId = 0;
9818 apiConnectptr.p->lastTcConnect = RNIL;
9819 tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
9820
9821 apiConnectptr.p->tcBlockref = tblockref;
9822 apiConnectptr.p->ndbapiBlockref = 0;
9823 apiConnectptr.p->ndbapiConnect = 0;
9824 apiConnectptr.p->buddyPtr = RNIL;
9825 apiConnectptr.p->m_transaction_nodes.clear();
9826 apiConnectptr.p->singleUserMode = 0;
9827 setApiConTimer(apiConnectptr.i, 0, __LINE__);
9828 switch(ttransStatus){
9829 case LqhTransConf::Committed:
9830 jam();
9831 apiConnectptr.p->globalcheckpointid = tgci;
9832 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
9833 break;
9834 case LqhTransConf::Prepared:
9835 jam();
9836 apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
9837 break;
9838 case LqhTransConf::Aborted:
9839 jam();
9840 apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
9841 break;
9842 case LqhTransConf::Marker:
9843 jam();
9844 apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
9845 break;
9846 default:
9847 jam();
9848 systemErrorLab(signal, __LINE__);
9849 }//if
9850 apiConnectptr.p->commitAckMarker = RNIL;
9851 if(LqhTransConf::getMarkerFlag(treqinfo)){
9852 jam();
9853 CommitAckMarkerPtr tmp;
9854 m_commitAckMarkerHash.seize(tmp);
9855
9856 ndbrequire(tmp.i != RNIL);
9857
9858 apiConnectptr.p->commitAckMarker = tmp.i;
9859 tmp.p->transid1 = ttransid1;
9860 tmp.p->transid2 = ttransid2;
9861 tmp.p->apiNodeId = refToNode(tapplRef);
9862 tmp.p->m_commit_ack_marker_nodes.clear();
9863 tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
9864 tmp.p->apiConnectPtr = apiConnectptr.i;
9865
9866 #if defined VM_TRACE || defined ERROR_INSERT
9867 {
9868 CommitAckMarkerPtr check;
9869 ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
9870 }
9871 #endif
9872 m_commitAckMarkerHash.add(tmp);
9873 }
9874 }//Dbtc::initApiConnectFail()
9875
9876 /*------------------------------------------------------------*/
9877 /* INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
9878 /* THE TC CONNECT RECORD. */
9879 /*------------------------------------------------------------*/
initTcConnectFail(Signal * signal,Uint32 instanceKey)9880 void Dbtc::initTcConnectFail(Signal* signal, Uint32 instanceKey)
9881 {
9882 tcConnectptr.p->apiConnect = apiConnectptr.i;
9883 tcConnectptr.p->tcOprec = ttcOprec;
9884 Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
9885 for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
9886 tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
9887 }//for
9888 tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
9889 tcConnectptr.p->failData[treplicaNo] = ttransStatus;
9890 tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
9891 tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
9892 tcConnectptr.p->lqhInstanceKey = instanceKey;
9893
9894 }//Dbtc::initTcConnectFail()
9895
9896 /*----------------------------------------------------------*/
9897 /* INITIALISE TC NODE FAIL RECORD. */
9898 /*----------------------------------------------------------*/
initTcFail(Signal * signal)9899 void Dbtc::initTcFail(Signal* signal)
9900 {
9901 tcNodeFailptr.i = 0;
9902 ptrAss(tcNodeFailptr, tcFailRecord);
9903 tcNodeFailptr.p->queueIndex = 0;
9904 tcNodeFailptr.p->failStatus = FS_IDLE;
9905 }//Dbtc::initTcFail()
9906
9907 /*----------------------------------------------------------*/
9908 /* RELEASE_TAKE_OVER */
9909 /*----------------------------------------------------------*/
releaseTakeOver(Signal * signal)9910 void Dbtc::releaseTakeOver(Signal* signal)
9911 {
9912 TcConnectRecordPtr rtoNextTcConnectptr;
9913
9914 rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
9915 do {
9916 jam();
9917 tcConnectptr.i = rtoNextTcConnectptr.i;
9918 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9919 rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
9920 releaseTcConnectFail(signal);
9921 } while (rtoNextTcConnectptr.i != RNIL);
9922 releaseApiConnectFail(signal);
9923 }//Dbtc::releaseTakeOver()
9924
9925 /*---------------------------------------------------------------------------*/
9926 /* SETUP_FAIL_DATA */
9927 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE */
9928 /* FAILURE SITUATIONS. */
9929 /*---------------------------------------------------------------------------*/
setupFailData(Signal * signal)9930 void Dbtc::setupFailData(Signal* signal)
9931 {
9932 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9933 do {
9934 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9935 switch (tcConnectptr.p->tcConnectstate) {
9936 case OS_PREPARED:
9937 case OS_COMMITTING:
9938 jam();
9939 arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9940 for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9941 jam();
9942 /*-------------------------------------------------------------------
9943 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9944 * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
9945 * COMMIT/ABORT DECISION.
9946 *------------------------------------------------------------------*/
9947 tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
9948 }//for
9949 break;
9950 case OS_COMMITTED:
9951 case OS_COMPLETING:
9952 jam();
9953 arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9954 for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9955 jam();
9956 /*-------------------------------------------------------------------
9957 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9958 * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
9959 * COMPLETE MESSAGE.
9960 *------------------------------------------------------------------*/
9961 tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
9962 }//for
9963 break;
9964 case OS_COMPLETED:
9965 jam();
9966 arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9967 for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9968 jam();
9969 /*-------------------------------------------------------------------
9970 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9971 * IN THIS CASE ALL LQH'S ARE COMPLETED.
9972 *-------------------------------------------------------------------*/
9973 tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
9974 }//for
9975 break;
9976 default:
9977 jam();
9978 sendSystemError(signal, __LINE__);
9979 break;
9980 }//switch
9981 if (tabortInd != ZCOMMIT_SETUP) {
9982 jam();
9983 for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
9984 hostptr.i = tcConnectptr.p->tcNodedata[Ti];
9985 ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9986 if (hostptr.p->hostStatus != HS_ALIVE) {
9987 jam();
9988 /*-----------------------------------------------------------------
9989 * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
9990 *-----------------------------------------------------------------*/
9991 tabortInd = ZTRUE;
9992 }//if
9993 }//for
9994 }//if
9995 tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
9996 tcConnectptr.p->tcOprec = tcConnectptr.i;
9997 tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9998 } while (tcConnectptr.i != RNIL);
9999 apiConnectptr.p->tcBlockref = cownref;
10000 apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
10001 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10002 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10003 apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10004 tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10005 }//Dbtc::setupFailData()
10006
10007 /*----------------------------------------------------------*/
10008 /* UPDATE THE STATE OF THE API CONNECT FOR THIS PART. */
10009 /*----------------------------------------------------------*/
updateApiStateFail(Signal * signal)10010 void Dbtc::updateApiStateFail(Signal* signal)
10011 {
10012 if(LqhTransConf::getMarkerFlag(treqinfo))
10013 {
10014 CommitAckMarkerPtr tmp;
10015 const Uint32 marker = apiConnectptr.p->commitAckMarker;
10016 if (marker == RNIL)
10017 {
10018 jam();
10019
10020 m_commitAckMarkerHash.seize(tmp);
10021 ndbrequire(tmp.i != RNIL);
10022
10023 apiConnectptr.p->commitAckMarker = tmp.i;
10024 tmp.p->transid1 = ttransid1;
10025 tmp.p->transid2 = ttransid2;
10026 tmp.p->apiNodeId = refToNode(tapplRef);
10027 tmp.p->apiConnectPtr = apiConnectptr.i;
10028 tmp.p->m_commit_ack_marker_nodes.clear();
10029 #if defined VM_TRACE || defined ERROR_INSERT
10030 {
10031 CommitAckMarkerPtr check;
10032 ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
10033 }
10034 #endif
10035 m_commitAckMarkerHash.add(tmp);
10036 } else {
10037 jam();
10038 tmp.i = marker;
10039 tmp.p = m_commitAckMarkerHash.getPtr(marker);
10040
10041 ndbassert(tmp.p->transid1 == ttransid1);
10042 ndbassert(tmp.p->transid2 == ttransid2);
10043 }
10044 tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
10045 }
10046
10047 switch (ttransStatus) {
10048 case LqhTransConf::Committed:
10049 jam();
10050 switch (apiConnectptr.p->apiConnectstate) {
10051 case CS_FAIL_COMMITTING:
10052 case CS_FAIL_COMMITTED:
10053 jam();
10054 ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
10055 break;
10056 case CS_FAIL_PREPARED:
10057 jam();
10058 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
10059 apiConnectptr.p->globalcheckpointid = tgci;
10060 break;
10061 case CS_FAIL_COMPLETED:
10062 jam();
10063 apiConnectptr.p->globalcheckpointid = tgci;
10064 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
10065 break;
10066 default:
10067 jam();
10068 systemErrorLab(signal, __LINE__);
10069 break;
10070 }//switch
10071 break;
10072 case LqhTransConf::Prepared:
10073 jam();
10074 switch (apiConnectptr.p->apiConnectstate) {
10075 case CS_FAIL_COMMITTED:
10076 jam();
10077 apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
10078 break;
10079 case CS_FAIL_ABORTED:
10080 jam();
10081 apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
10082 break;
10083 case CS_FAIL_COMMITTING:
10084 case CS_FAIL_PREPARED:
10085 case CS_FAIL_ABORTING:
10086 jam();
10087 /*empty*/;
10088 break;
10089 default:
10090 jam();
10091 systemErrorLab(signal, __LINE__);
10092 break;
10093 }//switch
10094 break;
10095 case LqhTransConf::Aborted:
10096 jam();
10097 switch (apiConnectptr.p->apiConnectstate) {
10098 case CS_FAIL_COMMITTING:
10099 case CS_FAIL_COMMITTED:
10100 jam();
10101 systemErrorLab(signal, __LINE__);
10102 break;
10103 case CS_FAIL_PREPARED:
10104 jam();
10105 apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
10106 break;
10107 case CS_FAIL_ABORTING:
10108 case CS_FAIL_ABORTED:
10109 jam();
10110 /*empty*/;
10111 break;
10112 default:
10113 jam();
10114 systemErrorLab(signal, __LINE__);
10115 break;
10116 }//switch
10117 break;
10118 case LqhTransConf::Marker:
10119 jam();
10120 break;
10121 default:
10122 jam();
10123 systemErrorLab(signal, __LINE__);
10124 break;
10125 }//switch
10126 }//Dbtc::updateApiStateFail()
10127
10128 /*------------------------------------------------------------*/
10129 /* UPDATE_TC_STATE_FAIL */
10130 /* */
10131 /* WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
10132 /* WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY */
10133 /* BETWEEN THE DIFFERENT REPLICAS. */
10134 /*------------------------------------------------------------*/
updateTcStateFail(Signal * signal,Uint32 instanceKey)10135 void Dbtc::updateTcStateFail(Signal* signal, Uint32 instanceKey)
10136 {
10137 const Uint8 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
10138 const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
10139 const Uint8 tdirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
10140
10141 TcConnectRecord * regTcPtr = tcConnectptr.p;
10142
10143 ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
10144 ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
10145 ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
10146 ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
10147
10148 regTcPtr->tcNodedata[treplicaNo] = tnodeid;
10149 regTcPtr->failData[treplicaNo] = ttransStatus;
10150 ndbrequire(regTcPtr->lqhInstanceKey == instanceKey)
10151 }//Dbtc::updateTcStateFail()
10152
execTCGETOPSIZEREQ(Signal * signal)10153 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
10154 {
10155 jamEntry();
10156 CRASH_INSERTION(8000);
10157
10158 UintR Tuserpointer = signal->theData[0]; /* DBDIH POINTER */
10159 BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
10160 signal->theData[0] = Tuserpointer;
10161 signal->theData[1] = coperationsize;
10162 sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
10163 }//Dbtc::execTCGETOPSIZEREQ()
10164
execTC_CLOPSIZEREQ(Signal * signal)10165 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
10166 {
10167 jamEntry();
10168 CRASH_INSERTION(8001);
10169
10170 tuserpointer = signal->theData[0];
10171 tusersblkref = signal->theData[1];
10172 /* DBDIH BLOCK REFERENCE */
10173 coperationsize = 0;
10174 signal->theData[0] = tuserpointer;
10175 sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
10176 }//Dbtc::execTC_CLOPSIZEREQ()
10177
10178 /* ######################################################################### */
10179 /* ####### ERROR MODULE ####### */
10180 /* ######################################################################### */
tabStateErrorLab(Signal * signal)10181 void Dbtc::tabStateErrorLab(Signal* signal)
10182 {
10183 terrorCode = ZSTATE_ERROR;
10184 releaseAtErrorLab(signal);
10185 }//Dbtc::tabStateErrorLab()
10186
wrongSchemaVersionErrorLab(Signal * signal)10187 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
10188 {
10189 const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
10190
10191 TableRecordPtr tabPtr;
10192 tabPtr.i = tcKeyReq->tableId;
10193 const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
10194 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
10195
10196 terrorCode = tabPtr.p->getErrorCode(schemVer);
10197
10198 abortErrorLab(signal);
10199 }//Dbtc::wrongSchemaVersionErrorLab()
10200
noFreeConnectionErrorLab(Signal * signal)10201 void Dbtc::noFreeConnectionErrorLab(Signal* signal)
10202 {
10203 terrorCode = ZNO_FREE_TC_CONNECTION;
10204 abortErrorLab(signal); /* RECORD. OTHERWISE GOTO ERRORHANDLING */
10205 }//Dbtc::noFreeConnectionErrorLab()
10206
aiErrorLab(Signal * signal)10207 void Dbtc::aiErrorLab(Signal* signal)
10208 {
10209 terrorCode = ZLENGTH_ERROR;
10210 abortErrorLab(signal);
10211 }//Dbtc::aiErrorLab()
10212
seizeDatabuferrorLab(Signal * signal)10213 void Dbtc::seizeDatabuferrorLab(Signal* signal)
10214 {
10215 terrorCode = ZGET_DATAREC_ERROR;
10216 releaseAtErrorLab(signal);
10217 }//Dbtc::seizeDatabuferrorLab()
10218
appendToSectionErrorLab(Signal * signal)10219 void Dbtc::appendToSectionErrorLab(Signal* signal)
10220 {
10221 terrorCode = ZGET_DATAREC_ERROR;
10222 releaseAtErrorLab(signal);
10223 }//Dbtc::appendToSectionErrorLab
10224
releaseAtErrorLab(Signal * signal)10225 void Dbtc::releaseAtErrorLab(Signal* signal)
10226 {
10227 ptrGuard(tcConnectptr);
10228 tcConnectptr.p->tcConnectstate = OS_ABORTING;
10229 /*-------------------------------------------------------------------------*
10230 * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
10231 * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
10232 * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
10233 * TO HANDLE THIS PROBLEM.
10234 * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
10235 * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
10236 * ANY SIGNALS.
10237 *-------------------------------------------------------------------------*/
10238 tcConnectptr.p->noOfNodes = 0;
10239 abortErrorLab(signal);
10240 }//Dbtc::releaseAtErrorLab()
10241
warningHandlerLab(Signal * signal,int line)10242 void Dbtc::warningHandlerLab(Signal* signal, int line)
10243 {
10244 ndbassert(false);
10245 }//Dbtc::warningHandlerLab()
10246
systemErrorLab(Signal * signal,int line)10247 void Dbtc::systemErrorLab(Signal* signal, int line)
10248 {
10249 progError(line, NDBD_EXIT_NDBREQUIRE);
10250 }//Dbtc::systemErrorLab()
10251
10252
10253 #ifdef ERROR_INSERT
testFragmentDrop(Signal * signal)10254 bool Dbtc::testFragmentDrop(Signal* signal)
10255 {
10256 Uint32 fragIdToDrop= ~0;
10257 /* Drop some fragments to test the dropped fragment handling code */
10258 if (ERROR_INSERTED(8074))
10259 fragIdToDrop= 1;
10260 else if (ERROR_INSERTED(8075))
10261 fragIdToDrop= 2;
10262 else if (ERROR_INSERTED(8076))
10263 fragIdToDrop= 3;
10264
10265 if ((signal->header.m_fragmentInfo == fragIdToDrop) ||
10266 ERROR_INSERTED(8077)) // Drop all fragments
10267 {
10268 /* This signal fragment should be dropped
10269 * Let's throw away the sections, and call the
10270 * signal dropped report handler
10271 * This code is replicating the effect of the code in
10272 * TransporterCallback::deliver_signal()
10273 */
10274 SectionHandle handle(this, signal);
10275 Uint32 secCount= handle.m_cnt;
10276 releaseSections(handle);
10277 SignalDroppedRep* rep = (SignalDroppedRep*)signal->theData;
10278 Uint32 gsn = signal->header.theVerId_signalNumber;
10279 Uint32 len = signal->header.theLength;
10280 Uint32 newLen= (len > 22 ? 22 : len);
10281 memmove(rep->originalData, signal->theData, (4 * newLen));
10282 rep->originalGsn = gsn;
10283 rep->originalLength = len;
10284 rep->originalSectionCount = secCount;
10285 signal->header.theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
10286 signal->header.theLength = newLen + 3;
10287 signal->header.m_noOfSections = 0;
10288
10289 executeFunction(GSN_SIGNAL_DROPPED_REP, signal);
10290 return true;
10291 }
10292 return false;
10293 }
10294 #endif
10295
10296 /* ######################################################################### *
10297 * ####### SCAN MODULE ####### *
10298 * ######################################################################### *
10299
10300 The application orders a scan of a table. We divide the scan into a scan on
10301 each fragment. The scan uses the primary replicas since the scan might be
10302 used for an update in a separate transaction.
10303
10304 Scans are always done as a separate transaction. Locks from the scan
10305 can be overtaken by another transaction. Scans can never lock the entire
10306 table. Locks are released immediately after the read has been verified
10307 by the application. There is not even an option to leave the locks.
10308 The reason is that this would hurt real-time behaviour too much.
10309
10310 -# The first step in handling a scan of a table is to receive all signals
10311 defining the scan. If failures occur during this step we release all
10312 resource and reply with SCAN_TABREF providing the error code.
10313 If system load is too high, the request will not be allowed.
10314
10315 -# The second step retrieves the number of fragments that exist in the
10316 table. It also ensures that the table actually exist. After this,
10317 the scan is ready to be parallelised. The idea is that the receiving
10318 process (hereafter called delivery process) will start up a number
10319 of scan processes. Each of these scan processes will
10320 independently scan one fragment at a time. The delivery
10321 process object is the scan record and the scan process object is
10322 the scan fragment record plus the scan operation record.
10323
10324 -# The third step is thus performed in parallel. In the third step each
10325 scan process retrieves the primary replica of the fragment it will
10326 scan. Then it starts the scan as soon as the load on that node permits.
10327
10328 The LQH returns either when it retrieved the maximum number of tuples or
10329 when it has retrived at least one tuple and is hindered by a lock to
10330 retrieve the next tuple. This is to ensure that a scan process never
10331 can be involved in a deadlock situation.
10332
10333 Tuples from each fragment scan are sent directly to API from TUP, and tuples
10334 from different fragments are delivered in parallel (so will be interleaved
10335 when received).
10336
10337 When a batch of tuples from one fragment has been fully fetched, the scan of
10338 that fragment will not continue until the previous batch has been
10339 acknowledged by API with a SCAN_NEXTREQ signal.
10340
10341
10342 ERROR HANDLING
10343
10344 As already mentioned it is rather easy to handle errors before the scan
10345 processes have started. In this case it is enough to release the resources
10346 and send SCAN_TAB_REF.
10347
10348 If an error occurs in any of the scan processes then we have to stop all
10349 scan processes. We do however only stop the delivery process and ask
10350 the api to order us to close the scan. The reason is that we can easily
10351 enter into difficult timing problems since the application and this
10352 block is out of synch we will thus always start by report the error to
10353 the application and wait for a close request. This error report uses the
10354 SCAN_TABREF signal with a special error code that the api must check for.
10355
10356
10357 CLOSING AN ACTIVE SCAN
10358
10359 The application can close a scan for several reasons before it is completed.
10360 One reason was mentioned above where an error in a scan process led to a
10361 request to close the scan. Another reason could simply be that the
10362 application found what it looked for and is thus not interested in the
10363 rest of the scan.
10364
10365 IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
10366
10367 When a close scan request is received, all scan processes are stopped and all
10368 resources belonging to those scan processes are released. Stopping the scan
10369 processes most often includes communication with an LQH where the local scan
10370 is controlled. Finally all resources belonging to the scan is released and
10371 the SCAN_TABCONF is sent with an indication of that the scan is closed.
10372
10373
10374 CLOSING A COMPLETED SCAN
10375
10376 When all scan processes are completed then a report is sent to the
10377 application which indicates that no more tuples can be fetched.
10378 The application will send a close scan and the same action as when
10379 closing an active scan is performed.
10380 In this case it will of course not find any active scan processes.
10381 It will even find all scan processes already released.
10382
10383 The reason for requiring the api to close the scan is the same as above.
10384 It is to avoid any timing problems due to that the api and this block
10385 is out of synch.
10386
10387 * ######################################################################## */
execSCAN_TABREQ(Signal * signal)10388 void Dbtc::execSCAN_TABREQ(Signal* signal)
10389 {
10390 jamEntry();
10391
10392 #ifdef ERROR_INSERT
10393 /* Test fragmented + dropped signal handling */
10394 if (ERROR_INSERTED(8074) ||
10395 ERROR_INSERTED(8075) ||
10396 ERROR_INSERTED(8076) ||
10397 ERROR_INSERTED(8077))
10398 {
10399 jam();
10400 if (testFragmentDrop(signal)) {
10401 jam();
10402 return;
10403 }
10404 } /* End of test fragmented + dropped signal handling */
10405 #endif
10406
10407 /* Reassemble if the request was fragmented */
10408 if (!assembleFragments(signal)){
10409 jam();
10410 return;
10411 }
10412
10413 const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
10414 const Uint32 ri = scanTabReq->requestInfo;
10415 const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
10416 const Uint32 transid1 = scanTabReq->transId1;
10417 const Uint32 transid2 = scanTabReq->transId2;
10418 const Uint32 tmpXX = scanTabReq->buddyConPtr;
10419 const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
10420 Uint32 currSavePointId = 0;
10421
10422 Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
10423 Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
10424 Uint32 scanParallel = scanConcurrency;
10425 Uint32 errCode;
10426 ScanRecordPtr scanptr;
10427
10428 /* Short SCANTABREQ has 1 section, Long has 2 or 3.
10429 * Section 0 : NDBAPI receiver ids (Mandatory)
10430 * Section 1 : ATTRINFO section (Mandatory for long SCAN_TABREQ
10431 * Section 2 : KEYINFO section (Optional for long SCAN_TABREQ
10432 */
10433 Uint32 numSections= signal->getNoOfSections();
10434 ndbassert( numSections >= 1 );
10435 bool isLongReq= numSections >= 2;
10436
10437 SectionHandle handle(this, signal);
10438 SegmentedSectionPtr api_op_ptr;
10439 handle.getSection(api_op_ptr, 0);
10440 copy(&cdata[0], api_op_ptr);
10441
10442 Uint32 aiLength= 0;
10443 Uint32 keyLen= 0;
10444
10445 if (likely(isLongReq))
10446 {
10447 SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
10448 /* Long SCANTABREQ, determine Ai and Key length from sections */
10449 handle.getSection(attrInfoPtr, ScanTabReq::AttrInfoSectionNum);
10450 aiLength= attrInfoPtr.sz;
10451 if (numSections == 3)
10452 {
10453 handle.getSection(keyInfoPtr, ScanTabReq::KeyInfoSectionNum);
10454 keyLen= keyInfoPtr.sz;
10455 }
10456 }
10457 else
10458 {
10459 /* Short SCANTABREQ, get Ai and Key length from signal */
10460 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
10461 keyLen = scanTabReq->attrLenKeyLen >> 16;
10462 }
10463
10464
10465 apiConnectptr.i = scanTabReq->apiConnectPtr;
10466 tabptr.i = scanTabReq->tableId;
10467
10468 if (apiConnectptr.i >= capiConnectFilesize)
10469 {
10470 jam();
10471 releaseSections(handle);
10472 warningHandlerLab(signal, __LINE__);
10473 return;
10474 }//if
10475
10476 ptrAss(apiConnectptr, apiConnectRecord);
10477 ApiConnectRecord * transP = apiConnectptr.p;
10478
10479 if (transP->apiConnectstate != CS_CONNECTED) {
10480 jam();
10481 // could be left over from TCKEYREQ rollback
10482 if (transP->apiConnectstate == CS_ABORTING &&
10483 transP->abortState == AS_IDLE) {
10484 jam();
10485 } else if(transP->apiConnectstate == CS_STARTED &&
10486 transP->firstTcConnect == RNIL){
10487 jam();
10488 // left over from simple/dirty read
10489 } else {
10490 jam();
10491 jamLine(transP->apiConnectstate);
10492 errCode = ZSTATE_ERROR;
10493 goto SCAN_TAB_error_no_state_change;
10494 }
10495 }
10496
10497 if(tabptr.i >= ctabrecFilesize)
10498 {
10499 errCode = ZUNKNOWN_TABLE_ERROR;
10500 goto SCAN_TAB_error;
10501 }
10502
10503 ptrAss(tabptr, tableRecord);
10504 if ((aiLength == 0) ||
10505 (!tabptr.p->checkTable(schemaVersion)) ||
10506 (scanConcurrency == 0) ||
10507 (cfirstfreeTcConnect == RNIL) ||
10508 (cfirstfreeScanrec == RNIL)) {
10509 goto SCAN_error_check;
10510 }
10511 if (buddyPtr != RNIL) {
10512 jam();
10513 ApiConnectRecordPtr buddyApiPtr;
10514 buddyApiPtr.i = buddyPtr;
10515 ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
10516 if ((transid1 == buddyApiPtr.p->transid[0]) &&
10517 (transid2 == buddyApiPtr.p->transid[1])) {
10518 jam();
10519
10520 if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
10521 // transaction has been aborted
10522 jam();
10523 errCode = buddyApiPtr.p->returncode;
10524 goto SCAN_TAB_error;
10525 }//if
10526 currSavePointId = buddyApiPtr.p->currSavePointId;
10527 buddyApiPtr.p->currSavePointId++;
10528 }
10529 }
10530
10531 if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
10532 getNodeState().getSingleUserApi() !=
10533 refToNode(apiConnectptr.p->ndbapiBlockref))
10534 {
10535 errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
10536 goto SCAN_TAB_error;
10537 }
10538
10539 seizeTcConnect(signal);
10540 tcConnectptr.p->apiConnect = apiConnectptr.i;
10541 tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
10542 apiConnectptr.p->lastTcConnect = tcConnectptr.i;
10543
10544 seizeCacheRecord(signal);
10545
10546 if (likely(isLongReq))
10547 {
10548 /* We keep the AttrInfo and KeyInfo sections */
10549 cachePtr.p->attrInfoSectionI= handle.m_ptr[ScanTabReq::AttrInfoSectionNum].i;
10550 if (keyLen)
10551 cachePtr.p->keyInfoSectionI= handle.m_ptr[ScanTabReq::KeyInfoSectionNum].i;
10552 }
10553
10554 releaseSection(handle.m_ptr[ScanTabReq::ReceiverIdSectionNum].i);
10555 handle.clear();
10556
10557 cachePtr.p->keylen = keyLen;
10558 cachePtr.p->save1 = 0;
10559 cachePtr.p->distributionKey = scanTabReq->distributionKey;
10560 cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
10561 scanptr = seizeScanrec(signal);
10562
10563 ndbrequire(transP->apiScanRec == RNIL);
10564 ndbrequire(scanptr.p->scanApiRec == RNIL);
10565
10566 errCode = initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag, aiLength, keyLen);
10567 if (unlikely(errCode))
10568 {
10569 jam();
10570 goto SCAN_TAB_error;
10571 }
10572
10573 transP->apiScanRec = scanptr.i;
10574 transP->returncode = 0;
10575 transP->transid[0] = transid1;
10576 transP->transid[1] = transid2;
10577 transP->buddyPtr = buddyPtr;
10578
10579 // The scan is started
10580 transP->apiConnectstate = CS_START_SCAN;
10581 transP->currSavePointId = currSavePointId;
10582
10583 /**********************************************************
10584 * We start the timer on scanRec to be able to discover a
10585 * timeout in the API the API now is in charge!
10586 ***********************************************************/
10587 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10588 updateBuddyTimer(apiConnectptr);
10589
10590 /***********************************************************
10591 * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
10592 * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
10593 * IF ANY TO RECEIVE.
10594 **********************************************************/
10595 scanptr.p->scanState = ScanRecord::WAIT_AI;
10596
10597 if (ERROR_INSERTED(8038))
10598 {
10599 /**
10600 * Force API_FAILREQ
10601 */
10602 DisconnectRep * const rep = (DisconnectRep *)signal->getDataPtrSend();
10603 rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
10604 rep->err = 8038;
10605
10606 sendSignal(CMVMI_REF, GSN_DISCONNECT_REP, signal, 2, JBA);
10607 CLEAR_ERROR_INSERT_VALUE;
10608 }
10609
10610 if (isLongReq)
10611 {
10612 /* All AttrInfo (and KeyInfo) has been received, continue
10613 * processing
10614 */
10615 diFcountReqLab(signal, scanptr);
10616 }
10617
10618 return;
10619
10620 SCAN_error_check:
10621 if (aiLength == 0) {
10622 jam();
10623 errCode = ZSCAN_AI_LEN_ERROR;
10624 goto SCAN_TAB_error;
10625 }//if
10626 if (!tabptr.p->checkTable(schemaVersion)){
10627 jam();
10628 errCode = tabptr.p->getErrorCode(schemaVersion);
10629 goto SCAN_TAB_error;
10630 }//if
10631 if (scanConcurrency == 0) {
10632 jam();
10633 errCode = ZNO_CONCURRENCY_ERROR;
10634 goto SCAN_TAB_error;
10635 }//if
10636 if (cfirstfreeTcConnect == RNIL) {
10637 jam();
10638 errCode = ZNO_FREE_TC_CONNECTION;
10639 goto SCAN_TAB_error;
10640 }//if
10641 ndbrequire(cfirstfreeScanrec == RNIL);
10642 jam();
10643 errCode = ZNO_SCANREC_ERROR;
10644 goto SCAN_TAB_error;
10645
10646 SCAN_TAB_error:
10647 jam();
10648 /**
10649 * Prepare for up coming ATTRINFO/KEYINFO
10650 */
10651 transP->apiConnectstate = CS_ABORTING;
10652 transP->abortState = AS_IDLE;
10653 transP->transid[0] = transid1;
10654 transP->transid[1] = transid2;
10655
10656 SCAN_TAB_error_no_state_change:
10657
10658 releaseSections(handle);
10659
10660 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
10661 ref->apiConnectPtr = transP->ndbapiConnect;
10662 ref->transId1 = transid1;
10663 ref->transId2 = transid2;
10664 ref->errorCode = errCode;
10665 ref->closeNeeded = 0;
10666 sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
10667 signal, ScanTabRef::SignalLength, JBB);
10668 return;
10669 }//Dbtc::execSCAN_TABREQ()
10670
10671 Uint32
initScanrec(ScanRecordPtr scanptr,const ScanTabReq * scanTabReq,UintR scanParallel,UintR noOprecPerFrag,Uint32 aiLength,Uint32 keyLength)10672 Dbtc::initScanrec(ScanRecordPtr scanptr,
10673 const ScanTabReq * scanTabReq,
10674 UintR scanParallel,
10675 UintR noOprecPerFrag,
10676 Uint32 aiLength,
10677 Uint32 keyLength)
10678 {
10679 const UintR ri = scanTabReq->requestInfo;
10680 scanptr.p->scanTcrec = tcConnectptr.i;
10681 scanptr.p->scanApiRec = apiConnectptr.i;
10682 scanptr.p->scanAiLength = aiLength;
10683 scanptr.p->scanKeyLen = keyLength;
10684 scanptr.p->scanTableref = tabptr.i;
10685 scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
10686 scanptr.p->scanParallel = scanParallel;
10687 scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
10688 scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
10689 scanptr.p->batch_size_rows = noOprecPerFrag;
10690 scanptr.p->m_scan_block_no = DBLQH;
10691
10692 Uint32 tmp = 0;
10693 ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
10694 ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
10695 ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
10696 ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
10697 ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
10698 ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
10699 ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
10700 ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
10701 if (ScanTabReq::getViaSPJFlag(ri))
10702 {
10703 jam();
10704 scanptr.p->m_scan_block_no = DBSPJ;
10705 }
10706
10707 scanptr.p->scanRequestInfo = tmp;
10708 scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
10709 scanptr.p->scanState = ScanRecord::RUNNING;
10710 scanptr.p->m_queued_count = 0;
10711 scanptr.p->m_scan_cookie = RNIL;
10712 scanptr.p->m_close_scan_req = false;
10713 scanptr.p->m_pass_all_confs = ScanTabReq::getPassAllConfsFlag(ri);
10714 scanptr.p->m_4word_conf = ScanTabReq::get4WordConf(ri);
10715
10716 ScanFragList list(c_scan_frag_pool,
10717 scanptr.p->m_running_scan_frags);
10718 for (Uint32 i = 0; i < scanParallel; i++) {
10719 jam();
10720 ScanFragRecPtr ptr;
10721 if (unlikely(list.seize(ptr) == false))
10722 {
10723 jam();
10724 goto errout;
10725 }
10726 ptr.p->scanFragState = ScanFragRec::IDLE;
10727 ptr.p->scanRec = scanptr.i;
10728 ptr.p->scanFragId = 0;
10729 ptr.p->m_apiPtr = cdata[i];
10730 }//for
10731
10732 (* (ScanTabReq::getRangeScanFlag(ri) ?
10733 &c_counters.c_range_scan_count :
10734 &c_counters.c_scan_count))++;
10735 return 0;
10736 errout:
10737 list.release();
10738 return ZSCAN_FRAGREC_ERROR;
10739 }//Dbtc::initScanrec()
10740
scanTabRefLab(Signal * signal,Uint32 errCode)10741 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
10742 {
10743 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
10744 ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
10745 ref->transId1 = apiConnectptr.p->transid[0];
10746 ref->transId2 = apiConnectptr.p->transid[1];
10747 ref->errorCode = errCode;
10748 ref->closeNeeded = 0;
10749 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
10750 signal, ScanTabRef::SignalLength, JBB);
10751 }//Dbtc::scanTabRefLab()
10752
10753 /**
10754 * scanKeyinfoLab
10755 * Handle reception of KeyInfo for a Scan
10756 */
scanKeyinfoLab(Signal * signal)10757 void Dbtc::scanKeyinfoLab(Signal* signal)
10758 {
10759 /* Receive KEYINFO for a SCAN operation
10760 * Note that old NDBAPI nodes sometimes send header-only KEYINFO signals
10761 */
10762 CacheRecord * const regCachePtr = cachePtr.p;
10763 UintR TkeyLen = regCachePtr->keylen;
10764 UintR Tlen = regCachePtr->save1;
10765
10766 Uint32 wordsInSignal= MIN(KeyInfo::DataLength,
10767 (TkeyLen - Tlen));
10768
10769 ndbassert( signal->getLength() ==
10770 (KeyInfo::HeaderLength + wordsInSignal) );
10771
10772 if (unlikely (! appendToSection(regCachePtr->keyInfoSectionI,
10773 &signal->theData[KeyInfo::HeaderLength],
10774 wordsInSignal)))
10775 {
10776 jam();
10777 seizeDatabuferrorLab(signal);
10778 return;
10779 }
10780
10781 Tlen+= wordsInSignal;
10782 regCachePtr->save1 = Tlen;
10783
10784 if (Tlen < TkeyLen)
10785 {
10786 jam();
10787 /* More KeyInfo still to come - continue waiting */
10788 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10789 return;
10790 }
10791
10792 /* All KeyInfo has been received, we will now start receiving
10793 * ATTRINFO
10794 */
10795 jam();
10796 ndbassert(Tlen == TkeyLen);
10797 return;
10798 } // scanKeyinfoLab
10799
10800 /*---------------------------------------------------------------------------*/
10801 /* */
10802 /* RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST. */
10803 /*---------------------------------------------------------------------------*/
scanAttrinfoLab(Signal * signal,UintR Tlen)10804 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
10805 {
10806 ScanRecordPtr scanptr;
10807 scanptr.i = apiConnectptr.p->apiScanRec;
10808 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10809 tcConnectptr.i = scanptr.p->scanTcrec;
10810 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10811 cachePtr.i = apiConnectptr.p->cachePtr;
10812 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10813 CacheRecord * const regCachePtr = cachePtr.p;
10814 ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
10815
10816 regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
10817
10818 if (unlikely(! appendToSection(regCachePtr->attrInfoSectionI,
10819 &signal->theData[AttrInfo::HeaderLength],
10820 Tlen)))
10821 {
10822 jam();
10823 abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
10824 return;
10825 }
10826
10827 if (regCachePtr->currReclenAi == scanptr.p->scanAiLength)
10828 {
10829 /* We have now received all the signals defining this
10830 * scan. We are ready to start executing the scan
10831 */
10832 diFcountReqLab(signal, scanptr);
10833 return;
10834 }
10835 else if (unlikely (regCachePtr->currReclenAi > scanptr.p->scanAiLength))
10836 {
10837 jam();
10838 abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
10839 return;
10840 }
10841
10842 /* Still some ATTRINFO to arrive...*/
10843 return;
10844 }//Dbtc::scanAttrinfoLab()
10845
diFcountReqLab(Signal * signal,ScanRecordPtr scanptr)10846 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
10847 {
10848 /**
10849 * Check so that the table is not being dropped
10850 */
10851 TableRecordPtr tabPtr;
10852 tabPtr.i = scanptr.p->scanTableref;
10853 tabPtr.p = &tableRecord[tabPtr.i];
10854 if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
10855 ;
10856 } else {
10857 abortScanLab(signal, scanptr,
10858 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
10859 true);
10860 return;
10861 }
10862
10863 scanptr.p->scanNextFragId = 0;
10864 scanptr.p->m_booked_fragments_count= 0;
10865 scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
10866
10867 /*************************************************
10868 * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
10869 ***************************************************/
10870 DihScanTabReq * req = (DihScanTabReq*)signal->getDataPtrSend();
10871 req->senderRef = reference();
10872 req->senderData = tcConnectptr.i;
10873 req->tableId = scanptr.p->scanTableref;
10874 req->schemaTransId = 0;
10875 sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_REQ, signal,
10876 DihScanTabReq::SignalLength, JBB);
10877 return;
10878 }//Dbtc::diFcountReqLab()
10879
10880 /********************************************************************
10881 * execDI_FCOUNTCONF
10882 *
10883 * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
10884 * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
10885 * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
10886 * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
10887 * CLOSES THE SCAN.
10888 ********************************************************************/
execDIH_SCAN_TAB_CONF(Signal * signal)10889 void Dbtc::execDIH_SCAN_TAB_CONF(Signal* signal)
10890 {
10891 jamEntry();
10892 DihScanTabConf * conf = (DihScanTabConf*)signal->getDataPtr();
10893 tcConnectptr.i = conf->senderData;
10894 Uint32 tfragCount = conf->fragmentCount;
10895 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10896 apiConnectptr.i = tcConnectptr.p->apiConnect;
10897 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10898 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
10899 ScanRecordPtr scanptr;
10900 scanptr.i = regApiPtr->apiScanRec;
10901 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10902 ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
10903 scanptr.p->m_scan_cookie = conf->scanCookie;
10904
10905 if (conf->reorgFlag)
10906 {
10907 jam();
10908 ScanFragReq::setReorgFlag(scanptr.p->scanRequestInfo, 1);
10909 }
10910 if (regApiPtr->apiFailState == ZTRUE) {
10911 jam();
10912 releaseScanResources(signal, scanptr, true);
10913 handleApiFailState(signal, apiConnectptr.i);
10914 return;
10915 }//if
10916 if (tfragCount == 0) {
10917 jam();
10918 abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
10919 return;
10920 }//if
10921
10922 /**
10923 * Check so that the table is not being dropped
10924 */
10925 TableRecordPtr tabPtr;
10926 tabPtr.i = scanptr.p->scanTableref;
10927 tabPtr.p = &tableRecord[tabPtr.i];
10928 if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
10929 ;
10930 } else {
10931 abortScanLab(signal, scanptr,
10932 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
10933 true);
10934 return;
10935 }
10936
10937 cachePtr.i = regApiPtr->cachePtr;
10938 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10939 CacheRecord * regCachePtrP = cachePtr.p;
10940
10941 Uint32 version = getNodeInfo(refToNode(regApiPtr->ndbapiBlockref)).m_version;
10942 if (unlikely(!ndb_scan_distributionkey(version)))
10943 {
10944 jam();
10945 regCachePtrP->distributionKeyIndicator = 0;
10946 }
10947 if (regCachePtrP->distributionKeyIndicator)
10948 {
10949 jam();
10950 ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType) ||
10951 tabPtr.p->get_user_defined_partitioning());
10952
10953 DiGetNodesReq * req = (DiGetNodesReq *)&signal->theData[0];
10954 const DiGetNodesConf * get_conf = (DiGetNodesConf *)&signal->theData[0];
10955 req->tableId = tabPtr.i;
10956 req->hashValue = cachePtr.p->distributionKey;
10957 req->distr_key_indicator = tabPtr.p->get_user_defined_partitioning();
10958 * (EmulatedJamBuffer**)req->jamBuffer = jamBuffer();
10959 EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
10960 DiGetNodesReq::SignalLength, 0);
10961 UintR TerrorIndicator = signal->theData[0];
10962 jamEntry();
10963 if (TerrorIndicator != 0)
10964 {
10965 jam();
10966 abortScanLab(signal, scanptr,
10967 signal->theData[1],
10968 true);
10969 return;
10970 }
10971
10972 scanptr.p->scanNextFragId = get_conf->fragId;
10973 tfragCount = 1;
10974 }
10975
10976 scanptr.p->scanParallel = tfragCount;
10977 scanptr.p->scanNoFrag = tfragCount;
10978 scanptr.p->scanState = ScanRecord::RUNNING;
10979
10980 setApiConTimer(apiConnectptr.i, 0, __LINE__);
10981 updateBuddyTimer(apiConnectptr);
10982
10983 ScanFragRecPtr ptr;
10984 ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
10985 for (list.first(ptr); !ptr.isNull() && tfragCount;
10986 list.next(ptr), tfragCount--){
10987 jam();
10988
10989 ptr.p->lqhBlockref = 0;
10990 ptr.p->startFragTimer(ctcTimer);
10991 ptr.p->scanFragId = scanptr.p->scanNextFragId++;
10992 ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
10993 ptr.p->startFragTimer(ctcTimer);
10994
10995
10996 DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
10997 req->senderRef = reference();
10998 req->senderData = ptr.i;
10999 req->tableId = scanptr.p->scanTableref;
11000 req->fragId = ptr.p->scanFragId;
11001 req->scanCookie = scanptr.p->m_scan_cookie;
11002 sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11003 DihScanGetNodesReq::SignalLength, JBB);
11004 }//for
11005
11006 ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
11007 for (; !ptr.isNull();)
11008 {
11009 ptr.p->m_ops = 0;
11010 ptr.p->m_totalLen = 0;
11011 ptr.p->m_scan_frag_conf_status = 1;
11012 ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
11013 ptr.p->stopFragTimer();
11014
11015 ScanFragRecPtr tmp;
11016 tmp.i = ptr.i;
11017 tmp.p = ptr.p;
11018 list.next(ptr);
11019 list.remove(tmp);
11020 queued.add(tmp);
11021 scanptr.p->m_queued_count++;
11022 }
11023 }//Dbtc::execDI_FCOUNTCONF()
11024
11025 /******************************************************
11026 * execDI_FCOUNTREF
11027 ******************************************************/
execDIH_SCAN_TAB_REF(Signal * signal)11028 void Dbtc::execDIH_SCAN_TAB_REF(Signal* signal)
11029 {
11030 jamEntry();
11031 DihScanTabRef * ref = (DihScanTabRef*)signal->getDataPtr();
11032 tcConnectptr.i = ref->senderData;
11033 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11034 const Uint32 errCode = ref->error;
11035 apiConnectptr.i = tcConnectptr.p->apiConnect;
11036 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11037 ScanRecordPtr scanptr;
11038 scanptr.i = apiConnectptr.p->apiScanRec;
11039 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11040 ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
11041 if (apiConnectptr.p->apiFailState == ZTRUE) {
11042 jam();
11043 releaseScanResources(signal, scanptr, true);
11044 handleApiFailState(signal, apiConnectptr.i);
11045 return;
11046 }//if
11047 abortScanLab(signal, scanptr, errCode, true);
11048 }//Dbtc::execDI_FCOUNTREF()
11049
abortScanLab(Signal * signal,ScanRecordPtr scanptr,Uint32 errCode,bool not_started)11050 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
11051 bool not_started)
11052 {
11053 scanTabRefLab(signal, errCode);
11054 releaseScanResources(signal, scanptr, not_started);
11055 }//Dbtc::abortScanLab()
11056
releaseScanResources(Signal * signal,ScanRecordPtr scanPtr,bool not_started)11057 void Dbtc::releaseScanResources(Signal* signal,
11058 ScanRecordPtr scanPtr,
11059 bool not_started)
11060 {
11061 if (apiConnectptr.p->cachePtr != RNIL) {
11062 cachePtr.i = apiConnectptr.p->cachePtr;
11063 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11064 releaseKeys();
11065 releaseAttrinfo();
11066 }//if
11067 tcConnectptr.i = scanPtr.p->scanTcrec;
11068 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11069 releaseTcCon();
11070
11071 if (not_started)
11072 {
11073 jam();
11074 ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
11075 ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
11076 run.release();
11077 queue.release();
11078 }
11079
11080 ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
11081 ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
11082 ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
11083
11084 ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
11085 ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
11086
11087 DihScanTabCompleteRep* rep = (DihScanTabCompleteRep*)signal->getDataPtrSend();
11088 rep->tableId = scanPtr.p->scanTableref;
11089 rep->scanCookie = scanPtr.p->m_scan_cookie;
11090 sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_COMPLETE_REP,
11091 signal, DihScanTabCompleteRep::SignalLength, JBB);
11092
11093 // link into free list
11094 scanPtr.p->nextScan = cfirstfreeScanrec;
11095 scanPtr.p->scanState = ScanRecord::IDLE;
11096 scanPtr.p->scanTcrec = RNIL;
11097 scanPtr.p->scanApiRec = RNIL;
11098 cfirstfreeScanrec = scanPtr.i;
11099
11100 apiConnectptr.p->apiScanRec = RNIL;
11101 apiConnectptr.p->apiConnectstate = CS_CONNECTED;
11102 setApiConTimer(apiConnectptr.i, 0, __LINE__);
11103 }//Dbtc::releaseScanResources()
11104
11105
11106 /****************************************************************
11107 * execDIGETPRIMCONF
11108 *
11109 * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT.
11110 * WE ARE NOW READY TO ASK FOR PERMISSION TO LOAD THIS
11111 * SPECIFIC NODE WITH A SCAN OPERATION.
11112 ****************************************************************/
execDIH_SCAN_GET_NODES_CONF(Signal * signal)11113 void Dbtc::execDIH_SCAN_GET_NODES_CONF(Signal* signal)
11114 {
11115 jamEntry();
11116 DihScanGetNodesConf * conf = (DihScanGetNodesConf*)signal->getDataPtr();
11117 scanFragptr.i = conf->senderData;
11118 c_scan_frag_pool.getPtr(scanFragptr);
11119
11120 tnodeid = conf->nodes[0];
11121 arrGuard(tnodeid, MAX_NDB_NODES);
11122
11123 if(ERROR_INSERTED(8050) && tnodeid != getOwnNodeId())
11124 {
11125 /* Asked to scan a fragment which is not on the same node as the
11126 * TC - transaction hinting / scan partition pruning has failed
11127 * Used by testPartitioning.cpp
11128 */
11129 CRASH_INSERTION(8050);
11130 }
11131
11132 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
11133 scanFragptr.p->stopFragTimer();
11134
11135 ScanRecordPtr scanptr;
11136 scanptr.i = scanFragptr.p->scanRec;
11137 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11138
11139 /**
11140 * This must be false as select count(*) otherwise
11141 * can "pass" committing on backup fragments and
11142 * get incorrect row count
11143 */
11144 if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
11145 {
11146 jam();
11147 Uint32 nodeid = getOwnNodeId();
11148 for(Uint32 i = 1; i<conf->count; i++)
11149 {
11150 if(conf->nodes[i] == nodeid)
11151 {
11152 jam();
11153 tnodeid = nodeid;
11154 break;
11155 }
11156 }
11157 }
11158
11159 {
11160 /**
11161 * Check table
11162 */
11163 TableRecordPtr tabPtr;
11164 tabPtr.i = scanptr.p->scanTableref;
11165 ptrAss(tabPtr, tableRecord);
11166 Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
11167 if (ERROR_INSERTED(8081) || tabPtr.p->checkTable(schemaVersion) == false)
11168 {
11169 jam();
11170 Uint32 err;
11171 if (ERROR_INSERTED(8081))
11172 {
11173 err = ZTIME_OUT_ERROR;
11174 CLEAR_ERROR_INSERT_VALUE;
11175 }
11176 else
11177 {
11178 err = tabPtr.p->getErrorCode(schemaVersion);
11179 }
11180 {
11181 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11182 run.release(scanFragptr);
11183 }
11184 scanError(signal, scanptr, err);
11185 return;
11186 }
11187 }
11188
11189 tcConnectptr.i = scanptr.p->scanTcrec;
11190 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11191 apiConnectptr.i = scanptr.p->scanApiRec;
11192 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11193 cachePtr.i = apiConnectptr.p->cachePtr;
11194 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11195 switch (scanptr.p->scanState) {
11196 case ScanRecord::CLOSING_SCAN:
11197 jam();
11198 updateBuddyTimer(apiConnectptr);
11199 {
11200 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11201 run.release(scanFragptr);
11202 }
11203 close_scan_req_send_conf(signal, scanptr);
11204 return;
11205 default:
11206 jam();
11207 /*empty*/;
11208 break;
11209 }//switch
11210
11211 /* Send SCANFRAGREQ to LQH block
11212 * SCANFRAGREQ with optional KEYINFO and mandatory ATTRINFO are
11213 * now sent to LQH
11214 * This starts the scan on the given fragment.
11215 * If this is the last SCANFRAGREQ, sendScanFragReq will release
11216 * the KeyInfo and AttrInfo sections when sending.
11217 */
11218 Uint32 instanceKey = conf->instanceKey;
11219 scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
11220 instanceKey, tnodeid);
11221 if (scanptr.p->m_scan_block_no == DBSPJ)
11222 {
11223 // only 1 instance
11224 scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
11225 tnodeid);
11226 }
11227 scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
11228
11229 /* Determine whether this is the last scanFragReq
11230 * Handle normal scan-all-fragments and partition pruned
11231 * scan-one-fragment cases.
11232 *
11233 * (Note that this assumes that fragments are processed in order,
11234 * and that DIH_SCAN_GET_NODES_CONF signals are received in the
11235 * order that the DIH_SCAN_GET_NODES_REQs were sent)
11236 */
11237 bool isLastScanFragReq= ((scanptr.p->scanNextFragId >=
11238 scanptr.p->scanNoFrag) &&
11239 (scanFragptr.p->scanFragId ==
11240 (scanptr.p->scanNextFragId - 1)));
11241
11242 sendScanFragReq(signal, scanptr.p, scanFragptr.p, isLastScanFragReq);
11243
11244 scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11245 scanFragptr.p->startFragTimer(ctcTimer);
11246 updateBuddyTimer(apiConnectptr);
11247 /*********************************************
11248 * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
11249 * WAIT FOR THE FIRST SCANNED RECORDS
11250 *********************************************/
11251 }//Dbtc::execDIGETPRIMCONF
11252
11253 /***************************************************
11254 * execDIGETPRIMREF
11255 *
11256 * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
11257 * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
11258 * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
11259 ***************************************************/
execDIH_SCAN_GET_NODES_REF(Signal * signal)11260 void Dbtc::execDIH_SCAN_GET_NODES_REF(Signal* signal)
11261 {
11262 jamEntry();
11263 // tcConnectptr.i in theData[0] is not used.
11264 scanFragptr.i = signal->theData[1];
11265 const Uint32 errCode = signal->theData[2];
11266 c_scan_frag_pool.getPtr(scanFragptr);
11267 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
11268
11269 ScanRecordPtr scanptr;
11270 scanptr.i = scanFragptr.p->scanRec;
11271 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11272
11273 {
11274 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11275 run.release(scanFragptr);
11276 }
11277
11278 scanError(signal, scanptr, errCode);
11279 }//Dbtc::execDIGETPRIMREF()
11280
11281 /**
11282 * Dbtc::execSCAN_FRAGREF
11283 * Our attempt to scan a fragment was refused
11284 * set error code and close all other fragment
11285 * scan's belonging to this scan
11286 */
execSCAN_FRAGREF(Signal * signal)11287 void Dbtc::execSCAN_FRAGREF(Signal* signal)
11288 {
11289 const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
11290
11291 jamEntry();
11292 const Uint32 errCode = ref->errorCode;
11293
11294 scanFragptr.i = ref->senderData;
11295 c_scan_frag_pool.getPtr(scanFragptr);
11296
11297 ScanRecordPtr scanptr;
11298 scanptr.i = scanFragptr.p->scanRec;
11299 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11300
11301 apiConnectptr.i = scanptr.p->scanApiRec;
11302 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11303
11304 Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
11305 Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
11306 transid1 = transid1 | transid2;
11307 if (transid1 != 0) {
11308 jam();
11309 systemErrorLab(signal, __LINE__);
11310 }//if
11311
11312 /**
11313 * Set errorcode, close connection to this lqh fragment,
11314 * stop fragment timer and call scanFragError to start
11315 * close of the other fragment scans
11316 */
11317 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
11318 scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
11319 scanFragptr.p->stopFragTimer();
11320 {
11321 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11322 run.release(scanFragptr);
11323 }
11324 scanError(signal, scanptr, errCode);
11325 }//Dbtc::execSCAN_FRAGREF()
11326
11327 /**
11328 * Dbtc::scanError
11329 *
11330 * Called when an error occurs during
11331 */
scanError(Signal * signal,ScanRecordPtr scanptr,Uint32 errorCode)11332 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
11333 {
11334 jam();
11335 ScanRecord* scanP = scanptr.p;
11336
11337 DEBUG("scanError, errorCode = "<< errorCode <<
11338 ", scanState = " << scanptr.p->scanState);
11339
11340 apiConnectptr.i = scanP->scanApiRec;
11341 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11342 ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
11343
11344 if(scanP->scanState == ScanRecord::CLOSING_SCAN){
11345 jam();
11346 close_scan_req_send_conf(signal, scanptr);
11347 return;
11348 }
11349
11350 ndbrequire(scanP->scanState == ScanRecord::RUNNING);
11351
11352 /**
11353 * Close scan wo/ having received an order to do so
11354 */
11355 close_scan_req(signal, scanptr, false);
11356
11357 const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
11358 if(apiFail){
11359 jam();
11360 return;
11361 }
11362
11363 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11364 ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11365 ref->transId1 = apiConnectptr.p->transid[0];
11366 ref->transId2 = apiConnectptr.p->transid[1];
11367 ref->errorCode = errorCode;
11368 ref->closeNeeded = 1;
11369 sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
11370 signal, ScanTabRef::SignalLength, JBB);
11371 }//Dbtc::scanError()
11372
11373 /************************************************************
11374 * execSCAN_FRAGCONF
11375 *
11376 * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
11377 * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
11378 ************************************************************/
execSCAN_FRAGCONF(Signal * signal)11379 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
11380 {
11381 Uint32 transid1, transid2, total_len;
11382 jamEntry();
11383
11384 const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
11385 const Uint32 noCompletedOps = conf->completedOps;
11386 const Uint32 status = conf->fragmentCompleted;
11387
11388 scanFragptr.i = conf->senderData;
11389 c_scan_frag_pool.getPtr(scanFragptr);
11390
11391 ScanRecordPtr scanptr;
11392 scanptr.i = scanFragptr.p->scanRec;
11393 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11394
11395 apiConnectptr.i = scanptr.p->scanApiRec;
11396 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11397
11398 transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
11399 transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
11400 total_len= conf->total_len;
11401 transid1 = transid1 | transid2;
11402 if (transid1 != 0) {
11403 jam();
11404 systemErrorLab(signal, __LINE__);
11405 }//if
11406
11407 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
11408
11409 if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
11410 jam();
11411 if(status == 0){
11412 /**
11413 * We have started closing = we sent a close -> ignore this
11414 */
11415 return;
11416 } else {
11417 jam();
11418 scanFragptr.p->stopFragTimer();
11419 scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
11420 {
11421 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11422 run.release(scanFragptr);
11423 }
11424 }
11425 close_scan_req_send_conf(signal, scanptr);
11426 return;
11427 }
11428
11429 if(noCompletedOps == 0 && status != 0 &&
11430 !scanptr.p->m_pass_all_confs &&
11431 scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
11432 /**
11433 * Start on next fragment. Don't do this if we scan via the SPJ block. In
11434 * that case, dropping the last SCAN_TABCONF message for a fragment would
11435 * mean dropping the 'nodeMask' (which is sent in ScanFragConf::total_len).
11436 * This would confuse the API with respect to which pushed operations that
11437 * would get new tuples in the next batch. If we use SPJ, we must thus
11438 * send SCAN_TABCONF and let the API ask for the next batch.
11439 */
11440 scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
11441 scanFragptr.p->startFragTimer(ctcTimer);
11442
11443 tcConnectptr.i = scanptr.p->scanTcrec;
11444 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11445 scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
11446 DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
11447 req->senderRef = reference();
11448 req->senderData = scanFragptr.i;
11449 req->tableId = scanptr.p->scanTableref;
11450 req->fragId = scanFragptr.p->scanFragId;
11451 req->scanCookie = scanptr.p->m_scan_cookie;
11452 sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11453 DihScanGetNodesReq::SignalLength, JBB);
11454 return;
11455 }
11456 /*
11457 Uint32 totalLen = 0;
11458 for(Uint32 i = 0; i<noCompletedOps; i++){
11459 Uint32 tmp = conf->opReturnDataLen[i];
11460 totalLen += tmp;
11461 }
11462 */
11463 {
11464 ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11465 ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
11466
11467 run.remove(scanFragptr);
11468 queued.add(scanFragptr);
11469 scanptr.p->m_queued_count++;
11470 }
11471
11472 if (status != 0 &&
11473 scanptr.p->m_pass_all_confs &&
11474 scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count
11475 < scanptr.p->scanNoFrag){
11476 /**
11477 * nodeMask(=total_len) should be zero since there will be no more
11478 * rows from this fragment.
11479 */
11480 ndbrequire(total_len==0);
11481 /**
11482 * Now set it to one to tell the API that there may be more rows from
11483 * the next fragment.
11484 */
11485 total_len = 1;
11486 }
11487
11488 scanFragptr.p->m_scan_frag_conf_status = status;
11489 scanFragptr.p->m_ops = noCompletedOps;
11490 scanFragptr.p->m_totalLen = total_len;
11491 scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
11492 scanFragptr.p->stopFragTimer();
11493
11494 if(scanptr.p->m_queued_count > /** Min */ 0){
11495 jam();
11496 sendScanTabConf(signal, scanptr);
11497 }
11498 }//Dbtc::execSCAN_FRAGCONF()
11499
11500 /****************************************************************************
11501 * execSCAN_NEXTREQ
11502 *
11503 * THE APPLICATION HAS PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
11504 * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
11505 ****************************************************************************/
execSCAN_NEXTREQ(Signal * signal)11506 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
11507 {
11508 const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
11509 const UintR transid1 = req->transId1;
11510 const UintR transid2 = req->transId2;
11511 const UintR stopScan = req->stopScan;
11512
11513 jamEntry();
11514
11515 SectionHandle handle(this, signal);
11516 apiConnectptr.i = req->apiConnectPtr;
11517 if (apiConnectptr.i >= capiConnectFilesize) {
11518 jam();
11519 releaseSections(handle);
11520 warningHandlerLab(signal, __LINE__);
11521 return;
11522 }//if
11523 ptrAss(apiConnectptr, apiConnectRecord);
11524
11525 /**
11526 * Check transid
11527 */
11528 const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
11529 const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
11530 if ((ctransid1 | ctransid2) != 0){
11531 releaseSections(handle);
11532 ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11533 ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11534 ref->transId1 = transid1;
11535 ref->transId2 = transid2;
11536 ref->errorCode = ZSTATE_ERROR;
11537 ref->closeNeeded = 0;
11538 sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
11539 signal, ScanTabRef::SignalLength, JBB);
11540 DEBUG("Wrong transid");
11541 return;
11542 }
11543
11544 /**
11545 * Check state of API connection
11546 */
11547 if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
11548 jam();
11549 releaseSections(handle);
11550 if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
11551 jam();
11552 /*********************************************************************
11553 * The application sends a SCAN_NEXTREQ after experiencing a time-out.
11554 * We will send a SCAN_TABREF to indicate a time-out occurred.
11555 *********************************************************************/
11556 DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
11557 ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
11558 ndbrequire(false); //B2 indication of strange things going on
11559 scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
11560 return;
11561 }
11562 DEBUG("scanTabRefLab: ZSTATE_ERROR");
11563 DEBUG(" apiConnectstate="<<apiConnectptr.p->apiConnectstate);
11564 ndbrequire(false); //B2 indication of strange things going on
11565 scanTabRefLab(signal, ZSTATE_ERROR);
11566 return;
11567 }//if
11568
11569 /*******************************************************
11570 * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
11571 ********************************************************/
11572 // Stop the timer that is used to check for timeout in the API
11573 setApiConTimer(apiConnectptr.i, 0, __LINE__);
11574 ScanRecordPtr scanptr;
11575 scanptr.i = apiConnectptr.p->apiScanRec;
11576 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11577 ScanRecord* scanP = scanptr.p;
11578
11579 /* Copy ReceiverIds to working space past end of signal
11580 * so that we don't overwrite them when sending signals
11581 */
11582 Uint32 len = 0;
11583 if (handle.m_cnt > 0)
11584 {
11585 jam();
11586 /* TODO : Add Dropped signal handling for SCAN_NEXTREQ */
11587 /* Receiver ids are in a long section */
11588 ndbrequire(signal->getLength() == ScanNextReq::SignalLength);
11589 ndbrequire(handle.m_cnt == 1);
11590 SegmentedSectionPtr receiverIdsSection;
11591 ndbrequire(handle.getSection(receiverIdsSection,
11592 ScanNextReq::ReceiverIdsSectionNum));
11593 len= receiverIdsSection.p->m_sz;
11594 ndbassert(len < (8192 - 25));
11595
11596 copy(signal->getDataPtrSend()+25, receiverIdsSection);
11597 releaseSections(handle);
11598 }
11599 else
11600 {
11601 jam();
11602 len= signal->getLength() - ScanNextReq::SignalLength;
11603 memcpy(signal->getDataPtrSend()+25,
11604 signal->getDataPtr()+ ScanNextReq::SignalLength,
11605 4 * len);
11606 }
11607
11608 if (stopScan == ZTRUE) {
11609 jam();
11610 /*********************************************************************
11611 * APPLICATION IS CLOSING THE SCAN.
11612 **********************************************************************/
11613 close_scan_req(signal, scanptr, true);
11614 return;
11615 }//if
11616
11617 if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
11618 jam();
11619 /**
11620 * The scan is closing (typically due to error)
11621 * but the API hasn't understood it yet
11622 *
11623 * Wait for API close request
11624 */
11625 return;
11626 }
11627
11628 ScanFragNextReq tmp;
11629 tmp.requestInfo = 0;
11630 tmp.transId1 = apiConnectptr.p->transid[0];
11631 tmp.transId2 = apiConnectptr.p->transid[1];
11632 tmp.batch_size_rows = scanP->batch_size_rows;
11633 tmp.batch_size_bytes = scanP->batch_byte_size;
11634
11635 ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
11636 ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
11637 for(Uint32 i = 0 ; i<len; i++){
11638 jam();
11639 scanFragptr.i = signal->theData[i+25];
11640 c_scan_frag_pool.getPtr(scanFragptr);
11641 ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
11642
11643 scanFragptr.p->startFragTimer(ctcTimer);
11644 scanFragptr.p->m_ops = 0;
11645
11646 if(scanFragptr.p->m_scan_frag_conf_status)
11647 {
11648 /**
11649 * last scan was complete
11650 */
11651 jam();
11652 ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
11653 jam();
11654 ndbassert(scanptr.p->m_booked_fragments_count);
11655 scanptr.p->m_booked_fragments_count--;
11656 scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
11657
11658 tcConnectptr.i = scanptr.p->scanTcrec;
11659 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11660 scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
11661
11662 DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
11663 req->senderRef = reference();
11664 req->senderData = scanFragptr.i;
11665 req->tableId = scanptr.p->scanTableref;
11666 req->fragId = scanFragptr.p->scanFragId;
11667 req->scanCookie = scanptr.p->m_scan_cookie;
11668 sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11669 DihScanGetNodesReq::SignalLength, JBB);
11670 }
11671 else
11672 {
11673 jam();
11674 scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11675 ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
11676 * req = tmp;
11677 req->senderData = scanFragptr.i;
11678 sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11679 ScanFragNextReq::SignalLength, JBB);
11680 }
11681 delivered.remove(scanFragptr);
11682 running.add(scanFragptr);
11683 }//for
11684
11685 }//Dbtc::execSCAN_NEXTREQ()
11686
11687 void
close_scan_req(Signal * signal,ScanRecordPtr scanPtr,bool req_received)11688 Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
11689
11690 ScanRecord* scanP = scanPtr.p;
11691 ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
11692 ScanRecord::ScanState old = scanPtr.p->scanState;
11693 scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
11694 scanPtr.p->m_close_scan_req = req_received;
11695
11696 if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
11697 {
11698 jam();
11699 scanPtr.p->scanState = old;
11700 return; // Will continue on execDI_FCOUNTCONF
11701 }
11702
11703 /**
11704 * Queue : Action
11705 * ============= : =================
11706 * completed : -
11707 * running : close -> LQH
11708 * delivered w/ : close -> LQH
11709 * delivered wo/ : move to completed
11710 * queued w/ : close -> LQH
11711 * queued wo/ : move to completed
11712 */
11713
11714 ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
11715 nextReq->requestInfo = ScanFragNextReq::ZCLOSE;
11716 nextReq->transId1 = apiConnectptr.p->transid[0];
11717 nextReq->transId2 = apiConnectptr.p->transid[1];
11718
11719 {
11720 ScanFragRecPtr ptr;
11721 ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
11722 ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
11723 ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
11724
11725 // Close running
11726 for(running.first(ptr); !ptr.isNull(); ){
11727 ScanFragRecPtr curr = ptr; // Remove while iterating...
11728 running.next(ptr);
11729
11730 switch(curr.p->scanFragState){
11731 case ScanFragRec::IDLE:
11732 jam(); // real early abort
11733 ndbrequire(old == ScanRecord::WAIT_AI);
11734 running.release(curr);
11735 continue;
11736 case ScanFragRec::WAIT_GET_PRIMCONF:
11737 jam();
11738 continue;
11739 case ScanFragRec::LQH_ACTIVE:
11740 jam();
11741 break;
11742 default:
11743 jamLine(curr.p->scanFragState);
11744 ndbrequire(false);
11745 }
11746
11747 curr.p->startFragTimer(ctcTimer);
11748 curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11749 nextReq->senderData = curr.i;
11750 sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11751 ScanFragNextReq::SignalLength, JBB);
11752 }
11753
11754 // Close delivered
11755 for(delivered.first(ptr); !ptr.isNull(); ){
11756 jam();
11757 ScanFragRecPtr curr = ptr; // Remove while iterating...
11758 delivered.next(ptr);
11759
11760 ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
11761 delivered.remove(curr);
11762
11763 if (curr.p->m_scan_frag_conf_status == 0)
11764 {
11765 jam();
11766 running.add(curr);
11767 curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11768 curr.p->startFragTimer(ctcTimer);
11769 nextReq->senderData = curr.i;
11770 sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11771 ScanFragNextReq::SignalLength, JBB);
11772
11773 }
11774 else
11775 {
11776 jam();
11777 c_scan_frag_pool.release(curr);
11778 curr.p->scanFragState = ScanFragRec::COMPLETED;
11779 curr.p->stopFragTimer();
11780 }
11781 }//for
11782
11783 /**
11784 * All queued with data should be closed
11785 */
11786 for(queued.first(ptr); !ptr.isNull(); ){
11787 jam();
11788 ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
11789 ScanFragRecPtr curr = ptr; // Remove while iterating...
11790 queued.next(ptr);
11791
11792 queued.remove(curr);
11793 scanP->m_queued_count--;
11794
11795 if (curr.p->m_scan_frag_conf_status == 0)
11796 {
11797 jam();
11798 running.add(curr);
11799 curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11800 curr.p->startFragTimer(ctcTimer);
11801 nextReq->senderData = curr.i;
11802 sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11803 ScanFragNextReq::SignalLength, JBB);
11804 }
11805 else
11806 {
11807 jam();
11808 c_scan_frag_pool.release(curr);
11809 curr.p->scanFragState = ScanFragRec::COMPLETED;
11810 curr.p->stopFragTimer();
11811 }
11812 }
11813 }
11814 close_scan_req_send_conf(signal, scanPtr);
11815 }
11816
11817 void
close_scan_req_send_conf(Signal * signal,ScanRecordPtr scanPtr)11818 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
11819
11820 jam();
11821
11822 ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
11823 ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
11824 //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
11825
11826 #if 0
11827 {
11828 ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
11829 ScanFragRecPtr ptr;
11830 for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
11831 ndbrequire(ptr.p->scanFragTimer == 0);
11832 ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
11833 }
11834 }
11835 #endif
11836
11837 if(!scanPtr.p->m_running_scan_frags.isEmpty()){
11838 jam();
11839 return;
11840 }
11841
11842 const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
11843
11844 if(!scanPtr.p->m_close_scan_req){
11845 jam();
11846 /**
11847 * The API hasn't order closing yet
11848 */
11849 return;
11850 }
11851
11852 Uint32 ref = apiConnectptr.p->ndbapiBlockref;
11853 if(!apiFail && ref){
11854 jam();
11855 ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
11856 conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11857 conf->requestInfo = ScanTabConf::EndOfData;
11858 conf->transId1 = apiConnectptr.p->transid[0];
11859 conf->transId2 = apiConnectptr.p->transid[1];
11860 sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
11861 }
11862
11863 releaseScanResources(signal, scanPtr);
11864
11865 if(apiFail){
11866 jam();
11867 /**
11868 * API has failed
11869 */
11870 handleApiFailState(signal, apiConnectptr.i);
11871 }
11872 }
11873
11874 Dbtc::ScanRecordPtr
seizeScanrec(Signal * signal)11875 Dbtc::seizeScanrec(Signal* signal) {
11876 ScanRecordPtr scanptr;
11877 scanptr.i = cfirstfreeScanrec;
11878 ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11879 cfirstfreeScanrec = scanptr.p->nextScan;
11880 scanptr.p->nextScan = RNIL;
11881 ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
11882 return scanptr;
11883 }//Dbtc::seizeScanrec()
11884
sendScanFragReq(Signal * signal,ScanRecord * scanP,ScanFragRec * scanFragP,bool isLastReq)11885 void Dbtc::sendScanFragReq(Signal* signal,
11886 ScanRecord* scanP,
11887 ScanFragRec* scanFragP,
11888 bool isLastReq)
11889 {
11890 Uint32 version= getNodeInfo(refToNode(scanFragP->lqhBlockref)).m_version;
11891 bool longFragReq= ((version >= NDBD_LONG_SCANFRAGREQ) &&
11892 (! ERROR_INSERTED(8070) &&
11893 ! ERROR_INSERTED(8088)));
11894 cachePtr.i = apiConnectptr.p->cachePtr;
11895 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11896
11897 Uint32 reqKeyLen = scanP->scanKeyLen;
11898
11899 SectionHandle sections(this);
11900 sections.m_ptr[0].i = cachePtr.p->attrInfoSectionI;
11901 sections.m_cnt = 1;
11902
11903 if (reqKeyLen > 0)
11904 {
11905 jam();
11906 ndbassert(cachePtr.p->keyInfoSectionI != RNIL);
11907 sections.m_ptr[1].i = cachePtr.p->keyInfoSectionI;
11908 sections.m_cnt = 2;
11909 }
11910
11911 if (isLastReq)
11912 {
11913 /* This send will release these sections, remove our
11914 * references to them
11915 */
11916 cachePtr.p->attrInfoSectionI = RNIL;
11917 cachePtr.p->keyInfoSectionI = RNIL;
11918 }
11919
11920 getSections(sections.m_cnt, sections.m_ptr);
11921
11922 ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
11923 Uint32 requestInfo = scanP->scanRequestInfo;
11924 ScanFragReq::setScanPrio(requestInfo, 1);
11925 apiConnectptr.i = scanP->scanApiRec;
11926 req->tableId = scanP->scanTableref;
11927 req->schemaVersion = scanP->scanSchemaVersion;
11928 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11929 req->senderData = scanFragptr.i;
11930 req->requestInfo = requestInfo;
11931 req->fragmentNoKeyLen = scanFragP->scanFragId;
11932 req->resultRef = apiConnectptr.p->ndbapiBlockref;
11933 req->savePointId = apiConnectptr.p->currSavePointId;
11934 req->transId1 = apiConnectptr.p->transid[0];
11935 req->transId2 = apiConnectptr.p->transid[1];
11936 req->clientOpPtr = scanFragP->m_apiPtr;
11937 req->batch_size_rows= scanP->batch_size_rows;
11938 req->batch_size_bytes= scanP->batch_byte_size;
11939
11940 if (likely(longFragReq))
11941 {
11942 jam();
11943 /* Send long, possibly fragmented SCAN_FRAGREQ */
11944
11945 // TODO :
11946 // 1) Consider whether to adjust fragmentation threshold
11947 // a) When to fragment signal vs fragment size
11948 // b) Fragment size
11949 /* To reduce the copy burden we want to keep hold of the
11950 * AttrInfo and KeyInfo sections after sending them to
11951 * LQH. To do this we perform the fragmented send inline,
11952 * so that all fragments are sent *now*. This avoids any
11953 * problems with the fragmented send CONTINUE 'thread' using
11954 * the section while we hold or even release it. The
11955 * signal receiver can still take realtime breaks when
11956 * receiving.
11957 *
11958 * Indicate to sendFirstFragment that we want to keep the
11959 * fragments, so it must not free them, unless this is the
11960 * last request in which case they can be freed. If the
11961 * last request is a local send then a copy is avoided.
11962 */
11963 FragmentSendInfo fragSendInfo;
11964
11965 sendFirstFragment(fragSendInfo,
11966 NodeReceiverGroup(scanFragP->lqhBlockref),
11967 GSN_SCAN_FRAGREQ,
11968 signal,
11969 ScanFragReq::SignalLength,
11970 JBB,
11971 §ions,
11972 !isLastReq); // Keep sent sections unless
11973 // last send
11974
11975 while (fragSendInfo.m_status != FragmentSendInfo::SendComplete)
11976 {
11977 jam();
11978 /* Send remaining fragments */
11979 sendNextSegmentedFragment(signal, fragSendInfo);
11980 }
11981
11982 /* Clear handle, section deallocation handled elsewhere. */
11983 sections.clear();
11984 }
11985 else
11986 {
11987 jam();
11988 /* Short SCANFRAGREQ with separate KeyInfo and AttrInfo trains
11989 * Sent to older NDBD nodes during upgrade
11990 */
11991 Uint32 reqAttrLen = sections.m_ptr[0].sz;
11992 ScanFragReq::setAttrLen(req->requestInfo, reqAttrLen);
11993 req->fragmentNoKeyLen |= reqKeyLen;
11994 sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
11995 ScanFragReq::SignalLength, JBB);
11996 if(reqKeyLen > 0)
11997 {
11998 jam();
11999 tcConnectptr.i = scanFragptr.i;
12000 /* Build KeyInfo train from KeyInfo long signal section */
12001 sendKeyInfoTrain(signal,
12002 scanFragP->lqhBlockref,
12003 scanFragptr.i,
12004 0, // Offset 0
12005 sections.m_ptr[1].i);
12006 }
12007
12008 if(ERROR_INSERTED(8035))
12009 globalTransporterRegistry.performSend();
12010
12011 if (!ERROR_INSERTED(8088))
12012 {
12013 ndbrequire(sendAttrInfoTrain(signal,
12014 scanFragP->lqhBlockref,
12015 scanFragptr.i,
12016 0, // Offset 0
12017 sections.m_ptr[0].i));
12018 }
12019
12020 if(ERROR_INSERTED(8035))
12021 globalTransporterRegistry.performSend();
12022
12023 if (isLastReq)
12024 {
12025 /* Free the sections here */
12026 releaseSections(sections);
12027 }
12028 else
12029 {
12030 sections.clear();
12031 }
12032 }
12033
12034 if (ERROR_INSERTED(8088))
12035 {
12036 signal->theData[0] = 9999;
12037 sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
12038 }
12039 }//Dbtc::sendScanFragReq()
12040
12041
sendScanTabConf(Signal * signal,ScanRecordPtr scanPtr)12042 void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
12043 jam();
12044 Uint32* ops = signal->getDataPtrSend()+4;
12045 Uint32 op_count = scanPtr.p->m_queued_count;
12046
12047 Uint32 words_per_op = 4;
12048 const Uint32 ref = apiConnectptr.p->ndbapiBlockref;
12049 if (!scanPtr.p->m_4word_conf)
12050 {
12051 jam();
12052 words_per_op = 3;
12053 }
12054
12055 if (4 + words_per_op * op_count > 25)
12056 {
12057 jam();
12058 ops += 21;
12059 }
12060
12061 int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
12062 Uint32 booked = scanPtr.p->m_booked_fragments_count;
12063
12064 ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
12065 conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
12066 conf->requestInfo = op_count;
12067 conf->transId1 = apiConnectptr.p->transid[0];
12068 conf->transId2 = apiConnectptr.p->transid[1];
12069 ScanFragRecPtr ptr;
12070 {
12071 ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
12072 ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
12073 for(queued.first(ptr); !ptr.isNull(); ){
12074 ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
12075 ScanFragRecPtr curr = ptr; // Remove while iterating...
12076 queued.next(ptr);
12077
12078 bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
12079 if(curr.p->m_scan_frag_conf_status)
12080 booked++;
12081
12082 * ops++ = curr.p->m_apiPtr;
12083 * ops++ = done ? RNIL : curr.i;
12084 if (words_per_op == 4)
12085 {
12086 * ops++ = curr.p->m_ops;
12087 * ops++ = curr.p->m_totalLen;
12088 }
12089 else
12090 {
12091 * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
12092 }
12093
12094 queued.remove(curr);
12095 if(!done){
12096 delivered.add(curr);
12097 curr.p->scanFragState = ScanFragRec::DELIVERED;
12098 curr.p->stopFragTimer();
12099 } else {
12100 c_scan_frag_pool.release(curr);
12101 curr.p->scanFragState = ScanFragRec::COMPLETED;
12102 curr.p->stopFragTimer();
12103 }
12104 }
12105 }
12106
12107 bool release = false;
12108 scanPtr.p->m_booked_fragments_count = booked;
12109 if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
12110 scanPtr.p->m_running_scan_frags.isEmpty())
12111 {
12112 jam();
12113 release = true;
12114 conf->requestInfo = op_count | ScanTabConf::EndOfData;
12115 }
12116 else
12117 {
12118 if (scanPtr.p->m_running_scan_frags.isEmpty())
12119 {
12120 jam();
12121 /**
12122 * All scan frags delivered...waiting for API
12123 */
12124 setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
12125 }
12126 }
12127
12128 if (4 + words_per_op * op_count > 25)
12129 {
12130 jam();
12131 LinearSectionPtr ptr[3];
12132 ptr[0].p = signal->getDataPtrSend()+25;
12133 ptr[0].sz = words_per_op * op_count;
12134 sendSignal(ref, GSN_SCAN_TABCONF, signal,
12135 ScanTabConf::SignalLength, JBB, ptr, 1);
12136 }
12137 else
12138 {
12139 jam();
12140 sendSignal(ref, GSN_SCAN_TABCONF, signal,
12141 ScanTabConf::SignalLength + words_per_op * op_count, JBB);
12142 }
12143 scanPtr.p->m_queued_count = 0;
12144
12145 if (release)
12146 {
12147 jam();
12148 releaseScanResources(signal, scanPtr);
12149 }
12150
12151 }//Dbtc::sendScanTabConf()
12152
12153
gcpTcfinished(Signal * signal,Uint64 gci)12154 void Dbtc::gcpTcfinished(Signal* signal, Uint64 gci)
12155 {
12156 GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
12157 conf->senderData = c_gcp_data;
12158 conf->gci_hi = Uint32(gci >> 32);
12159 conf->gci_lo = Uint32(gci);
12160 sendSignal(c_gcp_ref, GSN_GCP_TCFINISHED, signal,
12161 GCPTCFinished::SignalLength, JBB);
12162 }//Dbtc::gcpTcfinished()
12163
initApiConnect(Signal * signal)12164 void Dbtc::initApiConnect(Signal* signal)
12165 {
12166 Uint32 tiacTmp;
12167 Uint32 guard4;
12168
12169 tiacTmp = capiConnectFilesize / 3;
12170 ndbrequire(tiacTmp > 0);
12171 guard4 = tiacTmp + 1;
12172 for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
12173 refresh_watch_dog();
12174 ptrAss(cachePtr, cacheRecord);
12175 cachePtr.p->nextCacheRec = cachePtr.i + 1;
12176 }//for
12177 cachePtr.i = tiacTmp;
12178 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12179 cachePtr.p->nextCacheRec = RNIL;
12180 cfirstfreeCacheRec = 0;
12181
12182 guard4 = tiacTmp - 1;
12183 for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
12184 refresh_watch_dog();
12185 jam();
12186 ptrAss(apiConnectptr, apiConnectRecord);
12187 apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
12188 apiConnectptr.p->apiFailState = ZFALSE;
12189 setApiConTimer(apiConnectptr.i, 0, __LINE__);
12190 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12191 apiConnectptr.p->cachePtr = RNIL;
12192 apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12193 apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12194 apiConnectptr.p->commitAckMarker = RNIL;
12195 apiConnectptr.p->firstTcConnect = RNIL;
12196 apiConnectptr.p->lastTcConnect = RNIL;
12197 apiConnectptr.p->m_flags = 0;
12198 apiConnectptr.p->m_special_op_flags = 0;
12199 apiConnectptr.p->accumulatingIndexOp = RNIL;
12200 apiConnectptr.p->executingIndexOp = RNIL;
12201 apiConnectptr.p->buddyPtr = RNIL;
12202 apiConnectptr.p->currSavePointId = 0;
12203 apiConnectptr.p->m_transaction_nodes.clear();
12204 apiConnectptr.p->singleUserMode = 0;
12205 }//for
12206 apiConnectptr.i = tiacTmp - 1;
12207 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12208 apiConnectptr.p->nextApiConnect = RNIL;
12209 cfirstfreeApiConnect = 0;
12210 guard4 = (2 * tiacTmp) - 1;
12211 for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
12212 {
12213 refresh_watch_dog();
12214 jam();
12215 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12216 apiConnectptr.p->apiConnectstate = CS_RESTART;
12217 apiConnectptr.p->apiFailState = ZFALSE;
12218 setApiConTimer(apiConnectptr.i, 0, __LINE__);
12219 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12220 apiConnectptr.p->cachePtr = RNIL;
12221 apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12222 apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12223 apiConnectptr.p->commitAckMarker = RNIL;
12224 apiConnectptr.p->firstTcConnect = RNIL;
12225 apiConnectptr.p->lastTcConnect = RNIL;
12226 apiConnectptr.p->m_flags = 0;
12227 apiConnectptr.p->m_special_op_flags = 0;
12228 apiConnectptr.p->accumulatingIndexOp = RNIL;
12229 apiConnectptr.p->executingIndexOp = RNIL;
12230 apiConnectptr.p->buddyPtr = RNIL;
12231 apiConnectptr.p->currSavePointId = 0;
12232 apiConnectptr.p->m_transaction_nodes.clear();
12233 apiConnectptr.p->singleUserMode = 0;
12234 }//for
12235 apiConnectptr.i = (2 * tiacTmp) - 1;
12236 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12237 apiConnectptr.p->nextApiConnect = RNIL;
12238 cfirstfreeApiConnectCopy = tiacTmp;
12239 guard4 = (3 * tiacTmp) - 1;
12240 for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
12241 apiConnectptr.i++) {
12242 refresh_watch_dog();
12243 jam();
12244 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12245 setApiConTimer(apiConnectptr.i, 0, __LINE__);
12246 apiConnectptr.p->apiFailState = ZFALSE;
12247 apiConnectptr.p->apiConnectstate = CS_RESTART;
12248 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12249 apiConnectptr.p->cachePtr = RNIL;
12250 apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12251 apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12252 apiConnectptr.p->commitAckMarker = RNIL;
12253 apiConnectptr.p->firstTcConnect = RNIL;
12254 apiConnectptr.p->lastTcConnect = RNIL;
12255 apiConnectptr.p->m_flags = 0;
12256 apiConnectptr.p->m_special_op_flags = 0;
12257 apiConnectptr.p->accumulatingIndexOp = RNIL;
12258 apiConnectptr.p->executingIndexOp = RNIL;
12259 apiConnectptr.p->buddyPtr = RNIL;
12260 apiConnectptr.p->currSavePointId = 0;
12261 apiConnectptr.p->m_transaction_nodes.clear();
12262 apiConnectptr.p->singleUserMode = 0;
12263 }//for
12264 apiConnectptr.i = (3 * tiacTmp) - 1;
12265 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12266 apiConnectptr.p->nextApiConnect = RNIL;
12267 cfirstfreeApiConnectFail = 2 * tiacTmp;
12268 }//Dbtc::initApiConnect()
12269
initgcp(Signal * signal)12270 void Dbtc::initgcp(Signal* signal)
12271 {
12272 Ptr<GcpRecord> gcpPtr;
12273 ndbrequire(cgcpFilesize > 0);
12274 for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
12275 ptrAss(gcpPtr, gcpRecord);
12276 gcpPtr.p->nextGcp = gcpPtr.i + 1;
12277 }//for
12278 gcpPtr.i = cgcpFilesize - 1;
12279 ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
12280 gcpPtr.p->nextGcp = RNIL;
12281 cfirstfreeGcp = 0;
12282 cfirstgcp = RNIL;
12283 clastgcp = RNIL;
12284 }//Dbtc::initgcp()
12285
inithost(Signal * signal)12286 void Dbtc::inithost(Signal* signal)
12287 {
12288 cpackedListIndex = 0;
12289 ndbrequire(chostFilesize > 0);
12290 for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
12291 jam();
12292 ptrAss(hostptr, hostRecord);
12293 hostptr.p->hostStatus = HS_DEAD;
12294 hostptr.p->inPackedList = false;
12295 hostptr.p->lqhTransStatus = LTS_IDLE;
12296 hostptr.p->noOfWordsTCKEYCONF = 0;
12297 hostptr.p->noOfPackedWordsLqh = 0;
12298 hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
12299 hostptr.p->m_nf_bits = 0;
12300 }//for
12301 c_alive_nodes.clear();
12302 }//Dbtc::inithost()
12303
initialiseRecordsLab(Signal * signal,UintR Tdata0,Uint32 retRef,Uint32 retData)12304 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
12305 Uint32 retRef, Uint32 retData)
12306 {
12307 switch (Tdata0) {
12308 case 0:
12309 jam();
12310 initApiConnect(signal);
12311 break;
12312 case 1:
12313 jam();
12314 // UNUSED Free to initialise something
12315 break;
12316 case 2:
12317 jam();
12318 // UNUSED Free to initialise something
12319 break;
12320 case 3:
12321 jam();
12322 initgcp(signal);
12323 break;
12324 case 4:
12325 jam();
12326 inithost(signal);
12327 break;
12328 case 5:
12329 jam();
12330 // UNUSED Free to initialise something
12331 break;
12332 case 6:
12333 jam();
12334 initTable(signal);
12335 break;
12336 case 7:
12337 jam();
12338 initialiseScanrec(signal);
12339 break;
12340 case 8:
12341 jam();
12342 initialiseScanOprec(signal);
12343 break;
12344 case 9:
12345 jam();
12346 initialiseScanFragrec(signal);
12347 break;
12348 case 10:
12349 jam();
12350 initialiseTcConnect(signal);
12351 break;
12352 case 11:
12353 jam();
12354 initTcFail(signal);
12355
12356 {
12357 ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
12358 conf->senderRef = reference();
12359 conf->senderData = retData;
12360 sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
12361 ReadConfigConf::SignalLength, JBB);
12362 }
12363 return;
12364 break;
12365 default:
12366 jam();
12367 systemErrorLab(signal, __LINE__);
12368 return;
12369 break;
12370 }//switch
12371
12372 signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
12373 signal->theData[1] = Tdata0 + 1;
12374 signal->theData[2] = 0;
12375 signal->theData[3] = retRef;
12376 signal->theData[4] = retData;
12377 sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
12378 }
12379
12380 /* ========================================================================= */
12381 /* ======= INITIALISE_SCANREC ======= */
12382 /* */
12383 /* ========================================================================= */
initialiseScanrec(Signal * signal)12384 void Dbtc::initialiseScanrec(Signal* signal)
12385 {
12386 ScanRecordPtr scanptr;
12387 ndbrequire(cscanrecFileSize > 0);
12388 for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
12389 refresh_watch_dog();
12390 jam();
12391 ptrAss(scanptr, scanRecord);
12392 new (scanptr.p) ScanRecord();
12393 scanptr.p->scanState = ScanRecord::IDLE;
12394 scanptr.p->scanApiRec = RNIL;
12395 scanptr.p->nextScan = scanptr.i + 1;
12396 }//for
12397 scanptr.i = cscanrecFileSize - 1;
12398 ptrAss(scanptr, scanRecord);
12399 scanptr.p->nextScan = RNIL;
12400 cfirstfreeScanrec = 0;
12401 }//Dbtc::initialiseScanrec()
12402
initialiseScanFragrec(Signal * signal)12403 void Dbtc::initialiseScanFragrec(Signal* signal)
12404 {
12405 }//Dbtc::initialiseScanFragrec()
12406
initialiseScanOprec(Signal * signal)12407 void Dbtc::initialiseScanOprec(Signal* signal)
12408 {
12409 }//Dbtc::initialiseScanOprec()
12410
initTable(Signal * signal)12411 void Dbtc::initTable(Signal* signal)
12412 {
12413
12414 ndbrequire(ctabrecFilesize > 0);
12415 for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
12416 refresh_watch_dog();
12417 ptrAss(tabptr, tableRecord);
12418 tabptr.p->currentSchemaVersion = 0;
12419 tabptr.p->m_flags = 0;
12420 tabptr.p->set_storedTable(true);
12421 tabptr.p->tableType = 0;
12422 tabptr.p->set_enabled(false);
12423 tabptr.p->set_dropping(false);
12424 tabptr.p->noOfKeyAttr = 0;
12425 tabptr.p->hasCharAttr = 0;
12426 tabptr.p->noOfDistrKeys = 0;
12427 tabptr.p->hasVarKeys = 0;
12428 }//for
12429 }//Dbtc::initTable()
12430
initialiseTcConnect(Signal * signal)12431 void Dbtc::initialiseTcConnect(Signal* signal)
12432 {
12433 ndbrequire(ctcConnectFilesize >= 2);
12434
12435 // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
12436 Uint32 titcTmp = ctcConnectFilesize / 2;
12437 for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
12438 refresh_watch_dog();
12439 jam();
12440 ptrAss(tcConnectptr, tcConnectRecord);
12441 tcConnectptr.p->tcConnectstate = OS_RESTART;
12442 tcConnectptr.p->apiConnect = RNIL;
12443 tcConnectptr.p->noOfNodes = 0;
12444 tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
12445 tcConnectptr.p->commitAckMarker = RNIL;
12446 }//for
12447 tcConnectptr.i = titcTmp - 1;
12448 ptrAss(tcConnectptr, tcConnectRecord);
12449 tcConnectptr.p->nextTcConnect = RNIL;
12450 cfirstfreeTcConnectFail = 0;
12451
12452 // Place other half in cfirstfreeTcConnect list
12453 for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
12454 tcConnectptr.i++) {
12455 refresh_watch_dog();
12456 jam();
12457 ptrAss(tcConnectptr, tcConnectRecord);
12458 tcConnectptr.p->tcConnectstate = OS_RESTART;
12459 tcConnectptr.p->apiConnect = RNIL;
12460 tcConnectptr.p->noOfNodes = 0;
12461 tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
12462 tcConnectptr.p->commitAckMarker = RNIL;
12463 }//for
12464 tcConnectptr.i = ctcConnectFilesize - 1;
12465 ptrAss(tcConnectptr, tcConnectRecord);
12466 tcConnectptr.p->nextTcConnect = RNIL;
12467 cfirstfreeTcConnect = titcTmp;
12468 c_counters.cconcurrentOp = 0;
12469 }//Dbtc::initialiseTcConnect()
12470
12471 /* ------------------------------------------------------------------------- */
12472 /* ---- LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS */
12473 /* WAITING FOR COMPLETION. */
12474 /* ------------------------------------------------------------------------- */
linkGciInGcilist(Ptr<GcpRecord> gcpPtr)12475 void Dbtc::linkGciInGcilist(Ptr<GcpRecord> gcpPtr)
12476 {
12477 GcpRecordPtr tmpGcpPointer;
12478 if (cfirstgcp == RNIL) {
12479 jam();
12480 cfirstgcp = gcpPtr.i;
12481 } else {
12482 jam();
12483 tmpGcpPointer.i = clastgcp;
12484 ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
12485 tmpGcpPointer.p->nextGcp = gcpPtr.i;
12486 }//if
12487 clastgcp = gcpPtr.i;
12488 }//Dbtc::linkGciInGcilist()
12489
12490 /* ------------------------------------------------------------------------- */
12491 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS --- */
12492 /* ------------------------------------------------------------------------- */
linkTcInConnectionlist(Signal * signal)12493 void Dbtc::linkTcInConnectionlist(Signal* signal)
12494 {
12495 /* POINTER FOR THE CONNECT_RECORD */
12496 TcConnectRecordPtr ltcTcConnectptr;
12497
12498 tcConnectptr.p->nextTcConnect = RNIL;
12499 ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
12500 ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
12501 apiConnectptr.p->lastTcConnect = tcConnectptr.i;
12502 if (ltcTcConnectptr.i == RNIL) {
12503 jam();
12504 apiConnectptr.p->firstTcConnect = tcConnectptr.i;
12505 } else {
12506 jam();
12507 ptrGuard(ltcTcConnectptr);
12508 ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
12509 }//if
12510 }//Dbtc::linkTcInConnectionlist()
12511
12512 /*---------------------------------------------------------------------------*/
12513 /* RELEASE_ABORT_RESOURCES */
12514 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
12515 /* SENDS THE ABORT DECISION TO THE APPLICATION. */
12516 /*---------------------------------------------------------------------------*/
releaseAbortResources(Signal * signal)12517 void Dbtc::releaseAbortResources(Signal* signal)
12518 {
12519 TcConnectRecordPtr rarTcConnectptr;
12520
12521 c_counters.cabortCount++;
12522 if (apiConnectptr.p->cachePtr != RNIL) {
12523 cachePtr.i = apiConnectptr.p->cachePtr;
12524 ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12525 releaseAttrinfo();
12526 releaseKeys();
12527 }//if
12528 tcConnectptr.i = apiConnectptr.p->firstTcConnect;
12529 while (tcConnectptr.i != RNIL) {
12530 jam();
12531 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12532 // Clear any markers that were set in CS_RECEIVING state
12533 clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
12534 rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
12535 releaseTcCon();
12536 tcConnectptr.i = rarTcConnectptr.i;
12537 }//while
12538
12539 Uint32 marker = apiConnectptr.p->commitAckMarker;
12540 if (marker != RNIL)
12541 {
12542 jam();
12543 m_commitAckMarkerHash.release(marker);
12544 apiConnectptr.p->commitAckMarker = RNIL;
12545 }
12546
12547 apiConnectptr.p->firstTcConnect = RNIL;
12548 apiConnectptr.p->lastTcConnect = RNIL;
12549 apiConnectptr.p->m_transaction_nodes.clear();
12550 apiConnectptr.p->singleUserMode = 0;
12551
12552 // MASV let state be CS_ABORTING until all
12553 // signals in the "air" have been received. Reset to CS_CONNECTED
12554 // will be done when a TCKEYREQ with start flag is recieved
12555 // or releaseApiCon is called
12556 // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
12557 apiConnectptr.p->apiConnectstate = CS_ABORTING;
12558 apiConnectptr.p->abortState = AS_IDLE;
12559 releaseAllSeizedIndexOperations(apiConnectptr.p);
12560
12561 if (tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG) ||
12562 apiConnectptr.p->apiFailState == ZTRUE)
12563 {
12564 jam();
12565 bool ok = false;
12566 Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
12567 ReturnSignal ret = apiConnectptr.p->returnsignal;
12568 apiConnectptr.p->returnsignal = RS_NO_RETURN;
12569 tc_clearbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
12570 switch(ret){
12571 case RS_TCROLLBACKCONF:
12572 jam();
12573 ok = true;
12574 signal->theData[0] = apiConnectptr.p->ndbapiConnect;
12575 signal->theData[1] = apiConnectptr.p->transid[0];
12576 signal->theData[2] = apiConnectptr.p->transid[1];
12577 sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
12578 break;
12579 case RS_TCROLLBACKREP:{
12580 jam();
12581 ok = true;
12582 TcRollbackRep * const tcRollbackRep =
12583 (TcRollbackRep *) signal->getDataPtr();
12584
12585 tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
12586 tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
12587 tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
12588 tcRollbackRep->returnCode = apiConnectptr.p->returncode;
12589 tcRollbackRep->errorData = apiConnectptr.p->errorData;
12590 sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
12591 TcRollbackRep::SignalLength, JBB);
12592 }
12593 break;
12594 case RS_NO_RETURN:
12595 jam();
12596 ok = true;
12597 break;
12598 case RS_TCKEYCONF:
12599 case RS_TC_COMMITCONF:
12600 break;
12601 }
12602 if(!ok){
12603 jam();
12604 ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
12605 sendSystemError(signal, __LINE__);
12606 }//if
12607
12608 }
12609 setApiConTimer(apiConnectptr.i, 0,
12610 100000+c_apiConTimer_line[apiConnectptr.i]);
12611 if (apiConnectptr.p->apiFailState == ZTRUE) {
12612 jam();
12613 handleApiFailState(signal, apiConnectptr.i);
12614 return;
12615 }//if
12616 }//Dbtc::releaseAbortResources()
12617
releaseApiCon(Signal * signal,UintR TapiConnectPtr)12618 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
12619 {
12620 ApiConnectRecordPtr TlocalApiConnectptr;
12621
12622 TlocalApiConnectptr.i = TapiConnectPtr;
12623 ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
12624 TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
12625 cfirstfreeApiConnect = TlocalApiConnectptr.i;
12626 setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
12627 TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
12628 ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
12629 ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
12630 TlocalApiConnectptr.p->ndbapiBlockref = 0;
12631 }//Dbtc::releaseApiCon()
12632
releaseApiConnectFail(Signal * signal)12633 void Dbtc::releaseApiConnectFail(Signal* signal)
12634 {
12635 apiConnectptr.p->apiConnectstate = CS_RESTART;
12636 apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12637 setApiConTimer(apiConnectptr.i, 0, __LINE__);
12638 apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
12639 cfirstfreeApiConnectFail = apiConnectptr.i;
12640 ndbrequire(apiConnectptr.p->commitAckMarker == RNIL);
12641 }//Dbtc::releaseApiConnectFail()
12642
releaseKeys()12643 void Dbtc::releaseKeys()
12644 {
12645 Uint32 keyInfoSectionI= cachePtr.p->keyInfoSectionI;
12646
12647 /* Release KeyInfo section if there is one */
12648 releaseSection(keyInfoSectionI);
12649 cachePtr.p->keyInfoSectionI= RNIL;
12650
12651 }//Dbtc::releaseKeys()
12652
releaseTcConnectFail(Signal * signal)12653 void Dbtc::releaseTcConnectFail(Signal* signal)
12654 {
12655 ptrGuard(tcConnectptr);
12656 tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
12657 cfirstfreeTcConnectFail = tcConnectptr.i;
12658 }//Dbtc::releaseTcConnectFail()
12659
seizeApiConnect(Signal * signal)12660 void Dbtc::seizeApiConnect(Signal* signal)
12661 {
12662 if (cfirstfreeApiConnect != RNIL) {
12663 jam();
12664 terrorCode = ZOK;
12665 apiConnectptr.i = cfirstfreeApiConnect; /* ASSIGN A FREE RECORD FROM */
12666 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12667 cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
12668 apiConnectptr.p->nextApiConnect = RNIL;
12669 setApiConTimer(apiConnectptr.i, 0, __LINE__);
12670 apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
12671 tc_clearbit(apiConnectptr.p->m_flags,
12672 ApiConnectRecord::TF_TRIGGER_PENDING);
12673 apiConnectptr.p->m_special_op_flags = 0;
12674 } else {
12675 jam();
12676 terrorCode = ZNO_FREE_API_CONNECTION;
12677 }//if
12678 }//Dbtc::seizeApiConnect()
12679
seizeApiConnectFail(Signal * signal)12680 void Dbtc::seizeApiConnectFail(Signal* signal)
12681 {
12682 apiConnectptr.i = cfirstfreeApiConnectFail;
12683 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12684 cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
12685 }//Dbtc::seizeApiConnectFail()
12686
seizeTcConnect(Signal * signal)12687 void Dbtc::seizeTcConnect(Signal* signal)
12688 {
12689 tcConnectptr.i = cfirstfreeTcConnect;
12690 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12691 cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
12692 c_counters.cconcurrentOp++;
12693 tcConnectptr.p->m_special_op_flags = 0;
12694 tcConnectptr.p->tcConnectstate = OS_ABORTING;
12695 tcConnectptr.p->noOfNodes = 0;
12696 }//Dbtc::seizeTcConnect()
12697
seizeTcConnectFail(Signal * signal)12698 void Dbtc::seizeTcConnectFail(Signal* signal)
12699 {
12700 tcConnectptr.i = cfirstfreeTcConnectFail;
12701 ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12702 cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
12703 }//Dbtc::seizeTcConnectFail()
12704
12705 /**
12706 * sendAttrInfoTrain
12707 * This method sends an ATTRINFO signal train using AttrInfo
12708 * from the section passed, starting at the supplied offset
12709 */
sendAttrInfoTrain(Signal * signal,UintR TBRef,Uint32 connectPtr,Uint32 offset,Uint32 attrInfoIVal)12710 bool Dbtc::sendAttrInfoTrain(Signal* signal,
12711 UintR TBRef,
12712 Uint32 connectPtr,
12713 Uint32 offset,
12714 Uint32 attrInfoIVal)
12715 {
12716 ApiConnectRecord * const regApiPtr = apiConnectptr.p;
12717
12718 ndbassert( attrInfoIVal != RNIL );
12719 SectionReader attrInfoReader(attrInfoIVal, getSectionSegmentPool());
12720 Uint32 attrInfoLength= attrInfoReader.getSize();
12721
12722 ndbassert( offset < attrInfoLength );
12723 if (unlikely(! attrInfoReader.step( offset )))
12724 return false;
12725 attrInfoLength-= offset;
12726
12727 signal->theData[0] = connectPtr;
12728 signal->theData[1] = regApiPtr->transid[0];
12729 signal->theData[2] = regApiPtr->transid[1];
12730
12731 while (attrInfoLength != 0)
12732 {
12733 Uint32 dataInSignal= MIN(AttrInfo::DataLength, attrInfoLength);
12734
12735 if (unlikely(! attrInfoReader.getWords(&signal->theData[3],
12736 dataInSignal)))
12737 return false;
12738
12739 sendSignal(TBRef, GSN_ATTRINFO, signal,
12740 AttrInfo::HeaderLength + dataInSignal, JBB);
12741
12742 attrInfoLength-= dataInSignal;
12743 }
12744 return true;
12745 } //Dbtc::sendAttrInfoTrain()
12746
sendContinueTimeOutControl(Signal * signal,Uint32 TapiConPtr)12747 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
12748 {
12749 signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
12750 signal->theData[1] = TapiConPtr;
12751 sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
12752 }//Dbtc::sendContinueTimeOutControl()
12753
sendSystemError(Signal * signal,int line)12754 void Dbtc::sendSystemError(Signal* signal, int line)
12755 {
12756 progError(line, NDBD_EXIT_NDBREQUIRE);
12757 }//Dbtc::sendSystemError()
12758
12759 /* ========================================================================= */
12760 /* ------- LINK ACTUAL GCP OUT OF LIST ------- */
12761 /* ------------------------------------------------------------------------- */
unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)12762 void Dbtc::unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)
12763 {
12764 ndbrequire(cfirstgcp == tmpGcpPtr.i);
12765
12766 cfirstgcp = tmpGcpPtr.p->nextGcp;
12767 if (tmpGcpPtr.i == clastgcp) {
12768 jam();
12769 clastgcp = RNIL;
12770 }//if
12771
12772 tmpGcpPtr.p->nextGcp = cfirstfreeGcp;
12773 cfirstfreeGcp = tmpGcpPtr.i;
12774 }//Dbtc::unlinkGcp()
12775
12776 void
execDUMP_STATE_ORD(Signal * signal)12777 Dbtc::execDUMP_STATE_ORD(Signal* signal)
12778 {
12779 jamEntry();
12780 DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
12781 Uint32 arg = signal->theData[0];
12782 if (signal->theData[0] == DumpStateOrd::CommitAckMarkersSize)
12783 {
12784 infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
12785 m_commitAckMarkerPool.getNoOfFree(),
12786 m_commitAckMarkerPool.getSize());
12787 return;
12788 }
12789 if (signal->theData[0] == DumpStateOrd::CommitAckMarkersDump)
12790 {
12791 infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
12792 m_commitAckMarkerPool.getNoOfFree(),
12793 m_commitAckMarkerPool.getSize());
12794 CommitAckMarkerIterator iter;
12795 for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
12796 m_commitAckMarkerHash.next(iter)){
12797 infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
12798 " Api: %d %x %x %x %x bucket = %d",
12799 iter.curr.i,
12800 iter.curr.p->transid1,
12801 iter.curr.p->transid2,
12802 iter.curr.p->apiNodeId,
12803 iter.curr.p->m_commit_ack_marker_nodes.getWord(0),
12804 iter.curr.p->m_commit_ack_marker_nodes.getWord(1),
12805 iter.curr.p->m_commit_ack_marker_nodes.getWord(2),
12806 iter.curr.p->m_commit_ack_marker_nodes.getWord(3),
12807 iter.bucket);
12808 }
12809 return;
12810 }
12811 // Dump all ScanFragRecs
12812 if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
12813 Uint32 recordNo = 0;
12814 if (signal->getLength() == 1)
12815 infoEvent("TC: Dump all ScanFragRec - size: %d",
12816 cscanFragrecFileSize);
12817 else if (signal->getLength() == 2)
12818 recordNo = dumpState->args[1];
12819 else
12820 return;
12821
12822 dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
12823 dumpState->args[1] = recordNo;
12824 execDUMP_STATE_ORD(signal);
12825
12826 if (recordNo < cscanFragrecFileSize-1){
12827 dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
12828 dumpState->args[1] = recordNo+1;
12829 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12830 }
12831 }
12832
12833 // Dump one ScanFragRec
12834 if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
12835 Uint32 recordNo = RNIL;
12836 if (signal->getLength() == 2)
12837 recordNo = dumpState->args[1];
12838 else
12839 return;
12840
12841 if (recordNo >= cscanFragrecFileSize)
12842 return;
12843
12844 ScanFragRecPtr sfp;
12845 sfp.i = recordNo;
12846 c_scan_frag_pool.getPtr(sfp);
12847 infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
12848 sfp.i,
12849 sfp.p->scanFragState,
12850 sfp.p->scanFragId);
12851 infoEvent(" nodeid=%d, timer=%d",
12852 refToNode(sfp.p->lqhBlockref),
12853 sfp.p->scanFragTimer);
12854 }
12855
12856 // Dump all ScanRecords
12857 if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
12858 Uint32 recordNo = 0;
12859 if (signal->getLength() == 1)
12860 infoEvent("TC: Dump all ScanRecord - size: %d",
12861 cscanrecFileSize);
12862 else if (signal->getLength() == 2)
12863 recordNo = dumpState->args[1];
12864 else
12865 return;
12866
12867 dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
12868 dumpState->args[1] = recordNo;
12869 execDUMP_STATE_ORD(signal);
12870
12871 if (recordNo < cscanrecFileSize-1){
12872 dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
12873 dumpState->args[1] = recordNo+1;
12874 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12875 }
12876 }
12877
12878 // Dump all active ScanRecords
12879 if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
12880 Uint32 recordNo = 0;
12881 if (signal->getLength() == 1)
12882 infoEvent("TC: Dump active ScanRecord - size: %d",
12883 cscanrecFileSize);
12884 else if (signal->getLength() == 2)
12885 recordNo = dumpState->args[1];
12886 else
12887 return;
12888
12889 ScanRecordPtr sp;
12890 sp.i = recordNo;
12891 ptrAss(sp, scanRecord);
12892 if (sp.p->scanState != ScanRecord::IDLE){
12893 dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
12894 dumpState->args[1] = recordNo;
12895 execDUMP_STATE_ORD(signal);
12896 }
12897
12898 if (recordNo < cscanrecFileSize-1){
12899 dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
12900 dumpState->args[1] = recordNo+1;
12901 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12902 }
12903 }
12904
12905 // Dump one ScanRecord
12906 // and associated ScanFragRec and ApiConnectRecord
12907 if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
12908 Uint32 recordNo = RNIL;
12909 if (signal->getLength() == 2)
12910 recordNo = dumpState->args[1];
12911 else
12912 return;
12913
12914 if (recordNo >= cscanrecFileSize)
12915 return;
12916
12917 ScanRecordPtr sp;
12918 sp.i = recordNo;
12919 ptrAss(sp, scanRecord);
12920 infoEvent("Dbtc::ScanRecord[%d]: state=%d"
12921 "nextfrag=%d, nofrag=%d",
12922 sp.i,
12923 sp.p->scanState,
12924 sp.p->scanNextFragId,
12925 sp.p->scanNoFrag);
12926 infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
12927 sp.p->scanAiLength,
12928 sp.p->scanParallel,
12929 sp.p->scanReceivedOperations,
12930 sp.p->batch_size_rows);
12931 infoEvent(" schv=%d, tab=%d, sproc=%d",
12932 sp.p->scanSchemaVersion,
12933 sp.p->scanTableref,
12934 sp.p->scanStoredProcId);
12935 infoEvent(" apiRec=%d, next=%d",
12936 sp.p->scanApiRec, sp.p->nextScan);
12937
12938 if (sp.p->scanState != ScanRecord::IDLE){
12939 // Request dump of ScanFragRec
12940 ScanFragRecPtr sfptr;
12941 #define DUMP_SFR(x){\
12942 ScanFragList list(c_scan_frag_pool, x);\
12943 for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
12944 dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
12945 dumpState->args[1] = sfptr.i;\
12946 execDUMP_STATE_ORD(signal);\
12947 }}
12948
12949 DUMP_SFR(sp.p->m_running_scan_frags);
12950 DUMP_SFR(sp.p->m_queued_scan_frags);
12951 DUMP_SFR(sp.p->m_delivered_scan_frags);
12952
12953 // Request dump of ApiConnectRecord
12954 dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
12955 dumpState->args[1] = sp.p->scanApiRec;
12956 execDUMP_STATE_ORD(signal);
12957 }
12958
12959 }
12960
12961 // Dump all ApiConnectRecord(s)
12962 if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
12963 Uint32 recordNo = 0;
12964 if (signal->getLength() == 1)
12965 infoEvent("TC: Dump all ApiConnectRecord - size: %d",
12966 capiConnectFilesize);
12967 else if (signal->getLength() == 2)
12968 recordNo = dumpState->args[1];
12969 else
12970 return;
12971
12972 dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
12973 dumpState->args[1] = recordNo;
12974 execDUMP_STATE_ORD(signal);
12975
12976 if (recordNo < capiConnectFilesize-1){
12977 dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
12978 dumpState->args[1] = recordNo+1;
12979 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12980 }
12981 }
12982
12983 // Dump one ApiConnectRecord
12984 if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
12985 Uint32 recordNo = RNIL;
12986 if (signal->getLength() == 2)
12987 recordNo = dumpState->args[1];
12988 else
12989 return;
12990
12991 if (recordNo >= capiConnectFilesize)
12992 return;
12993
12994 ApiConnectRecordPtr ap;
12995 ap.i = recordNo;
12996 ptrAss(ap, apiConnectRecord);
12997 infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
12998 "apiFailState=%d",
12999 ap.i,
13000 ap.p->apiConnectstate,
13001 ap.p->abortState,
13002 ap.p->apiFailState);
13003 infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
13004 ap.p->transid[0],
13005 ap.p->transid[1],
13006 ap.p->ndbapiBlockref,
13007 ap.p->apiScanRec);
13008 infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
13009 "retsig=%d",
13010 ctcTimer, getApiConTimer(ap.i),
13011 ap.p->counter,
13012 ap.p->returncode,
13013 ap.p->returnsignal);
13014 infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
13015 "tckeyrec=%d",
13016 ap.p->lqhkeyconfrec,
13017 ap.p->lqhkeyreqrec,
13018 ap.p->tckeyrec);
13019 infoEvent(" next=%d ",
13020 ap.p->nextApiConnect);
13021 }
13022
13023 if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
13024 jam();
13025 if(signal->getLength() > 1){
13026 set_timeout_value(signal->theData[1]);
13027 }
13028 }
13029
13030 if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
13031 jam();
13032 if(signal->getLength() > 1){
13033 set_appl_timeout_value(signal->theData[1]);
13034 }
13035 }
13036
13037 if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
13038 {
13039 static int frequency = 1;
13040 if (signal->getLength() > 1)
13041 frequency = signal->theData[1];
13042 else
13043 if (refToBlock(signal->getSendersBlockRef()) != DBTC)
13044 frequency = 1;
13045
13046 if (frequency)
13047 {
13048 dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
13049 execDUMP_STATE_ORD(signal);
13050 dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
13051
13052 Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
13053 sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
13054 }
13055 }
13056
13057 if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
13058 {
13059 infoEvent("IndexOpCount: pool: %d free: %d",
13060 c_theIndexOperationPool.getSize(),
13061 c_theIndexOperationPool.getNoOfFree());
13062 }
13063
13064 if (dumpState->args[0] == 2514)
13065 {
13066 if (signal->getLength() == 2)
13067 {
13068 dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
13069 execDUMP_STATE_ORD(signal);
13070 }
13071
13072 NodeReceiverGroup rg(CMVMI, c_alive_nodes);
13073 dumpState->args[0] = 15;
13074 sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
13075
13076 signal->theData[0] = 2515;
13077 sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, 1000, 1);
13078 return;
13079 }
13080
13081 if (dumpState->args[0] == 2515)
13082 {
13083 NdbNodeBitmask mask = c_alive_nodes;
13084 mask.clear(getOwnNodeId());
13085 NodeReceiverGroup rg(NDBCNTR, mask);
13086
13087 sendSignal(rg, GSN_SYSTEM_ERROR, signal, 1, JBB);
13088 sendSignalWithDelay(cownref, GSN_SYSTEM_ERROR, signal, 300, 1);
13089 return;
13090 }
13091
13092 if (arg == 2550)
13093 {
13094 jam();
13095 Uint32 len = signal->getLength() - 1;
13096 if (len + 2 > 25)
13097 {
13098 jam();
13099 infoEvent("Too long filter");
13100 return;
13101 }
13102 if (validate_filter(signal))
13103 {
13104 jam();
13105 memmove(signal->theData + 2, signal->theData + 1, 4 * len);
13106 signal->theData[0] = 2551;
13107 signal->theData[1] = 0; // record
13108 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 2, JBB);
13109
13110 infoEvent("Starting dump of transactions");
13111 }
13112 return;
13113 }
13114
13115 if (arg == 2551)
13116 {
13117 jam();
13118 Uint32 record = signal->theData[1];
13119 Uint32 len = signal->getLength();
13120 ndbassert(len > 1);
13121
13122 ApiConnectRecordPtr ap;
13123 ap.i = record;
13124 ptrAss(ap, apiConnectRecord);
13125
13126 bool print = false;
13127 for (Uint32 i = 0; i<32; i++)
13128 {
13129 jam();
13130 print = match_and_print(signal, ap);
13131
13132 ap.i++;
13133 if (ap.i == capiConnectFilesize || print)
13134 {
13135 jam();
13136 break;
13137 }
13138
13139 ptrAss(ap, apiConnectRecord);
13140 }
13141
13142 if (ap.i == capiConnectFilesize)
13143 {
13144 jam();
13145 infoEvent("End of transaction dump");
13146 return;
13147 }
13148
13149 signal->theData[1] = ap.i;
13150 if (print)
13151 {
13152 jam();
13153 sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
13154 }
13155 else
13156 {
13157 jam();
13158 sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
13159 }
13160 return;
13161 }
13162 #ifdef ERROR_INSERT
13163 if (arg == 2552 || arg == 4002)
13164 {
13165 ndbrequire(m_commitAckMarkerPool.getNoOfFree() == m_commitAckMarkerPool.getSize());
13166 return;
13167 }
13168 #endif
13169
13170 if (arg == 7019 && signal->getLength() == 2)
13171 {
13172 jam();
13173 Uint32 nodeId = signal->theData[1];
13174 if (nodeId < MAX_NODES && nodeId < NDB_ARRAY_SIZE(capiConnectClosing))
13175 {
13176 warningEvent(" DBTC: capiConnectClosing[%u]: %u",
13177 nodeId, capiConnectClosing[nodeId]);
13178 }
13179 else
13180 {
13181 warningEvent(" DBTC: dump-7019 to unknown node: %u", nodeId);
13182 }
13183 }
13184 }//Dbtc::execDUMP_STATE_ORD()
13185
execDBINFO_SCANREQ(Signal * signal)13186 void Dbtc::execDBINFO_SCANREQ(Signal *signal)
13187 {
13188 DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
13189 const Ndbinfo::ScanCursor* cursor =
13190 CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
13191 Ndbinfo::Ratelimit rl;
13192
13193 jamEntry();
13194
13195 switch(req.tableId){
13196 case Ndbinfo::POOLS_TABLEID:
13197 {
13198 Ndbinfo::pool_entry pools[] =
13199 {
13200 { "Defined Trigger",
13201 c_theDefinedTriggerPool.getUsed(),
13202 c_theDefinedTriggerPool.getSize(),
13203 c_theDefinedTriggerPool.getEntrySize(),
13204 c_theDefinedTriggerPool.getUsedHi(),
13205 { CFG_DB_NO_TRIGGERS,0,0,0 }},
13206 { "Fired Trigger",
13207 c_theFiredTriggerPool.getUsed(),
13208 c_theFiredTriggerPool.getSize(),
13209 c_theFiredTriggerPool.getEntrySize(),
13210 c_theFiredTriggerPool.getUsedHi(),
13211 { CFG_DB_NO_TRIGGER_OPS,0,0,0 }},
13212 { "Index",
13213 c_theIndexPool.getUsed(),
13214 c_theIndexPool.getSize(),
13215 c_theIndexPool.getEntrySize(),
13216 c_theIndexPool.getUsedHi(),
13217 { CFG_DB_NO_TABLES,
13218 CFG_DB_NO_ORDERED_INDEXES,
13219 CFG_DB_NO_UNIQUE_HASH_INDEXES,0 }},
13220 { "Scan Fragment",
13221 c_scan_frag_pool.getUsed(),
13222 c_scan_frag_pool.getSize(),
13223 c_scan_frag_pool.getEntrySize(),
13224 c_scan_frag_pool.getUsedHi(),
13225 { CFG_DB_NO_LOCAL_SCANS,0,0,0 }},
13226 { "Commit ACK Marker",
13227 m_commitAckMarkerPool.getUsed(),
13228 m_commitAckMarkerPool.getSize(),
13229 m_commitAckMarkerPool.getEntrySize(),
13230 m_commitAckMarkerPool.getUsedHi(),
13231 { CFG_DB_NO_TRANSACTIONS,0,0,0 }},
13232 { "Index Op",
13233 c_theIndexOperationPool.getUsed(),
13234 c_theIndexOperationPool.getSize(),
13235 c_theIndexOperationPool.getEntrySize(),
13236 c_theIndexOperationPool.getUsedHi(),
13237 { CFG_DB_NO_INDEX_OPS,0,0,0 }},
13238 { "Operations",
13239 c_counters.cconcurrentOp,
13240 ctcConnectFilesize,
13241 sizeof(TcConnectRecord),
13242 0,
13243 { CFG_DB_NO_TRANSACTIONS,
13244 CFG_DB_NO_OPS,0,0 }},
13245 { NULL, 0,0,0,0,{0,0,0,0} }
13246 };
13247
13248 const size_t num_config_params =
13249 sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
13250 Uint32 pool = cursor->data[0];
13251 BlockNumber bn = blockToMain(number());
13252 while(pools[pool].poolname)
13253 {
13254 jam();
13255 Ndbinfo::Row row(signal, req);
13256 row.write_uint32(getOwnNodeId());
13257 row.write_uint32(bn); // block number
13258 row.write_uint32(instance()); // block instance
13259 row.write_string(pools[pool].poolname);
13260
13261 row.write_uint64(pools[pool].used);
13262 row.write_uint64(pools[pool].total);
13263 row.write_uint64(pools[pool].used_hi);
13264 row.write_uint64(pools[pool].entry_size);
13265 for (size_t i = 0; i < num_config_params; i++)
13266 row.write_uint32(pools[pool].config_params[i]);
13267 ndbinfo_send_row(signal, req, row, rl);
13268 pool++;
13269 if (rl.need_break(req))
13270 {
13271 jam();
13272 ndbinfo_send_scan_break(signal, req, rl, pool);
13273 return;
13274 }
13275 }
13276 break;
13277 }
13278
13279 case Ndbinfo::COUNTERS_TABLEID:
13280 {
13281 Ndbinfo::counter_entry counters[] = {
13282 { Ndbinfo::ATTRINFO_COUNTER, c_counters.cattrinfoCount },
13283 { Ndbinfo::TRANSACTIONS_COUNTER, c_counters.ctransCount },
13284 { Ndbinfo::COMMITS_COUNTER, c_counters.ccommitCount },
13285 { Ndbinfo::READS_COUNTER, c_counters.creadCount },
13286 { Ndbinfo::SIMPLE_READS_COUNTER, c_counters.csimpleReadCount },
13287 { Ndbinfo::WRITES_COUNTER, c_counters.cwriteCount },
13288 { Ndbinfo::ABORTS_COUNTER, c_counters.cabortCount },
13289 { Ndbinfo::TABLE_SCANS_COUNTER, c_counters.c_scan_count },
13290 { Ndbinfo::RANGE_SCANS_COUNTER, c_counters.c_range_scan_count }
13291 };
13292 const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
13293
13294 Uint32 i = cursor->data[0];
13295 BlockNumber bn = blockToMain(number());
13296 while(i < num_counters)
13297 {
13298 jam();
13299 Ndbinfo::Row row(signal, req);
13300 row.write_uint32(getOwnNodeId());
13301 row.write_uint32(bn); // block number
13302 row.write_uint32(instance()); // block instance
13303 row.write_uint32(counters[i].id);
13304
13305 row.write_uint64(counters[i].val);
13306 ndbinfo_send_row(signal, req, row, rl);
13307 i++;
13308 if (rl.need_break(req))
13309 {
13310 jam();
13311 ndbinfo_send_scan_break(signal, req, rl, i);
13312 return;
13313 }
13314 }
13315
13316 break;
13317 }
13318
13319 default:
13320 break;
13321 }
13322
13323 ndbinfo_send_scan_conf(signal, req, rl);
13324 }
13325
13326 bool
validate_filter(Signal * signal)13327 Dbtc::validate_filter(Signal* signal)
13328 {
13329 Uint32 * start = signal->theData + 1;
13330 Uint32 * end = signal->theData + signal->getLength();
13331 if (start == end)
13332 {
13333 infoEvent("No filter specified, not listing...");
13334 return false;
13335 }
13336
13337 while(start < end)
13338 {
13339 switch(* start){
13340 case 1: // API Node
13341 case 4: // Inactive time
13342 start += 2;
13343 break;
13344 case 2: // Transid
13345 start += 3;
13346 break;
13347 default:
13348 infoEvent("Invalid filter op: 0x%x pos: %ld",
13349 * start,
13350 (long int)(start - (signal->theData + 1)));
13351 return false;
13352 }
13353 }
13354
13355 if (start != end)
13356 {
13357 infoEvent("Invalid filter, unexpected end");
13358 return false;
13359 }
13360
13361 return true;
13362 }
13363
13364 bool
match_and_print(Signal * signal,ApiConnectRecordPtr apiPtr)13365 Dbtc::match_and_print(Signal* signal, ApiConnectRecordPtr apiPtr)
13366 {
13367 Uint32 conState = apiPtr.p->apiConnectstate;
13368 if (conState == CS_CONNECTED ||
13369 conState == CS_DISCONNECTED ||
13370 conState == CS_RESTART)
13371 return false;
13372
13373 Uint32 len = signal->getLength();
13374 Uint32* start = signal->theData + 2;
13375 Uint32* end = signal->theData + len;
13376 Uint32 apiTimer = getApiConTimer(apiPtr.i);
13377 while (start < end)
13378 {
13379 jam();
13380 switch(* start){
13381 case 1:
13382 jam();
13383 if (refToNode(apiPtr.p->ndbapiBlockref) != * (start + 1))
13384 return false;
13385 start += 2;
13386 break;
13387 case 2:
13388 jam();
13389 if (apiPtr.p->transid[0] != * (start + 1) ||
13390 apiPtr.p->transid[1] != * (start + 2))
13391 return false;
13392 start += 3;
13393 break;
13394 case 4:{
13395 jam();
13396 if (apiTimer == 0 || ((ctcTimer - apiTimer) / 100) < * (start + 1))
13397 return false;
13398 start += 2;
13399 break;
13400 }
13401 default:
13402 ndbassert(false);
13403 return false;
13404 }
13405 }
13406
13407 if (start != end)
13408 {
13409 ndbassert(false);
13410 return false;
13411 }
13412
13413 /**
13414 * Do print
13415 */
13416 Uint32 *temp = signal->theData + 25;
13417 memcpy(temp, signal->theData, 4 * len);
13418
13419 char state[10];
13420 const char *stateptr = "";
13421
13422 switch(apiPtr.p->apiConnectstate){
13423 case CS_STARTED:
13424 stateptr = "Prepared";
13425 break;
13426 case CS_RECEIVING:
13427 case CS_REC_COMMITTING:
13428 case CS_START_COMMITTING:
13429 stateptr = "Running";
13430 break;
13431 case CS_COMMITTING:
13432 stateptr = "Committing";
13433 break;
13434 case CS_COMPLETING:
13435 stateptr = "Completing";
13436 break;
13437 case CS_PREPARE_TO_COMMIT:
13438 stateptr = "Prepare to commit";
13439 break;
13440 case CS_COMMIT_SENT:
13441 stateptr = "Commit sent";
13442 break;
13443 case CS_COMPLETE_SENT:
13444 stateptr = "Complete sent";
13445 break;
13446 case CS_ABORTING:
13447 stateptr = "Aborting";
13448 break;
13449 case CS_START_SCAN:
13450 stateptr = "Scanning";
13451 break;
13452 case CS_WAIT_ABORT_CONF:
13453 case CS_WAIT_COMMIT_CONF:
13454 case CS_WAIT_COMPLETE_CONF:
13455 case CS_FAIL_PREPARED:
13456 case CS_FAIL_COMMITTING:
13457 case CS_FAIL_COMMITTED:
13458 case CS_REC_PREPARING:
13459 case CS_START_PREPARING:
13460 case CS_PREPARED:
13461 case CS_RESTART:
13462 case CS_FAIL_ABORTED:
13463 case CS_DISCONNECTED:
13464 default:
13465 BaseString::snprintf(state, sizeof(state),
13466 "%u", apiPtr.p->apiConnectstate);
13467 stateptr = state;
13468 break;
13469 }
13470
13471 char buf[100];
13472 BaseString::snprintf(buf, sizeof(buf),
13473 "TRX[%u]: API: %d(0x%x)"
13474 "transid: 0x%x 0x%x inactive: %u(%d) state: %s",
13475 apiPtr.i,
13476 refToNode(apiPtr.p->ndbapiBlockref),
13477 refToBlock(apiPtr.p->ndbapiBlockref),
13478 apiPtr.p->transid[0],
13479 apiPtr.p->transid[1],
13480 apiTimer ? (ctcTimer - apiTimer) / 100 : 0,
13481 c_apiConTimer_line[apiPtr.i],
13482 stateptr);
13483 infoEvent("%s", buf);
13484
13485 memcpy(signal->theData, temp, 4*len);
13486 return true;
13487 }
13488
execABORT_ALL_REQ(Signal * signal)13489 void Dbtc::execABORT_ALL_REQ(Signal* signal)
13490 {
13491 jamEntry();
13492 AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
13493 AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
13494
13495 const Uint32 senderData = req->senderData;
13496 const BlockReference senderRef = req->senderRef;
13497
13498 if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
13499 jam();
13500
13501 ref->senderData = senderData;
13502 ref->errorCode = AbortAllRef::InvalidState;
13503 sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13504 AbortAllRef::SignalLength, JBB);
13505 return;
13506 }
13507
13508 if(c_abortRec.clientRef != 0){
13509 jam();
13510
13511 ref->senderData = senderData;
13512 ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
13513 sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13514 AbortAllRef::SignalLength, JBB);
13515 return;
13516 }
13517
13518 if(refToNode(senderRef) != getOwnNodeId()){
13519 jam();
13520
13521 ref->senderData = senderData;
13522 ref->errorCode = AbortAllRef::FunctionNotImplemented;
13523 sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13524 AbortAllRef::SignalLength, JBB);
13525 return;
13526 }
13527
13528 c_abortRec.clientRef = senderRef;
13529 c_abortRec.clientData = senderData;
13530 c_abortRec.oldTimeOutValue = ctimeOutValue;
13531
13532 ctimeOutValue = 0;
13533 const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
13534
13535 checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
13536 }
13537
checkAbortAllTimeout(Signal * signal,Uint32 sleepTime)13538 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
13539 {
13540
13541 ndbrequire(c_abortRec.clientRef != 0);
13542
13543 if(sleepTime > 0){
13544 jam();
13545
13546 sleepTime -= 1;
13547 signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
13548 signal->theData[1] = sleepTime;
13549 sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
13550 return;
13551 }
13552
13553 AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
13554 conf->senderData = c_abortRec.clientData;
13555 sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
13556 AbortAllConf::SignalLength, JBB);
13557
13558 ctimeOutValue = c_abortRec.oldTimeOutValue;
13559 c_abortRec.clientRef = 0;
13560 }
13561
13562 /* **************************************************************** */
13563 /* ---------------------------------------------------------------- */
13564 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
13565 /* ---------------------------------------------------------------- */
13566 /* **************************************************************** */
13567
execCREATE_TRIG_IMPL_REQ(Signal * signal)13568 void Dbtc::execCREATE_TRIG_IMPL_REQ(Signal* signal)
13569 {
13570 jamEntry();
13571 if (!assembleFragments(signal))
13572 {
13573 jam();
13574 return;
13575 }
13576
13577 const CreateTrigImplReq* req = (const CreateTrigImplReq*)signal->getDataPtr();
13578 const Uint32 senderRef = req->senderRef;
13579 const Uint32 senderData = req->senderData;
13580
13581 SectionHandle handle(this, signal);
13582 releaseSections(handle); // Not using mask
13583
13584 TcDefinedTriggerData* triggerData;
13585 DefinedTriggerPtr triggerPtr;
13586
13587 triggerPtr.i = req->triggerId;
13588 if (ERROR_INSERTED(8033) ||
13589 !c_theDefinedTriggers.seizeId(triggerPtr, req->triggerId)) {
13590 jam();
13591 CLEAR_ERROR_INSERT_VALUE;
13592 // Failed to allocate trigger record
13593 ref:
13594 CreateTrigImplRef* ref = (CreateTrigImplRef*)signal->getDataPtrSend();
13595
13596 ref->senderRef = reference();
13597 ref->senderData = senderData;
13598 ref->errorCode = CreateTrigImplRef::InconsistentTC;
13599 ref->errorLine = __LINE__;
13600 sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_REF,
13601 signal, CreateTrigImplRef::SignalLength, JBB);
13602 return;
13603 }
13604
13605 triggerData = triggerPtr.p;
13606 triggerData->triggerId = req->triggerId;
13607 triggerData->triggerType = TriggerInfo::getTriggerType(req->triggerInfo);
13608 triggerData->triggerEvent = TriggerInfo::getTriggerEvent(req->triggerInfo);
13609 triggerData->oldTriggerIds[0] = RNIL;
13610 triggerData->oldTriggerIds[1] = RNIL;
13611
13612 switch(triggerData->triggerType){
13613 case TriggerType::SECONDARY_INDEX:
13614 jam();
13615 triggerData->indexId = req->indexId;
13616 break;
13617 case TriggerType::REORG_TRIGGER:
13618 jam();
13619 triggerData->tableId = req->tableId;
13620 break;
13621 default:
13622 c_theDefinedTriggers.release(triggerPtr);
13623 goto ref;
13624 }
13625
13626 if (unlikely(req->triggerId != req->upgradeExtra[1]))
13627 {
13628 /**
13629 * This is nasty upgrade for unique indexes
13630 */
13631 jam();
13632 ndbrequire(req->triggerId == req->upgradeExtra[0]);
13633 ndbrequire(triggerData->triggerType == TriggerType::SECONDARY_INDEX);
13634
13635 DefinedTriggerPtr insertPtr = triggerPtr;
13636 DefinedTriggerPtr updatePtr;
13637 DefinedTriggerPtr deletePtr;
13638 if (c_theDefinedTriggers.seizeId(updatePtr, req->upgradeExtra[1]) == false)
13639 {
13640 jam();
13641 c_theDefinedTriggers.release(insertPtr);
13642 goto ref;
13643 }
13644
13645 if (c_theDefinedTriggers.seizeId(deletePtr, req->upgradeExtra[2]) == false)
13646 {
13647 jam();
13648 c_theDefinedTriggers.release(insertPtr);
13649 c_theDefinedTriggers.release(updatePtr);
13650 goto ref;
13651 }
13652
13653 insertPtr.p->triggerEvent = TriggerEvent::TE_INSERT;
13654
13655 updatePtr.p->triggerId = req->upgradeExtra[1];
13656 updatePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
13657 updatePtr.p->triggerEvent = TriggerEvent::TE_UPDATE;
13658 updatePtr.p->oldTriggerIds[0] = RNIL;
13659 updatePtr.p->oldTriggerIds[1] = RNIL;
13660 updatePtr.p->indexId = req->indexId;
13661
13662 deletePtr.p->triggerId = req->upgradeExtra[2];
13663 deletePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
13664 deletePtr.p->triggerEvent = TriggerEvent::TE_DELETE;
13665 deletePtr.p->oldTriggerIds[0] = RNIL;
13666 deletePtr.p->oldTriggerIds[1] = RNIL;
13667 deletePtr.p->indexId = req->indexId;
13668 }
13669
13670 CreateTrigImplConf* conf = (CreateTrigImplConf*)signal->getDataPtrSend();
13671 conf->senderRef = reference();
13672 conf->senderData = senderData;
13673 sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_CONF,
13674 signal, CreateTrigImplConf::SignalLength, JBB);
13675 }
13676
execDROP_TRIG_IMPL_REQ(Signal * signal)13677 void Dbtc::execDROP_TRIG_IMPL_REQ(Signal* signal)
13678 {
13679 jamEntry();
13680 const DropTrigImplReq* req = (const DropTrigImplReq*)signal->getDataPtr();
13681 const Uint32 senderRef = req->senderRef;
13682 const Uint32 senderData = req->senderData;
13683
13684 DefinedTriggerPtr triggerPtr;
13685 triggerPtr.i = req->triggerId;
13686
13687 if (ERROR_INSERTED(8035) ||
13688 ((triggerPtr.p = c_theDefinedTriggers.getPtr(req->triggerId)) == NULL))
13689 {
13690 jam();
13691 CLEAR_ERROR_INSERT_VALUE;
13692 // Failed to find find trigger record
13693 DropTrigImplRef* ref = (DropTrigImplRef*)signal->getDataPtrSend();
13694
13695 ref->senderRef = reference();
13696 ref->senderData = senderData;
13697 ref->errorCode = DropTrigImplRef::InconsistentTC;
13698 ref->errorLine = __LINE__;
13699 sendSignal(senderRef, GSN_DROP_TRIG_IMPL_REF,
13700 signal, DropTrigImplRef::SignalLength, JBB);
13701 return;
13702 }
13703
13704 if (unlikely(triggerPtr.p->oldTriggerIds[0] != RNIL))
13705 {
13706 jam();
13707 c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[0]);
13708 c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[1]);
13709 }
13710
13711 // Release trigger record
13712 c_theDefinedTriggers.release(triggerPtr);
13713
13714 DropTrigImplConf* conf = (DropTrigImplConf*)signal->getDataPtrSend();
13715
13716 conf->senderRef = reference();
13717 conf->senderData = senderData;
13718
13719 sendSignal(senderRef, GSN_DROP_TRIG_IMPL_CONF,
13720 signal, DropTrigImplConf::SignalLength, JBB);
13721 }
13722
execCREATE_INDX_IMPL_REQ(Signal * signal)13723 void Dbtc::execCREATE_INDX_IMPL_REQ(Signal* signal)
13724 {
13725 jamEntry();
13726 const CreateIndxImplReq * const req =
13727 (const CreateIndxImplReq *)signal->getDataPtr();
13728 const Uint32 senderRef = req->senderRef;
13729 const Uint32 senderData = req->senderData;
13730 TcIndexData* indexData;
13731 TcIndexDataPtr indexPtr;
13732
13733 SectionHandle handle(this, signal);
13734 if (ERROR_INSERTED(8034) ||
13735 !c_theIndexes.seizeId(indexPtr, req->indexId)) {
13736 jam();
13737 CLEAR_ERROR_INSERT_VALUE;
13738 // Failed to allocate index record
13739 CreateIndxImplRef * const ref =
13740 (CreateIndxImplRef *)signal->getDataPtrSend();
13741
13742 ref->senderRef = reference();
13743 ref->senderData = senderData;
13744 ref->errorCode = CreateIndxImplRef::InconsistentTC;
13745 ref->errorLine = __LINE__;
13746 releaseSections(handle);
13747 sendSignal(senderRef, GSN_CREATE_INDX_IMPL_REF,
13748 signal, CreateIndxImplRef::SignalLength, JBB);
13749 return;
13750 }
13751 indexData = indexPtr.p;
13752 // Indexes always start in state IS_BUILDING
13753 // Will become IS_ONLINE in execALTER_INDX_IMPL_REQ
13754 indexData->indexState = IS_BUILDING;
13755 indexData->indexId = indexPtr.i;
13756 indexData->primaryTableId = req->tableId;
13757
13758 // So far need only attribute count
13759 SegmentedSectionPtr ssPtr;
13760 handle.getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
13761 SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
13762 r0.reset(); // undo implicit first()
13763 if (!r0.getWord(&indexData->attributeList.sz) ||
13764 !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
13765 ndbrequire(false);
13766 }
13767 indexData->primaryKeyPos = indexData->attributeList.sz;
13768
13769 releaseSections(handle);
13770
13771 CreateIndxImplConf * const conf =
13772 (CreateIndxImplConf *)signal->getDataPtrSend();
13773
13774 conf->senderRef = reference();
13775 conf->senderData = senderData;
13776 sendSignal(senderRef, GSN_CREATE_INDX_IMPL_CONF,
13777 signal, CreateIndxImplConf::SignalLength, JBB);
13778 }
13779
execALTER_INDX_IMPL_REQ(Signal * signal)13780 void Dbtc::execALTER_INDX_IMPL_REQ(Signal* signal)
13781 {
13782 jamEntry();
13783 const AlterIndxImplReq * const req =
13784 (const AlterIndxImplReq *)signal->getDataPtr();
13785 const Uint32 senderRef = req->senderRef;
13786 const Uint32 senderData = req->senderData;
13787 TcIndexData* indexData;
13788 const Uint32 requestType = req->requestType;
13789 const Uint32 indexId = req->indexId;
13790
13791 if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
13792 jam();
13793 // Failed to find index record
13794 AlterIndxImplRef * const ref =
13795 (AlterIndxImplRef *)signal->getDataPtrSend();
13796
13797 ref->senderRef = reference();
13798 ref->senderData = senderData;
13799 ref->errorCode = AlterIndxImplRef::InconsistentTC;
13800 ref->errorLine = __LINE__;
13801
13802 sendSignal(senderRef, GSN_ALTER_INDX_IMPL_REF,
13803 signal, AlterIndxImplRef::SignalLength, JBB);
13804 return;
13805 }
13806 // Found index record, alter it's state
13807 switch (requestType) {
13808 case AlterIndxImplReq::AlterIndexOnline:
13809 jam();
13810 indexData->indexState = IS_ONLINE;
13811 break;
13812 case AlterIndxImplReq::AlterIndexOffline:
13813 jam();
13814 indexData->indexState = IS_BUILDING; // wl3600_todo ??
13815 break;
13816 default:
13817 ndbrequire(false);
13818 break;
13819 }
13820 AlterIndxImplConf * const conf =
13821 (AlterIndxImplConf *)signal->getDataPtrSend();
13822
13823 conf->senderRef = reference();
13824 conf->senderData = senderData;
13825 sendSignal(senderRef, GSN_ALTER_INDX_IMPL_CONF,
13826 signal, AlterIndxImplConf::SignalLength, JBB);
13827 }
13828
execFIRE_TRIG_ORD(Signal * signal)13829 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
13830 {
13831 jamEntry();
13832 FireTrigOrd * const fireOrd = (FireTrigOrd *)signal->getDataPtr();
13833 ApiConnectRecordPtr transPtr;
13834 TcConnectRecordPtr opPtr;
13835 bool transIdOk = true;
13836 /* Check the received transaction id
13837 * Older nodes do not send transid info in FIRE_TRIG_ORD
13838 */
13839 const Uint32 sourceNode = refToNode(signal->getSendersBlockRef());
13840 const Uint32 sourceNodeVersion = getNodeInfo(sourceNode).m_version;
13841 bool sigContainsTransId = ndb_fire_trig_ord_transid(sourceNodeVersion);
13842
13843 /* Get triggering operation record */
13844 opPtr.i = fireOrd->getConnectionPtr();
13845 ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
13846
13847 /* Get transaction record */
13848 transPtr.i = opPtr.p->apiConnect;
13849 if (unlikely(transPtr.i == RNIL))
13850 {
13851 /* Looks like the connect record was released
13852 * Treat as a bad transid
13853 */
13854 transIdOk = false;
13855 }
13856 else
13857 {
13858 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
13859
13860 /* Check if signal's trans id and operation's transid are aligned */
13861 transIdOk = (! sigContainsTransId) |
13862 (! ((fireOrd->m_transId1 ^ transPtr.p->transid[0]) |
13863 (fireOrd->m_transId2 ^ transPtr.p->transid[1])));
13864 }
13865
13866 TcFiredTriggerData key;
13867 key.fireingOperation = opPtr.i;
13868 key.nodeId = refToNode(signal->getSendersBlockRef());
13869 FiredTriggerPtr trigPtr;
13870 if(likely(c_firedTriggerHash.find(trigPtr, key)))
13871 {
13872 jam();
13873 c_firedTriggerHash.remove(trigPtr);
13874
13875 trigPtr.p->triggerType = (TriggerType::Value)fireOrd->m_triggerType;
13876 trigPtr.p->triggerEvent = (TriggerEvent::Value)fireOrd->m_triggerEvent;
13877
13878 if (unlikely(signal->getLength() < FireTrigOrd::SignalLength))
13879 {
13880 jam();
13881 ndbrequire(! sigContainsTransId );
13882 Ptr<TcDefinedTriggerData> ptr;
13883 c_theDefinedTriggers.getPtr(ptr, trigPtr.p->triggerId);
13884 trigPtr.p->triggerType = ptr.p->triggerType;
13885 trigPtr.p->triggerEvent = ptr.p->triggerEvent;
13886 }
13887 trigPtr.p->fragId= fireOrd->fragId;
13888 bool ok = transIdOk;
13889 ok &= trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
13890 ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
13891 ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
13892
13893 if (ERROR_INSERTED(8085))
13894 {
13895 ok = false;
13896 }
13897
13898 if(likely( ok ))
13899 {
13900 jam();
13901 setApiConTimer(transPtr.i, ctcTimer, __LINE__);
13902 opPtr.p->noReceivedTriggers++;
13903 opPtr.p->triggerExecutionCount++; // Default 1 LQHKEYREQ per trigger
13904
13905 // Insert fired trigger in execution queue
13906 transPtr.p->theFiredTriggers.add(trigPtr);
13907 if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
13908 transPtr.p->isExecutingDeferredTriggers()) {
13909 executeTriggers(signal, &transPtr);
13910 }
13911 return;
13912 }
13913
13914 /* Trigger entry found but either :
13915 * - Overload resulted in loss of Trig_Attrinfo
13916 * : Release resources + Abort transaction
13917 * - Bad transaction id due to concurrent abort?
13918 * : Release resources
13919 */
13920 jam();
13921 // Release trigger records
13922 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13923 LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
13924 tmp1.release();
13925 LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
13926 tmp2.release();
13927 LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
13928 tmp3.release();
13929 c_theFiredTriggerPool.release(trigPtr);
13930 }
13931
13932 /* Either no trigger entry found, or overload, or
13933 * bad transid
13934 * If transid is ok, abort the transaction.
13935 * else, return.
13936 * (Note small risk of 'abort of innocent' in upgrade
13937 * scenario with no transid in FIRE_TRIG_ORD)
13938 */
13939 jam();
13940 if (transIdOk)
13941 {
13942 jam();
13943 abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
13944 }
13945
13946 return;
13947 }
13948
execTRIG_ATTRINFO(Signal * signal)13949 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
13950 {
13951 jamEntry();
13952 TrigAttrInfo * const trigAttrInfo = (TrigAttrInfo *)signal->getDataPtr();
13953 Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
13954 const Uint32 *src = trigAttrInfo->getData();
13955 FiredTriggerPtr firedTrigPtr;
13956
13957 TcFiredTriggerData key;
13958 key.fireingOperation = trigAttrInfo->getConnectionPtr();
13959 key.nodeId = refToNode(signal->getSendersBlockRef());
13960 if(!c_firedTriggerHash.find(firedTrigPtr, key)){
13961 jam();
13962 /* TODO : Node failure handling (use sig-train assembly) */
13963 if(!c_firedTriggerHash.seize(firedTrigPtr)){
13964 jam();
13965 /**
13966 * Will be handled when FIRE_TRIG_ORD arrives
13967 */
13968 ndbout_c("op: %d node: %d failed to seize",
13969 key.fireingOperation, key.nodeId);
13970 return;
13971 }
13972 ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
13973 firedTrigPtr.p->beforeValues.getSize() == 0 &&
13974 firedTrigPtr.p->afterValues.getSize() == 0);
13975
13976 firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
13977 firedTrigPtr.p->fireingOperation = key.fireingOperation;
13978 firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
13979 c_firedTriggerHash.add(firedTrigPtr);
13980 }
13981
13982 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13983 switch (trigAttrInfo->getAttrInfoType()) {
13984 case(TrigAttrInfo::PRIMARY_KEY):
13985 jam();
13986 {
13987 LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
13988 buf.append(src, attrInfoLength);
13989 }
13990 break;
13991 case(TrigAttrInfo::BEFORE_VALUES):
13992 jam();
13993 {
13994 LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
13995 buf.append(src, attrInfoLength);
13996 }
13997 break;
13998 case(TrigAttrInfo::AFTER_VALUES):
13999 jam();
14000 {
14001 LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
14002 buf.append(src, attrInfoLength);
14003 }
14004 break;
14005 default:
14006 ndbrequire(false);
14007 }
14008 }
14009
execDROP_INDX_IMPL_REQ(Signal * signal)14010 void Dbtc::execDROP_INDX_IMPL_REQ(Signal* signal)
14011 {
14012 jamEntry();
14013 const DropIndxImplReq * const req =
14014 (const DropIndxImplReq *)signal->getDataPtr();
14015 const Uint32 senderRef = req->senderRef;
14016 const Uint32 senderData = req->senderData;
14017 TcIndexData* indexData;
14018
14019 if (ERROR_INSERTED(8036) ||
14020 (indexData = c_theIndexes.getPtr(req->indexId)) == NULL) {
14021 jam();
14022 CLEAR_ERROR_INSERT_VALUE;
14023 // Failed to find index record
14024 DropIndxImplRef * const ref =
14025 (DropIndxImplRef *)signal->getDataPtrSend();
14026
14027 ref->senderRef = reference();
14028 ref->senderData = senderData;
14029 ref->errorCode = DropIndxImplRef::InconsistentTC;
14030 ref->errorLine = __LINE__;
14031 sendSignal(senderRef, GSN_DROP_INDX_IMPL_REF,
14032 signal, DropIndxImplRef::SignalLength, JBB);
14033 return;
14034 }
14035 // Release index record
14036 c_theIndexes.release(req->indexId);
14037
14038 DropIndxImplConf * const conf =
14039 (DropIndxImplConf *)signal->getDataPtrSend();
14040
14041 conf->senderRef = reference();
14042 conf->senderData = senderData;
14043 sendSignal(senderRef, GSN_DROP_INDX_IMPL_CONF,
14044 signal, DropIndxImplConf::SignalLength, JBB);
14045 }
14046
execTCINDXREQ(Signal * signal)14047 void Dbtc::execTCINDXREQ(Signal* signal)
14048 {
14049 jamEntry();
14050
14051 TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
14052 const UintR TapiIndex = tcIndxReq->apiConnectPtr;
14053 Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
14054 Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
14055 ApiConnectRecordPtr transPtr;
14056 bool isLongTcIndxReq= (signal->getNoOfSections() != 0);
14057 SectionHandle handle(this, signal);
14058
14059 transPtr.i = TapiIndex;
14060 if (transPtr.i >= capiConnectFilesize) {
14061 jam();
14062 warningHandlerLab(signal, __LINE__);
14063 releaseSections(handle);
14064 return;
14065 }//if
14066 ptrAss(transPtr, apiConnectRecord);
14067 ApiConnectRecord * const regApiPtr = transPtr.p;
14068 // Seize index operation
14069 TcIndexOperationPtr indexOpPtr;
14070 /**
14071 * NOTE this if-statement is incorrect,
14072 * see bug#50648
14073 *
14074 * The correct if is
14075 *
14076 if (startFlag == 1 &&
14077 (regApiPtr->apiConnectstate == CS_CONNECTED ||
14078 (regApiPtr->apiConnectstate == CS_STARTED &&
14079 regApiPtr->firstTcConnect == RNIL) ||
14080 (regApiPtr->apiConnectstate == CS_ABORTING &&
14081 regApiPtr->abortState == AS_IDLE)))
14082 */
14083 if (((startFlag == 1) &&
14084 (regApiPtr->apiConnectstate == CS_CONNECTED ||
14085 (regApiPtr->apiConnectstate == CS_STARTED &&
14086 regApiPtr->firstTcConnect == RNIL))) ||
14087 (regApiPtr->apiConnectstate == CS_ABORTING &&
14088 regApiPtr->abortState == AS_IDLE))
14089 {
14090 jam();
14091 // This is a newly started transaction, clean-up from any
14092 // previous transaction.
14093 releaseAllSeizedIndexOperations(regApiPtr);
14094
14095 regApiPtr->apiConnectstate = CS_STARTED;
14096 regApiPtr->transid[0] = tcIndxReq->transId1;
14097 regApiPtr->transid[1] = tcIndxReq->transId2;
14098 }//if
14099
14100 if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
14101 getNodeState().getSingleUserApi() !=
14102 refToNode(regApiPtr->ndbapiBlockref))
14103 {
14104 jam();
14105 releaseSections(handle);
14106 terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
14107 regApiPtr->m_flags |=
14108 TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
14109 ApiConnectRecord::TF_EXEC_FLAG : 0;
14110 apiConnectptr = transPtr;
14111 abortErrorLab(signal);
14112 return;
14113 }
14114
14115 if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
14116 jam();
14117 releaseSections(handle);
14118 // Failed to allocate index operation
14119 terrorCode = 288;
14120 regApiPtr->m_flags |=
14121 TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
14122 ApiConnectRecord::TF_EXEC_FLAG : 0;
14123 apiConnectptr = transPtr;
14124 abortErrorLab(signal);
14125 return;
14126 }
14127 TcIndexOperation* indexOp = indexOpPtr.p;
14128 indexOp->indexOpId = indexOpPtr.i;
14129
14130 // Save original signal
14131 indexOp->tcIndxReq = *tcIndxReq;
14132 indexOp->connectionIndex = TapiIndex;
14133 regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
14134
14135 if (isLongTcIndxReq)
14136 {
14137 jam();
14138 /* KeyInfo and AttrInfo already received into sections */
14139 SegmentedSectionPtr keyInfoSection, attrInfoSection;
14140
14141 /* Store i value for first long section of KeyInfo
14142 * and AttrInfo in Index operation
14143 */
14144 handle.getSection(keyInfoSection,
14145 TcKeyReq::KeyInfoSectionNum);
14146
14147 indexOp->keyInfoSectionIVal= keyInfoSection.i;
14148
14149 if (handle.m_cnt == 2)
14150 {
14151 handle.getSection(attrInfoSection,
14152 TcKeyReq::AttrInfoSectionNum);
14153 indexOp->attrInfoSectionIVal= attrInfoSection.i;
14154 }
14155
14156 /* Detach sections from the handle
14157 * Success path code, or index operation cleanup is
14158 * now responsible for freeing the sections
14159 */
14160 handle.clear();
14161
14162 /* All data received, process */
14163 readIndexTable(signal, regApiPtr, indexOp);
14164 return;
14165 }
14166 else
14167 {
14168 jam();
14169 /* Short TcIndxReq, build up KeyInfo and AttrInfo
14170 * sections from separate signals
14171 */
14172 Uint32 * dataPtr = &tcIndxReq->scanInfo;
14173 Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
14174 Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
14175
14176 indexOp->pendingKeyInfo = indexLength;
14177 indexOp->pendingAttrInfo = attrLength;
14178
14179 const Uint32 includedIndexLength = MIN(indexLength, TcKeyReq::MaxKeyInfo);
14180 const Uint32 includedAttrLength = MIN(attrLength, TcKeyReq::MaxAttrInfo);
14181 int ret;
14182
14183 if ((ret = saveINDXKEYINFO(signal,
14184 indexOp,
14185 dataPtr,
14186 includedIndexLength)) == 0)
14187 {
14188 jam();
14189 /* All KI + no AI received, process */
14190 readIndexTable(signal, regApiPtr, indexOp);
14191 return;
14192 }
14193 else if (ret == -1)
14194 {
14195 jam();
14196 return;
14197 }
14198
14199 dataPtr += includedIndexLength;
14200
14201 if (saveINDXATTRINFO(signal,
14202 indexOp,
14203 dataPtr,
14204 includedAttrLength) == 0) {
14205 jam();
14206 /* All KI and AI received, process */
14207 readIndexTable(signal, regApiPtr, indexOp);
14208 return;
14209 }
14210 }
14211 }
14212
execINDXKEYINFO(Signal * signal)14213 void Dbtc::execINDXKEYINFO(Signal* signal)
14214 {
14215 jamEntry();
14216 Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
14217 IndxKeyInfo * const indxKeyInfo = (IndxKeyInfo *)signal->getDataPtr();
14218 const Uint32 *src = indxKeyInfo->getData();
14219 const UintR TconnectIndex = indxKeyInfo->connectPtr;
14220 ApiConnectRecordPtr transPtr;
14221 transPtr.i = TconnectIndex;
14222 if (transPtr.i >= capiConnectFilesize) {
14223 jam();
14224 warningHandlerLab(signal, __LINE__);
14225 return;
14226 }//if
14227 ptrAss(transPtr, apiConnectRecord);
14228 ApiConnectRecord * const regApiPtr = transPtr.p;
14229 TcIndexOperationPtr indexOpPtr;
14230 TcIndexOperation* indexOp;
14231
14232 if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
14233 {
14234 TCKEY_abort(signal, 19);
14235 return;
14236 }
14237
14238 if (regApiPtr->apiConnectstate == CS_ABORTING)
14239 {
14240 jam();
14241 return;
14242 }
14243
14244 if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
14245 {
14246 indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14247
14248 ndbassert( indexOp->pendingKeyInfo > 0 );
14249
14250 if (saveINDXKEYINFO(signal,
14251 indexOp,
14252 src,
14253 keyInfoLength) == 0) {
14254 jam();
14255 /* All KI + AI received, process */
14256 readIndexTable(signal, regApiPtr, indexOp);
14257 }
14258 }
14259 }
14260
execINDXATTRINFO(Signal * signal)14261 void Dbtc::execINDXATTRINFO(Signal* signal)
14262 {
14263 jamEntry();
14264 Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
14265 IndxAttrInfo * const indxAttrInfo = (IndxAttrInfo *)signal->getDataPtr();
14266 const Uint32 *src = indxAttrInfo->getData();
14267 const UintR TconnectIndex = indxAttrInfo->connectPtr;
14268 ApiConnectRecordPtr transPtr;
14269 transPtr.i = TconnectIndex;
14270 if (transPtr.i >= capiConnectFilesize) {
14271 jam();
14272 warningHandlerLab(signal, __LINE__);
14273 return;
14274 }//if
14275 ptrAss(transPtr, apiConnectRecord);
14276 ApiConnectRecord * const regApiPtr = transPtr.p;
14277 TcIndexOperationPtr indexOpPtr;
14278 TcIndexOperation* indexOp;
14279
14280 if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
14281 {
14282 TCKEY_abort(signal, 19);
14283 return;
14284 }
14285
14286 if (regApiPtr->apiConnectstate == CS_ABORTING)
14287 {
14288 jam();
14289 return;
14290 }
14291
14292 if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
14293 {
14294 indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14295
14296 ndbassert( indexOp->pendingAttrInfo > 0 );
14297
14298 if (saveINDXATTRINFO(signal,
14299 indexOp,
14300 src,
14301 attrInfoLength) == 0) {
14302 jam();
14303 /* All KI + AI received, process */
14304 readIndexTable(signal, regApiPtr, indexOp);
14305 return;
14306 }
14307 return;
14308 }
14309 }
14310
14311 /**
14312 * Save received KeyInfo
14313 * Return true if we have received all needed data
14314 */
14315 int
saveINDXKEYINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)14316 Dbtc::saveINDXKEYINFO(Signal* signal,
14317 TcIndexOperation* indexOp,
14318 const Uint32 *src,
14319 Uint32 len)
14320 {
14321 if (ERROR_INSERTED(8052) ||
14322 ! appendToSection(indexOp->keyInfoSectionIVal,
14323 src,
14324 len))
14325 {
14326 jam();
14327 // Failed to seize keyInfo, abort transaction
14328 #ifdef VM_TRACE
14329 ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize buffer for KeyInfo\n");
14330 #endif
14331 // Abort transaction
14332 apiConnectptr.i = indexOp->connectionIndex;
14333 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14334 releaseIndexOperation(apiConnectptr.p, indexOp);
14335 terrorCode = 289;
14336 if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
14337 apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
14338 abortErrorLab(signal);
14339 return -1;
14340 }
14341 indexOp->pendingKeyInfo-= len;
14342
14343 if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
14344 jam();
14345 return 0;
14346 }
14347 return 1;
14348 }
14349
receivedAllINDXKEYINFO(TcIndexOperation * indexOp)14350 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
14351 {
14352 return (indexOp->pendingKeyInfo == 0);
14353 }
14354
14355 /**
14356 * Save signal INDXATTRINFO
14357 * Return true if we have received all needed data
14358 */
14359 int
saveINDXATTRINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)14360 Dbtc::saveINDXATTRINFO(Signal* signal,
14361 TcIndexOperation* indexOp,
14362 const Uint32 *src,
14363 Uint32 len)
14364 {
14365 if (ERROR_INSERTED(8051) ||
14366 ! appendToSection(indexOp->attrInfoSectionIVal,
14367 src,
14368 len))
14369 {
14370 jam();
14371 #ifdef VM_TRACE
14372 ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize buffer for attrInfo\n");
14373 #endif
14374 apiConnectptr.i = indexOp->connectionIndex;
14375 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14376 releaseIndexOperation(apiConnectptr.p, indexOp);
14377 terrorCode = 289;
14378 if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
14379 apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
14380 abortErrorLab(signal);
14381 return -1;
14382 }
14383
14384 indexOp->pendingAttrInfo-= len;
14385
14386 if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
14387 jam();
14388 return 0;
14389 }
14390 return 1;
14391 }
14392
receivedAllINDXATTRINFO(TcIndexOperation * indexOp)14393 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
14394 {
14395 return (indexOp->pendingAttrInfo == 0);
14396 }
14397
14398 #ifdef ERROR_INSERT
14399 extern bool ErrorImportActive;
14400 #endif
14401
saveTRANSID_AI(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)14402 bool Dbtc::saveTRANSID_AI(Signal* signal,
14403 TcIndexOperation* indexOp,
14404 const Uint32 *src,
14405 Uint32 len)
14406 {
14407 /* TransID_AI is received as a result of looking up a
14408 * unique index table
14409 * The unique index table is looked up using the index
14410 * key to receive a single attribute containing the
14411 * fragment holding the base table row and the base
14412 * table primary key.
14413 * This is later used to build a TCKEYREQ against the
14414 * base table.
14415 * In this method, we prepare a KEYINFO section for the
14416 * TCKEYREQ as we receive TRANSID_AI words.
14417 *
14418 * Expected TRANSID_AI words :
14419 *
14420 * Word(s) Description States
14421 *
14422 * 0 Attribute header ITAS_WAIT_HEADER
14423 * containing length -> ITAS_WAIT_FRAGID
14424 *
14425 * 1 Fragment Id ITAS_WAIT_FRAGID
14426 * -> ITAS_WAIT_KEY
14427 *
14428 * [2..N] Base table primary ITAS_WAIT_KEY
14429 * key info -> [ ITAS_WAIT_KEY |
14430 * ITAS_WAIT_KEY_FAIL ]
14431 * -> ITAS_ALL_RECEIVED
14432 *
14433 * The outgoing KeyInfo section contains the base
14434 * table primary key info, with the fragment id passed
14435 * as the distribution key.
14436 * ITAS_WAIT_KEY_FAIL state is entered when there is no
14437 * space to store received TRANSID_AI information and
14438 * key collection must fail. Transaction abort is performed
14439 * once all TRANSID_AI is received, and the system waits in
14440 * ITAS_WAIT_KEY_FAIL state until then.
14441 *
14442 */
14443 Uint32 remain= len;
14444
14445 while (remain != 0)
14446 {
14447 switch(indexOp->transIdAIState) {
14448 case ITAS_WAIT_HEADER:
14449 {
14450 jam();
14451 ndbassert(indexOp->transIdAISectionIVal == RNIL);
14452 /* Look at the first AttributeHeader to get the
14453 * expected size of the primary key attribute
14454 */
14455 AttributeHeader* head = (AttributeHeader *) src;
14456 ndbassert(head->getHeaderSize() == 1);
14457 indexOp->pendingTransIdAI = 1 + head->getDataSize();
14458
14459 src++;
14460 remain--;
14461 indexOp->transIdAIState = ITAS_WAIT_FRAGID;
14462 break;
14463 }
14464 case ITAS_WAIT_FRAGID:
14465 {
14466 jam();
14467 ndbassert(indexOp->transIdAISectionIVal == RNIL);
14468 /* Grab the fragment Id word */
14469 indexOp->fragmentId= *src;
14470
14471 src++;
14472 remain--;
14473 indexOp->transIdAIState = ITAS_WAIT_KEY;
14474 break;
14475 }
14476 case ITAS_WAIT_KEY:
14477 {
14478 jam();
14479 /* Add key information to long section */
14480 #ifdef ERROR_INSERT
14481 if (ERROR_INSERTED(8066))
14482 {
14483 ErrorImportActive = true;
14484 }
14485 #endif
14486
14487 bool res = appendToSection(indexOp->transIdAISectionIVal, src, remain);
14488 #ifdef ERROR_INSERT
14489 if (ERROR_INSERTED(8066))
14490 {
14491 ErrorImportActive = false;
14492 }
14493 #endif
14494
14495 if (res)
14496 {
14497 jam();
14498 remain= 0;
14499 break;
14500 }
14501 else
14502 {
14503 jam();
14504 #ifdef VM_TRACE
14505 ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize buffer for TRANSID_AI\n");
14506 #endif
14507 indexOp->transIdAIState= ITAS_WAIT_KEY_FAIL;
14508 /* Fall through to ITAS_WAIT_KEY_FAIL state handling */
14509 }
14510 }
14511
14512 case ITAS_WAIT_KEY_FAIL:
14513 {
14514 /* Failed when collecting key previously - if we have all the
14515 * TRANSID_AI now then we abort
14516 */
14517 if (indexOp->pendingTransIdAI > len)
14518 {
14519 /* Still some TransIdAI to arrive, keep waiting as if we had
14520 * stored it
14521 */
14522 remain= 0;
14523 break;
14524 }
14525
14526 /* All TransIdAI has arrived, abort */
14527 apiConnectptr.i = indexOp->connectionIndex;
14528 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14529 releaseIndexOperation(apiConnectptr.p, indexOp);
14530 terrorCode = ZGET_DATAREC_ERROR;
14531 abortErrorLab(signal);
14532 return false;
14533 }
14534
14535 case ITAS_ALL_RECEIVED:
14536 jam();
14537 // Fall through
14538 default:
14539 jam();
14540 /* Bad state, or bad state to receive TransId_Ai in */
14541 // Todo : Check error handling here.
14542 #ifdef VM_TRACE
14543 ndbout_c("Dbtc::saveTRANSID_AI: Bad state when receiving\n");
14544 #endif
14545 apiConnectptr.i = indexOp->connectionIndex;
14546 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14547 releaseIndexOperation(apiConnectptr.p, indexOp);
14548 terrorCode = 4349;
14549 abortErrorLab(signal);
14550 return false;
14551 } // switch
14552 } // while
14553
14554 if ((indexOp->pendingTransIdAI-= len) == 0)
14555 indexOp->transIdAIState = ITAS_ALL_RECEIVED;
14556
14557 return true;
14558 }
14559
receivedAllTRANSID_AI(TcIndexOperation * indexOp)14560 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
14561 {
14562 return (indexOp->transIdAIState == ITAS_ALL_RECEIVED);
14563 }
14564
14565 /**
14566 * Receive signal TCINDXCONF
14567 * This can be either the return of reading an index table
14568 * or performing an index operation
14569 */
execTCKEYCONF(Signal * signal)14570 void Dbtc::execTCKEYCONF(Signal* signal)
14571 {
14572 TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtr();
14573 TcIndexOperationPtr indexOpPtr;
14574
14575 jamEntry();
14576 indexOpPtr.i = tcKeyConf->apiConnectPtr;
14577 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14578 Uint32 confInfo = tcKeyConf->confInfo;
14579
14580 /**
14581 * Check on TCKEYCONF whether the the transaction was committed
14582 */
14583 ndbassert(TcKeyConf::getCommitFlag(confInfo) == false);
14584
14585 indexOpPtr.p = indexOp;
14586 if (!indexOp) {
14587 jam();
14588 // Missing index operation
14589 return;
14590 }
14591 const UintR TconnectIndex = indexOp->connectionIndex;
14592 ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
14593 apiConnectptr.p = regApiPtr;
14594 apiConnectptr.i = TconnectIndex;
14595 switch(indexOp->indexOpState) {
14596 case(IOS_NOOP): {
14597 jam();
14598 // Should never happen, abort
14599 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14600
14601 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14602 tcIndxRef->transId[0] = regApiPtr->transid[0];
14603 tcIndxRef->transId[1] = regApiPtr->transid[1];
14604 tcIndxRef->errorCode = 4349;
14605 tcIndxRef->errorData = 0;
14606 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14607 TcKeyRef::SignalLength, JBB);
14608 return;
14609 }
14610 case(IOS_INDEX_ACCESS): {
14611 jam();
14612 // Just waiting for the TRANSID_AI now
14613 indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
14614 break;
14615 }
14616 case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
14617 jam();
14618 // Double TCKEYCONF, should never happen, abort
14619 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14620
14621 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14622 tcIndxRef->transId[0] = regApiPtr->transid[0];
14623 tcIndxRef->transId[1] = regApiPtr->transid[1];
14624 tcIndxRef->errorCode = 4349;
14625 tcIndxRef->errorData = 0;
14626 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14627 TcKeyRef::SignalLength, JBB);
14628 return;
14629 }
14630 case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14631 jam();
14632 // Continue with index operation
14633 executeIndexOperation(signal, regApiPtr, indexOp);
14634 break;
14635 }
14636 }
14637 }
14638
execTCKEYREF(Signal * signal)14639 void Dbtc::execTCKEYREF(Signal* signal)
14640 {
14641 TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
14642 TcIndexOperationPtr indexOpPtr;
14643
14644 jamEntry();
14645 indexOpPtr.i = tcKeyRef->connectPtr;
14646 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14647 indexOpPtr.p = indexOp;
14648 if (!indexOp) {
14649 jam();
14650 // Missing index operation
14651 return;
14652 }
14653 const UintR TconnectIndex = indexOp->connectionIndex;
14654 ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
14655
14656 switch(indexOp->indexOpState) {
14657 case(IOS_NOOP): {
14658 jam();
14659 // Should never happen, abort
14660 break;
14661 }
14662 case(IOS_INDEX_ACCESS):
14663 case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
14664 case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14665 jam();
14666 // Send TCINDXREF
14667
14668 TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
14669 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14670
14671 tcIndxRef->connectPtr = tcIndxReq->senderData;
14672 tcIndxRef->transId[0] = tcKeyRef->transId[0];
14673 tcIndxRef->transId[1] = tcKeyRef->transId[1];
14674 tcIndxRef->errorCode = tcKeyRef->errorCode;
14675 tcIndxRef->errorData = 0;
14676
14677 releaseIndexOperation(regApiPtr, indexOp);
14678
14679 sendSignal(regApiPtr->ndbapiBlockref,
14680 GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
14681 return;
14682 }
14683 }
14684 }
14685
execTRANSID_AI_R(Signal * signal)14686 void Dbtc::execTRANSID_AI_R(Signal* signal){
14687 TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
14688 Uint32 sigLen = signal->length();
14689 Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
14690 Uint32 recBlockref = transIdAI->attrData[dataLen];
14691
14692 jamEntry();
14693
14694 SectionHandle handle(this, signal);
14695
14696 /**
14697 * Forward signal to final destination
14698 * Truncate last word since that was used to hold the final dest.
14699 */
14700 sendSignal(recBlockref, GSN_TRANSID_AI,
14701 signal, sigLen - 1, JBB,
14702 &handle);
14703 }
14704
execKEYINFO20_R(Signal * signal)14705 void Dbtc::execKEYINFO20_R(Signal* signal){
14706 KeyInfo20 * const keyInfo = (KeyInfo20 *)signal->getDataPtr();
14707 Uint32 sigLen = signal->length();
14708 Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
14709 Uint32 recBlockref = keyInfo->keyData[dataLen];
14710
14711 jamEntry();
14712
14713 SectionHandle handle(this, signal);
14714
14715 /**
14716 * Forward signal to final destination
14717 * Truncate last word since that was used to hold the final dest.
14718 */
14719 sendSignal(recBlockref, GSN_KEYINFO20,
14720 signal, sigLen - 1, JBB,
14721 &handle);
14722 }
14723
14724
14725 /**
14726 * execTRANSID_AI
14727 *
14728 * TRANSID_AI are received as a result of performing a read on
14729 * the index table as part of a (unique) index operation.
14730 * The data received is the primary key of the base table
14731 * which is then used to perform the index operation on the
14732 * base table.
14733 */
execTRANSID_AI(Signal * signal)14734 void Dbtc::execTRANSID_AI(Signal* signal)
14735 {
14736 TransIdAI * const transIdAI = (TransIdAI *)signal->getDataPtr();
14737
14738 jamEntry();
14739 TcIndexOperationPtr indexOpPtr;
14740 indexOpPtr.i = transIdAI->connectPtr;
14741 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14742 indexOpPtr.p = indexOp;
14743 if (!indexOp) {
14744 jam();
14745 // Missing index operation
14746 }
14747 const UintR TconnectIndex = indexOp->connectionIndex;
14748 ApiConnectRecordPtr transPtr;
14749
14750 transPtr.i = TconnectIndex;
14751 ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
14752 ApiConnectRecord * const regApiPtr = transPtr.p;
14753
14754 // Acccumulate attribute data
14755 SectionHandle handle(this, signal);
14756 bool longSignal = (handle.m_cnt == 1);
14757 if (longSignal)
14758 {
14759 SegmentedSectionPtr dataPtr;
14760 Uint32 dataLen;
14761 ndbrequire(handle.getSection(dataPtr, 0));
14762 dataLen = dataPtr.sz;
14763
14764 SectionSegment * ptrP = dataPtr.p;
14765 while (dataLen > NDB_SECTION_SEGMENT_SZ)
14766 {
14767 if (!saveTRANSID_AI(signal, indexOp, &ptrP->theData[0],
14768 NDB_SECTION_SEGMENT_SZ))
14769 {
14770 releaseSections(handle);
14771 goto save_error;
14772 }
14773 dataLen -= NDB_SECTION_SEGMENT_SZ;
14774 ptrP = g_sectionSegmentPool.getPtr(ptrP->m_nextSegment);
14775 }
14776 if (!saveTRANSID_AI(signal, indexOp, &ptrP->theData[0], dataLen))
14777 {
14778 releaseSections(handle);
14779 goto save_error;
14780 }
14781
14782 releaseSections(handle);
14783 }
14784 else
14785 {
14786 /* Short TransId_AI signal */
14787 if (!saveTRANSID_AI(signal,
14788 indexOp,
14789 transIdAI->getData(),
14790 signal->getLength() - TransIdAI::HeaderLength)) {
14791 save_error:
14792 jam();
14793 // Failed to allocate space for TransIdAI
14794 // Todo : How will this behave when transaction already aborted
14795 // in saveTRANSID_AI call?
14796 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14797
14798 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14799 tcIndxRef->transId[0] = regApiPtr->transid[0];
14800 tcIndxRef->transId[1] = regApiPtr->transid[1];
14801 tcIndxRef->errorCode = ZGET_DATAREC_ERROR;
14802 tcIndxRef->errorData = 0;
14803 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14804 TcKeyRef::SignalLength, JBB);
14805 return;
14806 }
14807 }
14808
14809 switch(indexOp->indexOpState) {
14810 case(IOS_NOOP): {
14811 jam();
14812 // Should never happen, abort
14813 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14814
14815 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14816 tcIndxRef->transId[0] = regApiPtr->transid[0];
14817 tcIndxRef->transId[1] = regApiPtr->transid[1];
14818 tcIndxRef->errorCode = 4349;
14819 tcIndxRef->errorData = 0;
14820 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14821 TcKeyRef::SignalLength, JBB);
14822 return;
14823 break;
14824 }
14825 case(IOS_INDEX_ACCESS): {
14826 jam();
14827 // Check if all TRANSID_AI have been received
14828 if (receivedAllTRANSID_AI(indexOp)) {
14829 jam();
14830 // Just waiting for a TCKEYCONF now
14831 indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
14832 }
14833 // else waiting for either TRANSID_AI or TCKEYCONF
14834 break;
14835 }
14836 case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14837 jam();
14838 #ifdef VM_TRACE
14839 ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
14840 #endif
14841 /*
14842 // Too many TRANSID_AI
14843 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14844
14845 tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
14846 tcIndxRef->transId[0] = regApiPtr->transid[0];
14847 tcIndxRef->transId[1] = regApiPtr->transid[1];
14848 tcIndxRef->errorCode = 4349;
14849 tcIndxRef->errorData = 0;
14850 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14851 TcKeyRef::SignalLength, JBB);
14852 */
14853 break;
14854 }
14855 case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
14856 jam();
14857 // Check if all TRANSID_AI have been received
14858 if (receivedAllTRANSID_AI(indexOp)) {
14859 jam();
14860 // Continue with index operation
14861 executeIndexOperation(signal, regApiPtr, indexOp);
14862 }
14863 // else continue waiting for more TRANSID_AI
14864 break;
14865 }
14866 }
14867 }
14868
execTCROLLBACKREP(Signal * signal)14869 void Dbtc::execTCROLLBACKREP(Signal* signal)
14870 {
14871 TcRollbackRep* tcRollbackRep = (TcRollbackRep *)signal->getDataPtr();
14872 jamEntry();
14873 TcIndexOperationPtr indexOpPtr;
14874 indexOpPtr.i = tcRollbackRep->connectPtr;
14875 TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14876 indexOpPtr.p = indexOp;
14877 tcRollbackRep = (TcRollbackRep *)signal->getDataPtrSend();
14878 tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
14879 sendSignal(apiConnectptr.p->ndbapiBlockref,
14880 GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
14881 }
14882
14883 /**
14884 * Read index table with the index attributes as PK
14885 */
readIndexTable(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)14886 void Dbtc::readIndexTable(Signal* signal,
14887 ApiConnectRecord* regApiPtr,
14888 TcIndexOperation* indexOp)
14889 {
14890 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
14891 Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
14892 TcIndexData* indexData;
14893 Uint32 transId1 = indexOp->tcIndxReq.transId1;
14894 Uint32 transId2 = indexOp->tcIndxReq.transId2;
14895
14896 const Operation_t opType =
14897 (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
14898
14899 // Find index table
14900 if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
14901 // TODO : Free KeyInfo and AttrInfo sections here if necessary
14902 // How is this operation cleaned up?
14903 jam();
14904 // Failed to find index record
14905 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14906
14907 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14908 tcIndxRef->transId[0] = regApiPtr->transid[0];
14909 tcIndxRef->transId[1] = regApiPtr->transid[1];
14910 tcIndxRef->errorCode = 4000;
14911 // tcIndxRef->errorData = ??; Where to find indexId
14912 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14913 TcKeyRef::SignalLength, JBB);
14914 return;
14915 }
14916 tcKeyReq->transId1 = transId1;
14917 tcKeyReq->transId2 = transId2;
14918 tcKeyReq->tableId = indexData->indexId;
14919 tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
14920 TcKeyReq::setOperationType(tcKeyRequestInfo,
14921 opType == ZREAD ? ZREAD : ZREAD_EX);
14922 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0); // No AI in long TCKEYREQ
14923 TcKeyReq::setInterpretedFlag(tcKeyRequestInfo, 0);
14924 tcKeyReq->senderData = indexOp->indexOpId;
14925 indexOp->indexOpState = IOS_INDEX_ACCESS;
14926 regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
14927 regApiPtr->accumulatingIndexOp = RNIL;
14928 regApiPtr->m_special_op_flags = TcConnectRecord::SOF_INDEX_TABLE_READ;
14929
14930 if (ERROR_INSERTED(8037))
14931 {
14932 ndbout_c("shifting index version");
14933 tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
14934 }
14935 tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
14936 tcKeyReq->requestInfo = tcKeyRequestInfo;
14937
14938 ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
14939 ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
14940
14941 /* Long TCKEYREQ Signal sections
14942 * We attach the KeyInfo section received from the user, and
14943 * create a new AttrInfo section with just one AttributeHeader
14944 * to retrieve the base table primary key
14945 */
14946 Ptr<SectionSegment> indexLookupAttrInfoSection;
14947 Uint32 singleAIWord;
14948
14949 AttributeHeader::init(&singleAIWord, indexData->primaryKeyPos, 0);
14950 if (! import(indexLookupAttrInfoSection,
14951 &singleAIWord,
14952 1))
14953 {
14954 jam();
14955 /* Error creating AttrInfo section to request primary
14956 * key from index table.
14957 */
14958 // TODO - verify error handling
14959 #ifdef VM_TRACE
14960 ndbout_c("Dbtc::readIndexTable: Failed to create AttrInfo section");
14961 #endif
14962 apiConnectptr.i = indexOp->connectionIndex;
14963 ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14964 releaseIndexOperation(apiConnectptr.p, indexOp);
14965 terrorCode = 4000;
14966 abortErrorLab(signal);
14967 return;
14968 }
14969
14970 ndbassert(signal->header.m_noOfSections == 0);
14971
14972 signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
14973 = indexOp->keyInfoSectionIVal;
14974
14975 /* We pass this section to TCKEYREQ next */
14976 indexOp->keyInfoSectionIVal= RNIL;
14977
14978 signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
14979 = indexLookupAttrInfoSection.i;
14980 signal->header.m_noOfSections= 2;
14981
14982 /* Direct execute of long TCKEYREQ
14983 * TCKEYREQ is responsible for freeing the KeyInfo and
14984 * AttrInfo sections passed to it
14985 */
14986 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
14987 jamEntry();
14988
14989 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
14990 {
14991 jam();
14992 }
14993 else
14994 {
14995 jam();
14996 /**
14997 * "Fool" TC not to start commiting transaction since it always will
14998 * have one outstanding lqhkeyreq
14999 * This is later decreased when the index read is complete
15000 */
15001 regApiPtr->lqhkeyreqrec++;
15002
15003 /**
15004 * Remember ptr to index read operation
15005 * (used to set correct save point id on index operation later)
15006 */
15007 indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
15008 }
15009
15010 return;
15011 }
15012
15013 /**
15014 * Execute the index operation with the result from
15015 * the index table read as PK
15016 */
executeIndexOperation(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)15017 void Dbtc::executeIndexOperation(Signal* signal,
15018 ApiConnectRecord* regApiPtr,
15019 TcIndexOperation* indexOp) {
15020
15021 TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
15022 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15023 Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
15024 TcIndexData* indexData;
15025
15026 // Find index table
15027 if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
15028 jam();
15029 // Failed to find index record
15030 // TODO : How is this operation cleaned up?
15031 TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
15032
15033 tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
15034 tcIndxRef->transId[0] = regApiPtr->transid[0];
15035 tcIndxRef->transId[1] = regApiPtr->transid[1];
15036 tcIndxRef->errorCode = 4349;
15037 tcIndxRef->errorData = 0;
15038 sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
15039 TcKeyRef::SignalLength, JBB);
15040 return;
15041 }
15042
15043 // Find schema version of primary table
15044 TableRecordPtr tabPtr;
15045 tabPtr.i = indexData->primaryTableId;
15046 ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
15047
15048 tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
15049 tcKeyReq->attrLen = tcIndxReq->attrLen;
15050 tcKeyReq->tableId = indexData->primaryTableId;
15051 tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
15052 tcKeyReq->transId1 = regApiPtr->transid[0];
15053 tcKeyReq->transId2 = regApiPtr->transid[1];
15054 tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
15055
15056 if (tabPtr.p->get_user_defined_partitioning())
15057 {
15058 jam();
15059 tcKeyReq->scanInfo = indexOp->fragmentId; // As read from Index table
15060 TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
15061 }
15062 regApiPtr->m_special_op_flags = 0;
15063 regApiPtr->executingIndexOp = 0;
15064
15065 /* KeyInfo section
15066 * Get the KeyInfo we received from the index table lookup
15067 */
15068 SegmentedSectionPtr keyInfoFromTransIdAI;
15069
15070 ndbassert( indexOp->transIdAISectionIVal != RNIL );
15071 getSection(keyInfoFromTransIdAI, indexOp->transIdAISectionIVal);
15072
15073 ndbassert( signal->header.m_noOfSections == 0 );
15074 signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
15075 = indexOp->transIdAISectionIVal;
15076 signal->header.m_noOfSections = 1;
15077
15078 indexOp->transIdAISectionIVal = RNIL;
15079
15080 /* AttrInfo section
15081 * Attach any AttrInfo section from original TCINDXREQ
15082 */
15083 if ( indexOp->attrInfoSectionIVal != RNIL )
15084 {
15085 jam();
15086 SegmentedSectionPtr attrInfoFromInitialReq;
15087
15088 getSection(attrInfoFromInitialReq, indexOp->attrInfoSectionIVal);
15089 signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
15090 = indexOp->attrInfoSectionIVal;
15091 signal->header.m_noOfSections = 2;
15092 indexOp->attrInfoSectionIVal = RNIL;
15093 }
15094
15095 releaseIndexOperation(regApiPtr, indexOp);
15096
15097 TcKeyReq::setKeyLength(tcKeyRequestInfo, keyInfoFromTransIdAI.sz);
15098 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15099 TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
15100 TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
15101 tcKeyReq->requestInfo = tcKeyRequestInfo;
15102
15103 ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
15104 ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
15105
15106 /**
15107 * Decrease lqhkeyreqrec to compensate for addition
15108 * during read of index table
15109 * I.e. let TC start committing when other operations has completed
15110 */
15111 regApiPtr->lqhkeyreqrec--;
15112
15113 /**
15114 * Fix savepoint id -
15115 * fix so that index operation has the same savepoint id
15116 * as the read of the index table (TCINDXREQ)
15117 */
15118 TcConnectRecordPtr tmp;
15119 tmp.i = indexOp->indexReadTcConnect;
15120 ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
15121 const Uint32 currSavePointId = regApiPtr->currSavePointId;
15122 regApiPtr->currSavePointId = tmp.p->savePointId;
15123
15124 #ifdef ERROR_INSERT
15125 bool err8072 = ERROR_INSERTED(8072);
15126 if (err8072)
15127 {
15128 CLEAR_ERROR_INSERT_VALUE;
15129 }
15130 #endif
15131
15132 /* Execute TCKEYREQ now - it is now responsible for freeing
15133 * the KeyInfo and AttrInfo sections
15134 */
15135 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15136 jamEntry();
15137
15138 #ifdef ERROR_INSERT
15139 if (err8072)
15140 {
15141 SET_ERROR_INSERT_VALUE(8072);
15142 }
15143 #endif
15144
15145 if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
15146 {
15147 // TODO : Presumably the abort cleans up the operation
15148 jam();
15149 return;
15150 }
15151
15152 regApiPtr->currSavePointId = currSavePointId;
15153
15154 }
15155
seizeIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperationPtr & indexOpPtr)15156 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
15157 TcIndexOperationPtr& indexOpPtr)
15158 {
15159 if (regApiPtr->theSeizedIndexOperations.seize(indexOpPtr))
15160 {
15161 ndbassert(indexOpPtr.p->pendingKeyInfo == 0);
15162 ndbassert(indexOpPtr.p->keyInfoSectionIVal == RNIL);
15163 ndbassert(indexOpPtr.p->pendingAttrInfo == 0);
15164 ndbassert(indexOpPtr.p->attrInfoSectionIVal == RNIL);
15165 ndbassert(indexOpPtr.p->transIdAIState == ITAS_WAIT_HEADER);
15166 ndbassert(indexOpPtr.p->pendingTransIdAI == 0);
15167 ndbassert(indexOpPtr.p->transIdAISectionIVal == RNIL);
15168 return true;
15169 }
15170
15171 return false;
15172 }
15173
releaseIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)15174 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
15175 TcIndexOperation* indexOp)
15176 {
15177 indexOp->indexOpState = IOS_NOOP;
15178 indexOp->pendingKeyInfo = 0;
15179 releaseSection(indexOp->keyInfoSectionIVal);
15180 indexOp->keyInfoSectionIVal= RNIL;
15181 indexOp->pendingAttrInfo = 0;
15182 releaseSection(indexOp->attrInfoSectionIVal);
15183 indexOp->attrInfoSectionIVal= RNIL;
15184 indexOp->transIdAIState = ITAS_WAIT_HEADER;
15185 indexOp->pendingTransIdAI = 0;
15186 releaseSection(indexOp->transIdAISectionIVal);
15187 indexOp->transIdAISectionIVal= RNIL;
15188 regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
15189 }
15190
releaseAllSeizedIndexOperations(ApiConnectRecord * regApiPtr)15191 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
15192 {
15193 TcIndexOperationPtr seizedIndexOpPtr;
15194
15195 regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
15196 while(seizedIndexOpPtr.i != RNIL) {
15197 jam();
15198 TcIndexOperation* indexOp = seizedIndexOpPtr.p;
15199
15200 indexOp->indexOpState = IOS_NOOP;
15201 indexOp->pendingKeyInfo = 0;
15202 releaseSection(indexOp->keyInfoSectionIVal);
15203 indexOp->keyInfoSectionIVal = RNIL;
15204 indexOp->pendingAttrInfo = 0;
15205 releaseSection(indexOp->attrInfoSectionIVal);
15206 indexOp->attrInfoSectionIVal = RNIL;
15207 indexOp->transIdAIState = ITAS_WAIT_HEADER;
15208 indexOp->pendingTransIdAI = 0;
15209 releaseSection(indexOp->transIdAISectionIVal);
15210 indexOp->transIdAISectionIVal = RNIL;
15211 regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
15212 }
15213 regApiPtr->theSeizedIndexOperations.release();
15214 }
15215
saveTriggeringOpState(Signal * signal,TcConnectRecord * trigOp)15216 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
15217 {
15218 LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
15219 copyFromToLen((UintR*)lqhKeyConf,
15220 &trigOp->savedState[0],
15221 LqhKeyConf::SignalLength);
15222 }
15223
15224 void
trigger_op_finished(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * triggeringOp)15225 Dbtc::trigger_op_finished(Signal* signal, ApiConnectRecordPtr regApiPtr,
15226 TcConnectRecord* triggeringOp)
15227 {
15228 if (!regApiPtr.p->isExecutingDeferredTriggers())
15229 {
15230 ndbassert(triggeringOp->triggerExecutionCount > 0);
15231 triggeringOp->triggerExecutionCount--;
15232 if (triggeringOp->triggerExecutionCount == 0)
15233 {
15234 /**
15235 * We have completed current trigger execution
15236 * Continue triggering operation
15237 */
15238 jam();
15239 continueTriggeringOp(signal, triggeringOp);
15240 }
15241 }
15242 else
15243 {
15244 jam();
15245 lqhKeyConf_checkTransactionState(signal, regApiPtr);
15246 }
15247 }
15248
continueTriggeringOp(Signal * signal,TcConnectRecord * trigOp)15249 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
15250 {
15251 LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
15252 copyFromToLen(&trigOp->savedState[0],
15253 (UintR*)lqhKeyConf,
15254 LqhKeyConf::SignalLength);
15255
15256 ndbassert(trigOp->savedState[LqhKeyConf::SignalLength-1] != ~Uint32(0));
15257 trigOp->savedState[LqhKeyConf::SignalLength-1] = ~Uint32(0);
15258
15259 lqhKeyConf->noFiredTriggers = 0;
15260 trigOp->noReceivedTriggers = 0;
15261
15262 // All triggers executed successfully, continue operation
15263 execLQHKEYCONF(signal);
15264 }
15265
executeTriggers(Signal * signal,ApiConnectRecordPtr * transPtr)15266 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
15267 {
15268 ApiConnectRecord* regApiPtr = transPtr->p;
15269 TcConnectRecord *localTcConnectRecord = tcConnectRecord;
15270 TcConnectRecordPtr opPtr;
15271 FiredTriggerPtr trigPtr;
15272
15273 if (!regApiPtr->theFiredTriggers.isEmpty()) {
15274 jam();
15275 if ((regApiPtr->apiConnectstate == CS_STARTED) ||
15276 (regApiPtr->apiConnectstate == CS_START_COMMITTING) ||
15277 (regApiPtr->apiConnectstate == CS_SEND_FIRE_TRIG_REQ) ||
15278 (regApiPtr->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ))
15279 {
15280 jam();
15281 regApiPtr->theFiredTriggers.first(trigPtr);
15282 while (trigPtr.i != RNIL) {
15283 jam();
15284 // Execute all ready triggers in parallel
15285 opPtr.i = trigPtr.p->fireingOperation;
15286 ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
15287 FiredTriggerPtr nextTrigPtr = trigPtr;
15288 regApiPtr->theFiredTriggers.next(nextTrigPtr);
15289 if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
15290 regApiPtr->isExecutingDeferredTriggers()) {
15291 jam();
15292 // Fireing operation is ready to have a trigger executing
15293 executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
15294 // Should allow for interleaving here by sending a CONTINUEB and
15295 // return
15296 // Release trigger records
15297 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15298 LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
15299 tmp1.release();
15300 LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
15301 tmp2.release();
15302 LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
15303 tmp3.release();
15304 regApiPtr->theFiredTriggers.release(trigPtr);
15305 }
15306 trigPtr = nextTrigPtr;
15307 }
15308 return;
15309 // No more triggers, continue transaction after last executed trigger has
15310 // reurned (in execLQHKEYCONF or execLQHKEYREF)
15311 } else {
15312
15313 jam();
15314 /* Not in correct state to fire triggers yet, need to wait
15315 * (or keep waiting)
15316 */
15317
15318 if ((regApiPtr->apiConnectstate == CS_RECEIVING) ||
15319 (regApiPtr->apiConnectstate == CS_REC_COMMITTING))
15320 {
15321 // Wait until transaction is ready to execute a trigger
15322 jam();
15323 if (!tc_testbit(regApiPtr->m_flags,
15324 ApiConnectRecord::TF_TRIGGER_PENDING))
15325 {
15326 jam();
15327 regApiPtr->m_flags |= ApiConnectRecord::TF_TRIGGER_PENDING;
15328 signal->theData[0] = TcContinueB::TRIGGER_PENDING;
15329 signal->theData[1] = transPtr->i;
15330 signal->theData[2] = regApiPtr->transid[0];
15331 signal->theData[3] = regApiPtr->transid[1];
15332 sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
15333 }
15334 // else
15335 // We are already waiting for a pending trigger (CONTINUEB)
15336 }
15337 else
15338 {
15339 /* Transaction has started aborting.
15340 * Forget about unprocessed triggers
15341 */
15342 ndbrequire(regApiPtr->apiConnectstate == CS_ABORTING);
15343 }
15344 }
15345 }
15346 }
15347
executeTrigger(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)15348 void Dbtc::executeTrigger(Signal* signal,
15349 TcFiredTriggerData* firedTriggerData,
15350 ApiConnectRecordPtr* transPtr,
15351 TcConnectRecordPtr* opPtr)
15352 {
15353 TcDefinedTriggerData* definedTriggerData;
15354
15355 if ((definedTriggerData =
15356 c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
15357 != NULL)
15358 {
15359 transPtr->p->pendingTriggers--;
15360 switch(firedTriggerData->triggerType) {
15361 case(TriggerType::SECONDARY_INDEX):
15362 jam();
15363 executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
15364 transPtr, opPtr);
15365 break;
15366 case TriggerType::REORG_TRIGGER:
15367 jam();
15368 executeReorgTrigger(signal, definedTriggerData, firedTriggerData,
15369 transPtr, opPtr);
15370 break;
15371 default:
15372 ndbrequire(false);
15373 }
15374 }
15375 }
15376
executeIndexTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)15377 void Dbtc::executeIndexTrigger(Signal* signal,
15378 TcDefinedTriggerData* definedTriggerData,
15379 TcFiredTriggerData* firedTriggerData,
15380 ApiConnectRecordPtr* transPtr,
15381 TcConnectRecordPtr* opPtr)
15382 {
15383 TcIndexData* indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
15384 ndbassert(indexData != NULL);
15385
15386 switch (firedTriggerData->triggerEvent) {
15387 case(TriggerEvent::TE_INSERT): {
15388 jam();
15389 insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15390 break;
15391 }
15392 case(TriggerEvent::TE_DELETE): {
15393 jam();
15394 deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15395 break;
15396 }
15397 case(TriggerEvent::TE_UPDATE): {
15398 jam();
15399 opPtr->p->triggerExecutionCount++; // One is already added...and this is 2
15400 deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15401 insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15402 break;
15403 }
15404 default:
15405 ndbrequire(false);
15406 }
15407 }
15408
releaseFiredTriggerData(DLFifoList<TcFiredTriggerData> * triggers)15409 void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
15410 {
15411 FiredTriggerPtr trigPtr;
15412
15413 triggers->first(trigPtr);
15414 while (trigPtr.i != RNIL) {
15415 jam();
15416 // Release trigger records
15417
15418 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15419 LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
15420 tmp1.release();
15421 LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
15422 tmp2.release();
15423 LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
15424 tmp3.release();
15425
15426 triggers->next(trigPtr);
15427 }
15428 triggers->release();
15429 }
15430
15431 /**
15432 * abortTransFromTrigger
15433 *
15434 * This method is called when there is a problem with trigger
15435 * handling and the transaction should be aborted with the
15436 * given error code
15437 */
abortTransFromTrigger(Signal * signal,const ApiConnectRecordPtr & transPtr,Uint32 error)15438 void Dbtc::abortTransFromTrigger(Signal* signal,
15439 const ApiConnectRecordPtr& transPtr,
15440 Uint32 error)
15441 {
15442 jam();
15443 terrorCode = error;
15444
15445 apiConnectptr = transPtr;
15446
15447 abortErrorLab(signal);
15448 }
15449
15450 /**
15451 * appendAttrDataToSection
15452 *
15453 * Copy data in AttrInfo form from the given databuffer
15454 * to the given section IVal (can be RNIL).
15455 * If attribute headers are to be copied they will be
15456 * renumbered consecutively, starting with the given
15457 * attrId.
15458 * hasNull is updated to indicate whether any Nulls
15459 * were encountered.
15460 */
appendAttrDataToSection(Uint32 & sectionIVal,DataBuffer<11> & values,bool withHeaders,Uint32 & attrId,bool & hasNull)15461 bool Dbtc::appendAttrDataToSection(Uint32& sectionIVal,
15462 DataBuffer<11>& values,
15463 bool withHeaders,
15464 Uint32& attrId,
15465 bool& hasNull)
15466 {
15467 AttributeBuffer::DataBufferIterator iter;
15468 bool moreData= values.first(iter);
15469 hasNull= false;
15470 const Uint32 segSize= values.getSegmentSize(); // 11
15471
15472 while (moreData)
15473 {
15474 AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
15475 Uint32 dataSize= attrHeader->getDataSize();
15476 hasNull |= (dataSize == 0);
15477
15478 if (withHeaders)
15479 {
15480 AttributeHeader ah(*iter.data);
15481 ah.setAttributeId(attrId); // Renumber AttrIds
15482 if (unlikely(!appendToSection(sectionIVal,
15483 &ah.m_value,
15484 1)))
15485 {
15486 releaseSection(sectionIVal);
15487 sectionIVal= RNIL;
15488 return false;
15489 }
15490 }
15491
15492 moreData= values.next(iter, 1);
15493
15494 while (dataSize)
15495 {
15496 ndbrequire(moreData);
15497 /* Copy as many contiguous words as possible */
15498 Uint32 contigLeft= segSize - iter.ind;
15499 ndbassert(contigLeft);
15500 Uint32 contigValid= MIN(dataSize, contigLeft);
15501
15502 if (unlikely(!appendToSection(sectionIVal,
15503 iter.data,
15504 contigValid)))
15505 {
15506 releaseSection(sectionIVal);
15507 sectionIVal= RNIL;
15508 return false;
15509 }
15510 moreData= values.next(iter, contigValid);
15511 dataSize-= contigValid;
15512 }
15513 attrId++;
15514 }
15515
15516 return true;
15517 }
15518
insertIntoIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)15519 void Dbtc::insertIntoIndexTable(Signal* signal,
15520 TcFiredTriggerData* firedTriggerData,
15521 ApiConnectRecordPtr* transPtr,
15522 TcConnectRecordPtr* opPtr,
15523 TcIndexData* indexData)
15524 {
15525 ApiConnectRecord* regApiPtr = transPtr->p;
15526 TcConnectRecord* opRecord = opPtr->p;
15527 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15528 Uint32 tcKeyRequestInfo = 0;
15529 TableRecordPtr indexTabPtr;
15530
15531 jam();
15532
15533 indexTabPtr.i = indexData->indexId;
15534 ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
15535 tcKeyReq->apiConnectPtr = transPtr->i;
15536 tcKeyReq->senderData = opPtr->i;
15537
15538 /* Key for insert to unique index table is the afterValues from the
15539 * base table operation (from update or insert on base).
15540 * Data for insert to unique index table is the afterValues from the
15541 * base table operation plus the fragment id and packed keyValues from
15542 * the base table operation
15543 */
15544 // Calculate key length and renumber attribute id:s
15545 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15546 LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
15547 LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
15548
15549 if (afterValues.getSize() == 0)
15550 {
15551 jam();
15552 ndbrequire(tc_testbit(regApiPtr->m_flags,
15553 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
15554 trigger_op_finished(signal, *transPtr, opRecord);
15555 return;
15556 }
15557
15558 Uint32 keyIVal= RNIL;
15559 Uint32 attrIVal= RNIL;
15560 bool appendOk= false;
15561 do
15562 {
15563 Uint32 attrId= 0;
15564 bool hasNull= false;
15565
15566 /* Build Insert KeyInfo section from aftervalues */
15567 if (unlikely(! appendAttrDataToSection(keyIVal,
15568 afterValues,
15569 false, // No AttributeHeaders
15570 attrId,
15571 hasNull)))
15572 {
15573 jam();
15574 break;
15575 }
15576
15577 if(ERROR_INSERTED(8086))
15578 {
15579 /* Simulate SS exhaustion */
15580 break;
15581 }
15582
15583 /* If there's Nulls in the values that become the index table's
15584 * PK then we skip this insert
15585 */
15586 if (hasNull)
15587 {
15588 jam();
15589 releaseSection(keyIVal);
15590 trigger_op_finished(signal, *transPtr, opRecord);
15591 return;
15592 }
15593
15594 /* Build Insert AttrInfo section from aftervalues,
15595 * fragment id + keyvalues
15596 */
15597 AttributeHeader ah(attrId, 0); // Length tbd.
15598 attrId= 0;
15599 if (unlikely((! appendAttrDataToSection(attrIVal,
15600 afterValues,
15601 true, // Include AttributeHeaders,
15602 attrId,
15603 hasNull)) ||
15604 (! appendToSection(attrIVal,
15605 &ah.m_value,
15606 1))))
15607 {
15608 jam();
15609 break;
15610 }
15611
15612 AttributeHeader* pkHeader= (AttributeHeader*) getLastWordPtr(attrIVal);
15613 Uint32 startSz= getSectionSz(attrIVal);
15614 if (unlikely((! appendToSection(attrIVal,
15615 &firedTriggerData->fragId,
15616 1)) ||
15617 (! appendAttrDataToSection(attrIVal,
15618 keyValues,
15619 false, // No AttributeHeaders
15620 attrId,
15621 hasNull))))
15622 {
15623 jam();
15624 break;
15625 }
15626
15627 appendOk= true;
15628
15629 /* Now go back and set pk header length */
15630 pkHeader->setDataSize(getSectionSz(attrIVal) - startSz);
15631 } while(0);
15632
15633 if (unlikely(!appendOk))
15634 {
15635 /* Some failure building up KeyInfo and AttrInfo */
15636 releaseSection(keyIVal);
15637 releaseSection(attrIVal);
15638 abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15639 return;
15640 }
15641
15642 /* Now build TcKeyReq for insert */
15643 TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15644 tcKeyReq->attrLen = 0;
15645 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15646 tcKeyReq->tableId = indexData->indexId;
15647 TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
15648 tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
15649 tcKeyReq->transId1 = regApiPtr->transid[0];
15650 tcKeyReq->transId2 = regApiPtr->transid[1];
15651 tcKeyReq->requestInfo = tcKeyRequestInfo;
15652
15653 /* Attach Key and AttrInfo sections to signal */
15654 ndbrequire(signal->header.m_noOfSections == 0);
15655 signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15656 signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
15657 signal->header.m_noOfSections= 2;
15658
15659 /*
15660 * Fix savepoint id -
15661 * fix so that insert has same savepoint id as triggering operation
15662 */
15663 const Uint32 currSavePointId = regApiPtr->currSavePointId;
15664 regApiPtr->currSavePointId = opRecord->savePointId;
15665 regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
15666 /* Pass trigger Id via ApiConnectRecord (nasty) */
15667 ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15668 regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15669
15670 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15671 jamEntry();
15672
15673 /*
15674 * Restore ApiConnectRecord state
15675 */
15676 regApiPtr->currSavePointId = currSavePointId;
15677 regApiPtr->immediateTriggerId = RNIL;
15678 }
15679
deleteFromIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)15680 void Dbtc::deleteFromIndexTable(Signal* signal,
15681 TcFiredTriggerData* firedTriggerData,
15682 ApiConnectRecordPtr* transPtr,
15683 TcConnectRecordPtr* opPtr,
15684 TcIndexData* indexData)
15685 {
15686 ApiConnectRecord* regApiPtr = transPtr->p;
15687 TcConnectRecord* opRecord = opPtr->p;
15688 TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15689 Uint32 tcKeyRequestInfo = 0;
15690 TableRecordPtr indexTabPtr;
15691
15692 indexTabPtr.i = indexData->indexId;
15693 ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
15694 tcKeyReq->apiConnectPtr = transPtr->i;
15695 tcKeyReq->senderData = opPtr->i;
15696
15697 // Calculate key length and renumber attribute id:s
15698 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15699 LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
15700
15701 Uint32 keyIVal= RNIL;
15702 Uint32 attrId= 0;
15703 bool hasNull= false;
15704
15705 if (beforeValues.getSize() == 0)
15706 {
15707 jam();
15708 ndbrequire(tc_testbit(regApiPtr->m_flags,
15709 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
15710 trigger_op_finished(signal, *transPtr, opRecord);
15711 return;
15712 }
15713
15714 /* Build Delete KeyInfo section from beforevalues */
15715 if (unlikely((! appendAttrDataToSection(keyIVal,
15716 beforeValues,
15717 false, // No AttributeHeaders
15718 attrId,
15719 hasNull)) ||
15720 ERROR_INSERTED(8086)))
15721 {
15722 jam();
15723 releaseSection(keyIVal);
15724 abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15725 return;
15726 }
15727
15728 /* If there's Nulls in the values that become the index table's
15729 * PK then we skip this delete
15730 */
15731 if (hasNull)
15732 {
15733 jam();
15734 releaseSection(keyIVal);
15735 trigger_op_finished(signal, *transPtr, opRecord);
15736 return;
15737 }
15738
15739 TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15740 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15741 tcKeyReq->attrLen = 0;
15742 tcKeyReq->tableId = indexData->indexId;
15743 TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
15744 tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
15745 tcKeyReq->transId1 = regApiPtr->transid[0];
15746 tcKeyReq->transId2 = regApiPtr->transid[1];
15747 tcKeyReq->requestInfo = tcKeyRequestInfo;
15748
15749 /* Attach KeyInfo section to signal */
15750 ndbrequire(signal->header.m_noOfSections == 0);
15751 signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15752 signal->header.m_noOfSections= 1;
15753
15754 /**
15755 * Fix savepoint id -
15756 * fix so that delete has same savepoint id as triggering operation
15757 */
15758 const Uint32 currSavePointId = regApiPtr->currSavePointId;
15759 regApiPtr->currSavePointId = opRecord->savePointId;
15760 regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
15761 /* Pass trigger Id via ApiConnectRecord (nasty) */
15762 ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15763 regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15764 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15765 jamEntry();
15766
15767 /*
15768 * Restore ApiConnectRecord state
15769 */
15770 regApiPtr->currSavePointId = currSavePointId;
15771 regApiPtr->immediateTriggerId = RNIL;
15772 }
15773
15774 Uint32
getErrorCode(Uint32 schemaVersion) const15775 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
15776 if(!get_enabled())
15777 return ZNO_SUCH_TABLE;
15778 if(get_dropping())
15779 return ZDROP_TABLE_IN_PROGRESS;
15780 if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
15781 return ZWRONG_SCHEMA_VERSION_ERROR;
15782 ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
15783 __FILE__, __LINE__);
15784 return 0;
15785 }
15786
executeReorgTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)15787 void Dbtc::executeReorgTrigger(Signal* signal,
15788 TcDefinedTriggerData* definedTriggerData,
15789 TcFiredTriggerData* firedTriggerData,
15790 ApiConnectRecordPtr* transPtr,
15791 TcConnectRecordPtr* opPtr)
15792 {
15793
15794 ApiConnectRecord* regApiPtr = transPtr->p;
15795 TcConnectRecord* opRecord = opPtr->p;
15796 TcKeyReq * tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15797
15798 tcKeyReq->apiConnectPtr = transPtr->i;
15799 tcKeyReq->senderData = opPtr->i;
15800
15801 AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15802 LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
15803 LocalDataBuffer<11> attrValues(pool, firedTriggerData->afterValues);
15804
15805 Uint32 optype;
15806 bool sendAttrInfo= true;
15807
15808 switch (firedTriggerData->triggerEvent) {
15809 case TriggerEvent::TE_INSERT:
15810 optype = ZINSERT;
15811 break;
15812 case TriggerEvent::TE_UPDATE:
15813 /**
15814 * Only update should be write, as COPY is done as update
15815 * a (maybe) better solution would be to have a different
15816 * trigger event for COPY
15817 */
15818 optype = ZWRITE;
15819 break;
15820 case TriggerEvent::TE_DELETE:
15821 optype = ZDELETE;
15822 sendAttrInfo= false;
15823 break;
15824 default:
15825 ndbrequire(false);
15826 }
15827
15828 Ptr<TableRecord> tablePtr;
15829 tablePtr.i = definedTriggerData->tableId;
15830 ptrCheckGuard(tablePtr, ctabrecFilesize, tableRecord);
15831 Uint32 tableVersion = tablePtr.p->currentSchemaVersion;
15832
15833 Uint32 tcKeyRequestInfo = 0;
15834 TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15835 TcKeyReq::setOperationType(tcKeyRequestInfo, optype);
15836 TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15837 tcKeyReq->attrLen = 0;
15838 tcKeyReq->tableId = tablePtr.i;
15839 tcKeyReq->requestInfo = tcKeyRequestInfo;
15840 tcKeyReq->tableSchemaVersion = tableVersion;
15841 tcKeyReq->transId1 = regApiPtr->transid[0];
15842 tcKeyReq->transId2 = regApiPtr->transid[1];
15843
15844 Uint32 keyIVal= RNIL;
15845 Uint32 attrIVal= RNIL;
15846 Uint32 attrId= 0;
15847 bool hasNull= false;
15848
15849 /* Prepare KeyInfo section */
15850 if (unlikely(!appendAttrDataToSection(keyIVal,
15851 keyValues,
15852 false, // No AttributeHeaders
15853 attrId,
15854 hasNull)))
15855 {
15856 releaseSection(keyIVal);
15857 abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15858 return;
15859 }
15860
15861 ndbrequire(!hasNull);
15862
15863 if (sendAttrInfo)
15864 {
15865 /* Prepare AttrInfo section from Key values and
15866 * After values
15867 */
15868 LocalDataBuffer<11>::Iterator attrIter;
15869 LocalDataBuffer<11>* buffers[2];
15870 buffers[0]= &keyValues;
15871 buffers[1]= &attrValues;
15872 const Uint32 segSize= keyValues.getSegmentSize(); // 11
15873 for (int buf=0; buf < 2; buf++)
15874 {
15875 Uint32 dataSize= buffers[buf]->getSize();
15876 bool moreData= buffers[buf]->first(attrIter);
15877
15878 while(dataSize)
15879 {
15880 ndbrequire(moreData);
15881 Uint32 contigLeft= segSize - attrIter.ind;
15882 Uint32 contigValid= MIN(dataSize, contigLeft);
15883
15884 if (unlikely(!appendToSection(attrIVal,
15885 attrIter.data,
15886 contigValid)))
15887 {
15888 releaseSection(keyIVal);
15889 releaseSection(attrIVal);
15890 abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15891 return;
15892 }
15893 moreData= buffers[buf]->next(attrIter, contigValid);
15894 dataSize-= contigValid;
15895 }
15896 ndbassert(!moreData);
15897 }
15898 }
15899
15900 /* Attach Key and optional AttrInfo sections to signal */
15901 ndbrequire(signal->header.m_noOfSections == 0);
15902 signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15903 signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
15904 signal->header.m_noOfSections= sendAttrInfo? 2 : 1;
15905
15906 /**
15907 * Fix savepoint id -
15908 * fix so that the op has same savepoint id as triggering operation
15909 */
15910 const Uint32 currSavePointId = regApiPtr->currSavePointId;
15911 regApiPtr->currSavePointId = opRecord->savePointId;
15912 regApiPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_TRIGGER;
15913 /* Pass trigger Id via ApiConnectRecord (nasty) */
15914 ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15915
15916 regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15917 EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15918 jamEntry();
15919
15920 /*
15921 * Restore ApiConnectRecord state
15922 */
15923 regApiPtr->currSavePointId = currSavePointId;
15924 regApiPtr->immediateTriggerId = RNIL;
15925 }
15926
15927 void
execROUTE_ORD(Signal * signal)15928 Dbtc::execROUTE_ORD(Signal* signal)
15929 {
15930 jamEntry();
15931 if(!assembleFragments(signal)){
15932 jam();
15933 return;
15934 }
15935
15936 SectionHandle handle(this, signal);
15937
15938 RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
15939 Uint32 dstRef = ord->dstRef;
15940 Uint32 srcRef = ord->srcRef;
15941 Uint32 gsn = ord->gsn;
15942
15943 if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
15944 {
15945 jam();
15946 Uint32 secCount = handle.m_cnt;
15947 ndbrequire(secCount >= 1 && secCount <= 3);
15948
15949 jamLine(secCount);
15950
15951 /**
15952 * Put section 0 in signal->theData
15953 */
15954 Uint32 sigLen = handle.m_ptr[0].sz;
15955 ndbrequire(sigLen <= 25);
15956 copy(signal->theData, handle.m_ptr[0]);
15957
15958 SegmentedSectionPtr save = handle.m_ptr[0];
15959 for (Uint32 i = 0; i < secCount - 1; i++)
15960 handle.m_ptr[i] = handle.m_ptr[i+1];
15961 handle.m_cnt--;
15962
15963 sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle);
15964
15965 handle.m_cnt = 1;
15966 handle.m_ptr[0] = save;
15967 releaseSections(handle);
15968 return ;
15969 }
15970
15971 releaseSections(handle);
15972 warningEvent("Unable to route GSN: %d from %x to %x",
15973 gsn, srcRef, dstRef);
15974
15975 }
15976