1 /* Copyright (c) 2003, 2021, Oracle and/or its affiliates.
2 
3    This program is free software; you can redistribute it and/or modify
4    it under the terms of the GNU General Public License, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
22 */
23 
24 #define DBTC_C
25 
26 #include "Dbtc.hpp"
27 #include "md5_hash.hpp"
28 #include <RefConvert.hpp>
29 #include <ndb_limits.h>
30 #include <ndb_rand.h>
31 
32 #include <signaldata/DiGetNodes.hpp>
33 #include <signaldata/EventReport.hpp>
34 #include <signaldata/TcKeyReq.hpp>
35 #include <signaldata/TcKeyConf.hpp>
36 #include <signaldata/TcKeyRef.hpp>
37 #include <signaldata/KeyInfo.hpp>
38 #include <signaldata/AttrInfo.hpp>
39 #include <signaldata/TransIdAI.hpp>
40 #include <signaldata/TcRollbackRep.hpp>
41 #include <signaldata/NodeFailRep.hpp>
42 #include <signaldata/ReadNodesConf.hpp>
43 #include <signaldata/NFCompleteRep.hpp>
44 #include <signaldata/LqhKey.hpp>
45 #include <signaldata/TcCommit.hpp>
46 #include <signaldata/TcContinueB.hpp>
47 #include <signaldata/TcKeyFailConf.hpp>
48 #include <signaldata/AbortAll.hpp>
49 #include <signaldata/DihScanTab.hpp>
50 #include <signaldata/ScanFrag.hpp>
51 #include <signaldata/ScanTab.hpp>
52 #include <signaldata/PrepDropTab.hpp>
53 #include <signaldata/DropTab.hpp>
54 #include <signaldata/AlterTab.hpp>
55 #include <signaldata/CreateTrig.hpp>
56 #include <signaldata/CreateTrigImpl.hpp>
57 #include <signaldata/DropTrig.hpp>
58 #include <signaldata/DropTrigImpl.hpp>
59 #include <signaldata/FireTrigOrd.hpp>
60 #include <signaldata/TrigAttrInfo.hpp>
61 #include <signaldata/CreateIndx.hpp>
62 #include <signaldata/CreateIndxImpl.hpp>
63 #include <signaldata/DropIndx.hpp>
64 #include <signaldata/DropIndxImpl.hpp>
65 #include <signaldata/AlterIndx.hpp>
66 #include <signaldata/AlterIndxImpl.hpp>
67 #include <signaldata/ScanTab.hpp>
68 #include <signaldata/SystemError.hpp>
69 #include <signaldata/DumpStateOrd.hpp>
70 #include <signaldata/DisconnectRep.hpp>
71 #include <signaldata/TcHbRep.hpp>
72 
73 #include <signaldata/PrepDropTab.hpp>
74 #include <signaldata/DropTab.hpp>
75 #include <signaldata/TcIndx.hpp>
76 #include <signaldata/IndxKeyInfo.hpp>
77 #include <signaldata/IndxAttrInfo.hpp>
78 #include <signaldata/PackedSignal.hpp>
79 #include <signaldata/SignalDroppedRep.hpp>
80 #include <signaldata/LqhTransReq.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 #include <TransporterRegistry.hpp> // error 8035
99 #include <EventLogger.hpp>
100 
101 #include <signaldata/CreateFKImpl.hpp>
102 #include <signaldata/DropFKImpl.hpp>
103 #include <kernel/Interpreter.hpp>
104 #include <signaldata/TuxBound.hpp>
105 
106 #define JAM_FILE_ID 353
107 
108 #define TC_TIME_SIGNAL_DELAY 50
109 
110 extern EventLogger * g_eventLogger;
111 
112 // Use DEBUG to print messages that should be
113 // seen only when we debug the product
114 #ifdef VM_TRACE
115 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
116 #else
117 #define DEBUG(x)
118 #endif
119 
120 #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
121 
122 #ifdef VM_TRACE
123 NdbOut &
operator <<(NdbOut & out,Dbtc::ConnectionState state)124 operator<<(NdbOut& out, Dbtc::ConnectionState state){
125   switch(state){
126   case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
127   case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
128   case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
129   case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
130   case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
131   case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
132   case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
133   case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
134   case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
135   case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
136   case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
137   case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
138   case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
139   case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
140   case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
141   case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
142   case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
143   case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
144   case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
145   case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
146   case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
147   case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
148   case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
149   default:
150     out << "Unknown: " << (int)state; break;
151   }
152   return out;
153 }
154 NdbOut &
operator <<(NdbOut & out,Dbtc::OperationState state)155 operator<<(NdbOut& out, Dbtc::OperationState state){
156   out << (int)state;
157   return out;
158 }
159 NdbOut &
operator <<(NdbOut & out,Dbtc::AbortState state)160 operator<<(NdbOut& out, Dbtc::AbortState state){
161   out << (int)state;
162   return out;
163 }
164 NdbOut &
operator <<(NdbOut & out,Dbtc::ReturnSignal state)165 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
166   out << (int)state;
167   return out;
168 }
169 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanRecord::ScanState state)170 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
171   out << (int)state;
172   return out;
173 }
174 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanFragRec::ScanFragState state)175 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
176   out << (int)state;
177   return out;
178 }
179 #endif
180 
181 extern int ErrorSignalReceive;
182 extern int ErrorMaxSegmentsToSeize;
183 
184 void
updateBuddyTimer(ApiConnectRecordPtr apiPtr)185 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
186 {
187   if (apiPtr.p->buddyPtr != RNIL) {
188     jam();
189     ApiConnectRecordPtr buddyApiPtr;
190     buddyApiPtr.i = apiPtr.p->buddyPtr;
191     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
192     if (getApiConTimer(buddyApiPtr.i) != 0) {
193       if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
194           (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
195         jam();
196         setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
197       } else {
198         jam();
199         // Not a buddy anymore since not the same transid
200         apiPtr.p->buddyPtr = RNIL;
201       }//if
202     }//if
203   }//if
204 }
205 
206 static
207 inline
208 bool
tc_testbit(Uint32 flags,Uint32 flag)209 tc_testbit(Uint32 flags, Uint32 flag)
210 {
211   return (flags & flag) != 0;
212 }
213 
214 static
215 inline
216 void
tc_clearbit(Uint32 & flags,Uint32 flag)217 tc_clearbit(Uint32 & flags, Uint32 flag)
218 {
219   flags &= ~(Uint32)flag;
220 }
221 
execCONTINUEB(Signal * signal)222 void Dbtc::execCONTINUEB(Signal* signal)
223 {
224   UintR tcase;
225 
226   jamEntry();
227   tcase = signal->theData[0];
228   UintR Tdata0 = signal->theData[1];
229   UintR Tdata1 = signal->theData[2];
230   UintR Tdata2 = signal->theData[3];
231   UintR Tdata3 = signal->theData[4];
232 #ifdef ERROR_INSERT
233   UintR Tdata4 = signal->theData[5];
234   UintR Tdata5 = signal->theData[6];
235 #endif
236   switch (tcase) {
237   case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
238     jam();
239     ndbrequire(false);
240     return;
241   case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
242     jam();
243     tcNodeFailptr.i = Tdata0;
244     ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
245     completeTransAtTakeOverLab(signal, Tdata1);
246     return;
247   case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
248     jam();
249     timeOutLoopStartLab(signal, Tdata0);
250     return;
251   case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
252     jam();
253     tcNodeFailptr.i = 0;
254     ptrAss(tcNodeFailptr, tcFailRecord);
255     nodeTakeOverCompletedLab(signal, Tdata0, 0);
256     return;
257   case TcContinueB::ZINITIALISE_RECORDS:
258     jam();
259     initialiseRecordsLab(signal, Tdata0, Tdata2, Tdata3);
260     return;
261   case TcContinueB::ZSEND_COMMIT_LOOP:
262     jam();
263     apiConnectptr.i = Tdata0;
264     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
265     tcConnectptr.i = Tdata1;
266     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
267     commit020Lab(signal);
268     return;
269   case TcContinueB::ZSEND_COMPLETE_LOOP:
270     jam();
271     apiConnectptr.i = Tdata0;
272     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
273     tcConnectptr.i = Tdata1;
274     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
275     complete010Lab(signal);
276     return;
277   case TcContinueB::ZHANDLE_FAILED_API_NODE:
278     jam();
279     handleFailedApiNode(signal, Tdata0, Tdata1);
280     return;
281   case TcContinueB::ZTRANS_EVENT_REP:
282     jam();
283     /* Send transaction counters report */
284     {
285       const Uint32 len = c_counters.build_event_rep(signal);
286       sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
287     }
288 
289     {
290       const Uint32 report_interval = 5000;
291       const Uint32 len = c_counters.build_continueB(signal);
292       signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
293       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, report_interval, len);
294     }
295     return;
296   case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
297     jam();
298     timeOutLoopStartFragLab(signal, Tdata0);
299     return;
300   case TcContinueB::ZABORT_BREAK:
301     jam();
302     tcConnectptr.i = Tdata0;
303     apiConnectptr.i = Tdata1;
304     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
305     apiConnectptr.p->counter--;
306     abort015Lab(signal);
307     return;
308   case TcContinueB::ZABORT_TIMEOUT_BREAK:
309     jam();
310     tcConnectptr.i = Tdata0;
311     apiConnectptr.i = Tdata1;
312     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
313     apiConnectptr.p->counter--;
314     sendAbortedAfterTimeout(signal, 1);
315     return;
316   case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
317     jam();
318     removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
319     return;
320   case TcContinueB::ZWAIT_ABORT_ALL:
321     jam();
322     checkAbortAllTimeout(signal, Tdata0);
323     return;
324   case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
325     jam();
326     checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
327     return;
328   case TcContinueB::ZNF_CHECK_TRANSACTIONS:
329     jam();
330     nodeFailCheckTransactions(signal, Tdata0, Tdata1);
331     return;
332   case TcContinueB::TRIGGER_PENDING:
333   {
334     jam();
335     ApiConnectRecordPtr transPtr;
336     transPtr.i = Tdata0;
337     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
338 #ifdef ERROR_INSERT
339     if (ERROR_INSERTED(8082))
340     {
341       /* Max of 100000 TRIGGER_PENDING TcContinueBs to
342        * single ApiConnectRecord
343        * See testBlobs -bug 45768
344        */
345       if (++transPtr.p->continueBCount > 100000)
346       {
347         ndbrequire(false);
348       }
349     }
350 #endif
351     /* Check that ConnectRecord is for the same Trans Id */
352     if (likely((transPtr.p->transid[0] == Tdata1) &&
353                (transPtr.p->transid[1] == Tdata2)))
354     {
355       ndbrequire(tc_testbit(transPtr.p->m_flags,
356                             ApiConnectRecord::TF_TRIGGER_PENDING));
357       tc_clearbit(transPtr.p->m_flags, ApiConnectRecord::TF_TRIGGER_PENDING);
358       /* Try executing triggers now */
359       executeTriggers(signal, &transPtr);
360     }
361     return;
362   }
363   case TcContinueB::DelayTCKEYCONF:
364     jam();
365     apiConnectptr.i = Tdata0;
366     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
367     sendtckeyconf(signal, Tdata1);
368     return;
369   case TcContinueB::ZSEND_FIRE_TRIG_REQ:
370     jam();
371     apiConnectptr.i = Tdata0;
372     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
373     if (unlikely(! (apiConnectptr.p->transid[0] == Tdata1 &&
374                     apiConnectptr.p->transid[1] == Tdata2 &&
375                     apiConnectptr.p->apiConnectstate == CS_SEND_FIRE_TRIG_REQ)))
376     {
377       warningReport(signal, 29);
378       return;
379     }
380     ndbrequire(apiConnectptr.p->lqhkeyreqrec > 0);
381     apiConnectptr.p->lqhkeyreqrec--; // UNDO: prevent early completion
382 
383     sendFireTrigReq(signal, apiConnectptr,
384                     signal->theData[4],
385                     signal->theData[5]);
386     return;
387   case TcContinueB::ZSTART_FRAG_SCANS:
388   {
389     jam();
390     SectionHandle handle(this, signal);
391     startFragScansLab(signal, Tdata0, handle, Tdata1);
392     return;
393   }
394 #ifdef ERROR_INSERT
395   case TcContinueB::ZDEBUG_DELAYED_ABORT:
396   {
397     char buf[128];
398     BaseString::snprintf(buf, sizeof(buf), "Received CONTINUEB:ZDEBUG_DELAYED_ABORT");
399     warningEvent("%s", buf);
400 
401     jam();
402     apiConnectptr.i = Tdata0;
403     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
404     apiConnectptr.p->returncode = Tdata3;
405     apiConnectptr.p->returnsignal = (Dbtc::ReturnSignal)Tdata4;
406     SET_ERROR_INSERT_VALUE(Tdata5);
407     abort010Lab(signal);
408     break;
409   }
410   case TcContinueB::ZDEBUG_DELAY_TCROLLBACKREP:
411   {
412     char buf[128];
413     BaseString::snprintf(buf, sizeof(buf), "Received CONTINUEB:ZDEBUG_DELAY_TCROLLBACKREP");
414     warningEvent("%s", buf);
415 
416     jam();
417     if (ERROR_INSERTED(8101))
418     {
419       jam();
420       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 6);
421     }
422     else
423     {
424       TcRollbackRep * const tcRollbackRep =
425         (TcRollbackRep *) signal->getDataPtr();
426       Uint32 blockRef = Tdata5;
427 
428       tcRollbackRep->connectPtr = Tdata0;
429       tcRollbackRep->transId[0] = Tdata1;
430       tcRollbackRep->transId[1] = Tdata2;
431       tcRollbackRep->returnCode = Tdata3;
432       tcRollbackRep->errorData = Tdata4;
433       sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
434                  TcRollbackRep::SignalLength, JBB);
435     }
436     break;
437   }
438 #endif
439   default:
440     ndbrequire(false);
441   }//switch
442 }
443 
execDIGETNODESREF(Signal * signal)444 void Dbtc::execDIGETNODESREF(Signal* signal)
445 {
446   jamEntry();
447   terrorCode = signal->theData[1];
448   releaseAtErrorLab(signal);
449 }
450 
execINCL_NODEREQ(Signal * signal)451 void Dbtc::execINCL_NODEREQ(Signal* signal)
452 {
453   jamEntry();
454   tblockref = signal->theData[0];
455   hostptr.i = signal->theData[1];
456   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
457   hostptr.p->hostStatus = HS_ALIVE;
458   c_alive_nodes.set(hostptr.i);
459 
460   signal->theData[0] = hostptr.i;
461   signal->theData[1] = cownref;
462 
463   if (ERROR_INSERTED(8039))
464   {
465     CLEAR_ERROR_INSERT_VALUE;
466     Uint32 save = signal->theData[0];
467     signal->theData[0] = 9999;
468     sendSignal(numberToRef(CMVMI, hostptr.i),
469 	       GSN_NDB_TAMPER, signal, 1, JBB);
470     signal->theData[0] = save;
471     sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
472     return;
473   }
474 
475   Uint32 Tnode = hostptr.i;
476 
477   sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
478 
479   if (m_deferred_enabled)
480   {
481     jam();
482     if (!ndbd_deferred_unique_constraints(getNodeInfo(Tnode).m_version))
483     {
484       jam();
485       m_deferred_enabled = 0;
486     }
487   }
488 }
489 
execREAD_NODESREF(Signal * signal)490 void Dbtc::execREAD_NODESREF(Signal* signal)
491 {
492   jamEntry();
493   ndbrequire(false);
494 }
495 
496 // create table prepare
execTC_SCHVERREQ(Signal * signal)497 void Dbtc::execTC_SCHVERREQ(Signal* signal)
498 {
499   jamEntry();
500   if (! assembleFragments(signal)) {
501     jam();
502     return;
503   }
504   const TcSchVerReq* req = CAST_CONSTPTR(TcSchVerReq, signal->getDataPtr());
505   tabptr.i = req->tableId;
506   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
507   tabptr.p->currentSchemaVersion = req->tableVersion;
508   tabptr.p->m_flags = 0;
509   tabptr.p->set_storedTable((bool)req->tableLogged);
510   BlockReference retRef = req->senderRef;
511   tabptr.p->tableType = (Uint8)req->tableType;
512   BlockReference retPtr = req->senderData;
513   Uint32 noOfKeyAttr = req->noOfPrimaryKeys;
514   tabptr.p->singleUserMode = (Uint8)req->singleUserMode;
515   Uint32 userDefinedPartitioning = (Uint8)req->userDefinedPartition;
516   ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
517 
518   const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
519   ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
520 
521   ndbrequire(tabptr.p->get_prepared() == false);
522   ndbrequire(tabptr.p->get_enabled() == false);
523   tabptr.p->set_prepared(true);
524   tabptr.p->set_enabled(false);
525   tabptr.p->set_dropping(false);
526   tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
527   tabptr.p->hasCharAttr = desc->hasCharAttr;
528   tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
529   tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
530   tabptr.p->set_user_defined_partitioning(userDefinedPartitioning);
531 
532   TcSchVerConf * conf = (TcSchVerConf*)signal->getDataPtr();
533   conf->senderRef = reference();
534   conf->senderData = retPtr;
535   sendSignal(retRef, GSN_TC_SCHVERCONF, signal,
536              TcSchVerConf::SignalLength, JBB);
537 }//Dbtc::execTC_SCHVERREQ()
538 
539 // create table commit
execTAB_COMMITREQ(Signal * signal)540 void Dbtc::execTAB_COMMITREQ(Signal* signal)
541 {
542   jamEntry();
543   Uint32 senderData = signal->theData[0];
544   Uint32 senderRef = signal->theData[1];
545   tabptr.i = signal->theData[2];
546   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
547 
548   ndbrequire(tabptr.p->get_prepared() == true);
549   ndbrequire(tabptr.p->get_enabled() == false);
550   tabptr.p->set_enabled(true);
551   tabptr.p->set_prepared(false);
552   tabptr.p->set_dropping(false);
553 
554   signal->theData[0] = senderData;
555   signal->theData[1] = reference();
556   signal->theData[2] = tabptr.i;
557   sendSignal(senderRef, GSN_TAB_COMMITCONF, signal, 3, JBB);
558 }
559 
560 void
execPREP_DROP_TAB_REQ(Signal * signal)561 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
562 {
563   jamEntry();
564 
565   PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
566 
567   TableRecordPtr tabPtr;
568   tabPtr.i = req->tableId;
569   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
570 
571   Uint32 senderRef = req->senderRef;
572   Uint32 senderData = req->senderData;
573 
574   if(!tabPtr.p->get_enabled())
575   {
576     jam();
577     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
578     ref->senderRef = reference();
579     ref->senderData = senderData;
580     ref->tableId = tabPtr.i;
581     ref->errorCode = PrepDropTabRef::NoSuchTable;
582     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
583 	       PrepDropTabRef::SignalLength, JBB);
584     return;
585   }
586 
587   if(tabPtr.p->get_dropping())
588   {
589     jam();
590     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
591     ref->senderRef = reference();
592     ref->senderData = senderData;
593     ref->tableId = tabPtr.i;
594     ref->errorCode = PrepDropTabRef::DropInProgress;
595     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
596 	       PrepDropTabRef::SignalLength, JBB);
597     return;
598   }
599 
600   tabPtr.p->set_dropping(true);
601   tabPtr.p->set_prepared(false);
602 
603   PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
604   conf->tableId = tabPtr.i;
605   conf->senderRef = reference();
606   conf->senderData = senderData;
607   sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
608              PrepDropTabConf::SignalLength, JBB);
609 }
610 
611 void
execDROP_TAB_REQ(Signal * signal)612 Dbtc::execDROP_TAB_REQ(Signal* signal)
613 {
614   jamEntry();
615 
616   DropTabReq* req = (DropTabReq*)signal->getDataPtr();
617 
618   TableRecordPtr tabPtr;
619   tabPtr.i = req->tableId;
620   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
621 
622   Uint32 senderRef = req->senderRef;
623   Uint32 senderData = req->senderData;
624   DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
625 
626   if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
627     jam();
628     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
629     ref->senderRef = reference();
630     ref->senderData = senderData;
631     ref->tableId = tabPtr.i;
632     ref->errorCode = DropTabRef::NoSuchTable;
633     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
634 	       DropTabRef::SignalLength, JBB);
635     return;
636   }
637 
638   if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
639     jam();
640     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
641     ref->senderRef = reference();
642     ref->senderData = senderData;
643     ref->tableId = tabPtr.i;
644     ref->errorCode = DropTabRef::DropWoPrep;
645     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
646 	       DropTabRef::SignalLength, JBB);
647     return;
648   }
649 
650   tabPtr.p->set_enabled(false);
651   tabPtr.p->set_prepared(false);
652   tabPtr.p->set_dropping(false);
653 
654   DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
655   conf->tableId = tabPtr.i;
656   conf->senderRef = reference();
657   conf->senderData = senderData;
658   sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
659 	     PrepDropTabConf::SignalLength, JBB);
660 }
661 
execALTER_TAB_REQ(Signal * signal)662 void Dbtc::execALTER_TAB_REQ(Signal * signal)
663 {
664   const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
665   const Uint32 senderRef = req->senderRef;
666   const Uint32 senderData = req->senderData;
667   const Uint32 tableVersion = req->tableVersion;
668   const Uint32 newTableVersion = req->newTableVersion;
669   AlterTabReq::RequestType requestType =
670     (AlterTabReq::RequestType) req->requestType;
671 
672   TableRecordPtr tabPtr;
673   tabPtr.i = req->tableId;
674   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
675 
676   switch (requestType) {
677   case AlterTabReq::AlterTablePrepare:
678     jam();
679     break;
680   case AlterTabReq::AlterTableRevert:
681     jam();
682     tabPtr.p->currentSchemaVersion = tableVersion;
683     break;
684   case AlterTabReq::AlterTableCommit:
685     jam();
686     tabPtr.p->currentSchemaVersion = newTableVersion;
687     break;
688   default:
689     ndbrequire(false);
690     break;
691   }
692 
693   // Request handled successfully
694   AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
695   conf->senderRef = reference();
696   conf->senderData = senderData;
697   conf->connectPtr = RNIL;
698   sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
699 	     AlterTabConf::SignalLength, JBB);
700 }
701 
702 /* ***************************************************************************/
703 /*                                START / RESTART                            */
704 /* ***************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)705 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
706 {
707   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
708   Uint32 ref = req->senderRef;
709   Uint32 senderData = req->senderData;
710   ndbrequire(req->noOfParameters == 0);
711 
712   jamEntry();
713 
714   const ndb_mgm_configuration_iterator * p =
715     m_ctx.m_config.getOwnConfigIterator();
716   ndbrequire(p != 0);
717 
718   initData();
719 
720   UintR apiConnect;
721   UintR tcConnect;
722   UintR tables;
723   UintR localScan;
724   UintR tcScan;
725 
726   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
727   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
728   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
729   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
730   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
731 
732   ccacheFilesize = (apiConnect/3) + 1;
733   capiConnectFilesize = apiConnect;
734   ctcConnectFilesize  = tcConnect;
735   ctabrecFilesize     = tables;
736   cscanrecFileSize = tcScan;
737   cscanFragrecFileSize = localScan;
738 
739   initRecords();
740   initialiseRecordsLab(signal, 0, ref, senderData);
741 
742   Uint32 val = 3000;
743   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
744   set_timeout_value(val);
745 
746   val = 1500;
747   ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
748   cDbHbInterval = (val < 10) ? 10 : val;
749 
750   val = 3000;
751   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
752   set_appl_timeout_value(val);
753 
754   val = 1;
755   //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
756   set_no_parallel_takeover(val);
757 
758   val = ~(Uint32)0;
759   ndb_mgm_get_int_parameter(p, CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION, &val);
760   m_max_writes_per_trans = val;
761 
762   ctimeOutCheckDelay = 50; // 500ms
763   ctimeOutCheckDelayScan = 40; // 400ms
764 
765   Pool_context pc;
766   pc.m_block = this;
767 
768   c_fk_hash.setSize(16);
769   c_fk_pool.init(RT_DBDICT_FILE, pc); // TODO
770 }
771 
execSTTOR(Signal * signal)772 void Dbtc::execSTTOR(Signal* signal)
773 {
774   Uint16 tphase;
775 
776   jamEntry();
777                                                      /* START CASE */
778   tphase = signal->theData[1];
779   csignalKey = signal->theData[6];
780   c_sttor_ref = signal->getSendersBlockRef();
781   switch (tphase) {
782   case ZSPH1:
783     jam();
784     startphase1x010Lab(signal);
785     return;
786   default:
787     jam();
788     sttorryLab(signal); /* START PHASE 255 */
789     return;
790   }//switch
791 }//Dbtc::execSTTOR()
792 
sttorryLab(Signal * signal)793 void Dbtc::sttorryLab(Signal* signal)
794 {
795   signal->theData[0] = csignalKey;
796   signal->theData[1] = 3;    /* BLOCK CATEGORY */
797   signal->theData[2] = 2;    /* SIGNAL VERSION NUMBER */
798   signal->theData[3] = ZSPH1;
799   signal->theData[4] = 255;
800   sendSignal(c_sttor_ref, GSN_STTORRY, signal, 5, JBB);
801 }//Dbtc::sttorryLab()
802 
803 /* ***************************************************************************/
804 /*                          INTERNAL  START / RESTART                        */
805 /*****************************************************************************/
execNDB_STTOR(Signal * signal)806 void Dbtc::execNDB_STTOR(Signal* signal)
807 {
808   Uint16 tndbstartphase;
809   Uint16 tstarttype;
810 
811   jamEntry();
812   tusersblkref = signal->theData[0];
813   NodeId nodeId = signal->theData[1];
814   tndbstartphase = signal->theData[2];   /* START PHASE      */
815   tstarttype = signal->theData[3];       /* START TYPE       */
816   c_sttor_ref = signal->getSendersBlockRef();
817   switch (tndbstartphase) {
818   case ZINTSPH1:
819     jam();
820     intstartphase1x010Lab(signal, nodeId);
821     return;
822   case ZINTSPH2:
823     jam();
824     ndbsttorry010Lab(signal);
825     return;
826   case ZINTSPH3:
827   {
828     jam();
829     intstartphase3x010Lab(signal);
830 
831     /* Start transaction counters event reporting. */
832     const Uint32 len = c_counters.build_continueB(signal);
833     signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
834     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
835     return;
836   }
837   case ZINTSPH6:
838   {
839     jam();
840     c_elapsed_time_millis = 0;
841     init_elapsed_time(signal, c_latestTIME_SIGNAL);
842     break;
843   }
844   default:
845     jam();
846     break;
847   }//switch
848   ndbsttorry010Lab(signal);
849   return;
850 }//Dbtc::execNDB_STTOR()
851 
ndbsttorry010Lab(Signal * signal)852 void Dbtc::ndbsttorry010Lab(Signal* signal)
853 {
854   signal->theData[0] = cownref;
855   sendSignal(c_sttor_ref, GSN_NDB_STTORRY, signal, 1, JBB);
856 }//Dbtc::ndbsttorry010Lab()
857 
858 void
set_timeout_value(Uint32 timeOut)859 Dbtc::set_timeout_value(Uint32 timeOut)
860 {
861   timeOut = timeOut / 10;
862   if (timeOut < 2) {
863     jam();
864     timeOut = 100;
865   }//if
866   ctimeOutValue = timeOut;
867 }
868 
869 void
set_appl_timeout_value(Uint32 timeOut)870 Dbtc::set_appl_timeout_value(Uint32 timeOut)
871 {
872   if (timeOut)
873   {
874     timeOut /= 10;
875     if (timeOut < ctimeOutValue) {
876       jam();
877       c_appl_timeout_value = ctimeOutValue;
878     }//if
879   }
880   c_appl_timeout_value = timeOut;
881 }
882 
883 void
set_no_parallel_takeover(Uint32 noParallelTakeOver)884 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
885 {
886   if (noParallelTakeOver == 0) {
887     jam();
888     noParallelTakeOver = 1;
889   } else if (noParallelTakeOver > MAX_NDB_NODES) {
890     jam();
891     noParallelTakeOver = MAX_NDB_NODES;
892   }//if
893   cnoParallelTakeOver = noParallelTakeOver;
894 }
895 
896 /* ***************************************************************************/
897 /*                        S T A R T P H A S E 1 X                            */
898 /*                     INITIALISE BLOCKREF AND BLOCKNUMBERS                  */
899 /* ***************************************************************************/
startphase1x010Lab(Signal * signal)900 void Dbtc::startphase1x010Lab(Signal* signal)
901 {
902   ctimeOutCheckCounter = 0;
903   ctimeOutCheckFragCounter = 0;
904   ctimeOutMissedHeartbeats = 0;
905   ctimeOutCheckHeartbeat = 0;
906   ctimeOutCheckLastHeartbeat = 0;
907   ctimeOutMissedHeartbeatsScan = 0;
908   ctimeOutCheckHeartbeatScan = 0;
909   ctimeOutCheckLastHeartbeatScan = 0;
910   ctimeOutCheckActive = TOCS_FALSE;
911   ctimeOutCheckFragActive = TOCS_FALSE;
912   sttorryLab(signal);
913 }//Dbtc::startphase1x010Lab()
914 
915 /*****************************************************************************/
916 /*                        I N T S T A R T P H A S E 1 X                      */
917 /*                         INITIALISE ALL RECORDS.                           */
918 /*****************************************************************************/
intstartphase1x010Lab(Signal * signal,NodeId nodeId)919 void Dbtc::intstartphase1x010Lab(Signal* signal, NodeId nodeId)
920 {
921   cownNodeid = nodeId;
922   cownref =          reference();
923   clqhblockref =     calcLqhBlockRef(cownNodeid);
924   cdihblockref =     calcDihBlockRef(cownNodeid);
925   cdictblockref =    calcDictBlockRef(cownNodeid);
926   cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
927   cerrorBlockref   = calcNdbCntrBlockRef(cownNodeid);
928   coperationsize = 0;
929   cfailure_nr = 0;
930   ndbsttorry010Lab(signal);
931 }//Dbtc::intstartphase1x010Lab()
932 
933 /*****************************************************************************/
934 /*                         I N T S T A R T P H A S E 3 X                     */
935 /*****************************************************************************/
intstartphase3x010Lab(Signal * signal)936 void Dbtc::intstartphase3x010Lab(Signal* signal)
937 {
938   signal->theData[0] = cownref;
939   sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
940 }//Dbtc::intstartphase3x010Lab()
941 
execREAD_NODESCONF(Signal * signal)942 void Dbtc::execREAD_NODESCONF(Signal* signal)
943 {
944   UintR guard0;
945 
946   jamEntry();
947 
948   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
949 
950   csystemnodes  = readNodes->noOfNodes;
951   cmasterNodeId = readNodes->masterNodeId;
952 
953   con_lineNodes = 0;
954   arrGuard(csystemnodes, MAX_NDB_NODES);
955   guard0 = csystemnodes - 1;
956   arrGuard(guard0, MAX_NDB_NODES);       // Check not zero nodes
957 
958   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
959     jam();
960     if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
961       hostptr.i = i;
962       ptrCheckGuard(hostptr, chostFilesize, hostRecord);
963 
964       if (NdbNodeBitmask::get(readNodes->inactiveNodes, i)) {
965         jam();
966         hostptr.p->hostStatus = HS_DEAD;
967       } else {
968         jam();
969         con_lineNodes++;
970         hostptr.p->hostStatus = HS_ALIVE;
971         c_alive_nodes.set(i);
972         if (!ndbd_deferred_unique_constraints(getNodeInfo(i).m_version))
973         {
974           jam();
975           m_deferred_enabled = 0;
976         }
977       }//if
978     }//if
979   }//for
980   ndbsttorry010Lab(signal);
981 }//Dbtc::execREAD_NODESCONF()
982 
983 /*****************************************************************************/
984 /*                     A P I _ F A I L R E Q                                 */
985 // An API node has failed for some reason. We need to disconnect all API
986 // connections to the API node. This also includes
987 /*****************************************************************************/
execAPI_FAILREQ(Signal * signal)988 void Dbtc::execAPI_FAILREQ(Signal* signal)
989 {
990   /***************************************************************************
991    * Set the block reference to return API_FAILCONF to. Set the number of api
992    * connects currently closing to one to indicate that we are still in the
993    * process of going through the api connect records. Thus checking for zero
994    * can only be true after all api connect records have been checked.
995    **************************************************************************/
996   jamEntry();
997 
998   if (ERROR_INSERTED(8056))
999   {
1000     CLEAR_ERROR_INSERT_VALUE;
1001     return;
1002   }
1003 #ifdef ERROR_INSERT
1004   if (ERROR_INSERTED(8078))
1005   {
1006     c_lastFailedApi = signal->theData[0];
1007     SET_ERROR_INSERT_VALUE(8079);
1008   }
1009 #endif
1010 
1011   capiFailRef = signal->theData[1];
1012   arrGuard(signal->theData[0], MAX_NODES);
1013   capiConnectClosing[signal->theData[0]] = 1;
1014   handleFailedApiNode(signal, signal->theData[0], (UintR)0);
1015 }
1016 
1017 void
handleFailedApiNode(Signal * signal,UintR TapiFailedNode,UintR TapiConnectPtr)1018 Dbtc::handleFailedApiNode(Signal* signal,
1019                           UintR TapiFailedNode,
1020                           UintR TapiConnectPtr)
1021 {
1022   UintR TloopCount = 0;
1023   arrGuard(TapiFailedNode, MAX_NODES);
1024   apiConnectptr.i = TapiConnectPtr;
1025   do {
1026     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
1027     const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
1028     if (TapiNode == TapiFailedNode) {
1029 #ifdef VM_TRACE
1030       if (apiConnectptr.p->apiFailState != ZFALSE) {
1031         ndbout << "Error in previous API fail handling discovered" << endl
1032 	       << "  apiConnectptr.i = " << apiConnectptr.i << endl
1033 	       << "  apiConnectstate = " << apiConnectptr.p->apiConnectstate
1034 	       << endl
1035 	       << "  ndbapiBlockref = " << hex
1036 	       << apiConnectptr.p->ndbapiBlockref << endl
1037 	       << "  apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
1038 	       << endl;
1039 	if (apiConnectptr.p->lastTcConnect != RNIL){
1040 	  jam();
1041 	  tcConnectptr.i = apiConnectptr.p->lastTcConnect;
1042 	  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
1043 	  ndbout << "  tcConnectptr.i = " << tcConnectptr.i << endl
1044 		 << "  tcConnectstate = " << tcConnectptr.p->tcConnectstate
1045 		 << endl;
1046 	}
1047       }//if
1048 #endif
1049 
1050       apiConnectptr.p->returnsignal = RS_NO_RETURN;
1051       /***********************************************************************/
1052       // The connected node is the failed node.
1053       /**********************************************************************/
1054       switch(apiConnectptr.p->apiConnectstate) {
1055       case CS_DISCONNECTED:
1056         /*********************************************************************/
1057         // These states do not need any special handling.
1058         // Simply continue with the next.
1059         /*********************************************************************/
1060         jam();
1061         break;
1062       case CS_ABORTING:
1063         /*********************************************************************/
1064         // This could actually mean that the API connection is already
1065         // ready to release if the abortState is IDLE.
1066         /*********************************************************************/
1067         if (apiConnectptr.p->abortState == AS_IDLE) {
1068           jam();
1069           releaseApiCon(signal, apiConnectptr.i);
1070         } else {
1071           jam();
1072           capiConnectClosing[TapiFailedNode]++;
1073           apiConnectptr.p->apiFailState = ZTRUE;
1074         }//if
1075         break;
1076       case CS_WAIT_ABORT_CONF:
1077       case CS_WAIT_COMMIT_CONF:
1078       case CS_START_COMMITTING:
1079       case CS_PREPARE_TO_COMMIT:
1080       case CS_COMMITTING:
1081       case CS_COMMIT_SENT:
1082         /*********************************************************************/
1083         // These states indicate that an abort process or commit process is
1084         // already ongoing. We will set a state in the api record indicating
1085         // that the API node has failed.
1086         // Also we will increase the number of outstanding api records to
1087         // wait for before we can respond with API_FAILCONF.
1088         /*********************************************************************/
1089         jam();
1090         capiConnectClosing[TapiFailedNode]++;
1091         apiConnectptr.p->apiFailState = ZTRUE;
1092         break;
1093       case CS_START_SCAN:
1094       {
1095         /*********************************************************************/
1096         // The api record was performing a scan operation. We need to check
1097         // on the scan state. Since completing a scan process might involve
1098         // sending several signals we will increase the loop count by 64.
1099         /*********************************************************************/
1100         jam();
1101 
1102 	apiConnectptr.p->apiFailState = ZTRUE;
1103 	capiConnectClosing[TapiFailedNode]++;
1104 
1105 	ScanRecordPtr scanPtr;
1106 	scanPtr.i = apiConnectptr.p->apiScanRec;
1107 	ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
1108 	close_scan_req(signal, scanPtr, true);
1109 
1110         TloopCount += 64;
1111         break;
1112       }
1113       case CS_CONNECTED:
1114       case CS_REC_COMMITTING:
1115       case CS_RECEIVING:
1116       case CS_STARTED:
1117       case CS_SEND_FIRE_TRIG_REQ:
1118       case CS_WAIT_FIRE_TRIG_REQ:
1119         /*********************************************************************/
1120         // The api record was in the process of performing a transaction but
1121         // had not yet sent all information.
1122         // We need to initiate an ABORT since the API will not provide any
1123         // more information.
1124         // Since the abort can send many signals we will insert a real-time
1125         // break after checking this record.
1126         /*********************************************************************/
1127         jam();
1128         apiConnectptr.p->apiFailState = ZTRUE;
1129         capiConnectClosing[TapiFailedNode]++;
1130         abort010Lab(signal);
1131         TloopCount = 256;
1132         break;
1133       case CS_RESTART:
1134         jam();
1135       case CS_COMPLETING:
1136         jam();
1137       case CS_COMPLETE_SENT:
1138         jam();
1139       case CS_WAIT_COMPLETE_CONF:
1140         jam();
1141       case CS_FAIL_ABORTING:
1142         jam();
1143       case CS_FAIL_ABORTED:
1144         jam();
1145       case CS_FAIL_PREPARED:
1146         jam();
1147       case CS_FAIL_COMMITTING:
1148         jam();
1149       case CS_FAIL_COMMITTED:
1150         /*********************************************************************/
1151         // These states are only valid on copy and fail API connections.
1152         /*********************************************************************/
1153       default:
1154         jam();
1155         jamLine(apiConnectptr.p->apiConnectstate);
1156         systemErrorLab(signal, __LINE__);
1157         break;
1158       }//switch
1159     } else {
1160       jam();
1161     }//if
1162     apiConnectptr.i++;
1163     if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
1164       jam();
1165       /**
1166        * Finished with scanning connection record
1167        *
1168        * Now scan markers
1169        */
1170       removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1171       return;
1172     }//if
1173   } while (TloopCount++ < 256);
1174   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1175   signal->theData[1] = TapiFailedNode;
1176   signal->theData[2] = apiConnectptr.i;
1177   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1178 }//Dbtc::handleFailedApiNode()
1179 
1180 void
removeMarkerForFailedAPI(Signal * signal,NodeId nodeId,Uint32 startBucket)1181 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1182                                NodeId nodeId,
1183                                Uint32 startBucket)
1184 {
1185   TcFailRecordPtr node_fail_ptr;
1186   node_fail_ptr.i = 0;
1187   ptrAss(node_fail_ptr, tcFailRecord);
1188   if(node_fail_ptr.p->failStatus != FS_IDLE) {
1189     jam();
1190     DEBUG("Restarting removeMarkerForFailedAPI");
1191     /**
1192      * TC take-over in progress
1193      *   needs to restart as this
1194      *   creates new markers
1195      */
1196     signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1197     signal->theData[1] = nodeId;
1198     signal->theData[2] = 0;
1199     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1200     return;
1201   }
1202 
1203   CommitAckMarkerIterator iter;
1204   m_commitAckMarkerHash.next(startBucket, iter);
1205 
1206   const Uint32 RT_BREAK = 256;
1207   for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1208     jam();
1209 
1210     if(iter.curr.i == RNIL){
1211       jam();
1212       /**
1213        * Done with iteration
1214        */
1215       capiConnectClosing[nodeId]--;
1216       if (capiConnectClosing[nodeId] == 0) {
1217         jam();
1218 
1219         /********************************************************************/
1220         // No outstanding ABORT or COMMIT's of this failed API node.
1221         // Perform SimulatedBlock level cleanup before sending
1222         // API_FAILCONF
1223         /********************************************************************/
1224         Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1225                        nodeId};
1226         simBlockNodeFailure(signal, nodeId, cb);
1227       }
1228       return;
1229     }
1230 
1231     if(iter.curr.p->apiNodeId == nodeId){
1232       jam();
1233 
1234       /**
1235        * Check so that the record is not still in use
1236        *
1237        */
1238       ApiConnectRecordPtr apiConnectPtr;
1239       apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1240       ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
1241       if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
1242 	jam();
1243         /**
1244          * The record is still active, this means that the transaction is
1245          * currentlygoing through the abort or commit process as started
1246          * in the API node failure handling, we have to wait until this
1247          * phase is completed until we continue with our processing of this.
1248          * If it goes through the aborting process the record will disappear
1249          * while we're waiting for it. If it goes through the commit process
1250          * it will eventually reach copyApi whereafter we can remove the
1251          * marker from LQH.
1252          *
1253          * Don't remove it, but continueb retry with a short delay
1254          */
1255         signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1256         signal->theData[1] = nodeId;
1257         signal->theData[2] = iter.bucket;
1258         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 1, 3);
1259         return;
1260       }
1261       /**
1262        * This should only happen if we have done copyApi and the referred
1263        * apiConnect record have already moved on to the free connections or
1264        * to a new transaction. The commit ack marker is still around,
1265        * normally the API would then send TC_COMMIT_ACK, but this hasn't
1266        * happened here since the API have failed. So we need to remove the
1267        * marker on behalf of the failed API, the failed API will not be able
1268        * to communicate its hearing of the commit, so we can simply remove
1269        * the commit ack marker in LQH.
1270        */
1271       sendRemoveMarkers(signal, iter.curr.p, 1);
1272       m_commitAckMarkerHash.release(iter.curr);
1273 
1274       break;
1275     }
1276     m_commitAckMarkerHash.next(iter);
1277   } // for (... i<RT_BREAK ...)
1278 
1279   // Takes a RT-break to avoid starving other activity
1280   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1281   signal->theData[1] = nodeId;
1282   signal->theData[2] = iter.bucket;
1283   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1284 }
1285 
handleApiFailState(Signal * signal,UintR TapiConnectptr)1286 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1287 {
1288   ApiConnectRecordPtr TlocalApiConnectptr;
1289   UintR TfailedApiNode;
1290 
1291   TlocalApiConnectptr.i = TapiConnectptr;
1292   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
1293   TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1294   arrGuard(TfailedApiNode, MAX_NODES);
1295   capiConnectClosing[TfailedApiNode]--;
1296   releaseApiCon(signal, TapiConnectptr);
1297   TlocalApiConnectptr.p->apiFailState = ZFALSE;
1298   if (capiConnectClosing[TfailedApiNode] == 0)
1299   {
1300     jam();
1301 
1302     /**
1303      * Perform block-level cleanups (e.g assembleFragments...)
1304      */
1305     Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1306                    TfailedApiNode};
1307     simBlockNodeFailure(signal, TfailedApiNode, cb);
1308   }//if
1309 }//Dbtc::handleApiFailState()
1310 
1311 /****************************************************************************
1312  *                                T C S E I Z E R E Q
1313  * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1314  * TRANSACTION
1315  * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1316  * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1317  ****************************************************************************/
execTCSEIZEREQ(Signal * signal)1318 void Dbtc::execTCSEIZEREQ(Signal* signal)
1319 {
1320   UintR tapiPointer;
1321   BlockReference tapiBlockref;       /* SENDER BLOCK REFERENCE*/
1322 
1323   jamEntry();
1324   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1325   tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1326 
1327   if (signal->getLength() > 2)
1328   {
1329     ndbassert(instance() == signal->theData[2]);
1330   }
1331 
1332   const NodeState::StartLevel sl =
1333     (NodeState::StartLevel)getNodeState().startLevel;
1334 
1335   const NodeId senderNodeId = refToNode(tapiBlockref);
1336   const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1337 
1338   {
1339     {
1340       if (!(sl == NodeState::SL_STARTED ||
1341 	    (sl == NodeState::SL_STARTING && local == true))) {
1342 	jam();
1343 
1344 	Uint32 errCode = 0;
1345 	if(!local)
1346 	  {
1347 	    switch(sl){
1348 	    case NodeState::SL_STARTING:
1349 	      errCode = ZSYSTEM_NOT_STARTED_ERROR;
1350 	      break;
1351 	    case NodeState::SL_STOPPING_1:
1352 	    case NodeState::SL_STOPPING_2:
1353               if (getNodeState().getSingleUserMode())
1354                 break;
1355 	    case NodeState::SL_STOPPING_3:
1356 	    case NodeState::SL_STOPPING_4:
1357 	      if(getNodeState().stopping.systemShutdown)
1358 		errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1359 	      else
1360 		errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1361 	      break;
1362 	    case NodeState::SL_SINGLEUSER:
1363 	      break;
1364 	    default:
1365 	      errCode = ZWRONG_STATE;
1366 	      break;
1367 	    }
1368             if (errCode)
1369             {
1370               ndbout << "error: " << errCode << " on " << tapiPointer << endl;
1371               signal->theData[0] = tapiPointer;
1372               signal->theData[1] = errCode;
1373               sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1374               return;
1375             }
1376 	  }//if (!(sl == SL_SINGLEUSER))
1377       } //if
1378     }
1379   }
1380 
1381   if (ERROR_INSERTED(8078) || ERROR_INSERTED(8079))
1382   {
1383     /* Clear testing of API_FAILREQ behaviour */
1384     CLEAR_ERROR_INSERT_VALUE;
1385   };
1386 
1387   seizeApiConnect(signal);
1388   if (terrorCode == ZOK) {
1389     jam();
1390     apiConnectptr.p->ndbapiConnect = tapiPointer;
1391     apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1392     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1393     signal->theData[1] = apiConnectptr.i;
1394     signal->theData[2] = reference();
1395     sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 3, JBB);
1396     return;
1397   }
1398 
1399   ndbout << "4006 on " << tapiPointer << endl;
1400   signal->theData[0] = tapiPointer;
1401   signal->theData[1] = terrorCode;
1402   sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1403 }//Dbtc::execTCSEIZEREQ()
1404 
1405 /****************************************************************************/
1406 /*                    T C R E L E A S E Q                                   */
1407 /*                  REQUEST TO RELEASE A CONNECT RECORD                     */
1408 /****************************************************************************/
execTCRELEASEREQ(Signal * signal)1409 void Dbtc::execTCRELEASEREQ(Signal* signal)
1410 {
1411   UintR tapiPointer;
1412   BlockReference tapiBlockref;     /* SENDER BLOCK REFERENCE*/
1413 
1414   jamEntry();
1415   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1416   tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1417   tuserpointer = signal->theData[2];
1418   if (tapiPointer >= capiConnectFilesize) {
1419     jam();
1420     ndbassert(false);
1421     signal->theData[0] = tuserpointer;
1422     signal->theData[1] = ZINVALID_CONNECTION;
1423     signal->theData[2] = __LINE__;
1424     sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1425     return;
1426   } else {
1427     jam();
1428     apiConnectptr.i = tapiPointer;
1429   }//if
1430   ptrAss(apiConnectptr, apiConnectRecord);
1431   if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
1432     jam();
1433     signal->theData[0] = tuserpointer;
1434     sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1435   } else {
1436     if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
1437       if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
1438 	  (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
1439 	   apiConnectptr.p->abortState == AS_IDLE) ||
1440 	  (apiConnectptr.p->apiConnectstate == CS_STARTED &&
1441 	   apiConnectptr.p->firstTcConnect == RNIL))
1442       {
1443         jam();                                   /* JUST REPLY OK */
1444 	apiConnectptr.p->m_transaction_nodes.clear();
1445         releaseApiCon(signal, apiConnectptr.i);
1446         signal->theData[0] = tuserpointer;
1447         sendSignal(tapiBlockref,
1448                    GSN_TCRELEASECONF, signal, 1, JBB);
1449       } else {
1450         jam();
1451         ndbassert(false);
1452         signal->theData[0] = tuserpointer;
1453         signal->theData[1] = ZINVALID_CONNECTION;
1454 	signal->theData[2] = __LINE__;
1455 	signal->theData[3] = apiConnectptr.p->apiConnectstate;
1456         sendSignal(tapiBlockref,
1457                    GSN_TCRELEASEREF, signal, 4, JBB);
1458       }
1459     } else {
1460       jam();
1461       ndbassert(false);
1462       signal->theData[0] = tuserpointer;
1463       signal->theData[1] = ZINVALID_CONNECTION;
1464       signal->theData[2] = __LINE__;
1465       signal->theData[3] = tapiBlockref;
1466       signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1467       sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1468     }//if
1469   }//if
1470 }//Dbtc::execTCRELEASEREQ()
1471 
1472 /****************************************************************************/
1473 // Error Handling for TCKEYREQ messages
1474 /****************************************************************************/
signalErrorRefuseLab(Signal * signal)1475 void Dbtc::signalErrorRefuseLab(Signal* signal)
1476 {
1477   ptrGuard(apiConnectptr);
1478   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1479     jam();
1480     apiConnectptr.p->abortState = AS_IDLE;
1481     apiConnectptr.p->apiConnectstate = CS_ABORTING;
1482   }//if
1483   sendSignalErrorRefuseLab(signal);
1484 }//Dbtc::signalErrorRefuseLab()
1485 
sendSignalErrorRefuseLab(Signal * signal)1486 void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
1487 {
1488   ndbassert(false);
1489   ptrGuard(apiConnectptr);
1490   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1491     jam();
1492     /* Force state print */
1493     printState(signal, 12, true);
1494     ndbrequire(false);
1495     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1496     signal->theData[1] = signal->theData[ttransid_ptr];
1497     signal->theData[2] = signal->theData[ttransid_ptr + 1];
1498     signal->theData[3] = ZSIGNAL_ERROR;
1499     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1500 	       signal, 4, JBB);
1501   }
1502 }//Dbtc::sendSignalErrorRefuseLab()
1503 
abortBeginErrorLab(Signal * signal)1504 void Dbtc::abortBeginErrorLab(Signal* signal)
1505 {
1506   apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1507   apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1508   abortErrorLab(signal);
1509 }//Dbtc::abortBeginErrorLab()
1510 
printState(Signal * signal,int place,bool force_trace)1511 void Dbtc::printState(Signal* signal, int place, bool force_trace)
1512 {
1513   /* Always give minimal ApiConnectState trace via jam */
1514   jam();
1515   jamLine(apiConnectptr.p->apiConnectstate);
1516   jam();
1517 
1518 #ifdef VM_TRACE
1519   /* Always trace in debug mode */
1520   force_trace = true;
1521 #endif
1522 
1523   if (!force_trace)
1524     return;
1525 
1526   ndbout << "-- Dbtc::printState -- " << endl;
1527   ndbout << "Received from place = " << place
1528 	 << " apiConnectptr.i = " << apiConnectptr.i
1529 	 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
1530   ndbout << "ctcTimer = " << ctcTimer
1531 	 << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
1532 	 << " Transid = " << apiConnectptr.p->transid[0]
1533 	 << " " << apiConnectptr.p->transid[1] << endl;
1534   ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
1535 	 << " counter = " << apiConnectptr.p->counter
1536 	 << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
1537 	 << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec
1538          << " cascading_scans = " << apiConnectptr.p->cascading_scans_count << endl;
1539   ndbout << "abortState = " << apiConnectptr.p->abortState
1540 	 << " apiScanRec = " << apiConnectptr.p->apiScanRec
1541 	 << " returncode = " << apiConnectptr.p->returncode << endl;
1542   ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
1543 	 << " returnsignal = " << apiConnectptr.p->returnsignal
1544 	 << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
1545   if (apiConnectptr.p->cachePtr != RNIL) {
1546     jam();
1547     CacheRecord *localCacheRecord = cacheRecord;
1548     UintR TcacheFilesize = ccacheFilesize;
1549     UintR TcachePtr = apiConnectptr.p->cachePtr;
1550     if (TcachePtr < TcacheFilesize) {
1551       jam();
1552       CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1553       ndbout << "currReclenAi = " << regCachePtr->currReclenAi
1554 	     << " attrlength = " << regCachePtr->attrlength
1555 	     << " tableref = " << regCachePtr->tableref
1556 	     << " keylen = " << regCachePtr->keylen << endl;
1557     } else {
1558       jam();
1559       systemErrorLab(signal, __LINE__);
1560     }//if
1561   }//if
1562   return;
1563 }//Dbtc::printState()
1564 
1565 void
TCKEY_abort(Signal * signal,int place)1566 Dbtc::TCKEY_abort(Signal* signal, int place)
1567 {
1568   switch (place) {
1569   case 0:
1570     jam();
1571     terrorCode = ZSTATE_ERROR;
1572     apiConnectptr.p->firstTcConnect = RNIL;
1573     printState(signal, 4);
1574     abortBeginErrorLab(signal);
1575     return;
1576   case 1:
1577     jam();
1578     printState(signal, 3);
1579     sendSignalErrorRefuseLab(signal);
1580     return;
1581   case 2:{
1582     printState(signal, 6);
1583     const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
1584     const Uint32 t1 = tcKeyReq->transId1;
1585     const Uint32 t2 = tcKeyReq->transId2;
1586     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1587     signal->theData[1] = t1;
1588     signal->theData[2] = t2;
1589     signal->theData[3] = ZABORT_ERROR;
1590     ndbrequire(false);
1591     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1592 	       signal, 4, JBB);
1593     return;
1594   }
1595   case 3:
1596     jam();
1597     printState(signal, 7);
1598     noFreeConnectionErrorLab(signal);
1599     return;
1600   case 4:
1601     jam();
1602     terrorCode = ZERO_KEYLEN_ERROR;
1603     releaseAtErrorLab(signal);
1604     return;
1605   case 5:
1606     jam();
1607     terrorCode = ZNO_AI_WITH_UPDATE;
1608     releaseAtErrorLab(signal);
1609     return;
1610   case 6:
1611     jam();
1612     warningHandlerLab(signal, __LINE__);
1613     return;
1614 
1615   case 7:
1616     jam();
1617     tabStateErrorLab(signal);
1618     return;
1619 
1620   case 8:
1621     jam();
1622     wrongSchemaVersionErrorLab(signal);
1623     return;
1624 
1625   case 9:
1626     jam();
1627     terrorCode = ZSTATE_ERROR;
1628     releaseAtErrorLab(signal);
1629     return;
1630 
1631   case 10:
1632     jam();
1633     systemErrorLab(signal, __LINE__);
1634     return;
1635 
1636   case 11:
1637     jam();
1638     terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
1639     releaseAtErrorLab(signal);
1640     return;
1641 
1642   case 12:
1643     jam();
1644     terrorCode = ZSIMPLE_READ_WITHOUT_AI;
1645     releaseAtErrorLab(signal);
1646     return;
1647 
1648   case 13:
1649     jam();
1650     switch (tcConnectptr.p->tcConnectstate) {
1651     case OS_WAIT_KEYINFO:
1652       jam();
1653       printState(signal, 8);
1654       terrorCode = ZSTATE_ERROR;
1655       abortErrorLab(signal);
1656       return;
1657     default:
1658       jam();
1659       /********************************************************************/
1660       /*       MISMATCH BETWEEN STATE ON API CONNECTION AND THIS          */
1661       /*       PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB   */
1662       /*       INTERNAL ERROR.                                            */
1663       /********************************************************************/
1664       systemErrorLab(signal, __LINE__);
1665       return;
1666     }//switch
1667     return;
1668 
1669   case 15:
1670     jam();
1671     terrorCode = ZSCAN_NODE_ERROR;
1672     releaseAtErrorLab(signal);
1673     return;
1674 
1675   case 16:
1676     jam();
1677     systemErrorLab(signal, __LINE__);
1678     return;
1679 
1680   case 17:
1681     jam();
1682     systemErrorLab(signal, __LINE__);
1683     return;
1684 
1685   case 18:
1686     jam();
1687     warningHandlerLab(signal, __LINE__);
1688     return;
1689 
1690   case 19:
1691     jam();
1692     return;
1693 
1694   case 20:
1695     jam();
1696     warningHandlerLab(signal, __LINE__);
1697     return;
1698 
1699   case 21:
1700     jam();
1701     systemErrorLab(signal, __LINE__);
1702     return;
1703 
1704   case 22:
1705     jam();
1706     systemErrorLab(signal, __LINE__);
1707     return;
1708 
1709   case 23:
1710     jam();
1711     systemErrorLab(signal, __LINE__);
1712     return;
1713 
1714   case 24:
1715     jam();
1716     appendToSectionErrorLab(signal);
1717     return;
1718 
1719   case 25:
1720     jam();
1721     warningHandlerLab(signal, __LINE__);
1722     return;
1723 
1724   case 26:
1725     jam();
1726     return;
1727 
1728   case 27:
1729     systemErrorLab(signal, __LINE__);
1730     jam();
1731     return;
1732 
1733   case 28:
1734     jam();
1735     // NOT USED
1736     return;
1737 
1738   case 29:
1739     jam();
1740     systemErrorLab(signal, __LINE__);
1741     return;
1742 
1743   case 30:
1744     jam();
1745     systemErrorLab(signal, __LINE__);
1746     return;
1747 
1748   case 31:
1749     jam();
1750     systemErrorLab(signal, __LINE__);
1751     return;
1752 
1753   case 32:
1754     jam();
1755     systemErrorLab(signal, __LINE__);
1756     return;
1757 
1758   case 33:
1759     jam();
1760     systemErrorLab(signal, __LINE__);
1761     return;
1762 
1763   case 34:
1764     jam();
1765     systemErrorLab(signal, __LINE__);
1766     return;
1767 
1768   case 35:
1769     jam();
1770     systemErrorLab(signal, __LINE__);
1771     return;
1772 
1773   case 36:
1774     jam();
1775     systemErrorLab(signal, __LINE__);
1776     return;
1777 
1778   case 37:
1779     jam();
1780     systemErrorLab(signal, __LINE__);
1781     return;
1782 
1783   case 38:
1784     jam();
1785     systemErrorLab(signal, __LINE__);
1786     return;
1787 
1788   case 39:
1789     jam();
1790     systemErrorLab(signal, __LINE__);
1791     return;
1792 
1793   case 40:
1794     jam();
1795     systemErrorLab(signal, __LINE__);
1796     return;
1797 
1798   case 41:
1799     jam();
1800     systemErrorLab(signal, __LINE__);
1801     return;
1802 
1803   case 42:
1804     jam();
1805     systemErrorLab(signal, __LINE__);
1806     return;
1807 
1808   case 43:
1809     jam();
1810     systemErrorLab(signal, __LINE__);
1811     return;
1812 
1813   case 44:
1814     jam();
1815     systemErrorLab(signal, __LINE__);
1816     return;
1817 
1818   case 45:
1819     jam();
1820     systemErrorLab(signal, __LINE__);
1821     return;
1822 
1823   case 46:
1824     jam();
1825     systemErrorLab(signal, __LINE__);
1826     return;
1827 
1828   case 47:
1829     jam();
1830     terrorCode = apiConnectptr.p->returncode;
1831     releaseAtErrorLab(signal);
1832     return;
1833 
1834   case 48:
1835     jam();
1836     terrorCode = ZCOMMIT_TYPE_ERROR;
1837     releaseAtErrorLab(signal);
1838     return;
1839 
1840   case 49:
1841     jam();
1842     abortErrorLab(signal);
1843     return;
1844 
1845   case 50:
1846     jam();
1847     systemErrorLab(signal, __LINE__);
1848     return;
1849 
1850   case 51:
1851     jam();
1852     abortErrorLab(signal);
1853     return;
1854 
1855   case 52:
1856     jam();
1857     abortErrorLab(signal);
1858     return;
1859 
1860   case 53:
1861     jam();
1862     abortErrorLab(signal);
1863     return;
1864 
1865   case 54:
1866     jam();
1867     abortErrorLab(signal);
1868     return;
1869 
1870   case 55:
1871     jam();
1872     printState(signal, 5);
1873     sendSignalErrorRefuseLab(signal);
1874     return;
1875 
1876   case 56:{
1877     jam();
1878     terrorCode = ZNO_FREE_TC_MARKER;
1879     abortErrorLab(signal);
1880     return;
1881   }
1882   case 57:{
1883     jam();
1884     /**
1885      * Initialize object before starting error handling
1886      */
1887     initApiConnectRec(signal, apiConnectptr.p, true);
1888 start_failure:
1889     switch(getNodeState().startLevel){
1890     case NodeState::SL_STOPPING_2:
1891       if (getNodeState().getSingleUserMode())
1892       {
1893         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1894         break;
1895       }
1896     case NodeState::SL_STOPPING_3:
1897     case NodeState::SL_STOPPING_4:
1898       if(getNodeState().stopping.systemShutdown)
1899 	terrorCode  = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1900       else
1901 	terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1902       break;
1903     case NodeState::SL_SINGLEUSER:
1904       terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1905       break;
1906     case NodeState::SL_STOPPING_1:
1907       if (getNodeState().getSingleUserMode())
1908       {
1909         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1910         break;
1911       }
1912     default:
1913       terrorCode = ZWRONG_STATE;
1914       break;
1915     }
1916     abortErrorLab(signal);
1917     return;
1918   }
1919 
1920   case 58:{
1921     jam();
1922     releaseAtErrorLab(signal);
1923     return;
1924   }
1925 
1926   case 59:{
1927     jam();
1928     terrorCode = ZABORTINPROGRESS;
1929     abortErrorLab(signal);
1930     return;
1931   }
1932 
1933   case 60:
1934   {
1935     jam();
1936     initApiConnectRec(signal, apiConnectptr.p, true);
1937     apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
1938     goto start_failure;
1939   }
1940   case 61:
1941   {
1942     jam();
1943     terrorCode = ZUNLOCKED_IVAL_TOO_HIGH;
1944     abortErrorLab(signal);
1945     return;
1946   }
1947   case 62:
1948   {
1949     jam();
1950     terrorCode = ZUNLOCKED_OP_HAS_BAD_STATE;
1951     abortErrorLab(signal);
1952     return;
1953   }
1954   case 63:
1955   {
1956     jam();
1957     /* Function not implemented yet */
1958     terrorCode = 4003;
1959     abortErrorLab(signal);
1960     return;
1961   }
1962   case 64:
1963   {
1964     jam();
1965     /* Invalid distribution key */
1966     terrorCode = ZBAD_DIST_KEY;
1967     abortErrorLab(signal);
1968     return;
1969   }
1970   case 65:
1971   {
1972     jam();
1973     terrorCode = ZTRANS_TOO_BIG;
1974     abortErrorLab(signal);
1975     return;
1976   }
1977   case 66:
1978   {
1979     jam();
1980     /* Function not implemented yet */
1981     terrorCode = 4003;
1982     abortErrorLab(signal);
1983     return;
1984   }
1985   case 67:
1986   {
1987     jam();
1988     terrorCode = ZNO_FREE_TC_MARKER_DATABUFFER;
1989     abortErrorLab(signal);
1990     return;
1991   }
1992   default:
1993     jam();
1994     systemErrorLab(signal, __LINE__);
1995     return;
1996   }//switch
1997 }
1998 
1999 static
2000 inline
2001 bool
compare_transid(Uint32 * val0,Uint32 * val1)2002 compare_transid(Uint32* val0, Uint32* val1)
2003 {
2004   Uint32 tmp0 = val0[0] ^ val1[0];
2005   Uint32 tmp1 = val0[1] ^ val1[1];
2006   return (tmp0 | tmp1) == 0;
2007 }
2008 
execKEYINFO(Signal * signal)2009 void Dbtc::execKEYINFO(Signal* signal)
2010 {
2011   jamEntry();
2012   apiConnectptr.i = signal->theData[0];
2013   tmaxData = 20;
2014   if (apiConnectptr.i >= capiConnectFilesize) {
2015     TCKEY_abort(signal, 18);
2016     return;
2017   }//if
2018   ptrAss(apiConnectptr, apiConnectRecord);
2019   ttransid_ptr = 1;
2020   if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
2021   {
2022     TCKEY_abort(signal, 19);
2023     return;
2024   }//if
2025   switch (apiConnectptr.p->apiConnectstate) {
2026   case CS_RECEIVING:
2027   case CS_REC_COMMITTING:
2028   case CS_START_SCAN:
2029     jam();
2030     /*empty*/;
2031     break;
2032   case CS_ABORTING:
2033     jam();
2034     return;     /* IGNORE */
2035   case CS_CONNECTED:
2036     jam();
2037     /****************************************************************>*/
2038     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2039     /*       SET STATE TO ABORTING.                                   */
2040     /****************************************************************>*/
2041     printState(signal, 11);
2042     signalErrorRefuseLab(signal);
2043     return;
2044   case CS_STARTED:
2045     jam();
2046     /****************************************************************>*/
2047     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2048     /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
2049     /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
2050     /****************************************************************>*/
2051     terrorCode = ZSIGNAL_ERROR;
2052     printState(signal, 2);
2053     abortErrorLab(signal);
2054     return;
2055   default:
2056     jam();
2057     warningHandlerLab(signal, __LINE__);
2058     return;
2059   }//switch
2060 
2061   CacheRecord *localCacheRecord = cacheRecord;
2062   UintR TcacheFilesize = ccacheFilesize;
2063   UintR TcachePtr = apiConnectptr.p->cachePtr;
2064   UintR TtcTimer = ctcTimer;
2065   CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2066   if (TcachePtr >= TcacheFilesize) {
2067     TCKEY_abort(signal, 42);
2068     return;
2069   }//if
2070   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2071   cachePtr.i = TcachePtr;
2072   cachePtr.p = regCachePtr;
2073 
2074   if (apiConnectptr.p->apiConnectstate == CS_START_SCAN)
2075   {
2076     jam();
2077     scanKeyinfoLab(signal);
2078     return;
2079   }
2080 
2081   tcConnectptr.i = apiConnectptr.p->lastTcConnect;
2082   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2083   switch (tcConnectptr.p->tcConnectstate) {
2084   case OS_WAIT_KEYINFO:
2085     jam();
2086     tckeyreq020Lab(signal);
2087     return;
2088   default:
2089     jam();
2090     terrorCode = ZSTATE_ERROR;
2091     abortErrorLab(signal);
2092     return;
2093   }//switch
2094 }//Dbtc::execKEYINFO()
2095 
2096 /**
2097  * sendKeyInfoTrain
2098  * Method to send a KeyInfo signal train from KeyInfo in the supplied
2099  * Section
2100  * KeyInfo will be taken from the section, starting at the supplied
2101  * offset
2102  */
sendKeyInfoTrain(Signal * signal,BlockReference TBRef,Uint32 connectPtr,Uint32 offset,Uint32 sectionIVal)2103 void Dbtc::sendKeyInfoTrain(Signal* signal,
2104                             BlockReference TBRef,
2105                             Uint32 connectPtr,
2106                             Uint32 offset,
2107                             Uint32 sectionIVal)
2108 {
2109   jam();
2110 
2111   signal->theData[0] = connectPtr;
2112   signal->theData[1] = apiConnectptr.p->transid[0];
2113   signal->theData[2] = apiConnectptr.p->transid[1];
2114   Uint32 * dst = signal->theData + KeyInfo::HeaderLength;
2115 
2116   ndbassert( sectionIVal != RNIL );
2117   SectionReader keyInfoReader(sectionIVal, getSectionSegmentPool());
2118 
2119   Uint32 totalLen= keyInfoReader.getSize();
2120 
2121   ndbassert( offset < totalLen );
2122 
2123   keyInfoReader.step(offset);
2124   totalLen-= offset;
2125 
2126   while(totalLen != 0)
2127   {
2128     Uint32 dataInSignal= MIN(KeyInfo::DataLength, totalLen);
2129     keyInfoReader.getWords(dst, dataInSignal);
2130     totalLen-= dataInSignal;
2131 
2132     sendSignal(TBRef, GSN_KEYINFO, signal,
2133                KeyInfo::HeaderLength + dataInSignal, JBB);
2134   }
2135 }//Dbtc::sendKeyInfoTrain()
2136 
2137 /**
2138  * tckeyreq020Lab
2139  * Handle received KEYINFO signal
2140  */
tckeyreq020Lab(Signal * signal)2141 void Dbtc::tckeyreq020Lab(Signal* signal)
2142 {
2143   CacheRecord * const regCachePtr = cachePtr.p;
2144   UintR TkeyLen = regCachePtr->keylen;
2145   UintR Tlen = regCachePtr->save1;
2146   UintR wordsInSignal= MIN(KeyInfo::DataLength,
2147                            (TkeyLen - Tlen));
2148 
2149   ndbassert(! regCachePtr->isLongTcKeyReq );
2150   ndbassert( regCachePtr->keyInfoSectionI != RNIL );
2151 
2152   /* Add received KeyInfo data to the existing KeyInfo section */
2153   if (! appendToSection(regCachePtr->keyInfoSectionI,
2154                         &signal->theData[KeyInfo::HeaderLength],
2155                         wordsInSignal))
2156   {
2157     jam();
2158     appendToSectionErrorLab(signal);
2159     return;
2160   }
2161   Tlen+= wordsInSignal;
2162 
2163   if (Tlen < TkeyLen)
2164   {
2165     /* More KeyInfo still to be read
2166      * Set timer and state and wait
2167      */
2168     jam();
2169     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2170     regCachePtr->save1 = Tlen;
2171     tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2172     return;
2173   }
2174   else
2175   {
2176     /* Have all the KeyInfo ... continue processing
2177      * TCKEYREQ
2178      */
2179     jam();
2180     tckeyreq050Lab(signal);
2181     return;
2182   }
2183 }//Dbtc::tckeyreq020Lab()
2184 
execATTRINFO(Signal * signal)2185 void Dbtc::execATTRINFO(Signal* signal)
2186 {
2187   UintR Tdata1 = signal->theData[0];
2188   UintR Tlength = signal->length();
2189   UintR TapiConnectFilesize = capiConnectFilesize;
2190   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2191 
2192   jamEntry();
2193   apiConnectptr.i = Tdata1;
2194   ttransid_ptr = 1;
2195   if (Tdata1 >= TapiConnectFilesize) {
2196     DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2197     TCKEY_abort(signal, 18);
2198     return;
2199   }//if
2200 
2201   ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
2202   apiConnectptr.p = regApiPtr;
2203 
2204   if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
2205   {
2206     DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2207 	  << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2208     TCKEY_abort(signal, 19);
2209     return;
2210   }//if
2211   if (Tlength < 4) {
2212     DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2213     TCKEY_abort(signal, 20);
2214     return;
2215   }
2216   Tlength -= AttrInfo::HeaderLength;
2217   UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2218   UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2219   UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2220 
2221   if (TcompBOTH) {
2222     jam();
2223     if (ERROR_INSERTED(8015)) {
2224       CLEAR_ERROR_INSERT_VALUE;
2225       return;
2226     }//if
2227     if (ERROR_INSERTED(8016)) {
2228       CLEAR_ERROR_INSERT_VALUE;
2229       return;
2230     }//if
2231     CacheRecord *localCacheRecord = cacheRecord;
2232     UintR TcacheFilesize = ccacheFilesize;
2233     UintR TcachePtr = regApiPtr->cachePtr;
2234     UintR TtcTimer = ctcTimer;
2235     CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2236     if (TcachePtr >= TcacheFilesize) {
2237       TCKEY_abort(signal, 43);
2238       return;
2239     }//if
2240 
2241     /* Update TC global cache ptr */
2242     cachePtr.i= TcachePtr;
2243     cachePtr.p= regCachePtr;
2244 
2245     regCachePtr->currReclenAi+= Tlength;
2246     int TattrlengthRemain = regCachePtr->attrlength -
2247       regCachePtr->currReclenAi;
2248 
2249     /* Setup tcConnectptr to ensure that error handling etc.
2250      * can access required state
2251      */
2252     tcConnectptr.i = regApiPtr->lastTcConnect;
2253     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2254 
2255     /* Add AttrInfo to any existing AttrInfo we have
2256      * Some short TCKEYREQ signals have no ATTRINFO in
2257      * the TCKEYREQ itself
2258      */
2259     if (! appendToSection(regCachePtr->attrInfoSectionI,
2260                           &signal->theData[AttrInfo::HeaderLength],
2261                           Tlength))
2262     {
2263       DEBUG("No more section segments available");
2264       appendToSectionErrorLab(signal);
2265       return;
2266     }//if
2267 
2268     setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2269 
2270     if (TattrlengthRemain == 0) {
2271       /****************************************************************>*/
2272       /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS       */
2273       /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2274       /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2275       /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER          */
2276       /* OPERATIONS.                                                     */
2277       /****************************************************************>*/
2278       if (TcompRECEIVING) {
2279         jam();
2280         regApiPtr->apiConnectstate = CS_STARTED;
2281       } else {
2282         jam();
2283         regApiPtr->apiConnectstate = CS_START_COMMITTING;
2284       }//if
2285       attrinfoDihReceivedLab(signal);
2286     } else if (TattrlengthRemain < 0) {
2287       jam();
2288       DEBUG("ATTRINFO wrong total length="<<Tlength
2289 	    <<", TattrlengthRemain="<<TattrlengthRemain
2290 	    <<", TattrLen="<< regCachePtr->attrlength
2291 	    <<", TcurrReclenAi="<< regCachePtr->currReclenAi);
2292       tcConnectptr.i = regApiPtr->lastTcConnect;
2293       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2294       aiErrorLab(signal);
2295     }//if
2296     return;
2297   } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
2298     jam();
2299     scanAttrinfoLab(signal, Tlength);
2300     return;
2301   } else {
2302     switch (regApiPtr->apiConnectstate) {
2303     case CS_ABORTING:
2304       jam();
2305       /* JUST IGNORE THE SIGNAL*/
2306       // DEBUG("Drop ATTRINFO, CS_ABORTING");
2307       return;
2308     case CS_CONNECTED:
2309       jam();
2310       /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2311       // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2312       return;
2313     case CS_STARTED:
2314       jam();
2315       /****************************************************************>*/
2316       /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2317       /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
2318       /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
2319       /****************************************************************>*/
2320       terrorCode = ZSIGNAL_ERROR;
2321       printState(signal, 1);
2322       abortErrorLab(signal);
2323       return;
2324     default:
2325       jam();
2326       /****************************************************************>*/
2327       /*       SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2328       /*       SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED.    */
2329       /****************************************************************>*/
2330       DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2331       printState(signal, 9);
2332       return;
2333     }//switch
2334   }//if
2335 }//Dbtc::execATTRINFO()
2336 
2337 /* *********************************************************************>> */
2338 /*                                                                        */
2339 /*       MODULE: HASH MODULE                                              */
2340 /*       DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION                 */
2341 /* *********************************************************************> */
hash(Signal * signal)2342 void Dbtc::hash(Signal* signal)
2343 {
2344   UintR*  Tdata32;
2345 
2346   CacheRecord * const regCachePtr = cachePtr.p;
2347   SegmentedSectionPtr keyInfoSection;
2348   UintR keylen = (UintR)regCachePtr->keylen;
2349   Uint32 distKey = regCachePtr->distributionKeyIndicator;
2350 
2351   getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
2352 
2353   ndbassert( keyInfoSection.sz <= MAX_KEY_SIZE_IN_WORDS );
2354   ndbassert( keyInfoSection.sz == keylen );
2355   /* Copy KeyInfo section from segmented storage into linear storage
2356    * in signal->theData
2357    */
2358   if (keylen <= SectionSegment::DataLength)
2359   {
2360     /* No need to copy keyinfo into a linear space
2361      * Note that we require that the data in the section is
2362      * 64-bit aligned for md5_hash below
2363      */
2364     ndbassert( keyInfoSection.p != NULL );
2365 
2366     Tdata32= &keyInfoSection.p->theData[0];
2367   }
2368   else
2369   {
2370     /* Copy segmented keyinfo into linear space in the signal */
2371     Tdata32= signal->theData;
2372     copy(Tdata32, keyInfoSection);
2373   }
2374 
2375   Uint32 tmp[4];
2376   if(!regCachePtr->m_special_hash)
2377   {
2378     md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2379   }
2380   else
2381   {
2382     if (regCachePtr->m_no_hash)
2383     {
2384       /* No need for tuple key hash at LQH */
2385       ndbassert(distKey); /* User must supply distkey */
2386       Uint32 zero[4] = {0, 0, 0, 0};
2387       *tmp = *zero;
2388     }
2389     else
2390     {
2391       handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2392     }
2393   }
2394 
2395   /* Primary key hash value is first word of hash on PK columns
2396    * Distribution key hash value is second word of hash on distribution
2397    * key columns, or a user defined value
2398    */
2399   thashValue = tmp[0];
2400   if (distKey){
2401     jam();
2402     tdistrHashValue = regCachePtr->distributionKey;
2403   } else {
2404     jam();
2405     tdistrHashValue = tmp[1];
2406   }//if
2407 }//Dbtc::hash()
2408 
2409 bool
handle_special_hash(Uint32 dstHash[4],const Uint32 * src,Uint32 srcLen,Uint32 tabPtrI,bool distr)2410 Dbtc::handle_special_hash(Uint32 dstHash[4],
2411                           const Uint32* src, Uint32 srcLen,
2412 			  Uint32 tabPtrI,
2413 			  bool distr)
2414 {
2415   const Uint32 MAX_KEY_SIZE_IN_LONG_WORDS=
2416     (MAX_KEY_SIZE_IN_WORDS + 1) / 2;
2417   Uint64 alignedWorkspace[MAX_KEY_SIZE_IN_LONG_WORDS * MAX_XFRM_MULTIPLY];
2418   Uint32* workspace= (Uint32*)alignedWorkspace;
2419   const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2420   const bool hasVarKeys = tabPtrP->hasVarKeys;
2421   const bool hasCharAttr = tabPtrP->hasCharAttr;
2422   const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2423 
2424   const Uint32 *hashInput = workspace;
2425   Uint32 inputLen = 0;
2426   Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2427   Uint32 * keyPartLenPtr;
2428 
2429   /* Normalise KeyInfo into workspace if necessary */
2430   if(hasCharAttr || (compute_distkey && hasVarKeys))
2431   {
2432     keyPartLenPtr = keyPartLen;
2433     inputLen = xfrm_key(tabPtrI,
2434                         src,
2435                         workspace,
2436                         sizeof(alignedWorkspace) >> 2,
2437                         keyPartLenPtr);
2438     if (unlikely(inputLen == 0))
2439     {
2440       goto error;
2441     }
2442   }
2443   else
2444   {
2445     /* Keyinfo already suitable for hash */
2446     hashInput = src;
2447     inputLen = srcLen;
2448     keyPartLenPtr = 0;
2449   }
2450 
2451   /* Calculate primary key hash */
2452   md5_hash(dstHash, (Uint64*)hashInput, inputLen);
2453 
2454   /* If the distribution key != primary key then we have to
2455    * form a distribution key from the primary key and calculate
2456    * a separate distribution hash based on this
2457    */
2458   if(compute_distkey)
2459   {
2460     jam();
2461 
2462     Uint32 distrKeyHash[4];
2463     /* Reshuffle primary key columns to get just distribution key */
2464     Uint32 len = create_distr_key(tabPtrI, hashInput, workspace, keyPartLenPtr);
2465     /* Calculate distribution key hash */
2466     md5_hash(distrKeyHash, (Uint64*) workspace, len);
2467 
2468     /* Just one word used for distribution */
2469     dstHash[1] = distrKeyHash[1];
2470   }
2471   return true;  // success
2472 
2473 error:
2474   terrorCode = ZINVALID_KEY;
2475   return false;
2476 }
2477 
2478 /*
2479 INIT_API_CONNECT_REC
2480 ---------------------------
2481 */
2482 /* ========================================================================= */
2483 /* =======                       INIT_API_CONNECT_REC                ======= */
2484 /*                                                                           */
2485 /* ========================================================================= */
initApiConnectRec(Signal * signal,ApiConnectRecord * const regApiPtr,bool releaseIndexOperations)2486 void Dbtc::initApiConnectRec(Signal* signal,
2487                              ApiConnectRecord * const regApiPtr,
2488 			     bool releaseIndexOperations)
2489 {
2490   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2491   UintR TfailureNr = cfailure_nr;
2492   UintR Ttransid0 = tcKeyReq->transId1;
2493   UintR Ttransid1 = tcKeyReq->transId2;
2494 
2495   tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
2496   regApiPtr->returncode = 0;
2497   regApiPtr->returnsignal = RS_TCKEYCONF;
2498   ndbassert(regApiPtr->firstTcConnect == RNIL);
2499   regApiPtr->firstTcConnect = RNIL;
2500   regApiPtr->lastTcConnect = RNIL;
2501   regApiPtr->globalcheckpointid = 0;
2502   regApiPtr->lqhkeyconfrec = 0;
2503   regApiPtr->lqhkeyreqrec = 0;
2504   regApiPtr->tckeyrec = 0;
2505   regApiPtr->tcindxrec = 0;
2506   tc_clearbit(regApiPtr->m_flags,
2507               ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
2508   regApiPtr->failureNr = TfailureNr;
2509   regApiPtr->transid[0] = Ttransid0;
2510   regApiPtr->transid[1] = Ttransid1;
2511   ndbrequire(regApiPtr->commitAckMarker == RNIL);
2512   ndbrequire(regApiPtr->num_commit_ack_markers == 0);
2513 /**
2514  * We wanted to verify those variables around commitAckMarkers,
2515  * So we have an ndbrequire around them, this means we can
2516  * remove the setting of them since we already verified that
2517  * they already have the correct value.
2518  * regApiPtr->num_commit_ack_markers = 0;
2519  * regApiPtr->commitAckMarker = RNIL;
2520  */
2521   regApiPtr->buddyPtr = RNIL;
2522   regApiPtr->currSavePointId = 0;
2523   regApiPtr->m_transaction_nodes.clear();
2524   regApiPtr->singleUserMode = 0;
2525   regApiPtr->m_pre_commit_pass = 0;
2526   regApiPtr->cascading_scans_count = 0;
2527   // FiredTriggers should have been released when previous transaction ended.
2528   ndbrequire(regApiPtr->theFiredTriggers.isEmpty());
2529   // Index data
2530   tc_clearbit(regApiPtr->m_flags,
2531               ApiConnectRecord::TF_INDEX_OP_RETURN);
2532   regApiPtr->noIndexOp = 0;
2533   if(releaseIndexOperations)
2534     releaseAllSeizedIndexOperations(regApiPtr);
2535   regApiPtr->immediateTriggerId = RNIL;
2536 
2537   tc_clearbit(regApiPtr->m_flags,
2538               ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
2539   tc_clearbit(regApiPtr->m_flags,
2540               ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS);
2541   c_counters.ctransCount++;
2542 
2543 #ifdef ERROR_INSERT
2544   regApiPtr->continueBCount = 0;
2545 #endif
2546 
2547   regApiPtr->m_write_count = 0;
2548 }//Dbtc::initApiConnectRec()
2549 
2550 int
seizeTcRecord(Signal * signal)2551 Dbtc::seizeTcRecord(Signal* signal)
2552 {
2553   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2554   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
2555   UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
2556   UintR TtcConnectFilesize = ctcConnectFilesize;
2557   tcConnectptr.i = TfirstfreeTcConnect;
2558   if (TfirstfreeTcConnect >= TtcConnectFilesize) {
2559     int place = 3;
2560     if (TfirstfreeTcConnect != RNIL) {
2561       place = 10;
2562     }//if
2563     TCKEY_abort(signal, place);
2564     return 1;
2565   }//if
2566   //--------------------------------------------------------------------------
2567   // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
2568   //--------------------------------------------------------------------------
2569   TcConnectRecord * const regTcPtr =
2570                            &localTcConnectRecord[TfirstfreeTcConnect];
2571 
2572   UintR TlastTcConnect = regApiPtr->lastTcConnect;
2573   UintR TtcConnectptrIndex = tcConnectptr.i;
2574   TcConnectRecordPtr tmpTcConnectptr;
2575 
2576   cfirstfreeTcConnect = regTcPtr->nextTcConnect;
2577   tcConnectptr.p = regTcPtr;
2578 
2579   c_counters.cconcurrentOp++;
2580 
2581   regTcPtr->prevTcConnect = TlastTcConnect;
2582   regTcPtr->nextTcConnect = RNIL;
2583   regTcPtr->numFiredTriggers = 0;
2584   regTcPtr->numReceivedTriggers = 0;
2585   regTcPtr->triggerExecutionCount = 0;
2586   regTcPtr->triggeringOperation = RNIL;
2587   regTcPtr->m_special_op_flags = 0;
2588   regTcPtr->indexOp = RNIL;
2589   regTcPtr->currentTriggerId = RNIL;
2590   regTcPtr->tcConnectstate = OS_ABORTING;
2591   regTcPtr->noOfNodes = 0;
2592 
2593   regApiPtr->lastTcConnect = TtcConnectptrIndex;
2594 
2595   if (TlastTcConnect == RNIL) {
2596     jam();
2597     regApiPtr->firstTcConnect = TtcConnectptrIndex;
2598   } else {
2599     tmpTcConnectptr.i = TlastTcConnect;
2600     jam();
2601     ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
2602     tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
2603   }//if
2604   return 0;
2605 }//Dbtc::seizeTcRecord()
2606 
2607 int
seizeCacheRecord(Signal * signal)2608 Dbtc::seizeCacheRecord(Signal* signal)
2609 {
2610   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2611   UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2612   UintR TcacheFilesize = ccacheFilesize;
2613   CacheRecord *localCacheRecord = cacheRecord;
2614   if (TfirstfreeCacheRec >= TcacheFilesize) {
2615     TCKEY_abort(signal, 41);
2616     return 1;
2617   }//if
2618   CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
2619 
2620   regApiPtr->cachePtr = TfirstfreeCacheRec;
2621   cfirstfreeCacheRec = regCachePtr->nextCacheRec;
2622   cachePtr.i = TfirstfreeCacheRec;
2623   cachePtr.p = regCachePtr;
2624 
2625   regCachePtr->currReclenAi = 0;
2626   regCachePtr->keyInfoSectionI = RNIL;
2627   regCachePtr->attrInfoSectionI = RNIL;
2628   return 0;
2629 }//Dbtc::seizeCacheRecord()
2630 
2631 void
releaseCacheRecord(ApiConnectRecordPtr transPtr,CacheRecord * regCachePtr)2632 Dbtc::releaseCacheRecord(ApiConnectRecordPtr transPtr, CacheRecord* regCachePtr)
2633 {
2634   ApiConnectRecord * const regApiPtr = transPtr.p;
2635   UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2636   UintR TCacheIndex = transPtr.p->cachePtr;
2637   regCachePtr->nextCacheRec = TfirstfreeCacheRec;
2638   cfirstfreeCacheRec = TCacheIndex;
2639   regApiPtr->cachePtr = RNIL;
2640 }
2641 
2642 void
dump_trans(ApiConnectRecordPtr transPtr)2643 Dbtc::dump_trans(ApiConnectRecordPtr transPtr)
2644 {
2645   printf("transid %u [ 0x%x 0x%x ] state: %u flags: 0x%x m_pre_commit_pass: %u\n",
2646          transPtr.i,
2647          transPtr.p->transid[0],
2648          transPtr.p->transid[1],
2649          transPtr.p->apiConnectstate,
2650          transPtr.p->m_flags,
2651          transPtr.p->m_pre_commit_pass);
2652 
2653   Uint32 i = 0;
2654   tcConnectptr.i = transPtr.p->firstTcConnect;
2655   while (tcConnectptr.i != RNIL)
2656   {
2657     jam();
2658     ptrCheckGuard(tcConnectptr,
2659                   ctcConnectFilesize, tcConnectRecord);
2660 
2661     Ptr<TcDefinedTriggerData> trigPtr;
2662     if (tcConnectptr.p->currentTriggerId != RNIL)
2663     {
2664       c_theDefinedTriggers.getPtr(trigPtr, tcConnectptr.p->currentTriggerId);
2665     }
2666 
2667     printf(" %u : opPtrI: 0x%x op: %u state: %u triggeringOperation: 0x%x flags: 0x%x triggerType: %u apiConnect: %u\n",
2668            i++,
2669            tcConnectptr.i,
2670            tcConnectptr.p->operation,
2671            tcConnectptr.p->tcConnectstate,
2672            tcConnectptr.p->triggeringOperation,
2673            tcConnectptr.p->m_special_op_flags,
2674            tcConnectptr.p->currentTriggerId == RNIL ? RNIL :
2675            (Uint32)trigPtr.p->triggerType,
2676            tcConnectptr.p->apiConnect);
2677 
2678     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
2679   }
2680 }
2681 
2682 bool
hasOp(ApiConnectRecordPtr transPtr,Uint32 opPtrI)2683 Dbtc::hasOp(ApiConnectRecordPtr transPtr, Uint32 opPtrI)
2684 {
2685   TcConnectRecordPtr tcPtr;
2686   tcPtr.i = transPtr.p->firstTcConnect;
2687   while (tcPtr.i != RNIL)
2688   {
2689     jam();
2690     ptrCheckGuard(tcPtr,
2691                   ctcConnectFilesize, tcConnectRecord);
2692     if (tcPtr.i == opPtrI)
2693     {
2694       return tcPtr.p->apiConnect == transPtr.i;
2695     }
2696 
2697     tcPtr.i = tcPtr.p->nextTcConnect;
2698   }
2699 
2700   return false;
2701 }
2702 
2703 /*****************************************************************************/
2704 /*                               T C K E Y R E Q                             */
2705 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN      */
2706 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST   */
2707 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES       */
2708 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA                */
2709 /*****************************************************************************/
execTCKEYREQ(Signal * signal)2710 void Dbtc::execTCKEYREQ(Signal* signal)
2711 {
2712   Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
2713   UintR compare_transid1, compare_transid2;
2714   const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
2715   UintR Treqinfo;
2716   SectionHandle handle(this, signal);
2717 
2718   jamEntry();
2719   /*-------------------------------------------------------------------------
2720    * Common error routines are used for several signals, they need to know
2721    * where to find the transaction identifier in the signal.
2722    *-------------------------------------------------------------------------*/
2723   const UintR TapiIndex = tcKeyReq->apiConnectPtr;
2724   const UintR TapiMaxIndex = capiConnectFilesize;
2725   const UintR TtabIndex = tcKeyReq->tableId;
2726   const UintR TtabMaxIndex = ctabrecFilesize;
2727   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2728 
2729   ttransid_ptr = 6;
2730   apiConnectptr.i = TapiIndex;
2731   if (TapiIndex >= TapiMaxIndex) {
2732     releaseSections(handle);
2733     TCKEY_abort(signal, 6);
2734     return;
2735   }//if
2736   if (TtabIndex >= TtabMaxIndex) {
2737     releaseSections(handle);
2738     TCKEY_abort(signal, 7);
2739     return;
2740   }//if
2741 
2742 #ifdef ERROR_INSERT
2743   if (ERROR_INSERTED(8079))
2744   {
2745     /* Test that no signals received after API_FAILREQ */
2746     if (sendersNodeId == c_lastFailedApi)
2747     {
2748       /* Signal from API node received *after* API_FAILREQ */
2749       ndbrequire(false);
2750     }
2751   }
2752 #endif
2753 
2754   Treqinfo = tcKeyReq->requestInfo;
2755   //--------------------------------------------------------------------------
2756   // Optimised version of ptrAss(tabptr, tableRecord)
2757   // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
2758   //--------------------------------------------------------------------------
2759   ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
2760   apiConnectptr.i = TapiIndex;
2761   apiConnectptr.p = regApiPtr;
2762 
2763   Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
2764   Uint32 TexecFlag =
2765     TcKeyReq::getExecuteFlag(Treqinfo) ? ApiConnectRecord::TF_EXEC_FLAG : 0;
2766 
2767   Uint16 Tspecial_op_flags = regApiPtr->m_special_op_flags;
2768   bool isIndexOpReturn = tc_testbit(regApiPtr->m_flags,
2769                                     ApiConnectRecord::TF_INDEX_OP_RETURN);
2770   bool isExecutingTrigger = Tspecial_op_flags & TcConnectRecord::SOF_TRIGGER;
2771   regApiPtr->m_special_op_flags = 0; // Reset marker
2772   regApiPtr->m_flags |= TexecFlag;
2773   TableRecordPtr localTabptr;
2774   localTabptr.i = TtabIndex;
2775   localTabptr.p = &tableRecord[TtabIndex];
2776   switch (regApiPtr->apiConnectstate) {
2777   case CS_CONNECTED:{
2778     if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2779       //---------------------------------------------------------------------
2780       // Initialise API connect record if transaction is started.
2781       //---------------------------------------------------------------------
2782       jam();
2783       initApiConnectRec(signal, regApiPtr);
2784       regApiPtr->m_flags |= TexecFlag;
2785     } else {
2786       releaseSections(handle);
2787       if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2788 	/*------------------------------------------------------------------
2789 	 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
2790 	 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
2791 	 * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
2792 	 *-----------------------------------------------------------------*/
2793 	TCKEY_abort(signal, 0);
2794 	return;
2795       } else {
2796 	/**
2797 	 * getAllowStartTransaction(sendersNodeId) == false
2798 	 */
2799 	TCKEY_abort(signal, TexecFlag ? 60 : 57);
2800 	return;
2801       }//if
2802     }
2803   }
2804   break;
2805   case CS_STARTED:
2806     if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
2807     {
2808       /**
2809        * If last operation in last transaction was a simple/dirty read
2810        *  it does not have to be committed or rollbacked hence,
2811        *  the state will be CS_STARTED
2812        */
2813       jam();
2814       if (unlikely(getNodeState().getSingleUserMode()) &&
2815           getNodeState().getSingleUserApi() != sendersNodeId &&
2816           !localTabptr.p->singleUserMode)
2817       {
2818         releaseSections(handle);
2819 	TCKEY_abort(signal, TexecFlag ? 60 : 57);
2820         return;
2821       }
2822       initApiConnectRec(signal, regApiPtr);
2823       regApiPtr->m_flags |= TexecFlag;
2824     } else {
2825       //----------------------------------------------------------------------
2826       // Transaction is started already.
2827       // Check that the operation is on the same transaction.
2828       //-----------------------------------------------------------------------
2829       compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
2830       compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
2831       jam();
2832       compare_transid1 = compare_transid1 | compare_transid2;
2833       if (compare_transid1 != 0) {
2834         releaseSections(handle);
2835 	TCKEY_abort(signal, 1);
2836 	return;
2837       }//if
2838     }
2839     break;
2840   case CS_ABORTING:
2841     if (regApiPtr->abortState == AS_IDLE) {
2842       if (TstartFlag == 1) {
2843         if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
2844           releaseSections(handle);
2845           TCKEY_abort(signal, TexecFlag ? 60 : 57);
2846           return;
2847         }
2848 	//--------------------------------------------------------------------
2849 	// Previous transaction had been aborted and the abort was completed.
2850 	// It is then OK to start a new transaction again.
2851 	//--------------------------------------------------------------------
2852         jam();
2853         initApiConnectRec(signal, regApiPtr);
2854 	regApiPtr->m_flags |= TexecFlag;
2855       } else if(TexecFlag) {
2856         releaseSections(handle);
2857 	TCKEY_abort(signal, 59);
2858 	return;
2859       } else {
2860 	//--------------------------------------------------------------------
2861 	// The current transaction was aborted successfully.
2862 	// We will not do anything before we receive an operation
2863 	// with a start indicator. We will ignore this signal.
2864 	//--------------------------------------------------------------------
2865 	jam();
2866 	DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
2867         releaseSections(handle);
2868         return;
2869       }//if
2870     } else {
2871       //----------------------------------------------------------------------
2872       // Previous transaction is still aborting
2873       //----------------------------------------------------------------------
2874       jam();
2875       releaseSections(handle);
2876       if (TstartFlag == 1) {
2877 	//--------------------------------------------------------------------
2878 	// If a new transaction tries to start while the old is
2879 	// still aborting, we will report this to the starting API.
2880 	//--------------------------------------------------------------------
2881         TCKEY_abort(signal, 2);
2882         return;
2883       } else if(TexecFlag) {
2884         TCKEY_abort(signal, 59);
2885         return;
2886       }
2887       //----------------------------------------------------------------------
2888       // Ignore signals without start indicator set when aborting transaction.
2889       //----------------------------------------------------------------------
2890       DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
2891       return;
2892     }//if
2893     break;
2894   case CS_START_COMMITTING:
2895   case CS_SEND_FIRE_TRIG_REQ:
2896   case CS_WAIT_FIRE_TRIG_REQ:
2897     jam();
2898     if(isIndexOpReturn || isExecutingTrigger){
2899       break;
2900     }
2901   default:
2902     jam();
2903     /*----------------------------------------------------------------------
2904      * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
2905      * WHEN IT WAS NOT EXPECTED TO.
2906      * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
2907      * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
2908      * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
2909      * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
2910      * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
2911      *---------------------------------------------------------------------*/
2912     releaseSections(handle);
2913     TCKEY_abort(signal, 55);
2914     return;
2915   }//switch
2916 
2917   if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
2918     ;
2919   } else {
2920     /*-----------------------------------------------------------------------*/
2921     /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT.  */
2922     /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED.                          */
2923     /*-----------------------------------------------------------------------*/
2924     releaseSections(handle);
2925     TCKEY_abort(signal, 8);
2926     return;
2927   }//if
2928 
2929   //-------------------------------------------------------------------------
2930   // Error Insertion for testing purposes. Test to see what happens when no
2931   // more TC records available.
2932   //-------------------------------------------------------------------------
2933   if (ERROR_INSERTED(8032)) {
2934     releaseSections(handle);
2935     TCKEY_abort(signal, 3);
2936     return;
2937   }//if
2938 
2939   if (seizeTcRecord(signal) != 0) {
2940     releaseSections(handle);
2941     return;
2942   }//if
2943 
2944   if (seizeCacheRecord(signal) != 0) {
2945     releaseSections(handle);
2946     return;
2947   }//if
2948 
2949   CRASH_INSERTION(8063);
2950 
2951   TcConnectRecord * const regTcPtr = tcConnectptr.p;
2952   CacheRecord * const regCachePtr = cachePtr.p;
2953 
2954   /*
2955     INIT_TC_CONNECT_REC
2956     -------------------------
2957   */
2958   /* ---------------------------------------------------------------------- */
2959   /* -------     INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS   ------- */
2960   /*                                                                        */
2961   /* ---------------------------------------------------------------------- */
2962 
2963   UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
2964   regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
2965 
2966   /* If we have any sections at all then this is a long TCKEYREQ */
2967   regCachePtr->isLongTcKeyReq= ( handle.m_cnt != 0 );
2968 
2969   UintR TapiConnectptrIndex = apiConnectptr.i;
2970   UintR TsenderData = tcKeyReq->senderData;
2971 
2972   if (ERROR_INSERTED(8065))
2973   {
2974     ErrorSignalReceive= 1;
2975     ErrorMaxSegmentsToSeize= 10;
2976   }
2977   if (ERROR_INSERTED(8066))
2978   {
2979     ErrorSignalReceive= 1;
2980     ErrorMaxSegmentsToSeize= 1;
2981   }
2982   if (ERROR_INSERTED(8067))
2983   {
2984     ErrorSignalReceive= 1;
2985     ErrorMaxSegmentsToSeize= 0;
2986   }
2987   if (ERROR_INSERTED(8068))
2988   {
2989     ErrorSignalReceive= 0;
2990     ErrorMaxSegmentsToSeize= 0;
2991     CLEAR_ERROR_INSERT_VALUE;
2992     DEBUG("Max segments to seize cleared");
2993   }
2994 #ifdef ERROR_INSERT
2995   if (ErrorSignalReceive)
2996     DEBUG("Max segments to seize : "
2997           << ErrorMaxSegmentsToSeize);
2998 #endif
2999 
3000   /* Key and attribute lengths are passed in the header for
3001    * short TCKEYREQ and  passed as section lengths for long
3002    * TCKEYREQ
3003    */
3004   UintR TkeyLength = 0;
3005   UintR TattrLen = 0;
3006   UintR titcLenAiInTckeyreq = 0;
3007 
3008   if (regCachePtr->isLongTcKeyReq)
3009   {
3010     SegmentedSectionPtr keyInfoSec;
3011     if (handle.getSection(keyInfoSec, TcKeyReq::KeyInfoSectionNum))
3012       TkeyLength= keyInfoSec.sz;
3013 
3014     SegmentedSectionPtr attrInfoSec;
3015     if (handle.getSection(attrInfoSec, TcKeyReq::AttrInfoSectionNum))
3016       TattrLen= attrInfoSec.sz;
3017 
3018     if (TcKeyReq::getDeferredConstraints(Treqinfo))
3019     {
3020       regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
3021     }
3022 
3023     if (TcKeyReq::getDisableFkConstraints(Treqinfo))
3024     {
3025       regApiPtr->m_flags |= ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS;
3026     }
3027   }
3028   else
3029   {
3030     TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
3031     TattrLen= TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
3032     titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
3033   }
3034 
3035   regCachePtr->keylen = TkeyLength;
3036   regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
3037   regCachePtr->currReclenAi = titcLenAiInTckeyreq;
3038 
3039   regTcPtr->apiConnect = TapiConnectptrIndex;
3040   regTcPtr->clientData = TsenderData;
3041   regTcPtr->commitAckMarker = RNIL;
3042   regTcPtr->m_special_op_flags = Tspecial_op_flags;
3043   regTcPtr->indexOp = regApiPtr->executingIndexOp;
3044   regTcPtr->savePointId = regApiPtr->currSavePointId;
3045   regApiPtr->executingIndexOp = RNIL;
3046 
3047   regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
3048 
3049   if (isExecutingTrigger)
3050   {
3051     // Save the TcOperationPtr for fireing operation
3052     regTcPtr->triggeringOperation = TsenderData;
3053     // ndbrequire(hasOp(apiConnectptr, TsenderData));
3054 
3055     // Grab trigger Id from ApiConnectRecord
3056     ndbrequire(regApiPtr->immediateTriggerId != RNIL);
3057     regTcPtr->currentTriggerId= regApiPtr->immediateTriggerId;
3058   }
3059   ndbassert(isExecutingTrigger ||
3060             (regApiPtr->immediateTriggerId == RNIL));
3061 
3062   if (TexecFlag){
3063     Uint32 currSPId = regApiPtr->currSavePointId;
3064     regApiPtr->currSavePointId = ++currSPId;
3065   }
3066 
3067   regCachePtr->attrlength = TattrLen;
3068   c_counters.cattrinfoCount += TattrLen;
3069 
3070   UintR TtabptrIndex = localTabptr.i;
3071   UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
3072   Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
3073   regCachePtr->tableref = TtabptrIndex;
3074   regCachePtr->schemaVersion = TtableSchemaVersion;
3075   regTcPtr->operation = TOperationType;
3076 
3077   Uint8 TSimpleFlag         = TcKeyReq::getSimpleFlag(Treqinfo);
3078   Uint8 TDirtyFlag          = TcKeyReq::getDirtyFlag(Treqinfo);
3079   Uint8 TInterpretedFlag    = TcKeyReq::getInterpretedFlag(Treqinfo);
3080   Uint8 TDistrKeyFlag       = TcKeyReq::getDistributionKeyFlag(Treqinfo);
3081   Uint8 TNoDiskFlag         = TcKeyReq::getNoDiskFlag(Treqinfo);
3082   Uint8 TexecuteFlag        = TexecFlag;
3083   Uint8 Treorg              = TcKeyReq::getReorgFlag(Treqinfo);
3084   const Uint8 TViaSPJFlag   = TcKeyReq::getViaSPJFlag(Treqinfo);
3085   const Uint8 Tqueue        = TcKeyReq::getQueueOnRedoProblemFlag(Treqinfo);
3086 
3087   if (Treorg)
3088   {
3089     if (TOperationType == ZWRITE)
3090       regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_COPY;
3091     else if (TOperationType == ZDELETE)
3092       regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_DELETE;
3093     else
3094     {
3095       ndbassert(false);
3096     }
3097   }
3098 
3099   regTcPtr->dirtyOp  = TDirtyFlag;
3100   regTcPtr->opSimple = TSimpleFlag;
3101   regCachePtr->opExec   = TInterpretedFlag;
3102   regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
3103   regCachePtr->m_no_disk_flag = TNoDiskFlag;
3104   regCachePtr->viaSPJFlag = TViaSPJFlag;
3105   regCachePtr->m_op_queue = Tqueue;
3106 
3107   //-------------------------------------------------------------
3108   // The next step is to read the upto three conditional words.
3109   //-------------------------------------------------------------
3110   Uint32 TkeyIndex;
3111   Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
3112   {
3113     Uint32  TDistrGHIndex    = TcKeyReq::getScanIndFlag(Treqinfo);
3114     Uint32  TDistrKeyIndex   = TDistrGHIndex;
3115 
3116     Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
3117 
3118     regCachePtr->scanTakeOverInd = TDistrGHIndex;
3119     regCachePtr->scanInfo = TscanInfo;
3120 
3121     regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
3122 
3123     TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
3124   }
3125 
3126   regCachePtr->m_no_hash = false;
3127 
3128   if (TOperationType == ZUNLOCK)
3129   {
3130     /* Unlock op has distribution key containing
3131      * LQH nodeid and fragid
3132      */
3133     ndbassert( regCachePtr->distributionKeyIndicator );
3134     regCachePtr->m_no_hash = 1;
3135     regCachePtr->unlockNodeId = (regCachePtr->distributionKey >> 16);
3136     regCachePtr->distributionKey &= 0xffff;
3137   }
3138 
3139   regCachePtr->m_special_hash =
3140     localTabptr.p->hasCharAttr |
3141     (localTabptr.p->noOfDistrKeys > 0) |
3142     regCachePtr->m_no_hash;
3143 
3144   if (TkeyLength == 0)
3145   {
3146     releaseSections(handle);
3147     TCKEY_abort(signal, 4);
3148     return;
3149   }
3150 
3151   if (unlikely(TViaSPJFlag &&
3152                /* Check that all nodes can handle SPJ requests. */
3153                !ndb_join_pushdown(getNodeVersionInfo().m_type[NodeInfo::DB]
3154                                   .m_min_version)))
3155   {
3156     jam();
3157     releaseSections(handle);
3158     TCKEY_abort(signal, 66);
3159     return;
3160   }
3161 
3162   /* KeyInfo and AttrInfo are buffered in segmented sections
3163    * If they arrived in segmented sections then there's nothing to do
3164    * If they arrived in short signals then they are appended into
3165    * segmented sections
3166    */
3167   if (regCachePtr->isLongTcKeyReq)
3168   {
3169     ndbassert( titcLenAiInTckeyreq == 0);
3170     /* Long TcKeyReq - KI and AI already in sections */
3171     SegmentedSectionPtr keyInfoSection, attrInfoSection;
3172 
3173     /* Store i value for first long section of KeyInfo
3174      * and AttrInfo in Cache Record
3175      */
3176     handle.getSection(keyInfoSection,
3177                       TcKeyReq::KeyInfoSectionNum);
3178 
3179     regCachePtr->keyInfoSectionI= keyInfoSection.i;
3180 
3181     if (regCachePtr->attrlength != 0)
3182     {
3183       ndbassert( handle.m_cnt == 2 );
3184       handle.getSection(attrInfoSection,
3185                         TcKeyReq::AttrInfoSectionNum);
3186       regCachePtr->attrInfoSectionI= attrInfoSection.i;
3187     }
3188     else
3189     {
3190       ndbassert( handle.m_cnt == 1 );
3191     }
3192 
3193     /* Detach sections from the handle, we are now responsible
3194      * for always freeing them before returning
3195      * For a long TcKeyReq, they will be freed at the end
3196      * of the processing this signal.
3197      */
3198     handle.clear();
3199   }
3200   else
3201   {
3202     /* Short TcKeyReq - need to receive KI and AI into
3203      * segmented sections
3204      * We store any KI and AI from the TCKeyReq now and
3205      * will then wait for further signals if necessary
3206      */
3207     ndbassert( handle.m_cnt == 0 );
3208     Uint32 keyInfoInTCKeyReq= MIN(TkeyLength, TcKeyReq::MaxKeyInfo);
3209 
3210     bool ok= appendToSection(regCachePtr->keyInfoSectionI,
3211                              &TOptionalDataPtr[TkeyIndex],
3212                              keyInfoInTCKeyReq);
3213     if (!ok)
3214     {
3215       jam();
3216       appendToSectionErrorLab(signal);
3217       return;
3218     }
3219 
3220     if (titcLenAiInTckeyreq != 0)
3221     {
3222       Uint32 TAIDataIndex= TkeyIndex + keyInfoInTCKeyReq;
3223 
3224       ok= appendToSection(regCachePtr->attrInfoSectionI,
3225                           &TOptionalDataPtr[TAIDataIndex],
3226                           titcLenAiInTckeyreq);
3227       if (!ok)
3228       {
3229         jam();
3230         appendToSectionErrorLab(signal);
3231         return;
3232       }
3233     }
3234   }
3235 
3236   if (TOperationType == ZUNLOCK)
3237   {
3238     jam();
3239     // TODO : Consider adding counter for unlock operations
3240   }
3241   else if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
3242     jam();
3243     c_counters.creadCount++;
3244   }
3245   else
3246   {
3247     /**
3248      * Insert, Update, Write, Delete
3249      * Markers are created on all nodes in a nodegroup
3250      * (as changes affect all replicas)
3251      * Therefore any survivable node failure will have a live
3252      * node with a marker for any marked write transaction.
3253      * Therefore only need one nodegroup marked - after that
3254      * needn't bother.
3255      */
3256     if (!tc_testbit(regApiPtr->m_flags,
3257                     ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED))
3258     {
3259       if(regApiPtr->commitAckMarker != RNIL)
3260         regTcPtr->commitAckMarker = regApiPtr->commitAckMarker;
3261       else
3262       {
3263         jam();
3264         CommitAckMarkerPtr tmp;
3265         if (ERROR_INSERTED(8087))
3266         {
3267           CLEAR_ERROR_INSERT_VALUE;
3268           TCKEY_abort(signal, 56);
3269           return;
3270         }
3271 
3272         if (!m_commitAckMarkerHash.seize(tmp))
3273         {
3274           TCKEY_abort(signal, 56);
3275           return;
3276         }
3277         else
3278         {
3279           regTcPtr->commitAckMarker = tmp.i;
3280           regApiPtr->commitAckMarker = tmp.i;
3281           new (tmp.p) CommitAckMarker();
3282           tmp.p->transid1      = tcKeyReq->transId1;
3283           tmp.p->transid2      = tcKeyReq->transId2;
3284           tmp.p->apiNodeId     = refToNode(regApiPtr->ndbapiBlockref);
3285           tmp.p->apiConnectPtr = TapiIndex;
3286 #if defined VM_TRACE || defined ERROR_INSERT
3287 	  {
3288 	    CommitAckMarkerPtr check;
3289 	    ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
3290           }
3291 #endif
3292           m_commitAckMarkerHash.add(tmp);
3293         }
3294       }
3295       regApiPtr->num_commit_ack_markers++;
3296     }
3297 
3298     UintR Toperationsize = coperationsize;
3299     /* --------------------------------------------------------------------
3300      *   THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
3301      *   THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
3302      *   TEMP TABLES DON'T PARTICIPATE.
3303      * -------------------------------------------------------------------- */
3304     if (localTabptr.p->get_storedTable()) {
3305       coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
3306     }
3307     c_counters.cwriteCount++;
3308     switch (TOperationType) {
3309     case ZUPDATE:
3310     case ZINSERT:
3311     case ZDELETE:
3312     case ZWRITE:
3313     case ZREFRESH:
3314       jam();
3315       regApiPtr->m_write_count++;
3316       if (regApiPtr->m_flags & ApiConnectRecord::TF_DEFERRED_CONSTRAINTS)
3317       {
3318         /**
3319          * Allow slave applier to ignore m_max_writes_per_trans
3320          */
3321         break;
3322       }
3323 
3324       if (unlikely(regApiPtr->m_write_count > m_max_writes_per_trans))
3325       {
3326         TCKEY_abort(signal, 65);
3327         return;
3328       }
3329       break;
3330     default:
3331       TCKEY_abort(signal, 9);
3332       return;
3333     }//switch
3334   }//if
3335 
3336   Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
3337   regTcPtr->m_execAbortOption = TabortOption;
3338 
3339   /*-------------------------------------------------------------------------
3340    * Check error handling per operation
3341    * If CommitFlag is set state accordingly and check for early abort
3342    *------------------------------------------------------------------------*/
3343   if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
3344     ndbrequire(TexecuteFlag);
3345     regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3346   } else {
3347     /* ---------------------------------------------------------------------
3348      *       PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
3349      * ---------------------------------------------------------------------
3350      *       ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
3351      * IF PREPARE TRANSACTION THEN
3352      *   API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
3353      * SET STATE TO PREPARING
3354      * --------------------------------------------------------------------- */
3355     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3356       jam();
3357       // Trigger execution at commit
3358       regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3359     } else if (!regApiPtr->isExecutingDeferredTriggers()) {
3360       jam();
3361       regApiPtr->apiConnectstate = CS_RECEIVING;
3362     }//if
3363   }//if
3364 
3365   if (regCachePtr->isLongTcKeyReq)
3366   {
3367     jam();
3368     /* Have all the KeyInfo (and AttrInfo), process now */
3369     tckeyreq050Lab(signal);
3370   }
3371   else if (TkeyLength <= TcKeyReq::MaxKeyInfo)
3372   {
3373     jam();
3374     /* Have all the KeyInfo, get any extra AttrInfo */
3375     tckeyreq050Lab(signal);
3376   }
3377   else
3378   {
3379     jam();
3380     /* --------------------------------------------------------------------
3381      * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
3382      * SAVE STATE AND WAIT FOR KEYINFO
3383      * --------------------------------------------------------------------*/
3384     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
3385     regCachePtr->save1 = 8;
3386     regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
3387     return;
3388   }//if
3389 
3390   return;
3391 }//Dbtc::execTCKEYREQ()
3392 
3393 static
3394 void
handle_reorg_trigger(DiGetNodesConf * conf)3395 handle_reorg_trigger(DiGetNodesConf * conf)
3396 {
3397   if (conf->reqinfo & DiGetNodesConf::REORG_MOVING)
3398   {
3399     conf->fragId = conf->nodes[MAX_REPLICAS];
3400     conf->reqinfo = conf->nodes[MAX_REPLICAS+1];
3401     memcpy(conf->nodes, conf->nodes+MAX_REPLICAS+2,
3402            sizeof(Uint32)*MAX_REPLICAS);
3403   }
3404   else
3405   {
3406     conf->nodes[0] = 0; // Should not execute...
3407   }
3408 }
3409 
3410 bool
isRefreshSupported() const3411 Dbtc::isRefreshSupported() const
3412 {
3413   const NodeVersionInfo& nvi = getNodeVersionInfo();
3414   const Uint32 minVer = nvi.m_type[NodeInfo::DB].m_min_version;
3415   const Uint32 maxVer = nvi.m_type[NodeInfo::DB].m_max_version;
3416 
3417   if (likely (minVer == maxVer))
3418   {
3419     /* Normal case, use function */
3420     return ndb_refresh_tuple(minVer);
3421   }
3422 
3423   /* As refresh feature was introduced across three minor versions
3424    * we check that all data nodes support it.  This slow path
3425    * should only be hit during upgrades between versions
3426    */
3427   for (Uint32 i=1; i < MAX_NODES; i++)
3428   {
3429     const NodeInfo& nodeInfo = getNodeInfo(i);
3430     if ((nodeInfo.m_type == NODE_TYPE_DB) &&
3431         (nodeInfo.m_connected) &&
3432         (! ndb_refresh_tuple(nodeInfo.m_version)))
3433       return false;
3434   }
3435   return true;
3436 }
3437 
3438 /**
3439  * tckeyreq050Lab
3440  * This method is executed once all KeyInfo has been obtained for
3441  * the TcKeyReq signal
3442  */
tckeyreq050Lab(Signal * signal)3443 void Dbtc::tckeyreq050Lab(Signal* signal)
3444 {
3445   UintR tnoOfBackup;
3446   UintR tnoOfStandby;
3447   UintR tnodeinfo;
3448 
3449   terrorCode = 0;
3450 
3451   hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
3452 
3453   CacheRecord * const regCachePtr = cachePtr.p;
3454   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3455   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3456 
3457   UintR TtcTimer = ctcTimer;
3458   UintR ThashValue = thashValue;
3459   UintR TdistrHashValue = tdistrHashValue;
3460   UintR Ttableref = regCachePtr->tableref;
3461   Uint16 Tspecial_op_flags = regTcPtr->m_special_op_flags;
3462 
3463   TableRecordPtr localTabptr;
3464   localTabptr.i = Ttableref;
3465   localTabptr.p = &tableRecord[localTabptr.i];
3466   Uint32 schemaVersion = regCachePtr->schemaVersion;
3467   if(localTabptr.p->checkTable(schemaVersion)){
3468     ;
3469   } else {
3470     terrorCode = localTabptr.p->getErrorCode(schemaVersion);
3471     TCKEY_abort(signal, 58);
3472     return;
3473   }
3474 
3475   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3476   regCachePtr->hashValue = ThashValue;
3477 
3478   ndbassert( signal->getNoOfSections() == 0 );
3479 
3480   DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
3481   req->tableId = Ttableref;
3482   req->hashValue = TdistrHashValue;
3483   req->distr_key_indicator = regCachePtr->distributionKeyIndicator;
3484   req->jamBufferPtr = jamBuffer();
3485 
3486   /*-------------------------------------------------------------*/
3487   /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
3488   /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE   */
3489   /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION.   */
3490   /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
3491   /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
3492   /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB.            */
3493   /*-------------------------------------------------------------*/
3494   EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
3495                  DiGetNodesReq::SignalLength, 0);
3496   DiGetNodesConf * conf = (DiGetNodesConf *)&signal->theData[0];
3497   UintR Tdata2 = conf->reqinfo;
3498   UintR TerrorIndicator = signal->theData[0];
3499   jamEntry();
3500   if (TerrorIndicator != 0) {
3501     execDIGETNODESREF(signal);
3502     return;
3503   }
3504 
3505   if((ERROR_INSERTED(8071) || ERROR_INSERTED(8072)) &&
3506      (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) &&
3507      signal->theData[3] != getOwnNodeId())
3508   {
3509     ndbassert(false);
3510     signal->theData[1] = 626;
3511     execDIGETNODESREF(signal);
3512     return;
3513   }
3514 
3515   if((ERROR_INSERTED(8050) || ERROR_INSERTED(8072)) &&
3516      refToBlock(regApiPtr->ndbapiBlockref) != DBUTIL &&
3517      regTcPtr->m_special_op_flags == 0 &&
3518      signal->theData[3] != getOwnNodeId())
3519   {
3520     ndbassert(false);
3521     signal->theData[1] = 626;
3522     execDIGETNODESREF(signal);
3523     return;
3524   }
3525 
3526   /****************>>*/
3527   /* DIGETNODESCONF >*/
3528   /* ***************>*/
3529   if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_TRIGGER_BASE)
3530   {
3531     jam();
3532     handle_reorg_trigger(conf);
3533     Tdata2 = conf->reqinfo;
3534   }
3535   else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_DELETE)
3536   {
3537     jam();
3538     handle_reorg_trigger(conf);
3539     Tdata2 = conf->reqinfo;
3540   }
3541   else if (Tdata2 & DiGetNodesConf::REORG_MOVING)
3542   {
3543     jam();
3544     regTcPtr->m_special_op_flags |= TcConnectRecord::SOF_REORG_MOVING;
3545   }
3546   else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_COPY)
3547   {
3548     jam();
3549     conf->nodes[0] = 0;
3550   }
3551 
3552   UintR Tdata1 = conf->fragId;
3553   UintR Tdata3 = conf->nodes[0];
3554   UintR Tdata4 = conf->nodes[1];
3555   UintR Tdata5 = conf->nodes[2];
3556   UintR Tdata6 = conf->nodes[3];
3557 
3558   regCachePtr->fragmentid = Tdata1;
3559   tnodeinfo = Tdata2;
3560 
3561   regTcPtr->tcNodedata[0] = Tdata3;
3562   regTcPtr->tcNodedata[1] = Tdata4;
3563   regTcPtr->tcNodedata[2] = Tdata5;
3564   regTcPtr->tcNodedata[3] = Tdata6;
3565 
3566   regTcPtr->lqhInstanceKey = (Tdata2 >> 24) & 127;// 1 bit used for reorg moving
3567 
3568   Uint8 Toperation = regTcPtr->operation;
3569   Uint8 TopSimple = regTcPtr->opSimple;
3570   Uint8 TopDirty = regTcPtr->dirtyOp;
3571   tnoOfBackup = tnodeinfo & 3;
3572   tnoOfStandby = (tnodeinfo >> 8) & 3;
3573 
3574   regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
3575   if (Toperation == ZREAD || Toperation == ZREAD_EX)
3576   {
3577     regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3578     if (TopSimple == 1 && TopDirty == 0){
3579       jam();
3580       /*-------------------------------------------------------------*/
3581       /*       A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND       */
3582       /*       BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS      */
3583       /*       NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION   */
3584       /*       WITH SIMPLE READS.                                    */
3585       /*-------------------------------------------------------------*/
3586       arrGuard(tnoOfBackup, MAX_REPLICAS);
3587       UintR Tindex;
3588       UintR TownNode = cownNodeid;
3589       for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
3590         UintR Tnode = regTcPtr->tcNodedata[Tindex];
3591         jam();
3592         if (Tnode == TownNode) {
3593           jam();
3594           regTcPtr->tcNodedata[0] = Tnode;
3595         }//if
3596       }//for
3597       if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
3598       {
3599 	for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
3600 	{
3601 	  UintR Tnode = regTcPtr->tcNodedata[Tindex];
3602 	  jam();
3603 	  if (Tnode != TownNode) {
3604 	    jam();
3605 	    regTcPtr->tcNodedata[0] = Tnode;
3606 	    ndbout_c("Choosing %d", Tnode);
3607 	  }//if
3608 	}//for
3609       }
3610     }//if
3611     jam();
3612     regTcPtr->lastReplicaNo = 0;
3613     regTcPtr->noOfNodes = 1;
3614 
3615     if (regTcPtr->tcNodedata[0] == getOwnNodeId())
3616       c_counters.clocalReadCount++;
3617   }
3618   else if (Toperation == ZUNLOCK)
3619   {
3620     regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3621 
3622     const Uint32 numNodes = tnoOfBackup + 1;
3623     /* Check that node from dist key is one of the nodes returned */
3624     bool found = false;
3625     for (Uint32 idx = 0; idx < numNodes; idx ++)
3626     {
3627       NodeId nodeId = regTcPtr->tcNodedata[ idx ];
3628       jam();
3629       if (nodeId == regCachePtr->unlockNodeId)
3630       {
3631         jam();
3632         found = true;
3633         break;
3634       }
3635     }
3636 
3637     if (unlikely(!found))
3638     {
3639       /* DIH says the specified node does not store the fragment
3640        * requested
3641        */
3642       jam();
3643       TCKEY_abort(signal, 64);
3644       return;
3645     }
3646 
3647     /* Check that the relevant LQH node can handle an unlock request */
3648     Uint32 lqhVersion = getNodeInfo(regCachePtr->unlockNodeId).m_version;
3649 
3650     if (unlikely( lqhVersion < NDBD_UNLOCK_OP_SUPPORTED ))
3651     {
3652       TCKEY_abort(signal, 63);
3653       return;
3654     }
3655 
3656     /* Select the specified node for the unlock op */
3657     regTcPtr->tcNodedata[0] = regCachePtr->unlockNodeId;
3658     regTcPtr->lastReplicaNo = 0;
3659     regTcPtr->noOfNodes = 1;
3660   }
3661   else {
3662     UintR TlastReplicaNo;
3663     jam();
3664     TlastReplicaNo = tnoOfBackup + tnoOfStandby;
3665     regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
3666     regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
3667     if (regTcPtr->tcNodedata[0] == getOwnNodeId())
3668       c_counters.clocalWriteCount++;
3669 
3670     if (unlikely((Toperation == ZREFRESH) &&
3671                  (! isRefreshSupported())))
3672     {
3673       /* Function not implemented yet */
3674       TCKEY_abort(signal,63);
3675       return;
3676     }
3677   }//if
3678 
3679   if (regCachePtr->isLongTcKeyReq ||
3680       (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength)) {
3681     /****************************************************************>*/
3682     /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS      */
3683     /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
3684     /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
3685     /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER         */
3686     /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
3687     /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET.                */
3688     /****************************************************************>*/
3689     switch (regApiPtr->apiConnectstate) {
3690     case CS_RECEIVING:
3691       jam();
3692       regApiPtr->apiConnectstate = CS_STARTED;
3693       break;
3694     case CS_REC_COMMITTING:
3695       jam();
3696       regApiPtr->apiConnectstate = CS_START_COMMITTING;
3697       break;
3698     case CS_SEND_FIRE_TRIG_REQ:
3699     case CS_WAIT_FIRE_TRIG_REQ:
3700       jam();
3701       break;
3702     default:
3703       jam();
3704       systemErrorLab(signal, __LINE__);
3705       return;
3706     }//switch
3707     attrinfoDihReceivedLab(signal);
3708     return;
3709   } else {
3710     if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
3711       TtcTimer = ctcTimer;
3712       jam();
3713       setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3714       regTcPtr->tcConnectstate = OS_WAIT_ATTR;
3715       return;
3716     } else {
3717       TCKEY_abort(signal, 11);
3718       return;
3719     }//if
3720   }//if
3721   return;
3722 }//Dbtc::tckeyreq050Lab()
3723 
attrinfoDihReceivedLab(Signal * signal)3724 void Dbtc::attrinfoDihReceivedLab(Signal* signal)
3725 {
3726   CacheRecord * const regCachePtr = cachePtr.p;
3727   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3728   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3729   Uint16 Tnode = regTcPtr->tcNodedata[0];
3730 
3731   TableRecordPtr localTabptr;
3732   localTabptr.i = regCachePtr->tableref;
3733   localTabptr.p = &tableRecord[localTabptr.i];
3734 
3735   if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
3736     ;
3737   } else {
3738     terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
3739     TCKEY_abort(signal, 58);
3740     return;
3741   }
3742   if (Tnode != 0)
3743   {
3744     jam();
3745     arrGuard(Tnode, MAX_NDB_NODES);
3746     Uint32 instanceKey = regTcPtr->lqhInstanceKey;
3747     BlockReference lqhRef;
3748     if(regCachePtr->viaSPJFlag){
3749       //ndbout << "TC:Choosing SPJ." << endl;
3750       lqhRef = numberToRef(DBSPJ, instanceKey, Tnode);
3751     }else{
3752       //ndbout << "TC:Choosing LQH." << endl;
3753       lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3754     }
3755     packLqhkeyreq(signal, lqhRef);
3756   }
3757   else
3758   {
3759     /**
3760      * 1) This is when a reorg trigger fired...
3761      *   but the tuple should *not* move
3762      *   This should be prevent using the LqhKeyReq::setReorgFlag
3763      *
3764      * 2) This also happens during reorg copy, when a row should *not* be moved
3765      */
3766     jam();
3767     Uint32 trigOp = regTcPtr->triggeringOperation;
3768     Uint32 TclientData = regTcPtr->clientData;
3769     releaseKeys();
3770     releaseAttrinfo();
3771     regApiPtr->lqhkeyreqrec--;
3772     unlinkReadyTcCon(signal);
3773     clearCommitAckMarker(regApiPtr, regTcPtr);
3774     releaseTcCon();
3775 
3776     if (trigOp != RNIL)
3777     {
3778       jam();
3779       //ndbassert(false); // see above
3780       TcConnectRecordPtr opPtr;
3781       opPtr.i = trigOp;
3782       ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
3783       trigger_op_finished(signal, apiConnectptr, RNIL, opPtr.p, 0);
3784       return;
3785     }
3786     else
3787     {
3788       jam();
3789       Uint32 Ttckeyrec = regApiPtr->tckeyrec;
3790       regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
3791       regApiPtr->tcSendArray[Ttckeyrec + 1] = 0;
3792       regApiPtr->tckeyrec = Ttckeyrec + 2;
3793       lqhKeyConf_checkTransactionState(signal, apiConnectptr);
3794     }
3795   }
3796 }//Dbtc::attrinfoDihReceivedLab()
3797 
packLqhkeyreq(Signal * signal,BlockReference TBRef)3798 void Dbtc::packLqhkeyreq(Signal* signal,
3799                          BlockReference TBRef)
3800 {
3801   CacheRecord * const regCachePtr = cachePtr.p;
3802   UintR Tkeylen = regCachePtr->keylen;
3803 
3804   ndbassert( signal->getNoOfSections() == 0 );
3805 
3806   sendlqhkeyreq(signal, TBRef);
3807 
3808   /* Do we need to send a KeyInfo signal train? */
3809   if ((! regCachePtr->useLongLqhKeyReq) &&
3810       (Tkeylen > LqhKeyReq::MaxKeyInfo))
3811   {
3812     /* Build KeyInfo train from KeyInfo long signal section */
3813     sendKeyInfoTrain(signal,
3814                      TBRef,
3815                      tcConnectptr.i,
3816                      LqhKeyReq::MaxKeyInfo,
3817                      regCachePtr->keyInfoSectionI);
3818   }//if
3819 
3820   if (tcConnectptr.p->triggeringOperation != RNIL &&
3821       tcConnectptr.p->currentTriggerId != RNIL)
3822   {
3823     jam();
3824     //NOTE: before packLqhkeyreq040Lab which might release operation...
3825     Ptr<TcDefinedTriggerData> trigPtr;
3826     c_theDefinedTriggers.getPtr(trigPtr, tcConnectptr.p->currentTriggerId);
3827     trigPtr.p->refCount++;
3828   }
3829 
3830   /* Release key storage */
3831   releaseKeys();
3832   packLqhkeyreq040Lab(signal,
3833                       TBRef);
3834 }//Dbtc::packLqhkeyreq()
3835 
3836 
sendlqhkeyreq(Signal * signal,BlockReference TBRef)3837 void Dbtc::sendlqhkeyreq(Signal* signal,
3838                          BlockReference TBRef)
3839 {
3840   UintR tslrAttrLen;
3841   UintR Tdata10;
3842   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3843   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3844   CacheRecord * const regCachePtr = cachePtr.p;
3845   Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
3846   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
3847 #ifdef ERROR_INSERT
3848   if (ERROR_INSERTED(8002)) {
3849     systemErrorLab(signal, __LINE__);
3850   }//if
3851   if (ERROR_INSERTED(8007)) {
3852     if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3853       CLEAR_ERROR_INSERT_VALUE;
3854       return;
3855     }//if
3856   }//if
3857   if (ERROR_INSERTED(8008)) {
3858     if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3859       CLEAR_ERROR_INSERT_VALUE;
3860       return;
3861     }//if
3862   }//if
3863   if (ERROR_INSERTED(8009)) {
3864     if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3865       return;
3866     }//if
3867   }//if
3868   if (ERROR_INSERTED(8010)) {
3869     if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3870       return;
3871     }//if
3872   }//if
3873 #endif
3874   Uint32 Tdeferred = tc_testbit(regApiPtr->m_flags,
3875                                 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
3876   Uint32 Tdisable_fk = tc_testbit(regApiPtr->m_flags,
3877                                   ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS);
3878   Uint32 reorg = ScanFragReq::REORG_ALL;
3879   Uint32 Tspecial_op = regTcPtr->m_special_op_flags;
3880   if (Tspecial_op == 0)
3881   {
3882   }
3883   else if (Tspecial_op & (TcConnectRecord::SOF_REORG_TRIGGER_BASE |
3884                           TcConnectRecord::SOF_REORG_DELETE))
3885   {
3886     reorg = ScanFragReq::REORG_NOT_MOVED;
3887   }
3888   else if (Tspecial_op & TcConnectRecord::SOF_REORG_MOVING)
3889   {
3890     reorg = ScanFragReq::REORG_MOVED;
3891   }
3892 
3893   Uint32 inlineKeyLen= 0;
3894   Uint32 inlineAttrLen= 0;
3895 
3896   /* We normally send long LQHKEYREQ unless the
3897    * destination cannot handle it or we are
3898    * testing
3899    */
3900   if (unlikely((version < NDBD_LONG_LQHKEYREQ) ||
3901                ERROR_INSERTED(8069)))
3902   {
3903     /* Short LQHKEYREQ, with some key/attr data inline */
3904     regCachePtr->useLongLqhKeyReq= 0;
3905     inlineKeyLen= regCachePtr->keylen;
3906     inlineAttrLen= regCachePtr->attrlength;
3907   }
3908   else
3909     /* Long LQHKEYREQ, with key/attr data in long sections */
3910     regCachePtr->useLongLqhKeyReq= 1;
3911 
3912   tslrAttrLen = 0;
3913   LqhKeyReq::setAttrLen(tslrAttrLen, inlineAttrLen);
3914   /* ---------------------------------------------------------------------- */
3915   // Bit16 == 0 since StoredProcedures are not yet supported.
3916   /* ---------------------------------------------------------------------- */
3917   LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
3918   LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
3919   LqhKeyReq::setReorgFlag(tslrAttrLen, reorg);
3920 
3921   Tdata10 = 0;
3922   sig0 = regTcPtr->opSimple;
3923   sig1 = regTcPtr->operation;
3924   sig2 = regTcPtr->dirtyOp;
3925   bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
3926   LqhKeyReq::setKeyLen(Tdata10, inlineKeyLen);
3927   LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
3928   if (unlikely(version < NDBD_ROWID_VERSION))
3929   {
3930     Uint32 op = regTcPtr->operation;
3931     Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
3932     LqhKeyReq::setLockType(Tdata10, lock);
3933   }
3934   /* ---------------------------------------------------------------------- */
3935   // Indicate Application Reference is present in bit 15
3936   /* ---------------------------------------------------------------------- */
3937   LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
3938   LqhKeyReq::setDirtyFlag(Tdata10, sig2);
3939   LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
3940   LqhKeyReq::setSimpleFlag(Tdata10, sig0);
3941   LqhKeyReq::setOperation(Tdata10, sig1);
3942   LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
3943   LqhKeyReq::setQueueOnRedoProblemFlag(Tdata10, regCachePtr->m_op_queue);
3944   LqhKeyReq::setDeferredConstraints(Tdata10, (Tdeferred & m_deferred_enabled));
3945   LqhKeyReq::setDisableFkConstraints(Tdata10, Tdisable_fk);
3946 
3947   /* -----------------------------------------------------------------------
3948    * If we are sending a short LQHKEYREQ, then there will be some AttrInfo
3949    * in the LQHKEYREQ.
3950    * Work out how much we'll send
3951    * ----------------------------------------------------------------------- */
3952   UintR aiInLqhKeyReq= 0;
3953 
3954   if (! regCachePtr->useLongLqhKeyReq)
3955   {
3956     /* Short LQHKEYREQ :
3957      * Send max 5 words of AttrInfo in LQHKEYREQ
3958      */
3959     aiInLqhKeyReq= MIN(LqhKeyReq::MaxAttrInfo, regCachePtr->attrlength);
3960   }
3961 
3962   LqhKeyReq::setAIInLqhKeyReq(Tdata10, aiInLqhKeyReq);
3963   /* -----------------------------------------------------------------------
3964    * Bit 27 == 0 since TC record is the same as the client record.
3965    * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
3966    * ----------------------------------------------------------------------- */
3967   LqhKeyReq::setMarkerFlag(Tdata10, regTcPtr->commitAckMarker != RNIL ? 1 : 0);
3968 
3969   if (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_FK_READ_COMMITTED)
3970   {
3971     LqhKeyReq::setNormalProtocolFlag(Tdata10, 1);
3972     LqhKeyReq::setDirtyFlag(Tdata10, 1);
3973   }
3974   /* ************************************************************> */
3975   /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT    */
3976   /* IS SENT TO A PRIMARY NODE.                                    */
3977   /* ************************************************************> */
3978 
3979   LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
3980 
3981   sig0 = tcConnectptr.i;
3982   sig2 = regCachePtr->hashValue;
3983   sig4 = cownref;
3984   sig5 = regTcPtr->savePointId;
3985 
3986   lqhKeyReq->clientConnectPtr = sig0;
3987   lqhKeyReq->attrLen = tslrAttrLen;
3988   lqhKeyReq->hashValue = sig2;
3989   lqhKeyReq->requestInfo = Tdata10;
3990   lqhKeyReq->tcBlockref = sig4;
3991   lqhKeyReq->savePointId = sig5;
3992 
3993   sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
3994   sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
3995   sig2 = regApiPtr->transid[0];
3996   sig3 = regApiPtr->transid[1];
3997   sig4 =
3998     (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) ?
3999     reference() : regApiPtr->ndbapiBlockref;
4000   sig5 = regTcPtr->clientData;
4001   sig6 = regCachePtr->scanInfo;
4002 
4003   if (! dirtyRead)
4004   {
4005     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
4006     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
4007     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
4008     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
4009   }
4010 
4011   lqhKeyReq->tableSchemaVersion = sig0;
4012   lqhKeyReq->fragmentData = sig1;
4013   lqhKeyReq->transId1 = sig2;
4014   lqhKeyReq->transId2 = sig3;
4015   lqhKeyReq->scanInfo = sig6;
4016 
4017   lqhKeyReq->variableData[0] = sig4;
4018   lqhKeyReq->variableData[1] = sig5;
4019 
4020   UintR nextPos = 2;
4021 
4022   if (regTcPtr->lastReplicaNo > 1) {
4023     sig0 = (UintR)regTcPtr->tcNodedata[2] +
4024            (UintR)(regTcPtr->tcNodedata[3] << 16);
4025     lqhKeyReq->variableData[nextPos] = sig0;
4026     nextPos++;
4027   }//if
4028 
4029   // Reset trigger count
4030   regTcPtr->numFiredTriggers = 0;
4031   regTcPtr->triggerExecutionCount = 0;
4032 
4033   if (regCachePtr->useLongLqhKeyReq)
4034   {
4035     /* Build long LQHKeyReq using Key + AttrInfo sections */
4036     SectionHandle handle(this);
4037     SegmentedSectionPtr keyInfoSection;
4038 
4039     getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
4040 
4041     handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
4042     handle.m_cnt= 1;
4043 
4044     if (regCachePtr->attrlength != 0)
4045     {
4046       SegmentedSectionPtr attrInfoSection;
4047 
4048       ndbassert(regCachePtr->attrInfoSectionI != RNIL);
4049       getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
4050 
4051       handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
4052       handle.m_cnt= 2;
4053     }
4054     sendSignal(TBRef, GSN_LQHKEYREQ, signal,
4055                nextPos + LqhKeyReq::FixedSignalLength, JBB,
4056                &handle);
4057 
4058     /* Long sections were freed as part of sendSignal */
4059     ndbassert( handle.m_cnt == 0 );
4060     regCachePtr->keyInfoSectionI= RNIL;
4061     regCachePtr->attrInfoSectionI= RNIL;
4062   }
4063   else
4064   {
4065     /* Build short LQHKeyReq from Key + AttrInfo sections
4066      *
4067      * Read upto 4 words of KeyInfo from TCKEYREQ KeyInfo section into
4068      * LqhKeyReq signal
4069      */
4070     SegmentedSectionPtr keyInfoSection;
4071 
4072     getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
4073     SectionReader keyInfoReader(keyInfoSection, getSectionSegmentPool());
4074 
4075     UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo, regCachePtr->keylen);
4076 
4077     keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos], keyLenInLqhKeyReq);
4078 
4079     nextPos+= keyLenInLqhKeyReq;
4080 
4081     if (aiInLqhKeyReq != 0)
4082     {
4083       /* Read upto 5 words of AttrInfo from TCKEYREQ KeyInfo section into
4084        * LqhKeyReq signal
4085        */
4086       SegmentedSectionPtr attrInfoSection;
4087 
4088       ndbassert(regCachePtr->attrInfoSectionI != RNIL);
4089 
4090       getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
4091       SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
4092 
4093       attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos], aiInLqhKeyReq);
4094 
4095       nextPos+= aiInLqhKeyReq;
4096     }
4097 
4098     sendSignal(TBRef, GSN_LQHKEYREQ, signal,
4099                nextPos + LqhKeyReq::FixedSignalLength, JBB);
4100   }
4101 }//Dbtc::sendlqhkeyreq()
4102 
packLqhkeyreq040Lab(Signal * signal,BlockReference TBRef)4103 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
4104                                BlockReference TBRef)
4105 {
4106   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4107   CacheRecord * const regCachePtr = cachePtr.p;
4108 #ifdef ERROR_INSERT
4109   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4110 
4111   if (ERROR_INSERTED(8009)) {
4112     if (regApiPtr->apiConnectstate == CS_STARTED) {
4113       CLEAR_ERROR_INSERT_VALUE;
4114       return;
4115     }//if
4116   }//if
4117   if (ERROR_INSERTED(8010)) {
4118     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
4119       CLEAR_ERROR_INSERT_VALUE;
4120       return;
4121     }//if
4122   }//if
4123 #endif
4124 
4125   /* Do we have an ATTRINFO train to send? */
4126   if (!regCachePtr->useLongLqhKeyReq)
4127   {
4128     /* Short LqhKeyReq */
4129     if (regCachePtr->attrlength > LqhKeyReq::MaxAttrInfo)
4130     {
4131       if (unlikely( !sendAttrInfoTrain(signal,
4132                                        TBRef,
4133                                        tcConnectptr.i,
4134                                        LqhKeyReq::MaxAttrInfo,
4135                                        regCachePtr->attrInfoSectionI)))
4136       {
4137         jam();
4138         TCKEY_abort(signal, 17);
4139         return;
4140       }
4141     }
4142   } // useLongLqhKeyReq
4143 
4144   /* Release AttrInfo related storage, and the Cache Record */
4145   releaseAttrinfo();
4146 
4147   UintR TtcTimer = ctcTimer;
4148   UintR Tread = (regTcPtr->operation == ZREAD);
4149   UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
4150   UintR Tboth = Tread & Tdirty;
4151   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
4152   jam();
4153   /*--------------------------------------------------------------------
4154    *   WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
4155    *---------------------------------------------------------------------*/
4156   if (Tboth) {
4157     jam();
4158     releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
4159     return;
4160   }//if
4161   regTcPtr->tcConnectstate = OS_OPERATING;
4162   return;
4163 }//Dbtc::packLqhkeyreq040Lab()
4164 
4165 /* ========================================================================= */
4166 /* -------      RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD  ------- */
4167 /* ========================================================================= */
releaseAttrinfo()4168 void Dbtc::releaseAttrinfo()
4169 {
4170   CacheRecord * const regCachePtr = cachePtr.p;
4171   Uint32 attrInfoSectionI= cachePtr.p->attrInfoSectionI;
4172 
4173   /* Release AttrInfo section if there is one */
4174   releaseSection( attrInfoSectionI );
4175   cachePtr.p->attrInfoSectionI= RNIL;
4176 
4177   //---------------------------------------------------
4178   // Now we will release the cache record at the same
4179   // time as releasing the attrinfo records.
4180   //---------------------------------------------------
4181   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4182   UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
4183   UintR TCacheIndex = cachePtr.i;
4184   regCachePtr->nextCacheRec = TfirstfreeCacheRec;
4185   cfirstfreeCacheRec = TCacheIndex;
4186   regApiPtr->cachePtr = RNIL;
4187   return;
4188 }//Dbtc::releaseAttrinfo()
4189 
4190 /* ========================================================================= */
4191 /* -------   RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION     ------- */
4192 /* ========================================================================= */
releaseDirtyRead(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * regTcPtr)4193 void Dbtc::releaseDirtyRead(Signal* signal,
4194                             ApiConnectRecordPtr regApiPtr,
4195                             TcConnectRecord* regTcPtr)
4196 {
4197   Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
4198   Uint32 TclientData = regTcPtr->clientData;
4199   Uint32 Tnode = regTcPtr->tcNodedata[0];
4200   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4201   ConnectionState state = regApiPtr.p->apiConnectstate;
4202 
4203   regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
4204   regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
4205   regApiPtr.p->tckeyrec = Ttckeyrec + 2;
4206 
4207   unlinkReadyTcCon(signal);
4208   releaseTcCon();
4209 
4210   /**
4211    * No LQHKEYCONF in Simple/Dirty read
4212    * Therefore decrese no LQHKEYCONF(REF) we are waiting for
4213    */
4214   c_counters.csimpleReadCount++;
4215   regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
4216 
4217   if(Tlqhkeyreqrec == 0)
4218   {
4219     /**
4220      * Special case of lqhKeyConf_checkTransactionState:
4221      * - commit with zero operations: handle only for simple read
4222      */
4223     sendtckeyconf(signal, state == CS_START_COMMITTING);
4224     regApiPtr.p->apiConnectstate =
4225       (state == CS_START_COMMITTING ? CS_CONNECTED : state);
4226     setApiConTimer(regApiPtr.i, 0, __LINE__);
4227 
4228     return;
4229   }
4230 
4231   /**
4232    * Emulate LQHKEYCONF
4233    */
4234   lqhKeyConf_checkTransactionState(signal, regApiPtr);
4235 }//Dbtc::releaseDirtyRead()
4236 
4237 /* ------------------------------------------------------------------------- */
4238 /* -------        CHECK IF ALL TC CONNECTIONS ARE COMPLETED          ------- */
4239 /* ------------------------------------------------------------------------- */
unlinkReadyTcCon(Signal * signal)4240 void Dbtc::unlinkReadyTcCon(Signal* signal)
4241 {
4242   TcConnectRecordPtr urtTcConnectptr;
4243 
4244   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4245   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4246   UintR TtcConnectFilesize = ctcConnectFilesize;
4247   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4248   if (regTcPtr->prevTcConnect != RNIL) {
4249     jam();
4250     urtTcConnectptr.i = regTcPtr->prevTcConnect;
4251     ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4252     urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
4253   } else {
4254     jam();
4255     regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
4256   }//if
4257   if (regTcPtr->nextTcConnect != RNIL) {
4258     jam();
4259     urtTcConnectptr.i = regTcPtr->nextTcConnect;
4260     ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4261     urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
4262   } else {
4263     jam();
4264     regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
4265   }//if
4266 }//Dbtc::unlinkReadyTcCon()
4267 
releaseTcCon()4268 void Dbtc::releaseTcCon()
4269 {
4270   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4271   UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
4272   UintR TtcConnectptrIndex = tcConnectptr.i;
4273 
4274   ndbrequire(regTcPtr->commitAckMarker == RNIL);
4275   regTcPtr->tcConnectstate = OS_CONNECTED;
4276   regTcPtr->nextTcConnect = TfirstfreeTcConnect;
4277   regTcPtr->apiConnect = RNIL;
4278   regTcPtr->m_special_op_flags = 0;
4279   regTcPtr->indexOp = RNIL;
4280   cfirstfreeTcConnect = TtcConnectptrIndex;
4281   c_counters.cconcurrentOp--;
4282 
4283   if (regTcPtr->triggeringOperation != RNIL &&
4284       regTcPtr->currentTriggerId != RNIL)
4285   {
4286     jam();
4287     Ptr<TcDefinedTriggerData> trigPtr;
4288     c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
4289     ndbassert(trigPtr.p->refCount);
4290     if (trigPtr.p->refCount)
4291     {
4292       trigPtr.p->refCount--;
4293     }
4294   }
4295 
4296   if (!regTcPtr->thePendingTriggers.isEmpty())
4297   {
4298     LocalDLFifoList<TcFiredTriggerData>
4299       list(c_theFiredTriggerPool, regTcPtr->thePendingTriggers);
4300     releaseFiredTriggerData(&list);
4301   }
4302 
4303   ndbrequire(regTcPtr->thePendingTriggers.isEmpty());
4304 
4305 }//Dbtc::releaseTcCon()
4306 
execPACKED_SIGNAL(Signal * signal)4307 void Dbtc::execPACKED_SIGNAL(Signal* signal)
4308 {
4309   LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
4310 
4311   UintR Ti;
4312   UintR Tstep = 0;
4313   UintR Tlength;
4314   UintR TpackedData[28];
4315   UintR Tdata1, Tdata2, Tdata3, Tdata4;
4316 
4317   jamEntry();
4318   Tlength = signal->length();
4319   if (Tlength > 25) {
4320     jam();
4321     systemErrorLab(signal, __LINE__);
4322     return;
4323   }//if
4324   Uint32* TpackDataPtr;
4325   for (Ti = 0; Ti < Tlength; Ti += 4) {
4326     Uint32* TsigDataPtr = &signal->theData[Ti];
4327     Tdata1 = TsigDataPtr[0];
4328     Tdata2 = TsigDataPtr[1];
4329     Tdata3 = TsigDataPtr[2];
4330     Tdata4 = TsigDataPtr[3];
4331 
4332     TpackDataPtr = &TpackedData[Ti];
4333     TpackDataPtr[0] = Tdata1;
4334     TpackDataPtr[1] = Tdata2;
4335     TpackDataPtr[2] = Tdata3;
4336     TpackDataPtr[3] = Tdata4;
4337   }//for
4338 
4339   if (VERIFY_PACKED_RECEIVE)
4340   {
4341     ndbrequire(PackedSignal::verify(&TpackedData[0],
4342                                     Tlength,
4343                                     cownref,
4344                                     TC_RECEIVE_TYPES,
4345                                     0)); /* Irrelevant */
4346   }
4347   while (Tlength > Tstep) {
4348 
4349     TpackDataPtr = &TpackedData[Tstep];
4350     Tdata1 = TpackDataPtr[0];
4351     Tdata2 = TpackDataPtr[1];
4352     Tdata3 = TpackDataPtr[2];
4353 
4354     lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
4355     lqhKeyConf->opPtr = Tdata2;
4356     lqhKeyConf->userRef = Tdata3;
4357 
4358     switch (Tdata1 >> 28) {
4359     case ZCOMMITTED:
4360       signal->header.theLength = 3;
4361       jamBuffer()->markEndOfSigExec();
4362       execCOMMITTED(signal);
4363       Tstep += 3;
4364       break;
4365     case ZCOMPLETED:
4366       signal->header.theLength = 3;
4367       jamBuffer()->markEndOfSigExec();
4368       execCOMPLETED(signal);
4369       Tstep += 3;
4370       break;
4371     case ZLQHKEYCONF:
4372       jam();
4373       Tdata1 = TpackDataPtr[3];
4374       Tdata2 = TpackDataPtr[4];
4375       Tdata3 = TpackDataPtr[5];
4376       Tdata4 = TpackDataPtr[6];
4377 
4378       lqhKeyConf->readLen = Tdata1;
4379       lqhKeyConf->transId1 = Tdata2;
4380       lqhKeyConf->transId2 = Tdata3;
4381       lqhKeyConf->numFiredTriggers = Tdata4;
4382       signal->header.theLength = LqhKeyConf::SignalLength;
4383       jamBuffer()->markEndOfSigExec();
4384       execLQHKEYCONF(signal);
4385       Tstep += LqhKeyConf::SignalLength;
4386       break;
4387     case ZFIRE_TRIG_CONF:
4388       jam();
4389       signal->header.theLength = 4;
4390       signal->theData[3] = TpackDataPtr[3];
4391       jamBuffer()->markEndOfSigExec();
4392       execFIRE_TRIG_CONF(signal);
4393       Tstep += 4;
4394       break;
4395     default:
4396       systemErrorLab(signal, __LINE__);
4397       return;
4398     }//switch
4399   }//while
4400   return;
4401 }//Dbtc::execPACKED_SIGNAL()
4402 
4403 
execSIGNAL_DROPPED_REP(Signal * signal)4404 void Dbtc::execSIGNAL_DROPPED_REP(Signal* signal)
4405 {
4406   /* An incoming signal was dropped, handle it
4407    * Dropped signal really means that we ran out of
4408    * long signal buffering to store its sections
4409    */
4410   jamEntry();
4411 
4412   if (!assembleDroppedFragments(signal))
4413   {
4414     jam();
4415     return;
4416   }
4417 
4418   const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4419   Uint32 originalGSN= rep->originalGsn;
4420 
4421   DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4422 
4423   switch(originalGSN) {
4424   case GSN_TCKEYREQ:
4425     jam();
4426     /* Fall through */
4427   case GSN_TCINDXREQ:
4428   {
4429     jam();
4430 
4431     /* Get original signal data - unfortunately it may
4432      * have been truncated.  We must not read beyond
4433      * word # 22
4434      * We will send an Abort to the Api using info from
4435      * the received signal and clean up our transaction
4436      * state
4437      */
4438     const TcKeyReq * const truncatedTcKeyReq =
4439       (TcKeyReq *) &rep->originalData[0];
4440 
4441     const UintR apiIndex = truncatedTcKeyReq->apiConnectPtr;
4442 
4443     if (apiIndex >= capiConnectFilesize)
4444     {
4445       jam();
4446       warningHandlerLab(signal, __LINE__);
4447       return;
4448     }
4449 
4450     /* We have a valid Api ConnectPtr...
4451      * Ensure that we have the  necessary information
4452      * to send a rollback to the client
4453      */
4454     apiConnectptr.i = apiIndex;
4455     ApiConnectRecord * const regApiPtr = &apiConnectRecord[apiIndex];
4456     apiConnectptr.p = regApiPtr;
4457     UintR transId1= truncatedTcKeyReq->transId1;
4458     UintR transId2= truncatedTcKeyReq->transId2;
4459 
4460     /* Ensure that the apiConnectptr global is initialised
4461      * may not be in cases where we drop the first signal of
4462      * a transaction
4463      */
4464     apiConnectptr.p->transid[0] = transId1;
4465     apiConnectptr.p->transid[1] = transId2;
4466     apiConnectptr.p->returncode = ZGET_DATAREC_ERROR;
4467 
4468     /* Set m_exec_flag according to the dropped request */
4469     apiConnectptr.p->m_flags |=
4470       TcKeyReq::getExecuteFlag(truncatedTcKeyReq->requestInfo) ?
4471       ApiConnectRecord::TF_EXEC_FLAG : 0;
4472 
4473     DEBUG(" Execute flag set to " << tc_testbit(apiConnectptr.p->m_flags,
4474                                                 ApiConnectRecord::TF_EXEC_FLAG)
4475           );
4476 
4477     abortErrorLab(signal);
4478 
4479     break;
4480   }
4481   case GSN_SCAN_TABREQ:
4482   {
4483     jam();
4484     /* Get information necessary to send SCAN_TABREF back to client */
4485     // TODO : Handle dropped signal fragments
4486     const ScanTabReq * const truncatedScanTabReq =
4487       (ScanTabReq *) &rep->originalData[0];
4488 
4489     Uint32 apiConnectPtr= truncatedScanTabReq->apiConnectPtr;
4490     Uint32 transId1= truncatedScanTabReq->transId1;
4491     Uint32 transId2= truncatedScanTabReq->transId2;
4492 
4493     if (apiConnectPtr >= capiConnectFilesize)
4494     {
4495       jam();
4496       warningHandlerLab(signal, __LINE__);
4497       return;
4498     }//if
4499 
4500     apiConnectptr.i = apiConnectPtr;
4501     ptrAss(apiConnectptr, apiConnectRecord);
4502     ApiConnectRecord * transP = apiConnectptr.p;
4503 
4504     /* Now send the SCAN_TABREF */
4505     ScanTabRef* ref= (ScanTabRef*)&signal->theData[0];
4506     ref->apiConnectPtr = transP->ndbapiConnect;
4507     ref->transId1= transId1;
4508     ref->transId2= transId2;
4509     ref->errorCode= ZGET_ATTRBUF_ERROR;
4510     ref->closeNeeded= 0;
4511 
4512     sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
4513                signal, ScanTabRef::SignalLength, JBB);
4514     break;
4515   }
4516   default:
4517     jam();
4518     /* Don't expect dropped signals for other GSNs,
4519      * default handling
4520      * TODO : Can TC get long TRANSID_AI as part of
4521      * Unique index operations?
4522      */
4523     SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
4524   };
4525 
4526   return;
4527 }
4528 
4529 bool
insert_in_commit_ack_marker(Dbtc * tc,Uint32 instanceKey,NodeId node_id)4530 Dbtc::CommitAckMarker::insert_in_commit_ack_marker(Dbtc *tc,
4531                                                    Uint32 instanceKey,
4532                                                    NodeId node_id)
4533 {
4534   const NodeInfo& nodeInfo = tc->getNodeInfo(node_id);
4535   Uint32 workers = nodeInfo.m_lqh_workers;
4536   assert(instanceKey != 0);
4537   Uint32 instanceNo = workers == 0 ? 0 : 1 + (instanceKey - 1) % workers;
4538   Uint32 item = instanceNo + (node_id << 16);
4539   CommitAckMarkerBuffer::DataBufferPool & pool =
4540     tc->c_theCommitAckMarkerBufferPool;
4541   // check for duplicate (todo DataBuffer method find-or-append)
4542   {
4543     LocalDataBuffer<5> tmp(pool, this->theDataBuffer);
4544     CommitAckMarkerBuffer::Iterator iter;
4545     bool next_flag = tmp.first(iter);
4546     while (next_flag)
4547     {
4548       Uint32 dataWord = *iter.data;
4549       if (dataWord == item)
4550       {
4551         return true;
4552       }
4553       next_flag = tmp.next(iter, 1);
4554     }
4555   }
4556   LocalDataBuffer<5> tmp(pool, this->theDataBuffer);
4557   return tmp.append(&item, (Uint32)1);
4558 }
4559 bool
insert_in_commit_ack_marker_all(Dbtc * tc,NodeId node_id)4560 Dbtc::CommitAckMarker::insert_in_commit_ack_marker_all(Dbtc *tc,
4561                                                        NodeId node_id)
4562 {
4563   for (Uint32 ikey = 1; ikey <= MAX_NDBMT_LQH_THREADS; ikey++)
4564   {
4565     if (!insert_in_commit_ack_marker(tc, ikey, node_id))
4566       return false;
4567   }
4568   return true;
4569 }
4570 
execLQHKEYCONF(Signal * signal)4571 void Dbtc::execLQHKEYCONF(Signal* signal)
4572 {
4573   const LqhKeyConf * lqhKeyConf = CAST_CONSTPTR(LqhKeyConf,
4574                                                 signal->getDataPtr());
4575 #ifdef UNUSED
4576   ndbout << "TC: Received LQHKEYCONF"
4577          << " transId1=" << lqhKeyConf-> transId1
4578          << " transId2=" << lqhKeyConf-> transId2
4579 	 << endl;
4580 #endif /*UNUSED*/
4581   UintR compare_transid1, compare_transid2;
4582   BlockReference tlastLqhBlockref;
4583   UintR tlastLqhConnect;
4584   UintR treadlenAi;
4585   UintR TtcConnectptrIndex;
4586   UintR TtcConnectFilesize = ctcConnectFilesize;
4587 
4588   tlastLqhConnect = lqhKeyConf->connectPtr;
4589   TtcConnectptrIndex = lqhKeyConf->opPtr;
4590   tlastLqhBlockref = lqhKeyConf->userRef;
4591   treadlenAi = lqhKeyConf->readLen;
4592   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4593 
4594   /*------------------------------------------------------------------------
4595    * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
4596    * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
4597    * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
4598    * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
4599    * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
4600    * OPERATIONS ON THE LQH CONNECT RECORD.
4601    *------------------------------------------------------------------------
4602    * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
4603    * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
4604    * PROBLEM  WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
4605    * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
4606    * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
4607    * BEFORE ACCEPTING THIS SIGNAL.
4608    * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
4609    * this.
4610    * This is more reason to ignore the signal if not all states are correct.
4611    *------------------------------------------------------------------------*/
4612   if (TtcConnectptrIndex >= TtcConnectFilesize) {
4613     TCKEY_abort(signal, 25);
4614     return;
4615   }//if
4616   TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
4617   OperationState TtcConnectstate = regTcPtr->tcConnectstate;
4618   tcConnectptr.i = TtcConnectptrIndex;
4619   tcConnectptr.p = regTcPtr;
4620   if (TtcConnectstate != OS_OPERATING) {
4621     warningReport(signal, 23);
4622     return;
4623   }//if
4624   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4625   UintR TapiConnectptrIndex = regTcPtr->apiConnect;
4626   UintR TapiConnectFilesize = capiConnectFilesize;
4627   UintR Ttrans1 = lqhKeyConf->transId1;
4628   UintR Ttrans2 = lqhKeyConf->transId2;
4629   Uint32 numFired = LqhKeyConf::getFiredCount(lqhKeyConf->numFiredTriggers);
4630   Uint32 deferreduk = LqhKeyConf::getDeferredUKBit(lqhKeyConf->numFiredTriggers);
4631   Uint32 deferredfk = LqhKeyConf::getDeferredFKBit(lqhKeyConf->numFiredTriggers);
4632 
4633   if (TapiConnectptrIndex >= TapiConnectFilesize) {
4634     TCKEY_abort(signal, 29);
4635     return;
4636   }//if
4637   Ptr<ApiConnectRecord> regApiPtr;
4638   regApiPtr.i = TapiConnectptrIndex;
4639   regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
4640   apiConnectptr.i = TapiConnectptrIndex;
4641   apiConnectptr.p = regApiPtr.p;
4642   compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
4643   compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
4644   compare_transid1 = compare_transid1 | compare_transid2;
4645   if (compare_transid1 != 0) {
4646     warningReport(signal, 24);
4647     return;
4648   }//if
4649 
4650 #ifdef ERROR_INSERT
4651   if (ERROR_INSERTED(8029)) {
4652     systemErrorLab(signal, __LINE__);
4653   }//if
4654   if (ERROR_INSERTED(8003)) {
4655     if (regApiPtr.p->apiConnectstate == CS_STARTED) {
4656       CLEAR_ERROR_INSERT_VALUE;
4657       return;
4658     }//if
4659   }//if
4660   if (ERROR_INSERTED(8004)) {
4661     if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
4662       CLEAR_ERROR_INSERT_VALUE;
4663       return;
4664     }//if
4665   }//if
4666   if (ERROR_INSERTED(8005)) {
4667     if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
4668       CLEAR_ERROR_INSERT_VALUE;
4669       return;
4670     }//if
4671   }//if
4672   if (ERROR_INSERTED(8006)) {
4673     if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
4674       CLEAR_ERROR_INSERT_VALUE;
4675       return;
4676     }//if
4677   }//if
4678   if (ERROR_INSERTED(8023)) {
4679     SET_ERROR_INSERT_VALUE(8024);
4680     return;
4681   }//if
4682   if (ERROR_INSERTED(8107))
4683   {
4684     jam();
4685     ndbout_c("Error 8107, timing out transaction");
4686     timeOutFoundLab(signal, apiConnectptr.i, ZTIME_OUT_ERROR);
4687     return;
4688   }
4689 
4690 #endif
4691   UintR TtcTimer = ctcTimer;
4692   regTcPtr->lastLqhCon = tlastLqhConnect;
4693   regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
4694   regTcPtr->numFiredTriggers = numFired;
4695   regTcPtr->m_special_op_flags |=
4696     ((deferreduk) ? TcConnectRecord::SOF_DEFERRED_UK_TRIGGER : 0 ) |
4697     ((deferredfk) ? TcConnectRecord::SOF_DEFERRED_FK_TRIGGER : 0 );
4698   regApiPtr.p->m_flags |=
4699     ((deferreduk) ? ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS : 0) |
4700     ((deferredfk) ? ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS : 0);
4701 
4702   UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
4703   UintR TclientData = regTcPtr->clientData;
4704   UintR TdirtyOp = regTcPtr->dirtyOp;
4705   Uint32 TopSimple = regTcPtr->opSimple;
4706   Uint32 Toperation = regTcPtr->operation;
4707   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4708 
4709   if (TapiConnectstate == CS_ABORTING) {
4710     warningReport(signal, 27);
4711     return;
4712   }//if
4713 
4714   Uint32 lockingOpI = RNIL;
4715   if (Toperation == ZUNLOCK)
4716   {
4717     /* For unlock operations readlen in TCKEYCONF carries
4718      * the locking operation TC reference
4719      */
4720     lockingOpI = treadlenAi;
4721     treadlenAi = 0;
4722   }
4723 
4724   /* Handle case where LQHKEYREQ requested an LQH CommitAckMarker */
4725   Uint32 commitAckMarker = regTcPtr->commitAckMarker;
4726   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
4727   if (commitAckMarker != RNIL)
4728   {
4729     /* Update TC CommitAckMarker record to track LQH CommitAckMarkers */
4730     const Uint32 noOfLqhs = regTcPtr->noOfNodes;
4731     CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
4732     jam();
4733     /**
4734      * Now that we have a marker in all nodes in at least one nodegroup,
4735      * don't need to request any more for this transaction
4736      */
4737     regApiPtr.p->m_flags |= ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED;
4738 
4739     /**
4740      * Populate LQH array
4741      */
4742     for(Uint32 i = 0; i < noOfLqhs; i++)
4743     {
4744       jam();
4745       if (ERROR_INSERTED(8096) && i+1 == noOfLqhs)
4746       {
4747         CLEAR_ERROR_INSERT_VALUE;
4748         TCKEY_abort(signal, 67);
4749         return;
4750       }
4751       if (!tmp->insert_in_commit_ack_marker(this,
4752                                             regTcPtr->lqhInstanceKey,
4753                                             regTcPtr->tcNodedata[i]))
4754       {
4755         TCKEY_abort(signal, 67);
4756         return;
4757       }
4758     }
4759   }
4760   if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4761     jam();
4762     // This was an internal TCKEYREQ
4763     // will be returned unpacked
4764     regTcPtr->attrInfoLen = treadlenAi;
4765   } else {
4766     if (numFired == 0 && regTcPtr->triggeringOperation == RNIL) {
4767       jam();
4768 
4769       if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
4770         TCKEY_abort(signal, 30);
4771         return;
4772       }
4773 
4774       /*
4775        * Skip counting triggering operations the first round
4776        * since they will enter execLQHKEYCONF a second time
4777        * Skip counting internally generated TcKeyReq
4778        */
4779       regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
4780       regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
4781       regApiPtr.p->tckeyrec = Ttckeyrec + 2;
4782     }//if
4783   }//if
4784   if (TdirtyOp == ZTRUE)
4785   {
4786     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4787     jam();
4788     releaseDirtyWrite(signal);
4789     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4790   }
4791   else if (Toperation == ZREAD && TopSimple)
4792   {
4793     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4794     jam();
4795     unlinkReadyTcCon(signal);
4796     releaseTcCon();
4797     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4798   }
4799   else if (Toperation == ZUNLOCK)
4800   {
4801     jam();
4802     /* We've unlocked and released a read operation in LQH
4803      * The readLenAi member contains the TC OP reference
4804      * for the unlocked operation.
4805      * So here we :
4806      * 1) Validate the TC OP reference
4807      * 2) Release the referenced TC op
4808      * 3) Send TCKEYCONF back to the user
4809      * 4) Release our own TC op
4810      */
4811     Uint32 unlockOpI = tcConnectptr.i;
4812 
4813     ndbrequire( numFired == 0 );
4814     ndbrequire( regTcPtr->triggeringOperation == RNIL );
4815 
4816     /* Switch to the original locking operation */
4817     if (unlikely( lockingOpI >= ctcConnectFilesize ))
4818     {
4819       jam();
4820       TCKEY_abort(signal, 61);
4821       return;
4822     }
4823     tcConnectptr.i = lockingOpI;
4824     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4825 
4826     const TcConnectRecord * regLockTcPtr = tcConnectptr.p;
4827 
4828     /* Validate the locking operation's state */
4829     bool locking_op_ok =
4830       ( ( regLockTcPtr->apiConnect == regTcPtr->apiConnect ) &&
4831         ( ( regLockTcPtr->operation == ZREAD ) ||
4832           ( regLockTcPtr->operation == ZREAD_EX ) ) &&
4833         ( regLockTcPtr->tcConnectstate == OS_PREPARED ) &&
4834         ( ! regLockTcPtr->dirtyOp ) &&
4835         ( ! regLockTcPtr->opSimple ) &&
4836         ( ! TcConnectRecord::isIndexOp(regLockTcPtr->m_special_op_flags) ) &&
4837         ( regLockTcPtr->commitAckMarker == RNIL ) );
4838 
4839     if (unlikely (! locking_op_ok ))
4840     {
4841       jam();
4842       TCKEY_abort(signal, 63);
4843       return;
4844     }
4845 
4846     /* Ok, all checks passed, release the original locking op */
4847     unlinkReadyTcCon(signal);
4848     releaseTcCon();
4849 
4850     /* Remove record of original locking op's LQHKEYREQ/CONF
4851      * etc.
4852      */
4853     ndbrequire( regApiPtr.p->lqhkeyreqrec );
4854     ndbrequire( regApiPtr.p->lqhkeyconfrec );
4855     regApiPtr.p->lqhkeyreqrec -= 1;
4856     regApiPtr.p->lqhkeyconfrec -= 1;
4857 
4858     /* Switch back to the unlock operation */
4859     tcConnectptr.i = unlockOpI;
4860     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4861 
4862     /* Release the unlock operation */
4863     unlinkReadyTcCon(signal);
4864     releaseTcCon();
4865 
4866     /* Remove record of unlock op's LQHKEYREQ */
4867     ndbrequire( regApiPtr.p->lqhkeyreqrec );
4868     regApiPtr.p->lqhkeyreqrec -= 1;
4869 
4870     /* TCKEYCONF sent below */
4871   }
4872   else
4873   {
4874     jam();
4875     if (numFired == 0) {
4876       jam();
4877       // No triggers to execute
4878       UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4879       regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
4880       regTcPtr->tcConnectstate = OS_PREPARED;
4881     }
4882   }//if
4883 
4884   /**
4885    * And now decide what to do next
4886    * 1) First check if there are fired triggers
4887    * 2) Then check if it's a index-table read
4888    * 3) Then check if op was created by trigger
4889    * 4) Else it's a normal op
4890    *
4891    * - trigger op, can cause new trigger ops (cascade)
4892    * - trigger op can be using uk
4893    */
4894   if (numFired)
4895   {
4896     // We have fired triggers
4897     jam();
4898     saveTriggeringOpState(signal, regTcPtr);
4899     if (regTcPtr->numReceivedTriggers == numFired)
4900     {
4901       // We have received all data
4902       jam();
4903       regApiPtr.p->theFiredTriggers.appendList(regTcPtr->thePendingTriggers);
4904       executeTriggers(signal, &regApiPtr);
4905     }
4906     // else wait for more trigger data
4907   }
4908   else if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags))
4909   {
4910     // This is a index-table read
4911     jam();
4912     setupIndexOpReturn(regApiPtr.p, regTcPtr);
4913     lqhKeyConf_checkTransactionState(signal, regApiPtr);
4914   }
4915   else if (regTcPtr->triggeringOperation == RNIL)
4916   {
4917     // This is "normal" path
4918     jam();
4919     lqhKeyConf_checkTransactionState(signal, regApiPtr);
4920   }
4921   else
4922   {
4923     jam();
4924     /**
4925      * This operation was created by a trigger executing operation
4926      * Thus no need to handle the operation any further, return to
4927      * the original operation instead. There can be many triggering
4928      * operations waiting on each other here.
4929      *
4930      * Restart the original operation if we have executed all it's
4931      * triggers.
4932      */
4933     TcConnectRecordPtr opPtr;
4934 
4935     opPtr.i = regTcPtr->triggeringOperation;
4936     ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
4937     trigger_op_finished(signal, regApiPtr, regTcPtr->currentTriggerId,
4938                         opPtr.p, 0);
4939   }
4940 }//Dbtc::execLQHKEYCONF()
4941 
setupIndexOpReturn(ApiConnectRecord * regApiPtr,TcConnectRecord * regTcPtr)4942 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
4943 			      TcConnectRecord* regTcPtr)
4944 {
4945   regApiPtr->m_flags |= ApiConnectRecord::TF_INDEX_OP_RETURN;
4946   regApiPtr->indexOp = regTcPtr->indexOp;
4947   TcIndexOperationPtr indexOpPtr;
4948   indexOpPtr.i = regApiPtr->indexOp;
4949   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
4950   if (tc_testbit(indexOp->savedFlags,
4951                  ApiConnectRecord::TF_DEFERRED_CONSTRAINTS))
4952   {
4953     regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
4954   }
4955 
4956   if (tc_testbit(indexOp->savedFlags,
4957                  ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS))
4958   {
4959     regApiPtr->m_flags |= ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS;
4960   }
4961   regApiPtr->clientData = regTcPtr->clientData;
4962   regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
4963 }
4964 
4965 /**
4966  * lqhKeyConf_checkTransactionState
4967  *
4968  * This functions checks state variables, and
4969  *   decides if it should wait for more LQHKEYCONF signals
4970  *   or if it should start commiting
4971  */
4972 void
lqhKeyConf_checkTransactionState(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)4973 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
4974 				       Ptr<ApiConnectRecord> regApiPtr)
4975 {
4976 /*---------------------------------------------------------------*/
4977 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
4978 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN   */
4979 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE   */
4980 /* WHOLE TRANSACTION                                             */
4981 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF  */
4982 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
4983 /* TRANSACTION                                                   */
4984 /*---------------------------------------------------------------*/
4985   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4986   UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4987   UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4988   int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
4989 
4990   apiConnectptr = regApiPtr;
4991   switch (TapiConnectstate) {
4992   case CS_START_COMMITTING:
4993     if (TnoOfOutStanding == 0) {
4994       jam();
4995       diverify010Lab(signal);
4996       return;
4997     } else if (TnoOfOutStanding > 0) {
4998       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4999         jam();
5000         sendtckeyconf(signal, 0);
5001         return;
5002       }
5003       else if (tc_testbit(regApiPtr.p->m_flags,
5004                           ApiConnectRecord::TF_INDEX_OP_RETURN))
5005       {
5006 	jam();
5007         sendtckeyconf(signal, 0);
5008         return;
5009       }//if
5010       jam();
5011       return;
5012     } else {
5013       TCKEY_abort(signal, 44);
5014       return;
5015     }//if
5016     return;
5017   case CS_STARTED:
5018   case CS_RECEIVING:
5019     if (TnoOfOutStanding == 0) {
5020       jam();
5021       sendtckeyconf(signal, 2);
5022       return;
5023     } else {
5024       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
5025         jam();
5026         sendtckeyconf(signal, 0);
5027         return;
5028       }
5029       else if (tc_testbit(regApiPtr.p->m_flags,
5030                           ApiConnectRecord::TF_INDEX_OP_RETURN))
5031       {
5032 	jam();
5033         sendtckeyconf(signal, 0);
5034         return;
5035       }//if
5036       jam();
5037     }//if
5038     return;
5039   case CS_REC_COMMITTING:
5040     if (TnoOfOutStanding > 0) {
5041       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
5042         jam();
5043         sendtckeyconf(signal, 0);
5044         return;
5045       }
5046       else if (tc_testbit(regApiPtr.p->m_flags,
5047                           ApiConnectRecord::TF_INDEX_OP_RETURN))
5048       {
5049         jam();
5050         sendtckeyconf(signal, 0);
5051         return;
5052       }//if
5053       jam();
5054       return;
5055     }//if
5056     TCKEY_abort(signal, 45);
5057     return;
5058   case CS_CONNECTED:
5059     jam();
5060 /*---------------------------------------------------------------*/
5061 /*       WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY     */
5062 /*       CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE        */
5063 /*       COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS.   */
5064 /*---------------------------------------------------------------*/
5065     regApiPtr.p->tckeyrec = 0;
5066     return;
5067   case CS_SEND_FIRE_TRIG_REQ:
5068     return;
5069   case CS_WAIT_FIRE_TRIG_REQ:
5070     if (tc_testbit(regApiPtr.p->m_flags,
5071                    ApiConnectRecord::TF_INDEX_OP_RETURN))
5072     {
5073       jam();
5074       sendtckeyconf(signal, 0);
5075       return;
5076     }
5077     else if (TnoOfOutStanding == 0 && regApiPtr.p->pendingTriggers == 0)
5078     {
5079       jam();
5080       regApiPtr.p->apiConnectstate = CS_START_COMMITTING;
5081       diverify010Lab(signal);
5082       return;
5083     }
5084     return;
5085   default:
5086     TCKEY_abort(signal, 46);
5087     return;
5088   }//switch
5089 }//Dbtc::lqhKeyConf_checkTransactionState()
5090 
sendtckeyconf(Signal * signal,UintR TcommitFlag)5091 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
5092 {
5093   if(ERROR_INSERTED(8049)){
5094     CLEAR_ERROR_INSERT_VALUE;
5095     signal->theData[0] = TcContinueB::DelayTCKEYCONF;
5096     signal->theData[1] = apiConnectptr.i;
5097     signal->theData[2] = TcommitFlag;
5098     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
5099     return;
5100   }
5101 
5102   HostRecordPtr localHostptr;
5103   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5104   const UintR TopWords = (UintR)regApiPtr->tckeyrec;
5105   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
5106   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
5107   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
5108   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
5109   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
5110   ptrAss(localHostptr, hostRecord);
5111   struct PackedWordsContainer * container = &localHostptr.p->packTCKEYCONF;
5112   UintR TcurrLen = container->noOfPackedWords;
5113   UintR confInfo = 0;
5114   TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
5115   TcKeyConf::setMarkerFlag(confInfo, Tmarker);
5116   const UintR TpacketLen = 6 + TopWords;
5117   regApiPtr->tckeyrec = 0;
5118 
5119   if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN))
5120   {
5121     jam();
5122     // Return internally generated TCKEY
5123     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
5124     TcKeyConf::setNoOfOperations(confInfo, 1);
5125     tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
5126     tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
5127     Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[1];
5128     * gci_lo = Uint32(regApiPtr->globalcheckpointid);
5129     tcKeyConf->confInfo = confInfo;
5130     tcKeyConf->transId1 = regApiPtr->transid[0];
5131     tcKeyConf->transId2 = regApiPtr->transid[1];
5132     tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
5133     tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
5134     Uint32 sigLen = 1 /** gci_lo */ +
5135       TcKeyConf::StaticLength + TcKeyConf::OperationLength;
5136     EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
5137     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN);
5138     if (TopWords == 0) {
5139       jam();
5140       return; // No queued TcKeyConf
5141     }//if
5142   }//if
5143   if(TcommitFlag){
5144     jam();
5145     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
5146   }
5147   TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
5148   if ((TpacketLen + 1 /** gci_lo */ > 25) ||!is_api){
5149     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
5150 
5151     jam();
5152     tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
5153     tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
5154     Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[TopWords >> 1];
5155     tcKeyConf->confInfo = confInfo;
5156     tcKeyConf->transId1 = regApiPtr->transid[0];
5157     tcKeyConf->transId2 = regApiPtr->transid[1];
5158     copyFromToLen(&regApiPtr->tcSendArray[0],
5159 		  (UintR*)&tcKeyConf->operations,
5160 		  (UintR)ZTCOPCONF_SIZE);
5161     * gci_lo = Uint32(regApiPtr->globalcheckpointid);
5162     sendSignal(regApiPtr->ndbapiBlockref,
5163 	       GSN_TCKEYCONF, signal, (TpacketLen - 1) + 1 /** gci_lo */, JBB);
5164     return;
5165   } else if (((TcurrLen + TpacketLen + 1 /** gci_lo */) > 25) &&
5166              (TcurrLen > 0)) {
5167     jam();
5168     sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
5169     TcurrLen = 0;
5170   } else {
5171     jam();
5172     updatePackedList(signal, localHostptr.p, localHostptr.i);
5173   }//if
5174   // -------------------------------------------------------------------------
5175   // The header contains the block reference of receiver plus the real signal
5176   // length - 3, since we have the real signal length plus one additional word
5177   // for the header we have to do - 4.
5178   // -------------------------------------------------------------------------
5179   container->noOfPackedWords = TcurrLen + TpacketLen + 1 /** gci_lo */;
5180 
5181   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4 + 1 /** gci_lo */);
5182   UintR Tpack1 = regApiPtr->ndbapiConnect;
5183   UintR Tpack2 = Uint32(regApiPtr->globalcheckpointid >> 32);
5184   UintR Tpack3 = confInfo;
5185   UintR Tpack4 = regApiPtr->transid[0];
5186   UintR Tpack5 = regApiPtr->transid[1];
5187   UintR Tpack6 = Uint32(regApiPtr->globalcheckpointid);
5188 
5189   container->packedWords[TcurrLen + 0] = Tpack0;
5190   container->packedWords[TcurrLen + 1] = Tpack1;
5191   container->packedWords[TcurrLen + 2] = Tpack2;
5192   container->packedWords[TcurrLen + 3] = Tpack3;
5193   container->packedWords[TcurrLen + 4] = Tpack4;
5194   container->packedWords[TcurrLen + 5] = Tpack5;
5195 
5196   container->packedWords[TcurrLen + TpacketLen] = Tpack6;
5197 
5198   for (Uint32 Ti = 6; Ti < TpacketLen; Ti++) {
5199     container->packedWords[TcurrLen + Ti] = regApiPtr->tcSendArray[Ti - 6];
5200   }//for
5201 
5202   if (unlikely(!ndb_check_micro_gcp(getNodeInfo(localHostptr.i).m_version)))
5203   {
5204     jam();
5205     ndbassert(Tpack6 == 0 ||
5206               getNodeInfo(localHostptr.i).m_version == 0); // Disconnected
5207   }
5208 }//Dbtc::sendtckeyconf()
5209 
copyFromToLen(UintR * sourceBuffer,UintR * destBuffer,UintR Tlen)5210 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
5211 {
5212   UintR Tindex = 0;
5213   UintR Ti;
5214   while (Tlen >= 4) {
5215     UintR Tdata0 = sourceBuffer[Tindex + 0];
5216     UintR Tdata1 = sourceBuffer[Tindex + 1];
5217     UintR Tdata2 = sourceBuffer[Tindex + 2];
5218     UintR Tdata3 = sourceBuffer[Tindex + 3];
5219     Tlen -= 4;
5220     destBuffer[Tindex + 0] = Tdata0;
5221     destBuffer[Tindex + 1] = Tdata1;
5222     destBuffer[Tindex + 2] = Tdata2;
5223     destBuffer[Tindex + 3] = Tdata3;
5224     Tindex += 4;
5225   }//while
5226   for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
5227     destBuffer[Tindex] = sourceBuffer[Tindex];
5228   }//for
5229 }//Dbtc::copyFromToLen()
5230 
execSEND_PACKED(Signal * signal)5231 void Dbtc::execSEND_PACKED(Signal* signal)
5232 {
5233   HostRecordPtr Thostptr;
5234   HostRecord *localHostRecord = hostRecord;
5235   UintR i;
5236   UintR TpackedListIndex = cpackedListIndex;
5237   jamEntry();
5238   for (i = 0; i < TpackedListIndex; i++) {
5239     jam();
5240     Thostptr.i = cpackedList[i];
5241     ptrAss(Thostptr, localHostRecord);
5242     arrGuard(Thostptr.i - 1, MAX_NODES - 1);
5243     for (Uint32 j = 0; j < NDB_ARRAY_SIZE(Thostptr.p->lqh_pack); j++)
5244     {
5245       struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[j];
5246       jam();
5247       if (container->noOfPackedWords > 0) {
5248         jam();
5249         sendPackedSignal(signal, container);
5250       }
5251     }
5252     struct PackedWordsContainer * container = &Thostptr.p->packTCKEYCONF;
5253     if (container->noOfPackedWords > 0) {
5254       jam();
5255       sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
5256     }//if
5257     Thostptr.p->inPackedList = false;
5258   }//for
5259   cpackedListIndex = 0;
5260   return;
5261 }//Dbtc::execSEND_PACKED()
5262 
5263 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 ahostIndex)5264 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
5265 {
5266   if (ahostptr->inPackedList == false) {
5267     UintR TpackedListIndex = cpackedListIndex;
5268     jam();
5269     ahostptr->inPackedList = true;
5270     cpackedList[TpackedListIndex] = ahostIndex;
5271     cpackedListIndex = TpackedListIndex + 1;
5272   }//if
5273 }//Dbtc::updatePackedList()
5274 
sendPackedSignal(Signal * signal,struct PackedWordsContainer * container)5275 void Dbtc::sendPackedSignal(Signal* signal,
5276                             struct PackedWordsContainer * container)
5277 {
5278   UintR TnoOfWords = container->noOfPackedWords;
5279   ndbassert(TnoOfWords <= 25);
5280   container->noOfPackedWords = 0;
5281   memcpy(&signal->theData[0], &container->packedWords[0], 4 * TnoOfWords);
5282   if (VERIFY_PACKED_SEND)
5283   {
5284     ndbrequire(refToMain(container->hostBlockRef) == DBLQH);
5285     ndbrequire(PackedSignal::verify(&signal->theData[0],
5286                                     TnoOfWords,
5287                                     container->hostBlockRef,
5288                                     LQH_RECEIVE_TYPES,
5289                                     5)); /* Commit signal length */
5290   }
5291   sendSignal(container->hostBlockRef,
5292              GSN_PACKED_SIGNAL,
5293              signal,
5294              TnoOfWords,
5295              JBB);
5296 }//Dbtc::sendPackedSignal()
5297 
sendPackedTCKEYCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)5298 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
5299                                HostRecord * ahostptr,
5300                                UintR hostId)
5301 {
5302   struct PackedWordsContainer * container = &ahostptr->packTCKEYCONF;
5303   UintR TnoOfWords = container->noOfPackedWords;
5304   ndbassert(TnoOfWords <= 25);
5305   container->noOfPackedWords = 0;
5306   BlockReference TBref = numberToRef(API_PACKED, hostId);
5307   memcpy(&signal->theData[0], &container->packedWords[0], 4 * TnoOfWords);
5308   sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
5309 }//Dbtc::sendPackedTCKEYCONF()
5310 
5311 void
startSendFireTrigReq(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)5312 Dbtc::startSendFireTrigReq(Signal* signal, Ptr<ApiConnectRecord> regApiPtr)
5313 {
5314   const Uint32 pass = regApiPtr.p->m_pre_commit_pass;
5315   const Uint32 step = pass & Uint32(TriggerPreCommitPass::TPCP_PASS_MAX);
5316   regApiPtr.p->pendingTriggers = 0;
5317   if (tc_testbit(regApiPtr.p->m_flags,
5318                  ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS))
5319   {
5320     jam();
5321     if (step == TriggerPreCommitPass::UK_PASS_1)
5322     {
5323       jam();
5324       // clear on second pass...
5325       tc_clearbit(regApiPtr.p->m_flags,
5326                   ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS);
5327     }
5328   }
5329   else
5330   {
5331     ndbassert(tc_testbit(regApiPtr.p->m_flags,
5332                          ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS));
5333     tc_clearbit(regApiPtr.p->m_flags,
5334                 ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS);
5335 
5336     Uint32 newpass = pass;
5337     newpass = newpass & ~Uint32(TriggerPreCommitPass::TPCP_PASS_MAX);
5338     newpass = newpass + TriggerPreCommitPass::FK_PASS_0;
5339     regApiPtr.p->m_pre_commit_pass = newpass;
5340   }
5341   sendFireTrigReq(signal, regApiPtr,
5342                   regApiPtr.p->firstTcConnect,
5343                   regApiPtr.p->lastTcConnect);
5344 }
5345 
5346 /*
5347 4.3.11 DIVERIFY
5348 ---------------
5349 */
5350 /*****************************************************************************/
5351 /*                               D I V E R I F Y                             */
5352 /*                                                                           */
5353 /*****************************************************************************/
diverify010Lab(Signal * signal)5354 void Dbtc::diverify010Lab(Signal* signal)
5355 {
5356   UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
5357   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5358   signal->theData[0] = apiConnectptr.i;
5359   signal->theData[1] = instance() ? instance() - 1 : 0;
5360   if (ERROR_INSERTED(8022)) {
5361     jam();
5362     systemErrorLab(signal, __LINE__);
5363   }//if
5364 
5365   if (tc_testbit(regApiPtr->m_flags,
5366                  (ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS +
5367                   ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS)))
5368   {
5369     /**
5370      * If trans has deferred triggers, let them fire just before
5371      *   transaction starts to commit
5372      */
5373     startSendFireTrigReq(signal, apiConnectptr);
5374     return;
5375   }
5376 
5377   if (regApiPtr->lqhkeyreqrec)
5378   {
5379     if (TfirstfreeApiConnectCopy != RNIL) {
5380       seizeApiConnectCopy(signal);
5381       regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
5382       /*-----------------------------------------------------------------------
5383        * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
5384        * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
5385        * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
5386        * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
5387        *---------------------------------------------------------------------*/
5388       * (EmulatedJamBuffer**)(signal->theData+2) = jamBuffer();
5389       EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal,
5390                      2 + sizeof(void*)/sizeof(Uint32), 0);
5391       if (signal->theData[3] == 0) {
5392         execDIVERIFYCONF(signal);
5393       }
5394       return;
5395     } else {
5396       /*-----------------------------------------------------------------------
5397        * There were no free copy connections available. We must abort the
5398        * transaction since otherwise we will have a problem with the report
5399        * to the application.
5400        * This should more or less not happen but if it happens we do
5401        * not want to crash and we do not want to create code to handle it
5402        * properly since it is difficult to test it and will be complex to
5403        * handle a problem more or less not occurring.
5404        *---------------------------------------------------------------------*/
5405       terrorCode = ZSEIZE_API_COPY_ERROR;
5406       abortErrorLab(signal);
5407       return;
5408     }
5409   }
5410   else
5411   {
5412     jam();
5413     sendtckeyconf(signal, 1);
5414     regApiPtr->apiConnectstate = CS_CONNECTED;
5415     regApiPtr->m_transaction_nodes.clear();
5416     setApiConTimer(apiConnectptr.i, 0,__LINE__);
5417   }
5418 }//Dbtc::diverify010Lab()
5419 
5420 /* ------------------------------------------------------------------------- */
5421 /* -------                  SEIZE_API_CONNECT                        ------- */
5422 /*                  SEIZE CONNECT RECORD FOR A REQUEST                       */
5423 /* ------------------------------------------------------------------------- */
seizeApiConnectCopy(Signal * signal)5424 void Dbtc::seizeApiConnectCopy(Signal* signal)
5425 {
5426   ApiConnectRecordPtr locApiConnectptr;
5427 
5428   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5429   UintR TapiConnectFilesize = capiConnectFilesize;
5430   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5431 
5432   locApiConnectptr.i = cfirstfreeApiConnectCopy;
5433   ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
5434   cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
5435   locApiConnectptr.p->nextApiConnect = RNIL;
5436   ndbassert(regApiPtr->apiCopyRecord == RNIL);
5437   regApiPtr->apiCopyRecord = locApiConnectptr.i;
5438   tc_clearbit(regApiPtr->m_flags,
5439               ApiConnectRecord::TF_TRIGGER_PENDING);
5440   regApiPtr->m_special_op_flags = 0;
5441 }//Dbtc::seizeApiConnectCopy()
5442 
execDIVERIFYCONF(Signal * signal)5443 void Dbtc::execDIVERIFYCONF(Signal* signal)
5444 {
5445   UintR TapiConnectptrIndex = signal->theData[0];
5446   UintR TapiConnectFilesize = capiConnectFilesize;
5447   UintR Tgci_hi = signal->theData[1];
5448   UintR Tgci_lo = signal->theData[2];
5449   Uint64 Tgci = Tgci_lo | (Uint64(Tgci_hi) << 32);
5450   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5451 
5452   jamEntry();
5453   if (ERROR_INSERTED(8017)) {
5454     CLEAR_ERROR_INSERT_VALUE;
5455     return;
5456   }//if
5457   if (TapiConnectptrIndex >= TapiConnectFilesize) {
5458     TCKEY_abort(signal, 31);
5459     return;
5460   }//if
5461   ApiConnectRecord * const regApiPtr =
5462                             &localApiConnectRecord[TapiConnectptrIndex];
5463   ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
5464   UintR TApifailureNr = regApiPtr->failureNr;
5465   UintR Tfailure_nr = cfailure_nr;
5466   apiConnectptr.i = TapiConnectptrIndex;
5467   apiConnectptr.p = regApiPtr;
5468   if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
5469     TCKEY_abort(signal, 32);
5470     return;
5471   }//if
5472   /*--------------------------------------------------------------------------
5473    * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
5474    * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
5475    * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
5476    * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
5477    * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
5478    *-------------------------------------------------------------------------*/
5479   if (TApifailureNr != Tfailure_nr ||
5480       ERROR_INSERTED(8094)) {
5481     jam();
5482     DIVER_node_fail_handling(signal, Tgci);
5483     return;
5484   }//if
5485   commitGciHandling(signal, Tgci);
5486 
5487   /**************************************************************************
5488    *                                 C O M M I T
5489    * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
5490    **************************************************************************/
5491 
5492   UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
5493   UintR TtcConnectFilesize = ctcConnectFilesize;
5494   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5495 
5496   regApiPtr->counter = regApiPtr->lqhkeyconfrec;
5497   regApiPtr->apiConnectstate = CS_COMMITTING;
5498   if (TtcConnectptrIndex >= TtcConnectFilesize) {
5499     TCKEY_abort(signal, 33);
5500     return;
5501   }//if
5502   TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
5503   tcConnectptr.i = TtcConnectptrIndex;
5504   tcConnectptr.p = regTcPtr;
5505   commit020Lab(signal);
5506 }//Dbtc::execDIVERIFYCONF()
5507 
5508 /*--------------------------------------------------------------------------*/
5509 /*                             COMMIT_GCI_HANDLING                          */
5510 /*       SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT.       */
5511 /*--------------------------------------------------------------------------*/
commitGciHandling(Signal * signal,Uint64 Tgci)5512 void Dbtc::commitGciHandling(Signal* signal, Uint64 Tgci)
5513 {
5514   GcpRecordPtr localGcpPointer;
5515 
5516   UintR TgcpFilesize = cgcpFilesize;
5517   UintR Tfirstgcp = cfirstgcp;
5518   Ptr<ApiConnectRecord> regApiPtr = apiConnectptr;
5519   GcpRecord *localGcpRecord = gcpRecord;
5520 
5521   regApiPtr.p->globalcheckpointid = Tgci;
5522   if (Tfirstgcp != RNIL) {
5523     /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
5524     localGcpPointer.i = Tfirstgcp;
5525     ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5526     do {
5527       if (regApiPtr.p->globalcheckpointid == localGcpPointer.p->gcpId) {
5528         jam();
5529         linkApiToGcp(localGcpPointer, regApiPtr);
5530         return;
5531       } else {
5532         if (unlikely(! (regApiPtr.p->globalcheckpointid > localGcpPointer.p->gcpId)))
5533         {
5534           ndbout_c("%u/%u %u/%u",
5535                    Uint32(regApiPtr.p->globalcheckpointid >> 32),
5536                    Uint32(regApiPtr.p->globalcheckpointid),
5537                    Uint32(localGcpPointer.p->gcpId >> 32),
5538                    Uint32(localGcpPointer.p->gcpId));
5539           crash_gcp(__LINE__);
5540         }
5541         localGcpPointer.i = localGcpPointer.p->nextGcp;
5542         jam();
5543         if (localGcpPointer.i != RNIL) {
5544           jam();
5545           ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5546           continue;
5547         }//if
5548       }//if
5549       seizeGcp(localGcpPointer, Tgci);
5550       linkApiToGcp(localGcpPointer, regApiPtr);
5551       return;
5552     } while (1);
5553   } else {
5554     jam();
5555     seizeGcp(localGcpPointer, Tgci);
5556     linkApiToGcp(localGcpPointer, regApiPtr);
5557   }//if
5558 }//Dbtc::commitGciHandling()
5559 
5560 /* --------------------------------------------------------------------------*/
5561 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
5562 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS   */
5563 /* LINKED OUT OF THE LIST.                                                   */
5564 /*---------------------------------------------------------------------------*/
linkApiToGcp(Ptr<GcpRecord> regGcpPtr,Ptr<ApiConnectRecord> regApiPtr)5565 void Dbtc::linkApiToGcp(Ptr<GcpRecord> regGcpPtr,
5566                         Ptr<ApiConnectRecord> regApiPtr)
5567 {
5568   ApiConnectRecordPtr localApiConnectptr;
5569   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5570 
5571   regApiPtr.p->nextGcpConnect = RNIL;
5572   if (regGcpPtr.p->firstApiConnect == RNIL) {
5573     regGcpPtr.p->firstApiConnect = regApiPtr.i;
5574     jam();
5575   } else {
5576     UintR TapiConnectFilesize = capiConnectFilesize;
5577     localApiConnectptr.i = regGcpPtr.p->lastApiConnect;
5578     jam();
5579     ptrCheckGuard(localApiConnectptr,
5580                   TapiConnectFilesize, localApiConnectRecord);
5581     localApiConnectptr.p->nextGcpConnect = regApiPtr.i;
5582   }//if
5583   UintR TlastApiConnect = regGcpPtr.p->lastApiConnect;
5584   regApiPtr.p->gcpPointer = regGcpPtr.i;
5585   regApiPtr.p->prevGcpConnect = TlastApiConnect;
5586   regGcpPtr.p->lastApiConnect = regApiPtr.i;
5587 }//Dbtc::linkApiToGcp()
5588 
5589 void
crash_gcp(Uint32 line)5590 Dbtc::crash_gcp(Uint32 line)
5591 {
5592   GcpRecordPtr localGcpPointer;
5593 
5594   localGcpPointer.i = cfirstgcp;
5595 
5596   while (localGcpPointer.i != RNIL)
5597   {
5598     ptrCheckGuard(localGcpPointer, cgcpFilesize, gcpRecord);
5599     ndbout_c("%u : %u/%u nomoretrans: %u api %u %u next: %u",
5600              localGcpPointer.i,
5601              Uint32(localGcpPointer.p->gcpId >> 32),
5602              Uint32(localGcpPointer.p->gcpId),
5603              localGcpPointer.p->gcpNomoretransRec,
5604              localGcpPointer.p->firstApiConnect,
5605              localGcpPointer.p->lastApiConnect,
5606              localGcpPointer.p->nextGcp);
5607     localGcpPointer.i = localGcpPointer.p->nextGcp;
5608   }
5609   progError(line, NDBD_EXIT_NDBREQUIRE);
5610   ndbrequire(false);
5611 }
5612 
seizeGcp(Ptr<GcpRecord> & dst,Uint64 Tgci)5613 void Dbtc::seizeGcp(Ptr<GcpRecord> & dst, Uint64 Tgci)
5614 {
5615   GcpRecordPtr tmpGcpPointer;
5616   GcpRecordPtr localGcpPointer;
5617 
5618   UintR Tfirstgcp = cfirstgcp;
5619   UintR TgcpFilesize = cgcpFilesize;
5620   GcpRecord *localGcpRecord = gcpRecord;
5621 
5622   localGcpPointer.i = cfirstfreeGcp;
5623   if (unlikely(localGcpPointer.i > TgcpFilesize))
5624   {
5625     ndbout_c("%u/%u", Uint32(Tgci >> 32), Uint32(Tgci));
5626     crash_gcp(__LINE__);
5627   }
5628   ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5629   UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
5630   localGcpPointer.p->gcpId = Tgci;
5631   localGcpPointer.p->nextGcp = RNIL;
5632   localGcpPointer.p->firstApiConnect = RNIL;
5633   localGcpPointer.p->lastApiConnect = RNIL;
5634   localGcpPointer.p->gcpNomoretransRec = ZFALSE;
5635   cfirstfreeGcp = TfirstfreeGcp;
5636 
5637   if (Tfirstgcp == RNIL) {
5638     jam();
5639     cfirstgcp = localGcpPointer.i;
5640   } else {
5641     tmpGcpPointer.i = clastgcp;
5642     jam();
5643     ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
5644     tmpGcpPointer.p->nextGcp = localGcpPointer.i;
5645   }//if
5646   clastgcp = localGcpPointer.i;
5647   dst = localGcpPointer;
5648 }//Dbtc::seizeGcp()
5649 
5650 /*---------------------------------------------------------------------------*/
5651 // Send COMMIT messages to all LQH operations involved in the transaction.
5652 /*---------------------------------------------------------------------------*/
commit020Lab(Signal * signal)5653 void Dbtc::commit020Lab(Signal* signal)
5654 {
5655   TcConnectRecordPtr localTcConnectptr;
5656   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5657   UintR TtcConnectFilesize = ctcConnectFilesize;
5658   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5659 
5660   localTcConnectptr.p = tcConnectptr.p;
5661   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5662   UintR Tcount = 0;
5663   do {
5664     /*-----------------------------------------------------------------------
5665      * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
5666      *-----------------------------------------------------------------------*/
5667     /* *********< */
5668     /*  COMMIT  < */
5669     /* *********< */
5670     localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
5671     /* Clear per-operation record CommitAckMarker ref if necessary */
5672     if (localTcConnectptr.p->commitAckMarker != RNIL)
5673     {
5674       ndbassert(regApiPtr->commitAckMarker != RNIL);
5675       ndbrequire(regApiPtr->num_commit_ack_markers--);
5676       localTcConnectptr.p->commitAckMarker = RNIL;
5677     }
5678     localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
5679     Tcount += sendCommitLqh(signal, localTcConnectptr.p);
5680 
5681     if (localTcConnectptr.i != RNIL) {
5682       if (Tcount < 16 &&
5683           ! (ERROR_INSERTED(8057) ||
5684              ERROR_INSERTED(8073) ||
5685              ERROR_INSERTED(8089)))
5686       {
5687         ptrCheckGuard(localTcConnectptr,
5688                       TtcConnectFilesize, localTcConnectRecord);
5689         jam();
5690         continue;
5691       } else {
5692         jam();
5693         if (ERROR_INSERTED(8014)) {
5694           CLEAR_ERROR_INSERT_VALUE;
5695           return;
5696         }//if
5697 
5698         if (ERROR_INSERTED(8073))
5699         {
5700           execSEND_PACKED(signal);
5701           signal->theData[0] = 9999;
5702           sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
5703           return;
5704         }
5705         signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
5706         signal->theData[1] = apiConnectptr.i;
5707         signal->theData[2] = localTcConnectptr.i;
5708         if (ERROR_INSERTED(8089))
5709         {
5710           sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
5711           return;
5712         }
5713         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5714         return;
5715       }//if
5716     } else {
5717       jam();
5718       if (ERROR_INSERTED(8057))
5719         CLEAR_ERROR_INSERT_VALUE;
5720 
5721       if (ERROR_INSERTED(8089))
5722         CLEAR_ERROR_INSERT_VALUE;
5723 
5724       regApiPtr->apiConnectstate = CS_COMMIT_SENT;
5725       ndbrequire(regApiPtr->num_commit_ack_markers == 0);
5726       return;
5727     }//if
5728   } while (1);
5729 }//Dbtc::commit020Lab()
5730 
5731 Uint32
sendCommitLqh(Signal * signal,TcConnectRecord * const regTcPtr)5732 Dbtc::sendCommitLqh(Signal* signal,
5733                     TcConnectRecord * const regTcPtr)
5734 {
5735   HostRecordPtr Thostptr;
5736   UintR ThostFilesize = chostFilesize;
5737   Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5738   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5739   Thostptr.i = regTcPtr->lastLqhNodeId;
5740   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5741 
5742   Uint32 Tnode = Thostptr.i;
5743   Uint32 self = getOwnNodeId();
5744   Uint32 ret = (Tnode == self) ? 4 : 1;
5745 
5746   Uint32 Tdata[5];
5747   Tdata[0] = regTcPtr->lastLqhCon;
5748   Tdata[1] = Uint32(regApiPtr->globalcheckpointid >> 32);
5749   Tdata[2] = regApiPtr->transid[0];
5750   Tdata[3] = regApiPtr->transid[1];
5751   Tdata[4] = Uint32(regApiPtr->globalcheckpointid);
5752   Uint32 len = 5;
5753 
5754   if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
5755   {
5756     jam();
5757     ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
5758     len = 4;
5759   }
5760   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
5761     memcpy(&signal->theData[0], &Tdata[0], len << 2);
5762     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5763     sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
5764     return ret;
5765   }
5766 
5767   struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[instanceKey];
5768 
5769   if (container->noOfPackedWords > 25 - len) {
5770     jam();
5771     sendPackedSignal(signal, container);
5772   } else {
5773     jam();
5774     ret = 1;
5775     updatePackedList(signal, Thostptr.p, Thostptr.i);
5776   }
5777 
5778   Tdata[0] |= (ZCOMMIT << 28);
5779   UintR Tindex = container->noOfPackedWords;
5780   container->noOfPackedWords = Tindex + len;
5781   UintR* TDataPtr = &container->packedWords[Tindex];
5782   memcpy(TDataPtr, &Tdata[0], len << 2);
5783   return ret;
5784 }
5785 
5786 void
DIVER_node_fail_handling(Signal * signal,Uint64 Tgci)5787 Dbtc::DIVER_node_fail_handling(Signal* signal, Uint64 Tgci)
5788 {
5789   /*------------------------------------------------------------------------
5790    * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
5791    * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
5792    * ABORT AND THE COMMIT CASES WE NEED  TO SET-UP THE DATA FOR THE
5793    * ABORT/COMMIT/COMPLETE  HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
5794    *------------------------------------------------------------------------*/
5795   tabortInd = ZFALSE;
5796   setupFailData(signal);
5797   if (false && tabortInd == ZFALSE) {
5798     jam();
5799     commitGciHandling(signal, Tgci);
5800     toCommitHandlingLab(signal);
5801   } else {
5802     jam();
5803     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
5804     apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
5805     toAbortHandlingLab(signal);
5806   }//if
5807   return;
5808 }//Dbtc::DIVER_node_fail_handling()
5809 
5810 
5811 /* ------------------------------------------------------------------------- */
5812 /* -------                       ENTER COMMITTED                     ------- */
5813 /*                                                                           */
5814 /* ------------------------------------------------------------------------- */
execCOMMITTED(Signal * signal)5815 void Dbtc::execCOMMITTED(Signal* signal)
5816 {
5817   TcConnectRecordPtr localTcConnectptr;
5818   ApiConnectRecordPtr localApiConnectptr;
5819   ApiConnectRecordPtr localCopyPtr;
5820 
5821   UintR TtcConnectFilesize = ctcConnectFilesize;
5822   UintR TapiConnectFilesize = capiConnectFilesize;
5823   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5824   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5825 
5826 #ifdef ERROR_INSERT
5827   if (ERROR_INSERTED(8018)) {
5828     CLEAR_ERROR_INSERT_VALUE;
5829     return;
5830   }//if
5831   CRASH_INSERTION(8030);
5832   if (ERROR_INSERTED(8025)) {
5833     SET_ERROR_INSERT_VALUE(8026);
5834     return;
5835   }//if
5836   if (ERROR_INSERTED(8041)) {
5837     CLEAR_ERROR_INSERT_VALUE;
5838     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
5839     return;
5840   }//if
5841   if (ERROR_INSERTED(8042)) {
5842     SET_ERROR_INSERT_VALUE(8046);
5843     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
5844     return;
5845   }//if
5846 #endif
5847   localTcConnectptr.i = signal->theData[0];
5848   jamEntry();
5849   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5850   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
5851   if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
5852     warningReport(signal, 4);
5853     return;
5854   }//if
5855   ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
5856 		localApiConnectRecord);
5857   UintR Tcounter = localApiConnectptr.p->counter - 1;
5858   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
5859   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
5860   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
5861   Tdata1 = Tdata1 | Tdata2;
5862   bool TcheckCondition =
5863     (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
5864 
5865   setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
5866   localApiConnectptr.p->counter = Tcounter;
5867   localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
5868   if (Tdata1 != 0) {
5869     warningReport(signal, 5);
5870     return;
5871   }//if
5872   if (TcheckCondition) {
5873     jam();
5874     /*-------------------------------------------------------*/
5875     // We have not sent all COMMIT requests yet. We could be
5876     // in the state that all sent are COMMITTED but we are
5877     // still waiting for a CONTINUEB to send the rest of the
5878     // COMMIT requests.
5879     /*-------------------------------------------------------*/
5880     return;
5881   }//if
5882   if (ERROR_INSERTED(8020)) {
5883     jam();
5884     systemErrorLab(signal, __LINE__);
5885   }//if
5886   /*-------------------------------------------------------*/
5887   /* THE ENTIRE TRANSACTION IS NOW COMMITED                */
5888   /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION.  */
5889   /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
5890   /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A     */
5891   /* NEW API CONNECT RECORD.                               */
5892   /*-------------------------------------------------------*/
5893 
5894   apiConnectptr = localApiConnectptr;
5895   localCopyPtr = sendApiCommit(signal);
5896 
5897   localTcConnectptr.i = localCopyPtr.p->firstTcConnect;
5898   UintR Tlqhkeyconfrec = localCopyPtr.p->lqhkeyconfrec;
5899   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5900   localCopyPtr.p->counter = Tlqhkeyconfrec;
5901 
5902   apiConnectptr = localCopyPtr;
5903   tcConnectptr = localTcConnectptr;
5904   complete010Lab(signal);
5905   return;
5906 
5907 }//Dbtc::execCOMMITTED()
5908 
5909 /*-------------------------------------------------------*/
5910 /*                       SEND_API_COMMIT                 */
5911 /*       SEND COMMIT DECISION TO THE API.                */
5912 /*-------------------------------------------------------*/
5913 Ptr<Dbtc::ApiConnectRecord>
sendApiCommit(Signal * signal)5914 Dbtc::sendApiCommit(Signal* signal)
5915 {
5916   ApiConnectRecordPtr regApiPtr = apiConnectptr;
5917 
5918   if (ERROR_INSERTED(8055))
5919   {
5920     /**
5921      * 1) Kill self
5922      * 2) Disconnect API
5923      * 3) Prevent execAPI_FAILREQ from handling trans...
5924      */
5925     signal->theData[0] = 9999;
5926     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
5927     Uint32 node = refToNode(regApiPtr.p->ndbapiBlockref);
5928     signal->theData[0] = node;
5929     sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
5930 
5931     SET_ERROR_INSERT_VALUE(8056);
5932 
5933     goto err8055;
5934   }
5935 
5936   if (regApiPtr.p->returnsignal == RS_TCKEYCONF)
5937   {
5938     if (ERROR_INSERTED(8054))
5939     {
5940       signal->theData[0] = 9999;
5941       sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 5000, 1);
5942     }
5943     else
5944     {
5945       sendtckeyconf(signal, 1);
5946     }
5947   }
5948   else if (regApiPtr.p->returnsignal == RS_TC_COMMITCONF)
5949   {
5950     jam();
5951     TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
5952     if(regApiPtr.p->commitAckMarker == RNIL)
5953     {
5954       jam();
5955       commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect;
5956     }
5957     else
5958     {
5959       jam();
5960       commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect | 1;
5961     }
5962     commitConf->transId1 = regApiPtr.p->transid[0];
5963     commitConf->transId2 = regApiPtr.p->transid[1];
5964     commitConf->gci_hi = Uint32(regApiPtr.p->globalcheckpointid >> 32);
5965     commitConf->gci_lo = Uint32(regApiPtr.p->globalcheckpointid);
5966 
5967     if (!ERROR_INSERTED(8054) && !ERROR_INSERTED(8108))
5968     {
5969       sendSignal(regApiPtr.p->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
5970                  TcCommitConf::SignalLength, JBB);
5971     }
5972   }
5973   else if (regApiPtr.p->returnsignal == RS_NO_RETURN)
5974   {
5975     jam();
5976   }
5977   else
5978   {
5979     TCKEY_abort(signal, 37);
5980     return regApiPtr;
5981   }//if
5982 
5983 err8055:
5984   Ptr<ApiConnectRecord> copyPtr;
5985   UintR TapiConnectFilesize = capiConnectFilesize;
5986   /**
5987    * Unlink copy connect record from main connect record to allow main record
5988    * re-use.
5989    */
5990   copyPtr.i = regApiPtr.p->apiCopyRecord;
5991   regApiPtr.p->apiCopyRecord = RNIL;
5992   UintR TapiFailState = regApiPtr.p->apiFailState;
5993   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5994 
5995   c_counters.ccommitCount++;
5996   ptrCheckGuard(copyPtr, TapiConnectFilesize, localApiConnectRecord);
5997   copyApi(copyPtr, regApiPtr);
5998   if (TapiFailState != ZTRUE) {
5999     return copyPtr;
6000   } else {
6001     jam();
6002     handleApiFailState(signal, regApiPtr.i);
6003     return copyPtr;
6004   }//if
6005 }//Dbtc::sendApiCommit()
6006 
6007 /* ========================================================================= */
6008 /* =======                  COPY_API                                 ======= */
6009 /*   COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT                */
6010 /*   IS PREPARED TO RECEIVE A NEW TRANSACTION.                               */
6011 /*===========================================================================*/
copyApi(ApiConnectRecordPtr copyPtr,ApiConnectRecordPtr regApiPtr)6012 void Dbtc::copyApi(ApiConnectRecordPtr copyPtr, ApiConnectRecordPtr regApiPtr)
6013 {
6014   UintR TndbapiConnect = regApiPtr.p->ndbapiConnect;
6015   UintR TfirstTcConnect = regApiPtr.p->firstTcConnect;
6016   UintR Ttransid1 = regApiPtr.p->transid[0];
6017   UintR Ttransid2 = regApiPtr.p->transid[1];
6018   UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
6019   UintR TgcpPointer = regApiPtr.p->gcpPointer;
6020   UintR TgcpFilesize = cgcpFilesize;
6021   NdbNodeBitmask Tnodes = regApiPtr.p->m_transaction_nodes;
6022   GcpRecord *localGcpRecord = gcpRecord;
6023 
6024   copyPtr.p->ndbapiBlockref = regApiPtr.p->ndbapiBlockref;
6025   copyPtr.p->ndbapiConnect = TndbapiConnect;
6026   copyPtr.p->firstTcConnect = TfirstTcConnect;
6027   copyPtr.p->apiConnectstate = CS_COMPLETING;
6028   copyPtr.p->transid[0] = Ttransid1;
6029   copyPtr.p->transid[1] = Ttransid2;
6030   copyPtr.p->lqhkeyconfrec = Tlqhkeyconfrec;
6031   copyPtr.p->commitAckMarker = RNIL;
6032   copyPtr.p->m_transaction_nodes = Tnodes;
6033   copyPtr.p->num_commit_ack_markers = 0;
6034   copyPtr.p->singleUserMode = 0;
6035 
6036   Ptr<GcpRecord> gcpPtr;
6037   gcpPtr.i = TgcpPointer;
6038   ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
6039   unlinkApiConnect(gcpPtr, regApiPtr);
6040   linkApiToGcp(gcpPtr, copyPtr);
6041   setApiConTimer(regApiPtr.i, 0, __LINE__);
6042   regApiPtr.p->apiConnectstate = CS_CONNECTED;
6043   regApiPtr.p->commitAckMarker = RNIL;
6044   regApiPtr.p->firstTcConnect = RNIL;
6045   regApiPtr.p->lastTcConnect = RNIL;
6046   regApiPtr.p->m_transaction_nodes.clear();
6047   regApiPtr.p->singleUserMode = 0;
6048   regApiPtr.p->num_commit_ack_markers = 0;
6049   releaseAllSeizedIndexOperations(regApiPtr.p);
6050 }//Dbtc::copyApi()
6051 
unlinkApiConnect(Ptr<GcpRecord> gcpPtr,Ptr<ApiConnectRecord> regApiPtr)6052 void Dbtc::unlinkApiConnect(Ptr<GcpRecord> gcpPtr,
6053                             Ptr<ApiConnectRecord> regApiPtr)
6054 {
6055   ApiConnectRecordPtr localApiConnectptr;
6056   UintR TapiConnectFilesize = capiConnectFilesize;
6057   UintR TprevGcpConnect = regApiPtr.p->prevGcpConnect;
6058   UintR TnextGcpConnect = regApiPtr.p->nextGcpConnect;
6059   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6060 
6061   if (TprevGcpConnect == RNIL) {
6062     gcpPtr.p->firstApiConnect = TnextGcpConnect;
6063     jam();
6064   } else {
6065     localApiConnectptr.i = TprevGcpConnect;
6066     jam();
6067     ptrCheckGuard(localApiConnectptr,
6068                   TapiConnectFilesize, localApiConnectRecord);
6069     localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
6070   }//if
6071   if (TnextGcpConnect == RNIL) {
6072     gcpPtr.p->lastApiConnect = TprevGcpConnect;
6073     jam();
6074   } else {
6075     localApiConnectptr.i = TnextGcpConnect;
6076     jam();
6077     ptrCheckGuard(localApiConnectptr,
6078                   TapiConnectFilesize, localApiConnectRecord);
6079     localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
6080   }//if
6081 }//Dbtc::unlinkApiConnect()
6082 
complete010Lab(Signal * signal)6083 void Dbtc::complete010Lab(Signal* signal)
6084 {
6085   TcConnectRecordPtr localTcConnectptr;
6086   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6087   UintR TtcConnectFilesize = ctcConnectFilesize;
6088   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6089 
6090   localTcConnectptr.p = tcConnectptr.p;
6091   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6092   UintR TapiConnectptrIndex = apiConnectptr.i;
6093   UintR Tcount = 0;
6094   do {
6095     localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
6096     localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
6097 
6098     /* ************ */
6099     /*  COMPLETE  < */
6100     /* ************ */
6101     const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
6102     Tcount += sendCompleteLqh(signal, localTcConnectptr.p);
6103     localTcConnectptr.i = nextTcConnect;
6104     if (localTcConnectptr.i != RNIL) {
6105       if (Tcount < 16) {
6106         ptrCheckGuard(localTcConnectptr,
6107                       TtcConnectFilesize, localTcConnectRecord);
6108         jam();
6109         continue;
6110       } else {
6111         jam();
6112         if (ERROR_INSERTED(8013)) {
6113           CLEAR_ERROR_INSERT_VALUE;
6114           return;
6115         }//if
6116         signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
6117         signal->theData[1] = apiConnectptr.i;
6118         signal->theData[2] = localTcConnectptr.i;
6119         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
6120         return;
6121       }//if
6122     } else {
6123       jam();
6124       regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
6125       return;
6126     }//if
6127   } while (1);
6128 }//Dbtc::complete010Lab()
6129 
6130 Uint32
sendCompleteLqh(Signal * signal,TcConnectRecord * const regTcPtr)6131 Dbtc::sendCompleteLqh(Signal* signal,
6132                       TcConnectRecord * const regTcPtr)
6133 {
6134   HostRecordPtr Thostptr;
6135   UintR ThostFilesize = chostFilesize;
6136   Uint32 instanceKey = regTcPtr->lqhInstanceKey;
6137   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6138   Thostptr.i = regTcPtr->lastLqhNodeId;
6139   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
6140 
6141   Uint32 Tnode = Thostptr.i;
6142   Uint32 self = getOwnNodeId();
6143   Uint32 ret = (Tnode == self) ? 4 : 1;
6144 
6145   Uint32 Tdata[3];
6146   Tdata[0] = regTcPtr->lastLqhCon;
6147   Tdata[1] = regApiPtr->transid[0];
6148   Tdata[2] = regApiPtr->transid[1];
6149   Uint32 len = 3;
6150 
6151   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
6152     memcpy(&signal->theData[0], &Tdata[0], len << 2);
6153     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
6154     sendSignal(lqhRef, GSN_COMPLETE, signal, 3, JBB);
6155     return ret;
6156   }
6157 
6158   struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[instanceKey];
6159 
6160   if (container->noOfPackedWords > 22) {
6161     jam();
6162     sendPackedSignal(signal, container);
6163   } else {
6164     jam();
6165     ret = 1;
6166     updatePackedList(signal, Thostptr.p, Thostptr.i);
6167   }
6168 
6169   Tdata[0] |= (ZCOMPLETE << 28);
6170   UintR Tindex = container->noOfPackedWords;
6171   container->noOfPackedWords = Tindex + len;
6172   UintR* TDataPtr = &container->packedWords[Tindex];
6173   memcpy(TDataPtr, &Tdata[0], len << 2);
6174   return ret;
6175 }
6176 
6177 static
6178 inline
6179 Uint32
getTcConnectRecordDeferredFlag(Uint32 pass)6180 getTcConnectRecordDeferredFlag(Uint32 pass)
6181 {
6182   switch(pass & TriggerPreCommitPass::TPCP_PASS_MAX){
6183   case TriggerPreCommitPass::UK_PASS_0:
6184   case TriggerPreCommitPass::UK_PASS_1:
6185     return Dbtc::TcConnectRecord::SOF_DEFERRED_UK_TRIGGER;
6186   case TriggerPreCommitPass::FK_PASS_0:
6187     return Dbtc::TcConnectRecord::SOF_DEFERRED_FK_TRIGGER;
6188   }
6189   assert(false);
6190   return 0;
6191 }
6192 
6193 static
6194 inline
6195 Uint8
getNextDeferredPass(Uint32 pass)6196 getNextDeferredPass(Uint32 pass)
6197 {
6198   Uint32 loop = (pass & ~Uint32(TriggerPreCommitPass::TPCP_PASS_MAX));
6199   switch(pass & TriggerPreCommitPass::TPCP_PASS_MAX){
6200   case TriggerPreCommitPass::UK_PASS_0:
6201     return loop + TriggerPreCommitPass::UK_PASS_1;
6202   case TriggerPreCommitPass::UK_PASS_1:
6203     return loop + TriggerPreCommitPass::FK_PASS_0;
6204   case TriggerPreCommitPass::FK_PASS_0:
6205     return loop + Uint32(TriggerPreCommitPass::TPCP_PASS_MAX) + 1;
6206   }
6207   assert(false);
6208   return 255;
6209 }
6210 
6211 void
sendFireTrigReq(Signal * signal,Ptr<ApiConnectRecord> regApiPtr,Uint32 TopPtrI,Uint32 TlastOpPtrI)6212 Dbtc::sendFireTrigReq(Signal* signal,
6213                       Ptr<ApiConnectRecord> regApiPtr,
6214                       Uint32 TopPtrI,
6215                       Uint32 TlastOpPtrI)
6216 {
6217   UintR TtcConnectFilesize = ctcConnectFilesize;
6218   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6219   TcConnectRecordPtr localTcConnectptr;
6220 
6221   setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
6222   regApiPtr.p->apiConnectstate = CS_SEND_FIRE_TRIG_REQ;
6223 
6224   localTcConnectptr.i = TopPtrI;
6225   ndbassert(TopPtrI != RNIL);
6226   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
6227   const Uint32 pass = regApiPtr.p->m_pre_commit_pass;
6228   const Uint32 passflag = getTcConnectRecordDeferredFlag(pass);
6229   Uint32 prevOpPtrI = RNIL;
6230 #if defined VM_TRACE || defined ERROR_INSERT
6231   const Uint32 LIMIT = 1 + rand() % 15;
6232 #else
6233   const Uint32 LIMIT = 16;
6234 #endif
6235   for (Uint32 i = 0; prevOpPtrI != TlastOpPtrI && i < LIMIT; i++)
6236   {
6237     ptrCheckGuard(localTcConnectptr,
6238                   TtcConnectFilesize, localTcConnectRecord);
6239 
6240     const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
6241     Uint32 flags = localTcConnectptr.p->m_special_op_flags;
6242     if (flags & passflag)
6243     {
6244       jam();
6245       tc_clearbit(flags, passflag);
6246       if (unlikely(! (localTcConnectptr.p->tcConnectstate == OS_PREPARED)))
6247       {
6248         ndbout_c("op: 0x%x trans [ 0x%.8x 0x%.8x ] state: %u (TopPtrI: %x)",
6249                  localTcConnectptr.i,
6250                  regApiPtr.p->transid[0],
6251                  regApiPtr.p->transid[1],
6252                  localTcConnectptr.p->tcConnectstate,
6253                  TopPtrI);
6254         dump_trans(regApiPtr);
6255       }
6256 
6257       ndbrequire(localTcConnectptr.p->tcConnectstate == OS_PREPARED);
6258       localTcConnectptr.p->tcConnectstate = OS_FIRE_TRIG_REQ;
6259       localTcConnectptr.p->m_special_op_flags = flags;
6260       i += sendFireTrigReqLqh(signal, localTcConnectptr, pass);
6261       Tlqhkeyreqrec++;
6262     }
6263 
6264     prevOpPtrI = localTcConnectptr.i;
6265     localTcConnectptr.i = nextTcConnect;
6266   }
6267 
6268   regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec;
6269   if (prevOpPtrI == TlastOpPtrI)
6270   {
6271     /**
6272      * Now wait for FIRE_TRIG_CONF
6273      */
6274     jam();
6275     regApiPtr.p->apiConnectstate = CS_WAIT_FIRE_TRIG_REQ;
6276     ndbrequire(pass < 255);
6277     regApiPtr.p->m_pre_commit_pass = getNextDeferredPass(pass);
6278 
6279     /**
6280      * Check if we are already finished...
6281      */
6282     if (regApiPtr.p->lqhkeyreqrec == regApiPtr.p->lqhkeyconfrec &&
6283         regApiPtr.p->pendingTriggers == 0)
6284     {
6285       jam();
6286       lqhKeyConf_checkTransactionState(signal, regApiPtr);
6287     }
6288     return;
6289   }
6290   else
6291   {
6292     jam();
6293     regApiPtr.p->lqhkeyreqrec++; // prevent early completion
6294     signal->theData[0] = TcContinueB::ZSEND_FIRE_TRIG_REQ;
6295     signal->theData[1] = regApiPtr.i;
6296     signal->theData[2] = regApiPtr.p->transid[0];
6297     signal->theData[3] = regApiPtr.p->transid[1];
6298     signal->theData[4] = localTcConnectptr.i;
6299     signal->theData[5] = TlastOpPtrI;
6300     if (ERROR_INSERTED_CLEAR(8090))
6301     {
6302       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 6);
6303     }
6304     else
6305     {
6306       sendSignal(cownref, GSN_CONTINUEB, signal, 6, JBB);
6307     }
6308   }
6309 }
6310 
6311 Uint32
sendFireTrigReqLqh(Signal * signal,Ptr<TcConnectRecord> regTcPtr,Uint32 pass)6312 Dbtc::sendFireTrigReqLqh(Signal* signal,
6313                          Ptr<TcConnectRecord> regTcPtr,
6314                          Uint32 pass)
6315 {
6316   HostRecordPtr Thostptr;
6317   UintR ThostFilesize = chostFilesize;
6318   Uint32 instanceKey = regTcPtr.p->lqhInstanceKey;
6319   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6320   Thostptr.i = regTcPtr.p->tcNodedata[0];
6321   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
6322 
6323   Uint32 Tnode = Thostptr.i;
6324   Uint32 self = getOwnNodeId();
6325   Uint32 ret = (Tnode == self) ? 4 : 1;
6326 
6327   Uint32 Tdata[FireTrigReq::SignalLength];
6328   FireTrigReq * req = CAST_PTR(FireTrigReq, Tdata);
6329   req->tcOpRec = regTcPtr.i;
6330   req->transId[0] = regApiPtr->transid[0];
6331   req->transId[1] = regApiPtr->transid[1];
6332   req->pass = pass;
6333   Uint32 len = FireTrigReq::SignalLength;
6334 
6335   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
6336     memcpy(signal->theData, Tdata, len << 2);
6337     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
6338     sendSignal(lqhRef, GSN_FIRE_TRIG_REQ, signal, len, JBB);
6339     return ret;
6340   }
6341 
6342   struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[instanceKey];
6343 
6344   if (container->noOfPackedWords > 25 - len) {
6345     jam();
6346     sendPackedSignal(signal, container);
6347   } else {
6348     jam();
6349     ret = 1;
6350     updatePackedList(signal, Thostptr.p, Thostptr.i);
6351   }
6352 
6353   Tdata[0] |= (ZFIRE_TRIG_REQ << 28);
6354   UintR Tindex = container->noOfPackedWords;
6355   container->noOfPackedWords = Tindex + len;
6356   UintR* TDataPtr = &container->packedWords[Tindex];
6357   memcpy(TDataPtr, Tdata, len << 2);
6358   return ret;
6359 }
6360 
6361 void
execFIRE_TRIG_CONF(Signal * signal)6362 Dbtc::execFIRE_TRIG_CONF(Signal* signal)
6363 {
6364   TcConnectRecordPtr localTcConnectptr;
6365   ApiConnectRecordPtr regApiPtr;
6366 
6367   UintR TtcConnectFilesize = ctcConnectFilesize;
6368   UintR TapiConnectFilesize = capiConnectFilesize;
6369   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6370   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6371 
6372   const FireTrigConf * conf = CAST_CONSTPTR(FireTrigConf, signal->theData);
6373   localTcConnectptr.i = conf->tcOpRec;
6374   jamEntry();
6375   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6376   regApiPtr.i = localTcConnectptr.p->apiConnect;
6377   if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
6378   {
6379     warningReport(signal, 28);
6380     return;
6381   }//if
6382   ptrCheckGuard(regApiPtr, TapiConnectFilesize,
6383                 localApiConnectRecord);
6384 
6385   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
6386   Uint32 TapiConnectstate = regApiPtr.p->apiConnectstate;
6387   UintR Tdata1 = regApiPtr.p->transid[0] - conf->transId[0];
6388   UintR Tdata2 = regApiPtr.p->transid[1] - conf->transId[1];
6389   Uint32 TcheckCondition =
6390     (TapiConnectstate != CS_SEND_FIRE_TRIG_REQ) &&
6391     (TapiConnectstate != CS_WAIT_FIRE_TRIG_REQ);
6392 
6393   Tdata1 = Tdata1 | Tdata2 | TcheckCondition;
6394 
6395   if (Tdata1 != 0) {
6396     warningReport(signal, 28);
6397     return;
6398   }//if
6399 
6400   if (ERROR_INSERTED_CLEAR(8091))
6401   {
6402     jam();
6403     return;
6404   }
6405 
6406   CRASH_INSERTION(8092);
6407 
6408   setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
6409   ndbassert(Tlqhkeyreqrec > 0);
6410   regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
6411   localTcConnectptr.p->tcConnectstate = OS_PREPARED;
6412 
6413   Uint32 numFired  = FireTrigConf::getFiredCount(conf->numFiredTriggers);
6414   Uint32 deferreduk = FireTrigConf::getDeferredUKBit(conf->numFiredTriggers);
6415   Uint32 deferredfk = FireTrigConf::getDeferredFKBit(conf->numFiredTriggers);
6416 
6417   regApiPtr.p->pendingTriggers += numFired;
6418   regApiPtr.p->m_flags |=
6419     ((deferreduk) ? ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS : 0) |
6420     ((deferredfk) ? ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS : 0);
6421   localTcConnectptr.p->m_special_op_flags |=
6422     ((deferreduk) ? TcConnectRecord::SOF_DEFERRED_UK_TRIGGER : 0) |
6423     ((deferredfk) ? TcConnectRecord::SOF_DEFERRED_FK_TRIGGER : 0);
6424 
6425   if (regApiPtr.p->pendingTriggers == 0)
6426   {
6427     jam();
6428     lqhKeyConf_checkTransactionState(signal, regApiPtr);
6429   }
6430 }
6431 
6432 void
execFIRE_TRIG_REF(Signal * signal)6433 Dbtc::execFIRE_TRIG_REF(Signal* signal)
6434 {
6435   TcConnectRecordPtr localTcConnectptr;
6436   ApiConnectRecordPtr regApiPtr;
6437 
6438   UintR TtcConnectFilesize = ctcConnectFilesize;
6439   UintR TapiConnectFilesize = capiConnectFilesize;
6440   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6441   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6442 
6443   const FireTrigRef * ref = CAST_CONSTPTR(FireTrigRef, signal->theData);
6444   localTcConnectptr.i = ref->tcOpRec;
6445   jamEntry();
6446   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6447   regApiPtr.i = localTcConnectptr.p->apiConnect;
6448   if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
6449   {
6450     warningReport(signal, 28);
6451     return;
6452   }//if
6453   ptrCheckGuard(regApiPtr, TapiConnectFilesize,
6454                 localApiConnectRecord);
6455 
6456   apiConnectptr = regApiPtr;
6457 
6458   UintR Tdata1 = regApiPtr.p->transid[0] - ref->transId[0];
6459   UintR Tdata2 = regApiPtr.p->transid[1] - ref->transId[1];
6460   Tdata1 = Tdata1 | Tdata2;
6461   if (Tdata1 != 0) {
6462     warningReport(signal, 28);
6463     return;
6464   }//if
6465 
6466   if (regApiPtr.p->apiConnectstate != CS_SEND_FIRE_TRIG_REQ &&
6467       regApiPtr.p->apiConnectstate != CS_WAIT_FIRE_TRIG_REQ)
6468   {
6469     jam();
6470     warningReport(signal, 28);
6471     return;
6472   }
6473 
6474   terrorCode = ref->errCode;
6475   abortErrorLab(signal);
6476 }
6477 
6478 /**
6479  * The NDB API has now reported that it has heard about the commit of
6480  * transaction, this means that we're ready to remove the commit ack
6481  * markers, both here in DBTC and in all the participating DBLQH's.
6482  */
6483 void
execTC_COMMIT_ACK(Signal * signal)6484 Dbtc::execTC_COMMIT_ACK(Signal* signal){
6485   jamEntry();
6486 
6487   CommitAckMarker key;
6488   key.transid1 = signal->theData[0];
6489   key.transid2 = signal->theData[1];
6490 
6491   CommitAckMarkerPtr removedMarker;
6492   m_commitAckMarkerHash.remove(removedMarker, key);
6493   if (removedMarker.i == RNIL) {
6494     jam();
6495     warningHandlerLab(signal, __LINE__);
6496     return;
6497   }//if
6498   sendRemoveMarkers(signal, removedMarker.p, 0);
6499   m_commitAckMarkerPool.release(removedMarker);
6500 }
6501 
6502 void
sendRemoveMarkers(Signal * signal,CommitAckMarker * marker,Uint32 removed_by_fail_api)6503 Dbtc::sendRemoveMarkers(Signal* signal,
6504                         CommitAckMarker * marker,
6505                         Uint32 removed_by_fail_api)
6506 {
6507   jam();
6508   const Uint32 transId1 = marker->transid1;
6509   const Uint32 transId2 = marker->transid2;
6510 
6511   CommitAckMarkerBuffer::DataBufferPool & pool =
6512     c_theCommitAckMarkerBufferPool;
6513   LocalDataBuffer<5> commitAckMarkers(pool, marker->theDataBuffer);
6514   CommitAckMarkerBuffer::DataBufferIterator iter;
6515   bool next_flag = commitAckMarkers.first(iter);
6516   while (next_flag)
6517   {
6518     jam();
6519     Uint32 dataWord = *iter.data;
6520     NodeId nodeId = dataWord >> 16;
6521     Uint32 instanceKey = dataWord & 0xFFFF;
6522     sendRemoveMarker(signal,
6523                      nodeId,
6524                      instanceKey,
6525                      transId1,
6526                      transId2,
6527                      removed_by_fail_api);
6528     next_flag = commitAckMarkers.next(iter, 1);
6529   }
6530   commitAckMarkers.release();
6531 }
6532 
6533 void
sendRemoveMarker(Signal * signal,NodeId nodeId,Uint32 instanceKey,Uint32 transid1,Uint32 transid2,Uint32 removed_by_fail_api)6534 Dbtc::sendRemoveMarker(Signal* signal,
6535                        NodeId nodeId,
6536                        Uint32 instanceKey,
6537                        Uint32 transid1,
6538                        Uint32 transid2,
6539                        Uint32 removed_by_fail_api){
6540   /**
6541    * Seize host ptr
6542    */
6543   HostRecordPtr hostPtr;
6544   const UintR ThostFilesize = chostFilesize;
6545   hostPtr.i = nodeId;
6546   ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
6547 
6548   Uint32 Tdata[3];
6549   Tdata[0] = removed_by_fail_api;
6550   Tdata[1] = transid1;
6551   Tdata[2] = transid2;
6552   Uint32 len = 3;
6553 
6554   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
6555     jam();
6556     // first word omitted
6557     memcpy(&signal->theData[0], &Tdata[1], (len - 1) << 2);
6558     Uint32 Tnode = hostPtr.i;
6559     BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
6560     sendSignal(ref, GSN_REMOVE_MARKER_ORD, signal, len - 1, JBB);
6561     return;
6562   }
6563 
6564   struct PackedWordsContainer * container = &hostPtr.p->lqh_pack[instanceKey];
6565 
6566   if (container->noOfPackedWords > (25 - 3)){
6567     jam();
6568     sendPackedSignal(signal, container);
6569   } else {
6570     jam();
6571     updatePackedList(signal, hostPtr.p, hostPtr.i);
6572   }
6573 
6574   UintR  numWord = container->noOfPackedWords;
6575   UintR* dataPtr = &container->packedWords[numWord];
6576 
6577   container->noOfPackedWords = numWord + len;
6578   Tdata[0] |= (ZREMOVE_MARKER << 28);
6579   memcpy(dataPtr, &Tdata[0], len << 2);
6580 }
6581 
execCOMPLETED(Signal * signal)6582 void Dbtc::execCOMPLETED(Signal* signal)
6583 {
6584   TcConnectRecordPtr localTcConnectptr;
6585   ApiConnectRecordPtr localApiConnectptr;
6586 
6587   UintR TtcConnectFilesize = ctcConnectFilesize;
6588   UintR TapiConnectFilesize = capiConnectFilesize;
6589   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6590   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6591 
6592 #ifdef ERROR_INSERT
6593   if (ERROR_INSERTED(8031)) {
6594     systemErrorLab(signal, __LINE__);
6595   }//if
6596   if (ERROR_INSERTED(8019)) {
6597     CLEAR_ERROR_INSERT_VALUE;
6598     return;
6599   }//if
6600   if (ERROR_INSERTED(8027)) {
6601     SET_ERROR_INSERT_VALUE(8028);
6602     return;
6603   }//if
6604   if (ERROR_INSERTED(8043)) {
6605     CLEAR_ERROR_INSERT_VALUE;
6606     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6607     return;
6608   }//if
6609   if (ERROR_INSERTED(8044)) {
6610     SET_ERROR_INSERT_VALUE(8047);
6611     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6612     return;
6613   }//if
6614 #endif
6615   localTcConnectptr.i = signal->theData[0];
6616   jamEntry();
6617   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6618   bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
6619   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
6620   if (Tcond1) {
6621     warningReport(signal, 6);
6622     return;
6623   }//if
6624   ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
6625 		localApiConnectRecord);
6626   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
6627   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
6628   UintR Tcounter = localApiConnectptr.p->counter - 1;
6629   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
6630   Tdata1 = Tdata1 | Tdata2;
6631   bool TcheckCondition =
6632     (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
6633   if (Tdata1 != 0) {
6634     warningReport(signal, 7);
6635     return;
6636   }//if
6637   setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
6638   localApiConnectptr.p->counter = Tcounter;
6639   localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
6640   localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
6641   if (TcheckCondition) {
6642     jam();
6643     /*-------------------------------------------------------*/
6644     // We have not sent all COMPLETE requests yet. We could be
6645     // in the state that all sent are COMPLETED but we are
6646     // still waiting for a CONTINUEB to send the rest of the
6647     // COMPLETE requests.
6648     /*-------------------------------------------------------*/
6649     return;
6650   }//if
6651   if (ERROR_INSERTED(8021)) {
6652     jam();
6653     systemErrorLab(signal, __LINE__);
6654   }//if
6655   apiConnectptr = localApiConnectptr;
6656   releaseTransResources(signal);
6657   CRASH_INSERTION(8054);
6658 }//Dbtc::execCOMPLETED()
6659 
6660 /*---------------------------------------------------------------------------*/
6661 /*                               RELEASE_TRANS_RESOURCES                     */
6662 /*       RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION.       */
6663 /*---------------------------------------------------------------------------*/
releaseTransResources(Signal * signal)6664 void Dbtc::releaseTransResources(Signal* signal)
6665 {
6666   TcConnectRecordPtr localTcConnectptr;
6667   UintR TtcConnectFilesize = ctcConnectFilesize;
6668   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6669   apiConnectptr.p->m_transaction_nodes.clear();
6670   localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
6671   do {
6672     jam();
6673     ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6674     UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
6675     tcConnectptr.i = localTcConnectptr.i;
6676     tcConnectptr.p = localTcConnectptr.p;
6677     localTcConnectptr.i = rtrTcConnectptrIndex;
6678     releaseTcCon();
6679   } while (localTcConnectptr.i != RNIL);
6680   handleGcp(signal, apiConnectptr);
6681   releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
6682   releaseAllSeizedIndexOperations(apiConnectptr.p);
6683   releaseApiConCopy(signal);
6684 }//Dbtc::releaseTransResources()
6685 
6686 /* *********************************************************************>> */
6687 /*       MODULE: HANDLE_GCP                                                */
6688 /*       DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
6689 /*       OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC   */
6690 /*       SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
6691 /*       GLOBAL CHECKPOINT HAVE COMPLETED.                                 */
6692 /* *********************************************************************>> */
handleGcp(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)6693 void Dbtc::handleGcp(Signal* signal, Ptr<ApiConnectRecord> regApiPtr)
6694 {
6695   GcpRecord *localGcpRecord = gcpRecord;
6696   GcpRecordPtr localGcpPtr;
6697   UintR TgcpFilesize = cgcpFilesize;
6698   localGcpPtr.i = apiConnectptr.p->gcpPointer;
6699   ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
6700   unlinkApiConnect(localGcpPtr, regApiPtr);
6701   if (localGcpPtr.p->firstApiConnect == RNIL) {
6702     if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
6703       if (c_ongoing_take_over_cnt == 0)
6704       {
6705         jam();
6706         gcpTcfinished(signal, localGcpPtr.p->gcpId);
6707         unlinkGcp(localGcpPtr);
6708       }
6709     }//if
6710   }
6711 }//Dbtc::handleGcp()
6712 
releaseApiConCopy(Signal * signal)6713 void Dbtc::releaseApiConCopy(Signal* signal)
6714 {
6715   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6716   ndbassert(regApiPtr->nextApiConnect == RNIL);
6717   UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
6718   cfirstfreeApiConnectCopy = apiConnectptr.i;
6719   regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
6720   setApiConTimer(apiConnectptr.i, 0, __LINE__);
6721   regApiPtr->apiConnectstate = CS_RESTART;
6722   ndbrequire(regApiPtr->commitAckMarker == RNIL);
6723 }//Dbtc::releaseApiConCopy()
6724 
6725 /* ========================================================================= */
6726 /* -------  RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
6727 /* ========================================================================= */
releaseDirtyWrite(Signal * signal)6728 void Dbtc::releaseDirtyWrite(Signal* signal)
6729 {
6730   clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
6731   unlinkReadyTcCon(signal);
6732   releaseTcCon();
6733   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6734   if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6735     if (regApiPtr->firstTcConnect == RNIL) {
6736       jam();
6737       regApiPtr->apiConnectstate = CS_CONNECTED;
6738       setApiConTimer(apiConnectptr.i, 0, __LINE__);
6739       sendtckeyconf(signal, 1);
6740     }//if
6741   }//if
6742 }//Dbtc::releaseDirtyWrite()
6743 
6744 /*****************************************************************************
6745  *                               L Q H K E Y R E F
6746  * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
6747  * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
6748  * TCROLLBACKREP WILL BE SENT TO THE API.
6749  *
6750  * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
6751  * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
6752  * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
6753  * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
6754  * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
6755  * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
6756  * "REC_LQHREFUSE",
6757  * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
6758  * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
6759  *****************************************************************************/
execLQHKEYREF(Signal * signal)6760 void Dbtc::execLQHKEYREF(Signal* signal)
6761 {
6762   const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
6763   Uint32 indexId = 0;
6764   jamEntry();
6765 
6766   UintR compare_transid1, compare_transid2;
6767   UintR TtcConnectFilesize = ctcConnectFilesize;
6768   /*-------------------------------------------------------------------------
6769    *
6770    * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
6771    * TRANSACTION PARTS ACTIVE ANYMORE.
6772    * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
6773    *-------------------------------------------------------------------------*/
6774   if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
6775     /*-----------------------------------------------------------------------
6776      * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
6777      * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
6778      * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
6779      * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
6780      * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
6781      * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
6782      * ALREADY COMPLETED (ABORTED).
6783      *-----------------------------------------------------------------------*/
6784     tcConnectptr.i = lqhKeyRef->connectPtr;
6785     Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
6786     ptrAss(tcConnectptr, tcConnectRecord);
6787     TcConnectRecord * const regTcPtr = tcConnectptr.p;
6788     if (regTcPtr->tcConnectstate == OS_OPERATING) {
6789       Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
6790       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6791       ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6792       compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
6793       compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
6794       compare_transid1 = compare_transid1 | compare_transid2;
6795       if (compare_transid1 != 0) {
6796 	warningReport(signal, 25);
6797 	return;
6798       }//if
6799 
6800       const Uint32 triggeringOp = regTcPtr->triggeringOperation;
6801       ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
6802 
6803       if (unlikely(TapiConnectstate == CS_ABORTING))
6804       {
6805         jam();
6806         goto do_abort;
6807       }
6808 
6809       if (triggeringOp != RNIL) {
6810         jam();
6811 	// This operation was created by a trigger execting operation
6812 	TcConnectRecordPtr opPtr;
6813 	TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6814 
6815         opPtr.i = triggeringOp;
6816         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
6817 
6818         const Uint32 opType = regTcPtr->operation;
6819         Ptr<TcDefinedTriggerData> trigPtr;
6820         c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
6821         switch(trigPtr.p->triggerType){
6822         case TriggerType::SECONDARY_INDEX:{
6823           jam();
6824 
6825           // The operation executed an index trigger
6826           TcIndexData* indexData = c_theIndexes.getPtr(trigPtr.p->indexId);
6827           indexId = indexData->indexId;
6828           regApiPtr->errorData = indexId;
6829           if (errCode == ZALREADYEXIST)
6830           {
6831             jam();
6832             errCode = terrorCode = ZNOTUNIQUE;
6833             goto do_abort;
6834           }
6835           else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
6836             jam();
6837             /**
6838              * "Normal path"
6839              */
6840             goto do_abort;
6841           }
6842           else
6843           {
6844             jam();
6845             /** ZDELETE && NOT_FOUND */
6846             if (indexData->indexState != IS_BUILDING)
6847             {
6848               jam();
6849               goto do_abort;
6850             }
6851           }
6852           goto do_ignore;
6853         }
6854         case TriggerType::REORG_TRIGGER:
6855           jam();
6856           if (opType == ZINSERT && errCode == ZALREADYEXIST)
6857           {
6858             jam();
6859             ndbout_c("reorg, ignore ZALREADYEXIST");
6860             goto do_ignore;
6861           }
6862           else if (errCode == ZNOT_FOUND)
6863           {
6864             jam();
6865             ndbout_c("reorg, ignore ZNOT_FOUND");
6866             goto do_ignore;
6867           }
6868           else if (errCode == 839)
6869           {
6870             jam();
6871             ndbout_c("reorg, ignore 839");
6872             goto do_ignore;
6873           }
6874           else
6875           {
6876             ndbout_c("reorg: opType: %u errCode: %u", opType, errCode);
6877           }
6878           // fall-through
6879           goto do_abort;
6880         case TriggerType::FK_CHILD:
6881           jam();
6882           if (errCode == ZNOT_FOUND)
6883           {
6884             errCode = terrorCode = ZFK_NO_PARENT_ROW_EXISTS;
6885           }
6886           goto do_abort;
6887         case TriggerType::FK_PARENT:
6888           jam();
6889           /**
6890            * on delete/update of parent...
6891            *   we found no child row...
6892            *   that means FK not violated...
6893            */
6894           if (errCode == ZNOT_FOUND)
6895           {
6896             jam();
6897             if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags))
6898             {
6899               jam();
6900               /**
6901                * execTCINDXREQ adds an extra regApiPtr->lqhkeyreqrec++
6902                *   undo this...
6903                */
6904               ndbassert(regApiPtr->lqhkeyreqrec > 0);
6905               regApiPtr->lqhkeyreqrec--;
6906             }
6907             goto do_ignore;
6908           }
6909           else
6910           {
6911             goto do_abort;
6912           }
6913         default:
6914           jam();
6915           ndbassert(false);
6916           goto do_abort;
6917         }
6918 
6919     do_ignore:
6920         jam();
6921         /**
6922          * Ignore error
6923          */
6924         regApiPtr->lqhkeyreqrec--;
6925 
6926         /**
6927          * An failing op in LQH, never leaves the commit ack marker around
6928          * TODO: This can be bug in ordinary code too!!!
6929          */
6930         clearCommitAckMarker(regApiPtr, regTcPtr);
6931 
6932         unlinkReadyTcCon(signal);
6933         releaseTcCon();
6934 
6935         trigger_op_finished(signal, apiConnectptr, RNIL, opPtr.p, 0);
6936 
6937         if (ERROR_INSERTED(8105))
6938         {
6939           abortTransFromTrigger(signal, apiConnectptr, ZGET_DATAREC_ERROR);
6940         }
6941         return;
6942       }
6943 
6944   do_abort:
6945       markOperationAborted(regApiPtr, regTcPtr);
6946 
6947       if(regApiPtr->apiConnectstate == CS_ABORTING){
6948 	/**
6949 	 * We're already aborting' so don't send an "extra" TCKEYREF
6950 	 */
6951 	jam();
6952 	return;
6953       }
6954 
6955       const Uint32 abort = regTcPtr->m_execAbortOption;
6956       if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
6957 	/**
6958 	 * No error is allowed on this operation
6959 	 */
6960 	TCKEY_abort(signal, 49);
6961 	return;
6962       }//if
6963 
6964       /* *************** */
6965       /*    TCKEYREF   < */
6966       /* *************** */
6967       TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
6968       tcKeyRef->transId[0] = regApiPtr->transid[0];
6969       tcKeyRef->transId[1] = regApiPtr->transid[1];
6970       tcKeyRef->errorCode = terrorCode;
6971       bool isIndexOp = regTcPtr->isIndexOp(regTcPtr->m_special_op_flags);
6972       Uint32 indexOp = tcConnectptr.p->indexOp;
6973       Uint32 clientData = regTcPtr->clientData;
6974       unlinkReadyTcCon(signal);   /* LINK TC CONNECT RECORD OUT OF  */
6975       releaseTcCon();       /* RELEASE THE TC CONNECT RECORD  */
6976       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6977       if (isIndexOp) {
6978         jam();
6979 	regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
6980 	tcKeyRef->connectPtr = indexOp;
6981         tcKeyRef->errorData = indexId;
6982 	EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
6983 	apiConnectptr.i = save;
6984 	apiConnectptr.p = regApiPtr;
6985       } else {
6986         jam();
6987 	tcKeyRef->connectPtr = clientData;
6988         tcKeyRef->errorData = indexId;
6989 	sendSignal(regApiPtr->ndbapiBlockref,
6990 		   GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
6991       }//if
6992 
6993       /*---------------------------------------------------------------------
6994        * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
6995        * LQHKEYREQ THAT HAVE RETURNED.
6996        * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
6997        * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
6998        *---------------------------------------------------------------------*/
6999       regApiPtr->lqhkeyreqrec--;
7000       if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
7001 	if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
7002           jam();
7003           diverify010Lab(signal);
7004 	  return;
7005 	}
7006         else if (regApiPtr->tckeyrec > 0 ||
7007                  tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG))
7008         {
7009 	  jam();
7010 	  sendtckeyconf(signal, 2);
7011 	  return;
7012 	}
7013       }//if
7014       return;
7015 
7016     } else {
7017       warningReport(signal, 26);
7018     }//if
7019   } else {
7020     errorReport(signal, 6);
7021   }//if
7022   return;
7023 }//Dbtc::execLQHKEYREF()
7024 
clearCommitAckMarker(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)7025 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
7026 				TcConnectRecord * const regTcPtr)
7027 {
7028   jam();
7029   const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
7030   if (regApiPtr->commitAckMarker == RNIL)
7031   {
7032     jam();
7033     ndbassert(commitAckMarker == RNIL);
7034   }
7035 
7036   if(commitAckMarker != RNIL)
7037   {
7038     jam();
7039     ndbrequire(regApiPtr->commitAckMarker == commitAckMarker);
7040     ndbrequire(regApiPtr->num_commit_ack_markers > 0);
7041     regApiPtr->num_commit_ack_markers--;
7042     regTcPtr->commitAckMarker = RNIL;
7043     if (regApiPtr->num_commit_ack_markers == 0)
7044     {
7045       jam();
7046       tc_clearbit(regApiPtr->m_flags,
7047                   ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
7048       releaseMarker(regApiPtr);
7049     }
7050   }
7051 }
7052 
markOperationAborted(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)7053 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
7054 				TcConnectRecord * const regTcPtr)
7055 {
7056   /*------------------------------------------------------------------------
7057    * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
7058    * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
7059    * ALREADY COMPLETED.
7060    *------------------------------------------------------------------------*/
7061   regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
7062   regTcPtr->tcConnectstate = OS_ABORTING;
7063   clearCommitAckMarker(regApiPtr, regTcPtr);
7064 }
7065 
7066 /*--------------------------------------*/
7067 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ  */
7068 /* OR TCROLLBACKREQ FROM THE USER TO    */
7069 /* CONTINUE THE TRANSACTION             */
7070 /*--------------------------------------*/
execTC_COMMITREQ(Signal * signal)7071 void Dbtc::execTC_COMMITREQ(Signal* signal)
7072 {
7073   UintR compare_transid1, compare_transid2;
7074 
7075   jamEntry();
7076   apiConnectptr.i = signal->theData[0];
7077   if (apiConnectptr.i < capiConnectFilesize) {
7078     ptrAss(apiConnectptr, apiConnectRecord);
7079     compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
7080     compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
7081     compare_transid1 = compare_transid1 | compare_transid2;
7082     if (compare_transid1 != 0) {
7083       jam();
7084       return;
7085     }//if
7086 
7087     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
7088 
7089     const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
7090     const Uint32 apiBlockRef   = regApiPtr->ndbapiBlockref;
7091     const Uint32 transId1      = regApiPtr->transid[0];
7092     const Uint32 transId2      = regApiPtr->transid[1];
7093     Uint32 errorCode           = 0;
7094 
7095     regApiPtr->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
7096     switch (regApiPtr->apiConnectstate) {
7097     case CS_STARTED:
7098       tcConnectptr.i = regApiPtr->firstTcConnect;
7099       if (tcConnectptr.i != RNIL) {
7100         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7101         if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
7102           jam();
7103           /*******************************************************************/
7104           // The proper case where the application is waiting for commit or
7105           // abort order.
7106           // Start the commit order.
7107           /*******************************************************************/
7108           regApiPtr->returnsignal = RS_TC_COMMITCONF;
7109           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7110           diverify010Lab(signal);
7111           return;
7112         } else {
7113           jam();
7114           /*******************************************************************/
7115           // The transaction is started but not all operations are completed.
7116           // It is not possible to commit the transaction in this state.
7117           // We will abort it instead.
7118           /*******************************************************************/
7119           regApiPtr->returnsignal = RS_NO_RETURN;
7120           errorCode = ZTRANS_STATUS_ERROR;
7121           abort010Lab(signal);
7122         }//if
7123       } else {
7124         jam();
7125         /**
7126          * No operations, accept commit
7127          */
7128         TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
7129         commitConf->apiConnectPtr = apiConnectPtr;
7130         commitConf->transId1 = transId1;
7131         commitConf->transId2 = transId2;
7132         commitConf->gci_hi = 0;
7133         commitConf->gci_lo = 0;
7134         sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
7135 		   TcCommitConf::SignalLength, JBB);
7136 
7137         regApiPtr->returnsignal = RS_NO_RETURN;
7138         releaseAbortResources(signal);
7139         return;
7140       }//if
7141       break;
7142     case CS_RECEIVING:
7143       jam();
7144       /***********************************************************************/
7145       // A transaction is still receiving data. We cannot commit an unfinished
7146       // transaction. We will abort it instead.
7147       /***********************************************************************/
7148       regApiPtr->returnsignal = RS_NO_RETURN;
7149       errorCode = ZPREPAREINPROGRESS;
7150       abort010Lab(signal);
7151       break;
7152 
7153     case CS_START_COMMITTING:
7154     case CS_COMMITTING:
7155     case CS_COMMIT_SENT:
7156     case CS_COMPLETING:
7157     case CS_COMPLETE_SENT:
7158     case CS_REC_COMMITTING:
7159     case CS_PREPARE_TO_COMMIT:
7160       jam();
7161       /***********************************************************************/
7162       // The transaction is already performing a commit but it is not concluded
7163       // yet.
7164       /***********************************************************************/
7165       errorCode = ZCOMMITINPROGRESS;
7166       break;
7167     case CS_ABORTING:
7168       jam();
7169       errorCode = regApiPtr->returncode ?
7170 	regApiPtr->returncode : ZABORTINPROGRESS;
7171       break;
7172     case CS_START_SCAN:
7173       jam();
7174       /***********************************************************************/
7175       // The transaction is a scan. Scans cannot commit
7176       /***********************************************************************/
7177       errorCode = ZSCANINPROGRESS;
7178       break;
7179     default:
7180       warningHandlerLab(signal, __LINE__);
7181       return;
7182     }//switch
7183     TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
7184     commitRef->apiConnectPtr = apiConnectPtr;
7185     commitRef->transId1 = transId1;
7186     commitRef->transId2 = transId2;
7187     commitRef->errorCode = errorCode;
7188     sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
7189 	       TcCommitRef::SignalLength, JBB);
7190     return;
7191   } else /** apiConnectptr.i < capiConnectFilesize */ {
7192     jam();
7193     warningHandlerLab(signal, __LINE__);
7194     return;
7195   }
7196 }//Dbtc::execTC_COMMITREQ()
7197 
7198 /**
7199  * TCROLLBACKREQ
7200  *
7201  * Format is:
7202  *
7203  * thedata[0] = apiconnectptr
7204  * thedata[1] = transid[0]
7205  * thedata[2] = transid[1]
7206  * OPTIONAL thedata[3] = flags
7207  *
7208  * Flags:
7209  *    0x1  =  potentiallyBad data from API (try not to assert)
7210  */
execTCROLLBACKREQ(Signal * signal)7211 void Dbtc::execTCROLLBACKREQ(Signal* signal)
7212 {
7213   bool potentiallyBad= false;
7214   UintR compare_transid1, compare_transid2;
7215 
7216   jamEntry();
7217 
7218   if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
7219   {
7220     ndbout_c("Trying to roll back potentially bad txn\n");
7221     potentiallyBad= true;
7222   }
7223 
7224   apiConnectptr.i = signal->theData[0];
7225   if (apiConnectptr.i >= capiConnectFilesize) {
7226     goto TC_ROLL_warning;
7227   }//if
7228   ptrAss(apiConnectptr, apiConnectRecord);
7229   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
7230   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
7231   compare_transid1 = compare_transid1 | compare_transid2;
7232   if (compare_transid1 != 0) {
7233     jam();
7234     return;
7235   }//if
7236 
7237   apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
7238   switch (apiConnectptr.p->apiConnectstate) {
7239   case CS_STARTED:
7240   case CS_RECEIVING:
7241     jam();
7242     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
7243     abort010Lab(signal);
7244     return;
7245   case CS_CONNECTED:
7246     jam();
7247     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
7248     signal->theData[1] = apiConnectptr.p->transid[0];
7249     signal->theData[2] = apiConnectptr.p->transid[1];
7250     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
7251 	       signal, 3, JBB);
7252     break;
7253   case CS_START_SCAN:
7254   case CS_PREPARE_TO_COMMIT:
7255   case CS_COMMITTING:
7256   case CS_COMMIT_SENT:
7257   case CS_COMPLETING:
7258   case CS_COMPLETE_SENT:
7259   case CS_WAIT_COMMIT_CONF:
7260   case CS_WAIT_COMPLETE_CONF:
7261   case CS_RESTART:
7262   case CS_DISCONNECTED:
7263   case CS_START_COMMITTING:
7264   case CS_REC_COMMITTING:
7265     jam();
7266     /* ***************< */
7267     /* TC_ROLLBACKREF < */
7268     /* ***************< */
7269     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
7270     signal->theData[1] = apiConnectptr.p->transid[0];
7271     signal->theData[2] = apiConnectptr.p->transid[1];
7272     signal->theData[3] = ZROLLBACKNOTALLOWED;
7273     signal->theData[4] = apiConnectptr.p->apiConnectstate;
7274     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
7275 	       signal, 5, JBB);
7276     break;
7277                                                  /* SEND A REFUSAL SIGNAL*/
7278   case CS_ABORTING:
7279     jam();
7280     if (apiConnectptr.p->abortState == AS_IDLE) {
7281       jam();
7282       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
7283       signal->theData[1] = apiConnectptr.p->transid[0];
7284       signal->theData[2] = apiConnectptr.p->transid[1];
7285       sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
7286 		 signal, 3, JBB);
7287     } else {
7288       jam();
7289       apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
7290     }//if
7291     break;
7292   case CS_WAIT_ABORT_CONF:
7293     jam();
7294     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
7295     break;
7296   default:
7297     goto TC_ROLL_system_error;
7298     break;
7299   }//switch
7300   return;
7301 
7302 TC_ROLL_warning:
7303   jam();
7304   if(likely(potentiallyBad==false))
7305     warningHandlerLab(signal, __LINE__);
7306   return;
7307 
7308 TC_ROLL_system_error:
7309   jam();
7310   if(likely(potentiallyBad==false))
7311     systemErrorLab(signal, __LINE__);
7312   return;
7313 }//Dbtc::execTCROLLBACKREQ()
7314 
execTC_HBREP(Signal * signal)7315 void Dbtc::execTC_HBREP(Signal* signal)
7316 {
7317   const TcHbRep * const tcHbRep =
7318     (TcHbRep *)signal->getDataPtr();
7319 
7320   jamEntry();
7321   apiConnectptr.i = tcHbRep->apiConnectPtr;
7322   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7323 
7324   if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
7325       apiConnectptr.p->transid[1] == tcHbRep->transId2){
7326 
7327     if (getApiConTimer(apiConnectptr.i) != 0){
7328       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7329     } else {
7330       DEBUG("TCHBREP received when timer was off apiConnectptr.i="
7331 	    << apiConnectptr.i);
7332     }
7333   }
7334 }//Dbtc::execTCHBREP()
7335 
7336 /*
7337 4.3.15 ABORT
7338 -----------
7339 */
7340 /*****************************************************************************/
7341 /*                                  A B O R T                                */
7342 /*                                                                           */
7343 /*****************************************************************************/
warningReport(Signal * signal,int place)7344 void Dbtc::warningReport(Signal* signal, int place)
7345 {
7346   switch (place) {
7347   case 0:
7348     jam();
7349 #ifdef ABORT_TRACE
7350     ndbout << "ABORTED to not active TC record" << endl;
7351 #endif
7352     break;
7353   case 1:
7354     jam();
7355 #ifdef ABORT_TRACE
7356     ndbout << "ABORTED to TC record active with new transaction" << endl;
7357 #endif
7358     break;
7359   case 2:
7360     jam();
7361 #ifdef ABORT_TRACE
7362     ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
7363 #endif
7364     break;
7365   case 3:
7366     jam();
7367 #ifdef ABORT_TRACE
7368     ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
7369     ndbout << "This is ok when aborting in node failure situations" << endl;
7370 #endif
7371     break;
7372   case 4:
7373     jam();
7374 #ifdef ABORT_TRACE
7375     ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
7376 #endif
7377     break;
7378   case 5:
7379     jam();
7380 #ifdef ABORT_TRACE
7381     ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
7382 #endif
7383     break;
7384   case 6:
7385     jam();
7386 #ifdef ABORT_TRACE
7387     ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
7388 #endif
7389     break;
7390   case 7:
7391     jam();
7392 #ifdef ABORT_TRACE
7393     ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
7394 #endif
7395     break;
7396   case 8:
7397     jam();
7398 #ifdef ABORT_TRACE
7399     ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
7400 #endif
7401     break;
7402   case 9:
7403     jam();
7404 #ifdef ABORT_TRACE
7405     ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
7406 #endif
7407     break;
7408   case 10:
7409     jam();
7410 #ifdef ABORT_TRACE
7411     ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
7412 #endif
7413     break;
7414   case 11:
7415     jam();
7416 #ifdef ABORT_TRACE
7417     ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
7418 #endif
7419     break;
7420   case 12:
7421     jam();
7422 #ifdef ABORT_TRACE
7423     ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
7424 #endif
7425     break;
7426   case 13:
7427     jam();
7428 #ifdef ABORT_TRACE
7429     ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
7430 #endif
7431     break;
7432   case 14:
7433     jam();
7434 #ifdef ABORT_TRACE
7435     ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
7436 #endif
7437     break;
7438   case 15:
7439     jam();
7440 #ifdef ABORT_TRACE
7441     ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
7442 #endif
7443     break;
7444   case 16:
7445     jam();
7446 #ifdef ABORT_TRACE
7447     ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
7448 #endif
7449     break;
7450   case 17:
7451     jam();
7452 #ifdef ABORT_TRACE
7453     ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
7454 #endif
7455     break;
7456   case 18:
7457     jam();
7458 #ifdef ABORT_TRACE
7459     ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
7460 #endif
7461     break;
7462   case 19:
7463     jam();
7464 #ifdef ABORT_TRACE
7465     ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
7466 #endif
7467     break;
7468   case 20:
7469     jam();
7470 #ifdef ABORT_TRACE
7471     ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
7472 #endif
7473     break;
7474   case 21:
7475     jam();
7476 #ifdef ABORT_TRACE
7477     ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
7478 #endif
7479     break;
7480   case 22:
7481     jam();
7482 #ifdef ABORT_TRACE
7483     ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
7484 #endif
7485     break;
7486   case 23:
7487     jam();
7488 #ifdef ABORT_TRACE
7489     ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
7490 #endif
7491     break;
7492   case 24:
7493     jam();
7494 #ifdef ABORT_TRACE
7495     ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
7496 #endif
7497     break;
7498   case 25:
7499     jam();
7500 #ifdef ABORT_TRACE
7501     ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
7502 #endif
7503     break;
7504   case 26:
7505     jam();
7506 #ifdef ABORT_TRACE
7507     ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
7508 #endif
7509     break;
7510   case 27:
7511     jam();
7512     // printState(signal, 27);
7513 #ifdef ABORT_TRACE
7514     ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
7515 #endif
7516     break;
7517   case 28:
7518     jam();
7519 #ifdef ABORT_TRACE
7520     ndbout << "Discarding FIRE_TRIG_REF/CONF in Dbtc" << endl;
7521 #endif
7522     break;
7523   case 29:
7524     jam();
7525 #ifdef ABORT_TRACE
7526     ndbout << "Discarding TcContinueB::ZSEND_FIRE_TRIG_REQ in Dbtc" << endl;
7527 #endif
7528     break;
7529   default:
7530     jam();
7531     break;
7532   }//switch
7533   return;
7534 }//Dbtc::warningReport()
7535 
errorReport(Signal * signal,int place)7536 void Dbtc::errorReport(Signal* signal, int place)
7537 {
7538   switch (place) {
7539   case 0:
7540     jam();
7541     break;
7542   case 1:
7543     jam();
7544     break;
7545   case 2:
7546     jam();
7547     break;
7548   case 3:
7549     jam();
7550     break;
7551   case 4:
7552     jam();
7553     break;
7554   case 5:
7555     jam();
7556     break;
7557   case 6:
7558     jam();
7559     break;
7560   default:
7561     jam();
7562     break;
7563   }//switch
7564   systemErrorLab(signal, __LINE__);
7565   return;
7566 }//Dbtc::errorReport()
7567 
7568 /* ------------------------------------------------------------------------- */
7569 /* -------                       ENTER ABORTED                       ------- */
7570 /*                                                                           */
7571 /*-------------------------------------------------------------------------- */
execABORTED(Signal * signal)7572 void Dbtc::execABORTED(Signal* signal)
7573 {
7574   UintR compare_transid1, compare_transid2;
7575 
7576   jamEntry();
7577   tcConnectptr.i = signal->theData[0];
7578   UintR Tnodeid = signal->theData[3];
7579   UintR TlastLqhInd = signal->theData[4];
7580 
7581   if (ERROR_INSERTED(8040)) {
7582     CLEAR_ERROR_INSERT_VALUE;
7583     sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
7584     return;
7585   }//if
7586   /*------------------------------------------------------------------------
7587    *    ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
7588    *------------------------------------------------------------------------*/
7589   if (tcConnectptr.i >= ctcConnectFilesize) {
7590     errorReport(signal, 0);
7591     return;
7592   }//if
7593   /*-------------------------------------------------------------------------
7594    *     WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
7595    *     TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
7596    *     IN TC WAITING FOR ABORTED.
7597    *-------------------------------------------------------------------------*/
7598   ptrAss(tcConnectptr, tcConnectRecord);
7599   if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
7600     warningReport(signal, 2);
7601     return;
7602     /*-----------------------------------------------------------------------*/
7603     // ABORTED reported on an operation not expecting ABORT.
7604     /*-----------------------------------------------------------------------*/
7605   }//if
7606   apiConnectptr.i = tcConnectptr.p->apiConnect;
7607   if (apiConnectptr.i >= capiConnectFilesize) {
7608     warningReport(signal, 0);
7609     return;
7610   }//if
7611   ptrAss(apiConnectptr, apiConnectRecord);
7612   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
7613   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
7614   compare_transid1 = compare_transid1 | compare_transid2;
7615   if (compare_transid1 != 0) {
7616     warningReport(signal, 1);
7617     return;
7618   }//if
7619   if (ERROR_INSERTED(8024)) {
7620     jam();
7621     systemErrorLab(signal, __LINE__);
7622   }//if
7623 
7624   /**
7625    * Release marker
7626    */
7627   clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
7628 
7629   Uint32 i;
7630   Uint32 Tfound = 0;
7631   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7632     jam();
7633     if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
7634       /*---------------------------------------------------------------------
7635        * We have received ABORTED from one of the participants in this
7636        * operation in this aborted transaction.
7637        * Record all nodes that have completed abort.
7638        * If last indicator is set it means that no more replica has
7639        * heard of the operation and are thus also aborted.
7640        *---------------------------------------------------------------------*/
7641       jam();
7642       Tfound = 1;
7643       clearTcNodeData(signal, TlastLqhInd, i);
7644     }//if
7645   }//for
7646   if (Tfound == 0) {
7647     warningReport(signal, 3);
7648     return;
7649   }
7650   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7651     if (tcConnectptr.p->tcNodedata[i] != 0) {
7652       /*--------------------------------------------------------------------
7653        * There are still outstanding ABORTED's to wait for.
7654        *--------------------------------------------------------------------*/
7655       jam();
7656       return;
7657     }//if
7658   }//for
7659   tcConnectptr.p->noOfNodes = 0;
7660   tcConnectptr.p->tcConnectstate = OS_ABORTING;
7661   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7662   apiConnectptr.p->counter--;
7663   if (apiConnectptr.p->counter > 0) {
7664     jam();
7665     /*----------------------------------------------------------------------
7666      *       WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
7667      *----------------------------------------------------------------------*/
7668     return;
7669   }//if
7670   /*------------------------------------------------------------------------*/
7671   /*                                                                        */
7672   /*     WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED  */
7673   /*     FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL   */
7674   /*     RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
7675   /*------------------------------------------------------------------------*/
7676   releaseAbortResources(signal);
7677 }//Dbtc::execABORTED()
7678 
clearTcNodeData(Signal * signal,UintR TLastLqhIndicator,UintR Tstart)7679 void Dbtc::clearTcNodeData(Signal* signal,
7680                            UintR TLastLqhIndicator,
7681                            UintR Tstart)
7682 {
7683   UintR Ti;
7684   if (TLastLqhIndicator == ZTRUE) {
7685     for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7686       jam();
7687       tcConnectptr.p->tcNodedata[Ti] = 0;
7688     }//for
7689   } else {
7690     jam();
7691     tcConnectptr.p->tcNodedata[Tstart] = 0;
7692   }//for
7693 }//clearTcNodeData()
7694 
abortErrorLab(Signal * signal)7695 void Dbtc::abortErrorLab(Signal* signal)
7696 {
7697   ptrGuard(apiConnectptr);
7698   ApiConnectRecord * transP = apiConnectptr.p;
7699   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7700     jam();
7701     return;
7702   }
7703   transP->returnsignal = RS_TCROLLBACKREP;
7704   if(transP->returncode == 0){
7705     jam();
7706     transP->returncode = terrorCode;
7707   }
7708   abort010Lab(signal);
7709 }//Dbtc::abortErrorLab()
7710 
abort010Lab(Signal * signal)7711 void Dbtc::abort010Lab(Signal* signal)
7712 {
7713   ApiConnectRecord * transP = apiConnectptr.p;
7714   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7715     jam();
7716     return;
7717   }
7718   transP->apiConnectstate = CS_ABORTING;
7719   /*------------------------------------------------------------------------*/
7720   /*     AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
7721   /*     ALL PARTICIPANTS IN THE TRANSACTION.                               */
7722   /*------------------------------------------------------------------------*/
7723   transP->abortState = AS_ACTIVE;
7724   transP->counter = 0;
7725 
7726   if (transP->firstTcConnect == RNIL) {
7727     jam();
7728     /*--------------------------------------------------------------------*/
7729     /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION.                        */
7730     /*--------------------------------------------------------------------*/
7731     releaseAbortResources(signal);
7732     return;
7733   }//if
7734   tcConnectptr.i = transP->firstTcConnect;
7735   abort015Lab(signal);
7736 }//Dbtc::abort010Lab()
7737 
7738 /*--------------------------------------------------------------------------*/
7739 /*                                                                          */
7740 /*       WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP    */
7741 /*       ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE.        */
7742 /*       EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE   */
7743 /*       MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES    */
7744 /*       NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
7745 /*       WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
7746 /*--------------------------------------------------------------------------*/
abort015Lab(Signal * signal)7747 void Dbtc::abort015Lab(Signal* signal)
7748 {
7749   Uint32 TloopCount = 0;
7750 ABORT020:
7751   jam();
7752   TloopCount++;
7753   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7754   switch (tcConnectptr.p->tcConnectstate) {
7755   case OS_WAIT_DIH:
7756   case OS_WAIT_KEYINFO:
7757   case OS_WAIT_ATTR:
7758     jam();
7759     /*----------------------------------------------------------------------*/
7760     /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
7761     /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING.              */
7762     /*----------------------------------------------------------------------*/
7763     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7764     tcConnectptr.p->tcConnectstate = OS_ABORTING;
7765     break;
7766   case OS_CONNECTED:
7767     jam();
7768     /*-----------------------------------------------------------------------
7769      *   WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
7770      *   NEED NOT BOTHER ABOUT ANY LQH ABORTS.
7771      *-----------------------------------------------------------------------*/
7772     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7773     tcConnectptr.p->tcConnectstate = OS_ABORTING;
7774     break;
7775   case OS_PREPARED:
7776     jam();
7777   case OS_OPERATING:
7778     jam();
7779   case OS_FIRE_TRIG_REQ:
7780     jam();
7781     /*----------------------------------------------------------------------
7782      * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
7783      * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
7784      * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
7785      *----------------------------------------------------------------------*/
7786     releaseAndAbort(signal);
7787     tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
7788     TloopCount += 127;
7789     break;
7790   case OS_ABORTING:
7791     jam();
7792     break;
7793   case OS_ABORT_SENT:
7794     jam();
7795     DEBUG("ABORT_SENT state in abort015Lab(), not expected");
7796     systemErrorLab(signal, __LINE__);
7797     return;
7798   default:
7799     jam();
7800     DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
7801     systemErrorLab(signal, __LINE__);
7802     return;
7803   }//switch
7804 
7805   if (tcConnectptr.p->nextTcConnect != RNIL) {
7806     jam();
7807     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7808     if (TloopCount < 1024 &&
7809         !ERROR_INSERTED(8089) &&
7810         !ERROR_INSERTED(8105))
7811     {
7812       goto ABORT020;
7813     }
7814     else
7815     {
7816       jam();
7817       /*---------------------------------------------------------------------
7818        * Reset timer to avoid time-out in real-time break.
7819        * Increase counter to ensure that we don't think that all ABORTED have
7820        * been received before all have been sent.
7821        *---------------------------------------------------------------------*/
7822       apiConnectptr.p->counter++;
7823       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7824       signal->theData[0] = TcContinueB::ZABORT_BREAK;
7825       signal->theData[1] = tcConnectptr.i;
7826       signal->theData[2] = apiConnectptr.i;
7827       signal->theData[3] = apiConnectptr.p->transid[0];
7828       signal->theData[4] = apiConnectptr.p->transid[1];
7829       if (ERROR_INSERTED(8089))
7830       {
7831         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
7832         return;
7833       }
7834       sendSignal(cownref, GSN_CONTINUEB, signal, 5, JBB);
7835       return;
7836     }//if
7837   }//if
7838 
7839   if (ERROR_INSERTED(8089))
7840   {
7841     CLEAR_ERROR_INSERT_VALUE;
7842   }
7843 
7844   if (apiConnectptr.p->counter > 0) {
7845     jam();
7846     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7847     return;
7848   }//if
7849   /*-----------------------------------------------------------------------
7850    *    WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
7851    *    FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
7852    *    RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
7853    *------------------------------------------------------------------------*/
7854   releaseAbortResources(signal);
7855 }//Dbtc::abort015Lab()
7856 
7857 /*--------------------------------------------------------------------------*/
7858 /*       RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK.  */
7859 /*--------------------------------------------------------------------------*/
releaseAndAbort(Signal * signal)7860 int Dbtc::releaseAndAbort(Signal* signal)
7861 {
7862   HostRecordPtr localHostptr;
7863   UintR TnoLoops = tcConnectptr.p->noOfNodes;
7864 
7865   apiConnectptr.p->counter++;
7866   bool prevAlive = false;
7867   for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
7868     localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
7869     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
7870     if (localHostptr.p->hostStatus == HS_ALIVE) {
7871       jam();
7872       if (prevAlive) {
7873         // if previous is alive, its LQH forwards abort to this node
7874         jam();
7875         continue;
7876       }
7877       /* ************< */
7878       /*    ABORT    < */
7879       /* ************< */
7880       Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7881       tblockref = numberToRef(DBLQH, instanceKey, localHostptr.i);
7882       signal->theData[0] = tcConnectptr.i;
7883       signal->theData[1] = cownref;
7884       signal->theData[2] = apiConnectptr.p->transid[0];
7885       signal->theData[3] = apiConnectptr.p->transid[1];
7886       sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
7887       prevAlive = true;
7888     } else {
7889       jam();
7890       signal->theData[0] = tcConnectptr.i;
7891       signal->theData[1] = apiConnectptr.p->transid[0];
7892       signal->theData[2] = apiConnectptr.p->transid[1];
7893       signal->theData[3] = localHostptr.i;
7894       signal->theData[4] = ZFALSE;
7895       sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7896       prevAlive = false;
7897     }//if
7898   }//for
7899   return 1;
7900 }//Dbtc::releaseAndAbort()
7901 
7902 /* ------------------------------------------------------------------------- */
7903 /* -------                       ENTER TIME_SIGNAL                   ------- */
7904 /*                                                                           */
7905 /* ------------------------------------------------------------------------- */
execTIME_SIGNAL(Signal * signal)7906 void Dbtc::execTIME_SIGNAL(Signal* signal)
7907 {
7908   jamEntry();
7909 
7910   const NDB_TICKS currentTime = NdbTick_getCurrentTicks();
7911   Uint64 num_ms_elapsed = elapsed_time(signal,
7912                                        currentTime,
7913                                        c_latestTIME_SIGNAL,
7914                                        Uint32(TC_TIME_SIGNAL_DELAY));
7915   sendTIME_SIGNAL(signal, currentTime, Uint32(TC_TIME_SIGNAL_DELAY));
7916 
7917   /**
7918    * The code here will make calls to timer_handling that appears to happen
7919    * every 10ms but in reality they come in batches of up to 10 10ms
7920    * intervals. The timer_handling will check if a new scan of PK timeouts
7921    * is to start, this happens after an idle check period of 500ms. So
7922    * we actually need only check this a divisor of 500 ms and 400ms. 400ms
7923    * is how long we are idle between scans to check for scan timeouts.
7924    * The reason to separate those is to make sure that they don't run
7925    * at the same time as much.
7926    *
7927    * One reason to run the updates of the timer_handling as often as once
7928    * per 50ms is that it is also then that we update the timer that is used
7929    * to check for timeouts on transaction. So 50ms is the granularity of
7930    * when we see timeouts.
7931    *
7932    * The reason for keeping the 10ms appearance of timer_handling is to
7933    * decrease changes in this part of the code. This could be changed
7934    * in the future.
7935    */
7936   c_elapsed_time_millis += num_ms_elapsed;
7937   while (c_elapsed_time_millis > Uint64(10))
7938   {
7939     jam();
7940     c_elapsed_time_millis -= Uint64(10);
7941     timer_handling(signal);
7942   }
7943 }//execTIME_SIGNAL()
7944 
timer_handling(Signal * signal)7945 void Dbtc::timer_handling(Signal *signal)
7946 {
7947   ctcTimer++;
7948   checkStartTimeout(signal);
7949   checkStartFragTimeout(signal);
7950 }
7951 
7952 /*------------------------------------------------*/
7953 /* Start timeout handling if not already going on */
7954 /*------------------------------------------------*/
checkStartTimeout(Signal * signal)7955 void Dbtc::checkStartTimeout(Signal* signal)
7956 {
7957   ctimeOutCheckCounter++;
7958   if (ctimeOutCheckActive == TOCS_TRUE) {
7959     jam();
7960     // Check heartbeat of timeout loop
7961     if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
7962       jam();
7963       ctimeOutMissedHeartbeats = 0;
7964     }else{
7965       jam();
7966       /**
7967        * This code simply checks that the scan for PK timeouts haven't
7968        * lost itself, a sort of watchdog for that code. If that would
7969        * occur we would no longer have any timeout handling of
7970        * transactions which would render the system useless. This is
7971        * to protect ourselves for future bugs in the code that we
7972        * might introduce by mistake.
7973        *
7974        * 100 is simply an arbitrary number that needs to be bigger
7975        * than the maximum number of calls to timer_handling that
7976        * we can have in one call to execTIME_SIGNAL. This is
7977        * currently 10 but could change in the future.
7978        */
7979       ctimeOutMissedHeartbeats++;
7980       if (ctimeOutMissedHeartbeats > 100){
7981 	jam();
7982 	systemErrorLab(signal, __LINE__);
7983       }
7984     }
7985     ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
7986     return;
7987   }//if
7988   if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
7989     jam();
7990     /*------------------------------------------------------------------*/
7991     /*                                                                  */
7992     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
7993     /*------------------------------------------------------------------*/
7994     return;
7995   }//if
7996   ctimeOutCheckActive = TOCS_TRUE;
7997   ctimeOutCheckCounter = 0;
7998   ctimeOutMissedHeartbeats = 0;
7999   timeOutLoopStartLab(signal, 0); // 0 is first api connect record
8000   return;
8001 }//checkStartTimeout()
8002 
8003 /*----------------------------------------------------------------*/
8004 /* Start fragment (scan) timeout handling if not already going on */
8005 /*----------------------------------------------------------------*/
checkStartFragTimeout(Signal * signal)8006 void Dbtc::checkStartFragTimeout(Signal* signal)
8007 {
8008   ctimeOutCheckFragCounter++;
8009   if (ctimeOutCheckFragActive == TOCS_TRUE) {
8010     jam();
8011     // Check heartbeat of scan timeout loop
8012     if(ctimeOutCheckHeartbeatScan > ctimeOutCheckLastHeartbeatScan)
8013     {
8014       jam();
8015       ctimeOutMissedHeartbeatsScan = 0;
8016     }
8017     else
8018     {
8019       /**
8020        * Exactly the same code as for PK timeouts, but here to check the
8021        * scan for scan timeouts. Same comments apply as above.
8022        */
8023       jam();
8024       ctimeOutMissedHeartbeatsScan++;
8025       if (ctimeOutMissedHeartbeatsScan > 100){
8026 	jam();
8027 	systemErrorLab(signal, __LINE__);
8028       }
8029     }
8030     ctimeOutCheckLastHeartbeatScan = ctimeOutCheckHeartbeatScan;
8031     return;
8032   }//if
8033   if (ctimeOutCheckFragCounter < ctimeOutCheckDelayScan) {
8034     jam();
8035     /*------------------------------------------------------------------*/
8036     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
8037     /*------------------------------------------------------------------*/
8038     return;
8039   }//if
8040 
8041   // Go through the fragment records and look for timeout in a scan.
8042   ctimeOutCheckFragActive = TOCS_TRUE;
8043   ctimeOutCheckFragCounter = 0;
8044   ctimeOutMissedHeartbeatsScan = 0;
8045   timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
8046 }//checkStartFragTimeout()
8047 
8048 /*------------------------------------------------------------------*/
8049 /*       IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE      */
8050 /*       BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM     */
8051 /*       SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM  */
8052 /*       THE WAITING PART OF A PROTOCOL.                            */
8053 /*
8054 The algorithm used here is to check 1024 transactions at a time before
8055 doing a real-time break.
8056 To avoid aborting both transactions in a deadlock detected by time-out
8057 we insert a random extra time-out of upto 630 ms by using the lowest
8058 six bits of the api connect reference.
8059 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
8060 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
8061 and otherwise we spread it out 310 ms.
8062 */
8063 /*------------------------------------------------------------------*/
timeOutLoopStartLab(Signal * signal,Uint32 api_con_ptr)8064 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
8065 {
8066   Uint32 end_ptr, time_passed, time_out_value, mask_value;
8067   Uint32 old_mask_value= 0;
8068   const Uint32 api_con_sz= capiConnectFilesize;
8069   const Uint32 tc_timer= ctcTimer;
8070   const Uint32 time_out_param= ctimeOutValue;
8071   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
8072 
8073   ctimeOutCheckHeartbeat = tc_timer;
8074 
8075   if (api_con_ptr + 1024 < api_con_sz) {
8076     jam();
8077     end_ptr= api_con_ptr + 1024;
8078   } else {
8079     jam();
8080     end_ptr= api_con_sz;
8081   }
8082   if (time_out_param > 300) {
8083     jam();
8084     mask_value= 63;
8085   } else if (time_out_param < 30) {
8086     jam();
8087     mask_value= 7;
8088   } else {
8089     jam();
8090     mask_value= 31;
8091   }
8092   if (time_out_param != old_time_out_param &&
8093       getNodeState().getSingleUserMode())
8094   {
8095     // abort during single user mode, use old_mask_value as flag
8096     // and calculate value to be used for connections with allowed api
8097     if (old_time_out_param > 300) {
8098       jam();
8099       old_mask_value= 63;
8100     } else if (old_time_out_param < 30) {
8101       jam();
8102       old_mask_value= 7;
8103     } else {
8104       jam();
8105       old_mask_value= 31;
8106     }
8107   }
8108   for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
8109     Uint32 api_timer= getApiConTimer(api_con_ptr);
8110     if (api_timer != 0) {
8111       jam();
8112       jamLine(api_con_ptr & 0xFFFF);
8113       Uint32 error= ZTIME_OUT_ERROR;
8114       time_out_value= time_out_param + (ndb_rand() & mask_value);
8115       if (unlikely(old_mask_value)) // abort during single user mode
8116       {
8117         apiConnectptr.i = api_con_ptr;
8118         ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8119         if ((getNodeState().getSingleUserApi() ==
8120              refToNode(apiConnectptr.p->ndbapiBlockref)) ||
8121             !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
8122         {
8123           // api allowed during single user, use original timeout
8124           time_out_value=
8125             old_time_out_param + (api_con_ptr & old_mask_value);
8126         }
8127         else
8128         {
8129           error= ZCLUSTER_IN_SINGLEUSER_MODE;
8130         }
8131       }
8132       time_passed= tc_timer - api_timer;
8133       if (time_passed > time_out_value)
8134       {
8135         jam();
8136         timeOutFoundLab(signal, api_con_ptr, error);
8137 	api_con_ptr++;
8138 	break;
8139       }
8140     }
8141   }
8142   if (api_con_ptr == api_con_sz) {
8143     jam();
8144     /*------------------------------------------------------------------*/
8145     /*                                                                  */
8146     /*       WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
8147     /*       STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW    */
8148     /*       READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK.            */
8149     /*------------------------------------------------------------------*/
8150     ctimeOutCheckActive = TOCS_FALSE;
8151   } else {
8152     jam();
8153     sendContinueTimeOutControl(signal, api_con_ptr);
8154   }
8155   return;
8156 }//Dbtc::timeOutLoopStartLab()
8157 
timeOutFoundLab(Signal * signal,Uint32 TapiConPtr,Uint32 errCode)8158 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
8159 {
8160   apiConnectptr.i = TapiConPtr;
8161   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8162   /*------------------------------------------------------------------*/
8163   /*                                                                  */
8164   /*       THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
8165   /*       FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
8166   /*------------------------------------------------------------------*/
8167   DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
8168 	<< " H'" << apiConnectptr.p->transid[1] << "] " << dec
8169 	<< "Time-out in state = " << apiConnectptr.p->apiConnectstate
8170 	<< " apiConnectptr.i = " << apiConnectptr.i
8171 	<< " - exec: "
8172         << tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG)
8173 	<< " - place: " << c_apiConTimer_line[apiConnectptr.i]
8174 	<< " code: " << errCode
8175         << " lqhkeyreqrec: " << apiConnectptr.p->lqhkeyreqrec
8176         << " lqhkeyconfrec: " << apiConnectptr.p->lqhkeyconfrec
8177         << " pendingTriggers: " << apiConnectptr.p->pendingTriggers
8178         );
8179   switch (apiConnectptr.p->apiConnectstate) {
8180   case CS_STARTED:
8181     if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
8182        errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
8183       jam();
8184       /*
8185       We are waiting for application to continue the transaction. In this
8186       particular state we will use the application timeout parameter rather
8187       than the shorter Deadlock detection timeout.
8188       */
8189       if (c_appl_timeout_value == 0 ||
8190           (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
8191         jam();
8192         return;
8193       }//if
8194     }
8195     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
8196     apiConnectptr.p->returncode = errCode;
8197     abort010Lab(signal);
8198     return;
8199   case CS_RECEIVING:
8200   case CS_REC_COMMITTING:
8201   case CS_START_COMMITTING:
8202   case CS_WAIT_FIRE_TRIG_REQ:
8203   case CS_SEND_FIRE_TRIG_REQ:
8204     jam();
8205     /*------------------------------------------------------------------*/
8206     /*       WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS  */
8207     /*       NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO     */
8208     /*       START ABORTING THE TRANSACTION. ALSO START CHECKING THE    */
8209     /*       REMAINING TRANSACTIONS.                                    */
8210     /*------------------------------------------------------------------*/
8211     terrorCode = errCode;
8212     abortErrorLab(signal);
8213     return;
8214   case CS_COMMITTING:
8215     jam();
8216     /*------------------------------------------------------------------*/
8217     // We are simply waiting for a signal in the job buffer. Only extreme
8218     // conditions should get us here. We ignore it.
8219     /*------------------------------------------------------------------*/
8220   case CS_COMPLETING:
8221     jam();
8222     /*------------------------------------------------------------------*/
8223     // We are simply waiting for a signal in the job buffer. Only extreme
8224     // conditions should get us here. We ignore it.
8225     /*------------------------------------------------------------------*/
8226   case CS_PREPARE_TO_COMMIT:
8227   {
8228     jam();
8229     /*------------------------------------------------------------------*/
8230     /*       WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
8231     /*       KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO.  */
8232     /*       IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE.  */
8233     // To ensure against strange bugs we crash the system if we have passed
8234     // time-out period by a factor of 10 and it is also at least 5 seconds.
8235     /*------------------------------------------------------------------*/
8236     Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
8237     if (time_passed > 500 &&
8238         time_passed > (5 * cDbHbInterval) &&
8239         time_passed > (10 * ctimeOutValue))
8240     {
8241       jam();
8242       ndbout_c("timeOutFoundLab trans: 0x%x 0x%x state: %u",
8243                apiConnectptr.p->transid[0],
8244                apiConnectptr.p->transid[1],
8245                (Uint32)apiConnectptr.p->apiConnectstate);
8246 
8247       // Reset timeout to not flood log...
8248       setApiConTimer(apiConnectptr.i, 0, __LINE__);
8249     }//if
8250     break;
8251   }
8252   case CS_COMMIT_SENT:
8253     jam();
8254     /*------------------------------------------------------------------*/
8255     /*       WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
8256     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE   */
8257     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL  */
8258     /*       TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO   */
8259     /*       A NODE FAILURE.                                            */
8260     /*------------------------------------------------------------------*/
8261     tabortInd = ZCOMMIT_SETUP;
8262     setupFailData(signal);
8263     toCommitHandlingLab(signal);
8264     return;
8265   case CS_COMPLETE_SENT:
8266     jam();
8267     /*--------------------------------------------------------------------*/
8268     /*       WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
8269     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE     */
8270     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL  */
8271     /*       TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO   */
8272     /*       A NODE FAILURE.                                              */
8273     /*--------------------------------------------------------------------*/
8274     tabortInd = ZCOMMIT_SETUP;
8275     setupFailData(signal);
8276     toCompleteHandlingLab(signal);
8277     return;
8278   case CS_ABORTING:
8279     jam();
8280     /*------------------------------------------------------------------*/
8281     /*       TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL     */
8282     /*       NODES THAT HAVE FAILED BEFORE SENDING ABORTED.             */
8283     /*------------------------------------------------------------------*/
8284     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8285     sendAbortedAfterTimeout(signal, 0);
8286     break;
8287   case CS_START_SCAN:{
8288     jam();
8289 
8290     /*
8291       We are waiting for application to continue the transaction. In this
8292       particular state we will use the application timeout parameter rather
8293       than the shorter Deadlock detection timeout.
8294     */
8295     if (c_appl_timeout_value == 0 ||
8296 	(ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
8297       jam();
8298       return;
8299     }//if
8300 
8301     ScanRecordPtr scanPtr;
8302     scanPtr.i = apiConnectptr.p->apiScanRec;
8303     ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
8304     scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
8305     break;
8306   }
8307   case CS_WAIT_ABORT_CONF:
8308     jam();
8309     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
8310     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8311     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
8312     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
8313     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8314     if (hostptr.p->hostStatus == HS_ALIVE) {
8315       /*------------------------------------------------------------------*/
8316       // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
8317       // case.
8318       /*------------------------------------------------------------------*/
8319       warningReport(signal, 20);
8320       apiConnectptr.p->timeOutCounter++;
8321       if (apiConnectptr.p->timeOutCounter > 3) {
8322 	/*------------------------------------------------------------------*/
8323 	// 100 time-outs are not acceptable. We will shoot down the node
8324 	// not responding.
8325 	/*------------------------------------------------------------------*/
8326         reportNodeFailed(signal, hostptr.i);
8327       }//if
8328       apiConnectptr.p->currentReplicaNo++;
8329     }//if
8330     tcurrentReplicaNo = (Uint8)Z8NIL;
8331     toAbortHandlingLab(signal);
8332     return;
8333   case CS_WAIT_COMMIT_CONF:
8334     jam();
8335     CRASH_INSERTION(8053);
8336     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
8337     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8338     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
8339     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
8340     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8341     if (hostptr.p->hostStatus == HS_ALIVE) {
8342       /*------------------------------------------------------------------*/
8343       // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
8344       // case.
8345       /*------------------------------------------------------------------*/
8346       warningReport(signal, 21);
8347       apiConnectptr.p->timeOutCounter++;
8348       if (apiConnectptr.p->timeOutCounter > 3) {
8349 	/*------------------------------------------------------------------*/
8350 	// 100 time-outs are not acceptable. We will shoot down the node
8351 	// not responding.
8352 	/*------------------------------------------------------------------*/
8353         reportNodeFailed(signal, hostptr.i);
8354       }//if
8355       apiConnectptr.p->currentReplicaNo++;
8356     }//if
8357     tcurrentReplicaNo = (Uint8)Z8NIL;
8358     toCommitHandlingLab(signal);
8359     return;
8360   case CS_WAIT_COMPLETE_CONF:
8361     jam();
8362     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
8363     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8364     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
8365     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
8366     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8367     if (hostptr.p->hostStatus == HS_ALIVE) {
8368       /*------------------------------------------------------------------*/
8369       // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
8370       // just in case.
8371       /*------------------------------------------------------------------*/
8372       warningReport(signal, 22);
8373       apiConnectptr.p->timeOutCounter++;
8374       if (apiConnectptr.p->timeOutCounter > 100) {
8375 	/*------------------------------------------------------------------*/
8376 	// 100 time-outs are not acceptable. We will shoot down the node
8377 	// not responding.
8378 	/*------------------------------------------------------------------*/
8379         reportNodeFailed(signal, hostptr.i);
8380       }//if
8381       apiConnectptr.p->currentReplicaNo++;
8382     }//if
8383     tcurrentReplicaNo = (Uint8)Z8NIL;
8384     toCompleteHandlingLab(signal);
8385     return;
8386   case CS_FAIL_PREPARED:
8387     jam();
8388   case CS_FAIL_COMMITTING:
8389     jam();
8390   case CS_FAIL_COMMITTED:
8391     jam();
8392   case CS_RESTART:
8393     jam();
8394   case CS_FAIL_ABORTED:
8395     jam();
8396   case CS_DISCONNECTED:
8397     jam();
8398   default:
8399     jam();
8400     /*------------------------------------------------------------------*/
8401     /*       AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM.              */
8402     /*------------------------------------------------------------------*/
8403     DEBUG("State = " << apiConnectptr.p->apiConnectstate);
8404     systemErrorLab(signal, __LINE__);
8405     return;
8406   }//switch
8407   return;
8408 }//Dbtc::timeOutFoundLab()
8409 
sendAbortedAfterTimeout(Signal * signal,int Tcheck)8410 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
8411 {
8412   ApiConnectRecord * transP = apiConnectptr.p;
8413   if(transP->abortState == AS_IDLE){
8414     jam();
8415     warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
8416 		 __LINE__,
8417 		 apiConnectptr.i,
8418 		 transP->apiConnectstate,
8419 		 c_apiConTimer_line[apiConnectptr.i],
8420 		 transP->firstTcConnect,
8421 		 c_apiConTimer[apiConnectptr.i]
8422 		 );
8423     ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
8424 	     __LINE__,
8425 	     apiConnectptr.i,
8426 	     transP->apiConnectstate,
8427 	     c_apiConTimer_line[apiConnectptr.i],
8428 	     transP->firstTcConnect,
8429 	     c_apiConTimer[apiConnectptr.i]
8430 	     );
8431     ndbrequire(false);
8432     setApiConTimer(apiConnectptr.i, 0, __LINE__);
8433     return;
8434   }
8435 
8436   bool found = false;
8437   OperationState tmp[16];
8438 
8439   Uint32 TloopCount = 0;
8440   do {
8441     jam();
8442     if (tcConnectptr.i == RNIL) {
8443       jam();
8444 
8445 #ifdef VM_TRACE
8446       ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
8447 	       found, Tcheck, apiConnectptr.p->counter);
8448 #endif
8449       if (found || apiConnectptr.p->counter)
8450       {
8451 	jam();
8452 	/**
8453 	 * We sent atleast one ABORT/ABORTED
8454 	 *   or ZABORT_TIMEOUT_BREAK is in job buffer
8455 	 *   wait for reception...
8456 	 */
8457 	return;
8458       }
8459 
8460       if (Tcheck == 1)
8461       {
8462 	jam();
8463 	releaseAbortResources(signal);
8464 	return;
8465       }
8466 
8467       if (Tcheck == 0)
8468       {
8469         jam();
8470 	/*------------------------------------------------------------------
8471 	 * All nodes had already reported ABORTED for all tcConnect records.
8472 	 * Crash since it is an error situation that we then received a
8473 	 * time-out.
8474 	 *------------------------------------------------------------------*/
8475 	char buf[96]; buf[0] = 0;
8476 	char buf2[96];
8477 	BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
8478 			     __LINE__, apiConnectptr.i,
8479 			     apiConnectptr.p->counter);
8480 	for(Uint32 i = 0; i<TloopCount; i++)
8481 	{
8482 	  BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
8483 	  BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
8484 	}
8485 	warningEvent("%s", buf);
8486 	ndbout_c("%s", buf);
8487 	ndbrequire(false);
8488 	releaseAbortResources(signal);
8489 	return;
8490       }
8491 
8492       return;
8493     }//if
8494     TloopCount++;
8495     if (TloopCount >= 1024) {
8496       jam();
8497       /*------------------------------------------------------------------*/
8498       // Insert a real-time break for large transactions to avoid blowing
8499       // away the job buffer.
8500       /*------------------------------------------------------------------*/
8501       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8502       apiConnectptr.p->counter++;
8503       signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
8504       signal->theData[1] = tcConnectptr.i;
8505       signal->theData[2] = apiConnectptr.i;
8506       if (ERROR_INSERTED(8080))
8507       {
8508 	ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
8509 		 Tcheck, apiConnectptr.p->counter);
8510 	sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
8511       }
8512       else
8513       {
8514 	sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8515       }
8516       return;
8517     }//if
8518     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8519     if(TloopCount < 16){
8520       jam();
8521       tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
8522     }
8523 
8524     if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
8525       jam();
8526       /*------------------------------------------------------------------*/
8527       // We have sent an ABORT signal to this node but not yet received any
8528       // reply. We have to send an ABORTED signal on our own in some cases.
8529       // If the node is declared as up and running and still do not respond
8530       // in time to the ABORT signal we will declare it as dead.
8531       /*------------------------------------------------------------------*/
8532       UintR Ti = 0;
8533       arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
8534       for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
8535         jam();
8536         if (tcConnectptr.p->tcNodedata[Ti] != 0) {
8537           TloopCount += 31;
8538 	  found = true;
8539           hostptr.i = tcConnectptr.p->tcNodedata[Ti];
8540           ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8541           if (hostptr.p->hostStatus == HS_ALIVE) {
8542             jam();
8543 	    /*---------------------------------------------------------------
8544 	     * A backup replica has not sent ABORTED.
8545 	     * Could be that a node before him has crashed.
8546 	     * Send an ABORT signal specifically to this node.
8547 	     * We will not send to any more nodes after this
8548 	     * to avoid race problems.
8549 	     * To also ensure that we use this message also as a heartbeat
8550 	     * we will move this node to the primary replica seat.
8551 	     * The primary replica and any failed node after it will
8552 	     * be removed from the node list. Update also number of nodes.
8553 	     * Finally break the loop to ensure we don't mess
8554 	     * things up by executing another loop.
8555 	     * We also update the timer to ensure we don't get time-out
8556 	     * too early.
8557 	     *--------------------------------------------------------------*/
8558             Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
8559             BlockReference TBRef = numberToRef(DBLQH, instanceKey, hostptr.i);
8560             signal->theData[0] = tcConnectptr.i;
8561             signal->theData[1] = cownref;
8562             signal->theData[2] = apiConnectptr.p->transid[0];
8563             signal->theData[3] = apiConnectptr.p->transid[1];
8564             sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
8565             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8566             break;
8567           } else {
8568             jam();
8569 	    /*--------------------------------------------------------------
8570 	     * The node we are waiting for is dead. We will send ABORTED to
8571 	     * ourselves vicarious for the failed node.
8572 	     *--------------------------------------------------------------*/
8573             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8574             signal->theData[0] = tcConnectptr.i;
8575             signal->theData[1] = apiConnectptr.p->transid[0];
8576             signal->theData[2] = apiConnectptr.p->transid[1];
8577             signal->theData[3] = hostptr.i;
8578             signal->theData[4] = ZFALSE;
8579             sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
8580           }//if
8581         }//if
8582       }//for
8583     }//if
8584     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
8585   } while (1);
8586 }//Dbtc::sendAbortedAfterTimeout()
8587 
reportNodeFailed(Signal * signal,NodeId nodeId)8588 void Dbtc::reportNodeFailed(Signal* signal, NodeId nodeId)
8589 {
8590   DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
8591   rep->nodeId = nodeId;
8592   rep->err = DisconnectRep::TcReportNodeFailed;
8593   sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
8594 	     DisconnectRep::SignalLength, JBB);
8595 }//Dbtc::reportNodeFailed()
8596 
8597 /*-------------------------------------------------*/
8598 /*      Timeout-loop for scanned fragments.        */
8599 /*-------------------------------------------------*/
timeOutLoopStartFragLab(Signal * signal,Uint32 TscanConPtr)8600 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
8601 {
8602   ScanFragRecPtr timeOutPtr[8];
8603   UintR tfragTimer[8];
8604   UintR texpiredTime[8];
8605   UintR TloopCount = 0;
8606   Uint32 TtcTimer = ctcTimer;
8607 
8608   ctimeOutCheckHeartbeatScan = TtcTimer;
8609 
8610   while ((TscanConPtr + 8) < cscanFragrecFileSize) {
8611     jam();
8612     timeOutPtr[0].i  = TscanConPtr + 0;
8613     timeOutPtr[1].i  = TscanConPtr + 1;
8614     timeOutPtr[2].i  = TscanConPtr + 2;
8615     timeOutPtr[3].i  = TscanConPtr + 3;
8616     timeOutPtr[4].i  = TscanConPtr + 4;
8617     timeOutPtr[5].i  = TscanConPtr + 5;
8618     timeOutPtr[6].i  = TscanConPtr + 6;
8619     timeOutPtr[7].i  = TscanConPtr + 7;
8620 
8621     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
8622     c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
8623     c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
8624     c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
8625     c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
8626     c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
8627     c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
8628     c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
8629 
8630     tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
8631     tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
8632     tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
8633     tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
8634     tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
8635     tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
8636     tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
8637     tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
8638 
8639     texpiredTime[0] = TtcTimer - tfragTimer[0];
8640     texpiredTime[1] = TtcTimer - tfragTimer[1];
8641     texpiredTime[2] = TtcTimer - tfragTimer[2];
8642     texpiredTime[3] = TtcTimer - tfragTimer[3];
8643     texpiredTime[4] = TtcTimer - tfragTimer[4];
8644     texpiredTime[5] = TtcTimer - tfragTimer[5];
8645     texpiredTime[6] = TtcTimer - tfragTimer[6];
8646     texpiredTime[7] = TtcTimer - tfragTimer[7];
8647 
8648     for (Uint32 Ti = 0; Ti < 8; Ti++) {
8649       jam();
8650       if (tfragTimer[Ti] != 0) {
8651 
8652         if (texpiredTime[Ti] > ctimeOutValue) {
8653 	  jam();
8654 	  DEBUG("Fragment timeout found:"<<
8655 		" ctimeOutValue=" <<ctimeOutValue
8656 		<<", texpiredTime="<<texpiredTime[Ti]<<endl
8657 		<<"      tfragTimer="<<tfragTimer[Ti]
8658 		<<", ctcTimer="<<ctcTimer);
8659           timeOutFoundFragLab(signal, TscanConPtr + Ti);
8660           return;
8661         }//if
8662       }//if
8663     }//for
8664     TscanConPtr += 8;
8665     /*----------------------------------------------------------------*/
8666     /* We split the process up checking 1024 fragmentrecords at a time*/
8667     /* to maintain real time behaviour.                               */
8668     /*----------------------------------------------------------------*/
8669     if (TloopCount++ > 128 ) {
8670       jam();
8671       signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8672       signal->theData[1] = TscanConPtr;
8673       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8674       return;
8675     }//if
8676   }//while
8677   for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
8678     jam();
8679     timeOutPtr[0].i = TscanConPtr;
8680     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
8681     if (timeOutPtr[0].p->scanFragTimer != 0) {
8682       texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
8683       if (texpiredTime[0] > ctimeOutValue) {
8684         jam();
8685 	DEBUG("Fragment timeout found:"<<
8686 	      " ctimeOutValue=" <<ctimeOutValue
8687 	      <<", texpiredTime="<<texpiredTime[0]<<endl
8688 		<<"      tfragTimer="<<tfragTimer[0]
8689 		<<", ctcTimer="<<ctcTimer);
8690         timeOutFoundFragLab(signal, TscanConPtr);
8691         return;
8692       }//if
8693     }//if
8694   }//for
8695   ctimeOutCheckFragActive = TOCS_FALSE;
8696 
8697   return;
8698 }//timeOutLoopStartFragLab()
8699 
8700 /*--------------------------------------------------------------------------*/
8701 /*Handle the heartbeat signal from LQH in a scan process                    */
8702 // (Set timer on fragrec.)
8703 /*--------------------------------------------------------------------------*/
execSCAN_HBREP(Signal * signal)8704 void Dbtc::execSCAN_HBREP(Signal* signal)
8705 {
8706   jamEntry();
8707 
8708   scanFragptr.i = signal->theData[0];
8709   c_scan_frag_pool.getPtr(scanFragptr);
8710   switch (scanFragptr.p->scanFragState){
8711   case ScanFragRec::LQH_ACTIVE:
8712     break;
8713   default:
8714     DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
8715     systemErrorLab(signal, __LINE__);
8716     break;
8717   }
8718 
8719   ScanRecordPtr scanptr;
8720   scanptr.i = scanFragptr.p->scanRec;
8721   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8722 
8723   apiConnectptr.i = scanptr.p->scanApiRec;
8724   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8725 
8726   if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
8727 	apiConnectptr.p->transid[1] == signal->theData[2])){
8728     jam();
8729     /**
8730      * Send signal back to sender so that the crash occurs there
8731      */
8732     // Save original transid
8733     signal->theData[3] = signal->theData[0];
8734     signal->theData[4] = signal->theData[1];
8735     // Set transid to illegal values
8736     signal->theData[1] = RNIL;
8737     signal->theData[2] = RNIL;
8738 
8739     sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
8740     DEBUG("SCAN_HBREP with wrong transid("
8741 	  <<signal->theData[3]<<", "<<signal->theData[4]<<")");
8742     return;
8743   }//if
8744 
8745   // Update timer on ScanFragRec
8746   if (scanFragptr.p->scanFragTimer != 0){
8747     updateBuddyTimer(apiConnectptr);
8748     scanFragptr.p->startFragTimer(ctcTimer);
8749   } else {
8750     ndbassert(false);
8751     DEBUG("SCAN_HBREP when scanFragTimer was turned off");
8752   }
8753 }//execSCAN_HBREP()
8754 
8755 /*--------------------------------------------------------------------------*/
8756 /*      Timeout has occured on a fragment which means a scan has timed out. */
8757 /*      If this is true we have an error in LQH/ACC.                        */
8758 /*--------------------------------------------------------------------------*/
timeOutFoundFragLab(Signal * signal,UintR TscanConPtr)8759 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
8760 {
8761   ScanFragRecPtr ptr;
8762   c_scan_frag_pool.getPtr(ptr, TscanConPtr);
8763 #ifdef VM_TRACE
8764   {
8765     ScanRecordPtr scanptr;
8766     scanptr.i = ptr.p->scanRec;
8767     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8768     ApiConnectRecordPtr TlocalApiConnectptr;
8769     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8770     ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8771 
8772     DEBUG("[ H'" << hex << TlocalApiConnectptr.p->transid[0]
8773 	<< " H'" << TlocalApiConnectptr.p->transid[1] << "] "
8774         << TscanConPtr << " timeOutFoundFragLab: scanFragState = "
8775         << ptr.p->scanFragState);
8776   }
8777 #endif
8778 
8779   const Uint32 time_out_param= ctimeOutValue;
8780   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
8781 
8782   if (unlikely(time_out_param != old_time_out_param &&
8783 	       getNodeState().getSingleUserMode()))
8784   {
8785     jam();
8786     ScanRecordPtr scanptr;
8787     scanptr.i = ptr.p->scanRec;
8788     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8789     ApiConnectRecordPtr TlocalApiConnectptr;
8790     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8791     ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8792 
8793     if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
8794 	getNodeState().getSingleUserApi())
8795     {
8796       jam();
8797       Uint32 val = ctcTimer - ptr.p->scanFragTimer;
8798       if (val <= old_time_out_param)
8799       {
8800 	jam();
8801 	goto next;
8802       }
8803     }
8804   }
8805 
8806   /*-------------------------------------------------------------------------*/
8807   // The scan fragment has expired its timeout. Check its state to decide
8808   // what to do.
8809   /*-------------------------------------------------------------------------*/
8810   switch (ptr.p->scanFragState) {
8811   case ScanFragRec::WAIT_GET_PRIMCONF:
8812     jam();
8813     /**
8814      * Time-out waiting for local DIH, we will continue waiting forever.
8815      * This should only occur when we run in an unstable environment where
8816      * the main thread goes slow.
8817      * We reset timer to avoid getting here again immediately.
8818      */
8819     ptr.p->startFragTimer(ctcTimer);
8820 #ifdef VM_TRACE
8821     g_eventLogger->warning("Time-out in WAIT_GET_PRIMCONF: scanRecord = %u",
8822                            ptr.i);
8823 #endif
8824     break;
8825   case ScanFragRec::LQH_ACTIVE:{
8826     jam();
8827 
8828     /**
8829      * The LQH expired it's timeout, try to close it
8830      */
8831     NodeId nodeId = refToNode(ptr.p->lqhBlockref);
8832     Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
8833     ScanRecordPtr scanptr;
8834     scanptr.i = ptr.p->scanRec;
8835     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8836 
8837     if(connectCount != ptr.p->m_connectCount){
8838       jam();
8839       /**
8840        * The node has died
8841        */
8842       ptr.p->scanFragState = ScanFragRec::COMPLETED;
8843       ptr.p->stopFragTimer();
8844       {
8845         ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8846         run.release(ptr);
8847       }
8848     }
8849 
8850     scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
8851     break;
8852   }
8853   case ScanFragRec::DELIVERED:
8854     jam();
8855   case ScanFragRec::IDLE:
8856     jam();
8857   case ScanFragRec::QUEUED_FOR_DELIVERY:
8858     jam();
8859     /*-----------------------------------------------------------------------
8860      * Should never occur. We will simply report set the timer to zero and
8861      * continue. In a debug version we should crash here but not in a release
8862      * version. In a release version we will simply set the time-out to zero.
8863      *-----------------------------------------------------------------------*/
8864 #ifdef VM_TRACE
8865     systemErrorLab(signal, __LINE__);
8866 #endif
8867     scanFragptr.p->stopFragTimer();
8868     break;
8869   default:
8870     jam();
8871     /*-----------------------------------------------------------------------
8872      * Non-existent state. Crash.
8873      *-----------------------------------------------------------------------*/
8874     systemErrorLab(signal, __LINE__);
8875     break;
8876   }//switch
8877 
8878 next:
8879   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8880   signal->theData[1] = TscanConPtr + 1;
8881   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8882   return;
8883 }//timeOutFoundFragLab()
8884 
8885 
8886 /*
8887   4.3.16 GCP_NOMORETRANS
8888   ----------------------
8889 */
8890 /*****************************************************************************
8891  *                         G C P _ N O M O R E T R A N S
8892  *
8893  *  WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
8894  *  THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
8895  *  SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
8896  *  CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
8897  *  FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
8898  *  COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
8899  *  THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
8900  *  THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
8901  *  TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
8902  *****************************************************************************/
execGCP_NOMORETRANS(Signal * signal)8903 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
8904 {
8905   jamEntry();
8906   GCPNoMoreTrans* req = (GCPNoMoreTrans*)signal->getDataPtr();
8907   c_gcp_ref = req->senderRef;
8908   c_gcp_data = req->senderData;
8909   Uint32 gci_lo = req->gci_lo;
8910   Uint32 gci_hi = req->gci_hi;
8911   tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32);
8912 
8913   Ptr<GcpRecord> gcpPtr;
8914   if (cfirstgcp != RNIL) {
8915     jam();
8916                                       /* A GLOBAL CHECKPOINT IS GOING ON */
8917     gcpPtr.i = cfirstgcp;             /* SET POINTER TO FIRST GCP IN QUEUE*/
8918     ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8919     if (gcpPtr.p->gcpId == tcheckGcpId)
8920     {
8921       jam();
8922       bool empty = gcpPtr.p->firstApiConnect == RNIL;
8923       bool nfhandling = c_ongoing_take_over_cnt;
8924 
8925       if (empty && nfhandling)
8926       {
8927         jam();
8928         ndbout_c("NOT returning gcpTcfinished due to nfhandling %u/%u",
8929                  gci_hi, gci_lo);
8930       }
8931 
8932       if (!empty || c_ongoing_take_over_cnt)
8933       {
8934         jam();
8935         gcpPtr.p->gcpNomoretransRec = ZTRUE;
8936       } else {
8937         jam();
8938         gcpTcfinished(signal, tcheckGcpId);
8939         unlinkGcp(gcpPtr);
8940       }//if
8941     }
8942     else if (c_ongoing_take_over_cnt == 0)
8943     {
8944       jam();
8945       /*------------------------------------------------------------*/
8946       /*       IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO       */
8947       /*       RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE  */
8948       /*       THE GLOBAL CHECKPOINTS IN ORDER.                     */
8949       /*------------------------------------------------------------*/
8950       gcpTcfinished(signal, tcheckGcpId);
8951     }
8952     else
8953     {
8954       jam();
8955       goto outoforder;
8956     }
8957   }
8958   else if (c_ongoing_take_over_cnt == 0)
8959   {
8960     jam();
8961     gcpTcfinished(signal, tcheckGcpId);
8962   }
8963   else
8964   {
8965 seize:
8966     jam();
8967     ndbout_c("execGCP_NOMORETRANS(%u/%u) c_ongoing_take_over_cnt -> seize",
8968              gci_hi, gci_lo);
8969     seizeGcp(gcpPtr, tcheckGcpId);
8970     gcpPtr.p->gcpNomoretransRec = ZTRUE;
8971   }
8972   return;
8973 
8974 outoforder:
8975   printf("ooo: execGCP_NOMORETRANS tcheckGcpId: %u/%u cfirstgcp: %u/%u",
8976          gci_hi, gci_lo,
8977          Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8978 
8979   if (tcheckGcpId < gcpPtr.p->gcpId)
8980   {
8981     jam();
8982 
8983     Ptr<GcpRecord> tmp;
8984     tmp.i = cfirstfreeGcp;
8985     ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8986     cfirstfreeGcp = tmp.p->nextGcp;
8987 
8988     tmp.p->gcpId = tcheckGcpId;
8989     tmp.p->nextGcp = cfirstgcp;
8990     tmp.p->firstApiConnect = RNIL;
8991     tmp.p->lastApiConnect = RNIL;
8992     tmp.p->gcpNomoretransRec = ZTRUE;
8993     cfirstgcp = tmp.i;
8994     ndbout_c("LINK FIRST");
8995     return;
8996   }
8997   else
8998   {
8999     Ptr<GcpRecord> prev = gcpPtr;
9000     while (tcheckGcpId > gcpPtr.p->gcpId)
9001     {
9002       jam();
9003       if (gcpPtr.p->nextGcp == RNIL)
9004       {
9005         printf("nextGcp == RNIL -> ");
9006         goto seize;
9007       }
9008 
9009       prev = gcpPtr;
9010       gcpPtr.i = gcpPtr.p->nextGcp;
9011       ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
9012     }
9013 
9014     if (tcheckGcpId == gcpPtr.p->gcpId)
9015     {
9016       jam();
9017       gcpPtr.p->gcpNomoretransRec = ZTRUE;
9018       ndbout_c("found");
9019       return;
9020     }
9021     ndbrequire(prev.i != gcpPtr.i); // checked earlier with initial "<"
9022     ndbrequire(prev.p->gcpId < tcheckGcpId);
9023     ndbrequire(gcpPtr.p->gcpId > tcheckGcpId);
9024 
9025     Ptr<GcpRecord> tmp;
9026     tmp.i = cfirstfreeGcp;
9027     ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
9028     cfirstfreeGcp = tmp.p->nextGcp;
9029 
9030     tmp.p->gcpId = tcheckGcpId;
9031     tmp.p->nextGcp = gcpPtr.i;
9032     tmp.p->firstApiConnect = RNIL;
9033     tmp.p->lastApiConnect = RNIL;
9034     tmp.p->gcpNomoretransRec = ZTRUE;
9035     prev.p->nextGcp = tmp.i;
9036     ndbout_c("link middle %u/%u < %u/%u < %u/%u",
9037              Uint32(prev.p->gcpId >> 32), Uint32(prev.p->gcpId),
9038              gci_hi, gci_lo,
9039              Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
9040     return;
9041   }
9042 }//Dbtc::execGCP_NOMORETRANS()
9043 
9044 /*****************************************************************************/
9045 /*                                                                           */
9046 /*                            TAKE OVER MODULE                               */
9047 /*                                                                           */
9048 /*****************************************************************************/
9049 /*                                                                           */
9050 /*    THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE  */
9051 /*    NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT   */
9052 /*    ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE   */
9053 /*    FAILED.                                                                */
9054 /*                                                                           */
9055 /*    AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
9056 /*    CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
9057 /*    COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED.    */
9058 /*    IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO  */
9059 /*    WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT.            */
9060 /*****************************************************************************/
execNODE_FAILREP(Signal * signal)9061 void Dbtc::execNODE_FAILREP(Signal* signal)
9062 {
9063   jamEntry();
9064 
9065   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
9066 
9067   cfailure_nr = nodeFail->failNo;
9068   const Uint32 tnoOfNodes  = nodeFail->noOfNodes;
9069   const Uint32 tnewMasterId = nodeFail->masterNodeId;
9070   Uint32 cdata[MAX_NDB_NODES];
9071 
9072   arrGuard(tnoOfNodes, MAX_NDB_NODES);
9073   Uint32 i;
9074   int index = 0;
9075   for (i = 1; i< MAX_NDB_NODES; i++)
9076   {
9077     if(NdbNodeBitmask::get(nodeFail->theNodes, i))
9078     {
9079       cdata[index] = i;
9080       index++;
9081     }//if
9082   }//for
9083 
9084   cmasterNodeId = tnewMasterId;
9085 
9086   if (ERROR_INSERTED(8098))
9087     SET_ERROR_INSERT_VALUE(8099);  /* Disable 8098 on node failure */
9088 
9089   HostRecordPtr myHostPtr;
9090 
9091   tcNodeFailptr.i = 0;
9092   ptrAss(tcNodeFailptr, tcFailRecord);
9093   for (i = 0; i < tnoOfNodes; i++)
9094   {
9095     jam();
9096     myHostPtr.i = cdata[i];
9097     ptrCheckGuard(myHostPtr, chostFilesize, hostRecord);
9098 
9099     /*------------------------------------------------------------*/
9100     /*       SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS   */
9101     /*       FAILED.                                              */
9102     /*------------------------------------------------------------*/
9103     myHostPtr.p->hostStatus = HS_DEAD;
9104     myHostPtr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
9105     c_ongoing_take_over_cnt++;
9106     c_alive_nodes.clear(myHostPtr.i);
9107 
9108     if (tcNodeFailptr.p->failStatus == FS_LISTENING)
9109     {
9110       jam();
9111       /*------------------------------------------------------------*/
9112       /*       THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE   */
9113       /*       FAILURE.                                             */
9114       /*------------------------------------------------------------*/
9115       if (myHostPtr.p->lqhTransStatus == LTS_ACTIVE)
9116       {
9117 	jam();
9118 	/*------------------------------------------------------------*/
9119 	/*       WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
9120 	/*       PROTOCOL FOR TC.                                     */
9121 	/*------------------------------------------------------------*/
9122 	signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
9123 	signal->theData[1] = myHostPtr.i;
9124 	sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
9125       }//if
9126     }//if
9127 
9128     jam();
9129     signal->theData[0] = myHostPtr.i;
9130     sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
9131 
9132     checkScanActiveInFailedLqh(signal, 0, myHostPtr.i);
9133     nodeFailCheckTransactions(signal, 0, myHostPtr.i);
9134     Callback cb = {safe_cast(&Dbtc::ndbdFailBlockCleanupCallback),
9135                   myHostPtr.i};
9136     simBlockNodeFailure(signal, myHostPtr.i, cb);
9137   }
9138 
9139   if (m_deferred_enabled == 0)
9140   {
9141     jam();
9142     Uint32 ok = 1;
9143     for(Uint32 n = c_alive_nodes.find_first();
9144         n != c_alive_nodes.NotFound;
9145         n = c_alive_nodes.find_next(n+1))
9146     {
9147       if (!ndbd_deferred_unique_constraints(getNodeInfo(n).m_version))
9148       {
9149         jam();
9150         ok = 0;
9151         break;
9152       }
9153     }
9154     if (ok)
9155     {
9156       jam();
9157       m_deferred_enabled = ~Uint32(0);
9158     }
9159   }
9160 }//Dbtc::execNODE_FAILREP()
9161 
9162 void
checkNodeFailComplete(Signal * signal,Uint32 failedNodeId,Uint32 bit)9163 Dbtc::checkNodeFailComplete(Signal* signal,
9164 			    Uint32 failedNodeId,
9165 			    Uint32 bit)
9166 {
9167   hostptr.i = failedNodeId;
9168   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9169   hostptr.p->m_nf_bits &= ~bit;
9170   if (hostptr.p->m_nf_bits == 0)
9171   {
9172     NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
9173     nfRep->blockNo      = DBTC;
9174     nfRep->nodeId       = cownNodeid;
9175     nfRep->failedNodeId = hostptr.i;
9176 
9177     if (instance() == 0)
9178     {
9179       jam();
9180       sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
9181                  NFCompleteRep::SignalLength, JBB);
9182       sendSignal(QMGR_REF, GSN_NF_COMPLETEREP, signal,
9183                  NFCompleteRep::SignalLength, JBB);
9184     }
9185     else
9186     {
9187       /**
9188        * Send to proxy
9189        */
9190       sendSignal(DBTC_REF, GSN_NF_COMPLETEREP, signal,
9191                  NFCompleteRep::SignalLength, JBB);
9192     }
9193   }
9194 
9195   CRASH_INSERTION(8058);
9196   if (ERROR_INSERTED(8059))
9197   {
9198     signal->theData[0] = 9999;
9199     sendSignalWithDelay(numberToRef(CMVMI, hostptr.i),
9200                         GSN_NDB_TAMPER, signal, 100, 1);
9201   }
9202 }
9203 
checkScanActiveInFailedLqh(Signal * signal,Uint32 scanPtrI,Uint32 failedNodeId)9204 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
9205 				      Uint32 scanPtrI,
9206 				      Uint32 failedNodeId){
9207 
9208   ScanRecordPtr scanptr;
9209   for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
9210     jam();
9211     ptrAss(scanptr, scanRecord);
9212     bool found = false;
9213     if (scanptr.p->scanState != ScanRecord::IDLE){
9214       jam();
9215       ScanFragRecPtr ptr;
9216       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9217 
9218       for(run.first(ptr); !ptr.isNull(); ){
9219 	jam();
9220 	ScanFragRecPtr curr = ptr;
9221 	run.next(ptr);
9222 	if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
9223 	    refToNode(curr.p->lqhBlockref) == failedNodeId){
9224 	  jam();
9225 
9226 	  run.release(curr);
9227 	  curr.p->scanFragState = ScanFragRec::COMPLETED;
9228 	  curr.p->stopFragTimer();
9229 	  found = true;
9230 	}
9231       }
9232 
9233       ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
9234       for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
9235       {
9236 	jam();
9237 	if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
9238 	{
9239 	  jam();
9240 	  found = true;
9241 	  break;
9242 	}
9243       }
9244     }
9245     if(found){
9246       jam();
9247       scanError(signal, scanptr, ZSCAN_LQH_ERROR);
9248     }
9249 
9250     // Send CONTINUEB to continue later
9251     signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
9252     signal->theData[1] = scanptr.i + 1; // Check next scanptr
9253     signal->theData[2] = failedNodeId;
9254     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9255     return;
9256   }//for
9257 
9258   checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
9259 }
9260 
9261 void
nodeFailCheckTransactions(Signal * signal,Uint32 transPtrI,Uint32 failedNodeId)9262 Dbtc::nodeFailCheckTransactions(Signal* signal,
9263 				Uint32 transPtrI,
9264 				Uint32 failedNodeId)
9265 {
9266   jam();
9267   Ptr<ApiConnectRecord> transPtr;
9268   Uint32 TtcTimer = ctcTimer;
9269   Uint32 TapplTimeout = c_appl_timeout_value;
9270   Uint32 RT_BREAK = 64;
9271   Uint32 endPtrI = transPtrI + RT_BREAK;
9272   if (endPtrI > capiConnectFilesize)
9273   {
9274     endPtrI = capiConnectFilesize;
9275   }
9276 
9277   for (transPtr.i = transPtrI; transPtr.i < endPtrI; transPtr.i++)
9278   {
9279     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
9280     if (transPtr.p->m_transaction_nodes.get(failedNodeId))
9281     {
9282       jam();
9283 
9284       // Force timeout regardless of state
9285       c_appl_timeout_value = 1;
9286       setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
9287       timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
9288       c_appl_timeout_value = TapplTimeout;
9289 
9290       transPtr.i++;
9291       break;
9292     }
9293   }
9294 
9295   if (transPtr.i == capiConnectFilesize)
9296   {
9297     jam();
9298     checkNodeFailComplete(signal, failedNodeId,
9299                           HostRecord::NF_CHECK_TRANSACTION);
9300   }
9301   else
9302   {
9303     signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
9304     signal->theData[1] = transPtr.i;
9305     signal->theData[2] = failedNodeId;
9306     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9307   }
9308 }
9309 
9310 void
ndbdFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)9311 Dbtc::ndbdFailBlockCleanupCallback(Signal* signal,
9312                                    Uint32 failedNodeId,
9313                                    Uint32 ignoredRc)
9314 {
9315   jamEntry();
9316 
9317   checkNodeFailComplete(signal, failedNodeId,
9318                         HostRecord::NF_BLOCK_HANDLE);
9319 }
9320 
9321 void
apiFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)9322 Dbtc::apiFailBlockCleanupCallback(Signal* signal,
9323                                   Uint32 failedNodeId,
9324                                   Uint32 ignoredRc)
9325 {
9326   jamEntry();
9327 
9328   signal->theData[0] = failedNodeId;
9329   signal->theData[1] = reference();
9330   sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
9331 }
9332 
9333 void
checkScanFragList(Signal * signal,Uint32 failedNodeId,ScanRecord * scanP,ScanFragList::Head & head)9334 Dbtc::checkScanFragList(Signal* signal,
9335 			Uint32 failedNodeId,
9336 			ScanRecord * scanP,
9337 			ScanFragList::Head & head){
9338 
9339   DEBUG("checkScanActiveInFailedLqh: scanFragError");
9340 }
9341 
execTAKE_OVERTCCONF(Signal * signal)9342 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
9343 {
9344   jamEntry();
9345 
9346   if (!checkNodeFailSequence(signal))
9347   {
9348     jam();
9349     return;
9350   }
9351 
9352   Uint32 failedNodeId = signal->theData[0];
9353   hostptr.i = failedNodeId;
9354   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9355 
9356   Uint32 senderRef = signal->theData[1];
9357   if (signal->getLength() < 2)
9358   {
9359     jam();
9360     senderRef = 0; // currently only used to see if it's from self
9361   }
9362 
9363   if (senderRef != reference())
9364   {
9365     jam();
9366 
9367     tcNodeFailptr.i = 0;
9368     ptrAss(tcNodeFailptr, tcFailRecord);
9369 
9370     /**
9371      * Node should be in queue
9372      */
9373     Uint32 i = 0;
9374     Uint32 end = tcNodeFailptr.p->queueIndex;
9375     for (; i<end; i++)
9376     {
9377       jam();
9378       if (tcNodeFailptr.p->queueList[i] == hostptr.i)
9379       {
9380         g_eventLogger->info("DBTC instance %u: Removed node %u"
9381           " from takeover queue, %u failed nodes remaining",
9382                             instance(),
9383                             hostptr.i,
9384                             end - 1);
9385 
9386         jam();
9387         break;
9388       }
9389     }
9390     ndbrequire(i != end);
9391     tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[end-1];
9392     tcNodeFailptr.p->queueIndex = end - 1;
9393   }
9394 
9395   Uint32 cnt = c_ongoing_take_over_cnt;
9396   ndbrequire(cnt);
9397   c_ongoing_take_over_cnt = cnt - 1;
9398   checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
9399 
9400   if (cnt == 1 && cfirstgcp != RNIL)
9401   {
9402     /**
9403      * Check if there are any hanging GCP_NOMORETRANS
9404      */
9405     GcpRecordPtr tmpGcpPointer;
9406     tmpGcpPointer.i = cfirstgcp;
9407     ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
9408     if (tmpGcpPointer.p->gcpNomoretransRec &&
9409         tmpGcpPointer.p->firstApiConnect == RNIL)
9410     {
9411       jam();
9412       ndbout_c("completing gcp %u/%u in execTAKE_OVERTCCONF",
9413                Uint32(tmpGcpPointer.p->gcpId >> 32),
9414                Uint32(tmpGcpPointer.p->gcpId));
9415       gcpTcfinished(signal, tmpGcpPointer.p->gcpId);
9416       unlinkGcp(tmpGcpPointer);
9417     }
9418   }
9419 }//Dbtc::execTAKE_OVERTCCONF()
9420 
execTAKE_OVERTCREQ(Signal * signal)9421 void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
9422 {
9423   jamEntry();
9424   Uint32 failedNodeId = signal->theData[0];
9425   tcNodeFailptr.i = 0;
9426   ptrAss(tcNodeFailptr, tcFailRecord);
9427   if (tcNodeFailptr.p->failStatus != FS_IDLE ||
9428       cmasterNodeId != getOwnNodeId() ||
9429       (! (instance() == 0 /* single TC */ ||
9430           instance() == TAKE_OVER_INSTANCE))) /* in mt-TC case let 1 instance
9431                                                  do take-over */
9432   {
9433     jam();
9434     /*------------------------------------------------------------*/
9435     /*       WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
9436     /*------------------------------------------------------------*/
9437     /*       IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL      */
9438     /*       QUEUE THE TAKE OVER AND START IT AS SOON AS THE      */
9439     /*       PREVIOUS ARE COMPLETED.                              */
9440     /*------------------------------------------------------------*/
9441     g_eventLogger->info("DBTC instance %u: Inserting failed node %u into"
9442                         " takeover queue, length now=%u",
9443                         instance(),
9444                         failedNodeId,
9445                         tcNodeFailptr.p->queueIndex + 1);
9446     arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
9447     tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = failedNodeId;
9448     tcNodeFailptr.p->queueIndex++;
9449     return;
9450   }//if
9451   ndbrequire(instance() == 0 || instance() == TAKE_OVER_INSTANCE);
9452   g_eventLogger->info("DBTC instance %u: Starting take over of node %u",
9453                       instance(),
9454                       failedNodeId);
9455   startTakeOverLab(signal, 0, failedNodeId);
9456 }//Dbtc::execTAKE_OVERTCREQ()
9457 
9458 /**
9459   TC Takeover protocol
9460   --------------------
9461   When a node fails it has a set of transactions ongoing in many cases. In
9462   order to complete those transactions we have implemented a take over
9463   protocol.
9464 
9465   The failed node was transaction controller for a set of transactions.
9466   The transaction controller has failed, so we cannot ask it for the
9467   state of the transactions. This means that we need to rebuild the
9468   transaction state of all transactions that was controlled by the failed
9469   node. If there are several node failures at the same time, then we'll
9470   take over one node at a time. The TC take over is only handled by the
9471   first TC instance, most of the work of the take over is handled by the
9472   LQH instances that need to scan all ongoing operations to send the
9473   operations to the TC instance that takes over. For the ndbd it is handled
9474   by the TC instance simply.
9475 
9476   With the introduction of multiple TC instances we have also seen it fit
9477   to handle also the take over of one TC instance in multiple steps. We use
9478   one step per TC instance we take over. If the TC take over fails due to
9479   not having sufficient amount of transaction records or operations records,
9480   we will also run several steps for each TC instance we take over.
9481 
9482   The TC take over process will eventually complete as long as there isn't
9483   any transaction that is bigger than the number of operation records
9484   available for TC take over.
9485 
9486   The protocol works as follows:
9487 
9488   Master TC (take over TC instance, starting at instance 0):
9489   Sends:
9490   LQH_TRANSREQ (Take over data reference,
9491                 Master TC block reference,
9492                 TC Take over node id,
9493                 TC Take over instance id)
9494 
9495   This signal is sent to the LQH proxy block in each of the alive nodes.
9496   From the proxy block it is sent to each LQH instance. For ndbd's we
9497   send it directly to the LQH block.
9498 
9499   Each LQH instance scans the operations for any operations that has a
9500   TC reference that comes from the TC node and TC instance that has failed.
9501   For each such operation it sends a LQH_TRANSCONF signal that contains a
9502   lot of data about the transaction operation.
9503 
9504   When the LQH instance have completed the scan of its operations then it
9505   will send a special LQH_TRANSCONF with a last operation flag set. All
9506   LQH_TRANSCONF is sent through the LQH proxy such that we can check when
9507   all LQH instances have completed their scans. We will only send one
9508   LQH_TRANSCONF signal from each node.
9509 
9510   The Master TC that performs the take over builds the state of each
9511   transaction such that it can decide whether the transaction was
9512   committed or not, if it wasn't committed we will abort it.
9513 
9514   The design is certain that each step will at least handle one transaction
9515   for each take over step. Normally it will complete all transactions in
9516   one instance in each step, we can though handle also other uncommon cases.
9517 */
9518 
9519 /*------------------------------------------------------------*/
9520 /*       INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS  */
9521 /*       AND OPERATIONS DURING TC TAKE OVER.                  */
9522 /*------------------------------------------------------------*/
startTakeOverLab(Signal * signal,Uint32 instanceId,Uint32 failedNodeId)9523 void Dbtc::startTakeOverLab(Signal* signal,
9524                             Uint32 instanceId,
9525                             Uint32 failedNodeId)
9526 {
9527   for (Uint32 i = 0; i < TRANSID_FAIL_HASH_SIZE; i++) {
9528     ctransidFailHash[i] = RNIL;
9529   }//for
9530   for (Uint32 i = 0; i < TC_FAIL_HASH_SIZE; i++) {
9531     ctcConnectFailHash[i] = RNIL;
9532   }//for
9533   tcNodeFailptr.p->failStatus = FS_LISTENING;
9534   tcNodeFailptr.p->takeOverNode = failedNodeId;
9535   tcNodeFailptr.p->takeOverInstanceId = instanceId;
9536   tcNodeFailptr.p->takeOverFailed = false;
9537   tcNodeFailptr.p->maxInstanceId = 0;
9538   tcNodeFailptr.p->handledOneTransaction = false;
9539   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
9540     jam();
9541     ptrAss(hostptr, hostRecord);
9542     if (hostptr.p->hostStatus == HS_ALIVE)
9543     {
9544       LqhTransReq * const lqhTransReq  = (LqhTransReq *)&signal->theData[0];
9545       Uint32 sig_len;
9546       jam();
9547       tblockref = calcLqhBlockRef(hostptr.i);
9548       hostptr.p->lqhTransStatus = LTS_ACTIVE;
9549       lqhTransReq->senderData = tcNodeFailptr.i;
9550       lqhTransReq->senderRef = cownref;
9551       lqhTransReq->failedNodeId = failedNodeId;
9552       lqhTransReq->instanceId = instanceId;
9553       if (ndbd_multi_tc_instance_takeover(getNodeInfo(hostptr.i).m_version))
9554       {
9555         /* The node does support the new LQH_TRANSREQ protocol */
9556         sig_len = LqhTransReq::SignalLength;
9557       }
9558       else
9559       {
9560         sig_len = LqhTransReq::OldSignalLength;
9561       }
9562       if (ERROR_INSERTED(8064) && hostptr.i == getOwnNodeId())
9563       {
9564         ndbout_c("sending delayed GSN_LQH_TRANSREQ to self");
9565         sendSignalWithDelay(tblockref, GSN_LQH_TRANSREQ, signal, 100, sig_len);
9566         CLEAR_ERROR_INSERT_VALUE;
9567       }
9568       else
9569       {
9570         sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, sig_len, JBB);
9571       }
9572     }//if
9573   }//for
9574 }//Dbtc::startTakeOverLab()
9575 
9576 Uint32
get_transid_fail_bucket(Uint32 transid1)9577 Dbtc::get_transid_fail_bucket(Uint32 transid1)
9578 {
9579   return transid1 & (TRANSID_FAIL_HASH_SIZE - 1);
9580 }
9581 
9582 void
insert_transid_fail_hash(Uint32 transid1)9583 Dbtc::insert_transid_fail_hash(Uint32 transid1)
9584 {
9585   Uint32 bucket = get_transid_fail_bucket(transid1);
9586   apiConnectptr.p->nextApiConnect = ctransidFailHash[bucket];
9587   ctransidFailHash[bucket] = apiConnectptr.i;
9588   return;
9589 }
9590 
9591 bool
findApiConnectFail(Signal * signal,Uint32 transid1,Uint32 transid2)9592 Dbtc::findApiConnectFail(Signal *signal, Uint32 transid1, Uint32 transid2)
9593 {
9594   Uint32 bucket = get_transid_fail_bucket(transid1);
9595   apiConnectptr.i = ctransidFailHash[bucket];
9596 
9597   while (apiConnectptr.i != RNIL)
9598   {
9599     jam();
9600     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9601     if (apiConnectptr.p->transid[0] == transid1 &&
9602         apiConnectptr.p->transid[1] == transid2)
9603     {
9604       jam();
9605       return true;
9606     }
9607     apiConnectptr.i = apiConnectptr.p->nextApiConnect;
9608   }
9609   jam();
9610   return false;
9611 }
9612 
releaseMarker(ApiConnectRecord * const regApiPtr)9613 void Dbtc::releaseMarker(ApiConnectRecord * const regApiPtr)
9614 {
9615   Uint32 marker = regApiPtr->commitAckMarker;
9616   if (marker != RNIL)
9617   {
9618     regApiPtr->commitAckMarker = RNIL;
9619     CommitAckMarkerBuffer::DataBufferPool & pool =
9620       c_theCommitAckMarkerBufferPool;
9621     CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(marker);
9622     LocalDataBuffer<5> commitAckMarkers(pool, tmp->theDataBuffer);
9623     commitAckMarkers.release();
9624     m_commitAckMarkerHash.release(marker);
9625   }
9626 }
9627 
remove_from_transid_fail_hash(Signal * signal,Uint32 transid1)9628 void Dbtc::remove_from_transid_fail_hash(Signal *signal, Uint32 transid1)
9629 {
9630   ApiConnectRecordPtr locApiConnectptr;
9631   ApiConnectRecordPtr prevApiConptr;
9632 
9633   prevApiConptr.i = RNIL;
9634   Uint32 bucket = get_transid_fail_bucket(transid1);
9635   locApiConnectptr.i = ctransidFailHash[bucket];
9636   ndbrequire(locApiConnectptr.i != RNIL);
9637   do
9638   {
9639     ptrCheckGuard(locApiConnectptr, capiConnectFilesize, apiConnectRecord);
9640     if (locApiConnectptr.i == apiConnectptr.i)
9641     {
9642       if (prevApiConptr.i == RNIL)
9643       {
9644         jam();
9645         /* We were first in the hash linked list */
9646         ndbassert(ctransidFailHash[bucket] == apiConnectptr.i);
9647         ctransidFailHash[bucket] = apiConnectptr.p->nextApiConnect;
9648       }
9649       else
9650       {
9651         /* Link past our record in the hash list */
9652         jam();
9653         ptrCheckGuard(prevApiConptr, capiConnectFilesize, apiConnectRecord);
9654         prevApiConptr.p->nextApiConnect = apiConnectptr.p->nextApiConnect;
9655       }
9656       apiConnectptr.p->nextApiConnect = RNIL;
9657       return;
9658     }
9659     else
9660     {
9661       jam();
9662       prevApiConptr.i = locApiConnectptr.i;
9663       locApiConnectptr.i = locApiConnectptr.p->nextApiConnect;
9664     }
9665   } while (locApiConnectptr.i != RNIL);
9666   ndbrequire(false);
9667 }
9668 
9669 Uint32
get_tc_fail_bucket(Uint32 transid1,Uint32 opRec)9670 Dbtc::get_tc_fail_bucket(Uint32 transid1, Uint32 opRec)
9671 {
9672   return (transid1 ^ opRec) & (TC_FAIL_HASH_SIZE - 1);
9673 }
9674 
9675 void
insert_tc_fail_hash(Uint32 transid1,Uint32 tcOprec)9676 Dbtc::insert_tc_fail_hash(Uint32 transid1, Uint32 tcOprec)
9677 {
9678   Uint32 bucket = get_tc_fail_bucket(transid1, tcOprec);
9679   tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[bucket];
9680   ctcConnectFailHash[bucket] = tcConnectptr.i;
9681 }
9682 
9683 bool
findTcConnectFail(Signal * signal,Uint32 transid1,Uint32 transid2,Uint32 tcOprec)9684 Dbtc::findTcConnectFail(Signal* signal,
9685                         Uint32 transid1,
9686                         Uint32 transid2,
9687                         Uint32 tcOprec)
9688 {
9689   Uint32 bucket = get_tc_fail_bucket(transid1, tcOprec);
9690 
9691   tcConnectptr.i = ctcConnectFailHash[bucket];
9692   while (tcConnectptr.i != RNIL)
9693   {
9694     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9695     if (tcConnectptr.p->tcOprec == tcOprec &&
9696         tcConnectptr.p->apiConnect == apiConnectptr.i &&
9697         apiConnectptr.p->transid[0] == transid1 &&
9698         apiConnectptr.p->transid[1] == transid2)
9699     {
9700       jam();
9701       return true;
9702     }
9703     else
9704     {
9705       jam();
9706       tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
9707     }
9708   }
9709   jam();
9710   return false;
9711 }
9712 
remove_transaction_from_tc_fail_hash(Signal * signal)9713 void Dbtc::remove_transaction_from_tc_fail_hash(Signal *signal)
9714 {
9715   TcConnectRecordPtr remTcConnectptr;
9716 
9717   remTcConnectptr.i = apiConnectptr.p->firstTcConnect;
9718   while (remTcConnectptr.i != RNIL)
9719   {
9720     jam();
9721     TcConnectRecordPtr loopTcConnectptr;
9722     TcConnectRecordPtr prevTcConnectptr;
9723     ptrCheckGuard(remTcConnectptr, ctcConnectFilesize, tcConnectRecord);
9724     bool found = false;
9725     Uint32 bucket = get_tc_fail_bucket(apiConnectptr.p->transid[0],
9726                                        remTcConnectptr.p->tcOprec);
9727     prevTcConnectptr.i = RNIL;
9728     loopTcConnectptr.i = ctcConnectFailHash[bucket];
9729     while (loopTcConnectptr.i != RNIL)
9730     {
9731       if (loopTcConnectptr.i == remTcConnectptr.i)
9732       {
9733         found = true;
9734         if (prevTcConnectptr.i == RNIL)
9735         {
9736           jam();
9737           /* We were first in the hash linked list */
9738           ndbassert(ctcConnectFailHash[bucket] == remTcConnectptr.i);
9739           ctcConnectFailHash[bucket] = remTcConnectptr.p->nextTcFailHash;
9740         }
9741         else
9742         {
9743           /* Link past our record in the hash list */
9744           jam();
9745           ptrCheckGuard(prevTcConnectptr, ctcConnectFilesize, tcConnectRecord);
9746           prevTcConnectptr.p->nextTcFailHash =
9747             remTcConnectptr.p->nextTcFailHash;
9748         }
9749         remTcConnectptr.p->nextTcFailHash = RNIL;
9750         break;
9751       }
9752       else
9753       {
9754         jam();
9755         ptrCheckGuard(loopTcConnectptr, ctcConnectFilesize, tcConnectRecord);
9756         prevTcConnectptr.i = loopTcConnectptr.i;
9757         loopTcConnectptr.i = loopTcConnectptr.p->nextTcFailHash;
9758       }
9759     }
9760     ndbrequire(found);
9761     remTcConnectptr.i = remTcConnectptr.p->nextTcConnect;
9762   }
9763 }
9764 
9765 /*------------------------------------------------------------*/
9766 /*       A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
9767 /*------------------------------------------------------------*/
execLQH_TRANSCONF(Signal * signal)9768 void Dbtc::execLQH_TRANSCONF(Signal* signal)
9769 {
9770   jamEntry();
9771   LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
9772 
9773   if (ERROR_INSERTED(8102))
9774   {
9775     jam();
9776     if ((((LqhTransConf::OperationStatus)lqhTransConf->operationStatus) ==
9777          LqhTransConf::LastTransConf) &&
9778         signal->getSendersBlockRef() != reference())
9779     {
9780       jam();
9781       ndbout_c("Delaying final LQH_TRANSCONF from Lqh @ node %u",
9782                refToNode(signal->getSendersBlockRef()));
9783       // Force multi-tc takeover
9784       ((LqhTransConf*)lqhTransConf)->maxInstanceId = 4;
9785       sendSignalWithDelay(reference(),
9786                           GSN_LQH_TRANSCONF,
9787                           signal,
9788                           5000,
9789                           signal->getLength());
9790       return;
9791     }
9792   }
9793 
9794   CRASH_INSERTION(8060);
9795 
9796   tcNodeFailptr.i = lqhTransConf->tcRef;
9797   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
9798   NodeId nodeId = lqhTransConf->lqhNodeId;
9799   LqhTransConf::OperationStatus transStatus =
9800     (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
9801   Uint32 transid1    = lqhTransConf->transId1;
9802   Uint32 transid2    = lqhTransConf->transId2;
9803   Uint32 tcOprec     = lqhTransConf->oldTcOpRec;
9804   Uint32 reqinfo     = lqhTransConf->requestInfo;
9805   Uint64 gci         = Uint64(lqhTransConf->gci_hi) << 32;
9806   cnodes[0]    = lqhTransConf->nextNodeId1;
9807   cnodes[1]    = lqhTransConf->nextNodeId2;
9808   cnodes[2]    = lqhTransConf->nextNodeId3;
9809   const BlockReference ref = lqhTransConf->apiRef;
9810   BlockReference applRef = lqhTransConf->apiRef;
9811   Uint32 applOprec   = lqhTransConf->apiOpRec;
9812   const Uint32 tableId = lqhTransConf->tableId;
9813   Uint32 gci_lo = lqhTransConf->gci_lo;
9814   Uint32 fragId = lqhTransConf->fragId;
9815 
9816   if (transStatus == LqhTransConf::Committed &&
9817       unlikely(signal->getLength() < LqhTransConf::SignalLength_GCI_LO))
9818   {
9819     jam();
9820     gci_lo = 0;
9821     ndbassert(!ndb_check_micro_gcp(getNodeInfo(nodeId).m_version));
9822   }
9823   gci |= gci_lo;
9824 
9825   if (transStatus == LqhTransConf::LastTransConf){
9826     jam();
9827     Uint32 maxInstanceId = lqhTransConf->maxInstanceId;
9828     if (unlikely(signal->getLength() < LqhTransConf::SignalLength_INST_ID))
9829     {
9830       maxInstanceId = 0;
9831     }
9832     ndbassert(maxInstanceId < NDBMT_MAX_BLOCK_INSTANCES);
9833     /* A node has reported one phase of take over handling as completed. */
9834     nodeTakeOverCompletedLab(signal, nodeId, maxInstanceId);
9835     return;
9836   }//if
9837   if (transStatus == LqhTransConf::Marker){
9838     jam();
9839     reqinfo = 0;
9840     LqhTransConf::setMarkerFlag(reqinfo, 1);
9841   } else {
9842     TableRecordPtr tabPtr;
9843     tabPtr.i = tableId;
9844     ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
9845     switch((DictTabInfo::TableType)tabPtr.p->tableType){
9846     case DictTabInfo::SystemTable:
9847     case DictTabInfo::UserTable:
9848       break;
9849     default:
9850       applRef = 0;
9851       applOprec = 0;
9852     }
9853   }
9854 
9855   if (findApiConnectFail(signal, transid1, transid2))
9856   {
9857     /**
9858      * Found a transaction record, record the added info about this
9859      * transaction as received in this message
9860      */
9861     updateApiStateFail(signal,
9862                        transid1,
9863                        transid2,
9864                        transStatus,
9865                        reqinfo,
9866                        applRef,
9867                        gci,
9868                        nodeId);
9869   }
9870   else
9871   {
9872     if (cfirstfreeApiConnectFail == RNIL)
9873     {
9874       jam();
9875       /**
9876        * We failed to allocate a transaction record, we will record that
9877        * we failed to handle all transactions and we will not allocate
9878        * any more transaction records as part of taking over this instance
9879        * of the failed TC. The failed transactions will be taken over in
9880        * a second step of the TC take over of this instance and possibly
9881        * even more than two steps will be performed.
9882        *
9883        * This could happen if the master node has less transaction records
9884        * than the failed node which is possible but not recommended.
9885        */
9886       Uint32 apiConnect = capiConnectFilesize / 3;
9887       g_eventLogger->info("Need to do another round of TC takeover handling."
9888                           " The failed node had a higher setting of "
9889                           "MaxNoOfConcurrentTransactions than this node has, "
9890                           "this node has MaxNoOfConcurrentTransactions = %u",
9891                           apiConnect);
9892       tcNodeFailptr.p->takeOverFailed = true;
9893       return;
9894     }
9895     else if (tcNodeFailptr.p->takeOverFailed)
9896     {
9897       jam();
9898       /**
9899        * After we failed to allocate a transaction record we won't
9900        * try to allocate any new ones since it might mean that we
9901        * miss operations of a transaction.
9902        */
9903       return;
9904     }
9905     /**
9906      * A new transaction was found, allocate a record for it and fill
9907      * it with info as received in LQH_TRANSCONF message. Also insert
9908      * it in hash table for transaction records in TC take over.
9909      */
9910     seizeApiConnectFail(signal);
9911     insert_transid_fail_hash(transid1);
9912     initApiConnectFail(signal,
9913                        transid1,
9914                        transid2,
9915                        transStatus,
9916                        reqinfo,
9917                        applRef,
9918                        gci,
9919                        nodeId);
9920   }
9921 
9922   if(apiConnectptr.p->ndbapiBlockref == 0 && applRef != 0)
9923   {
9924     jam();
9925     apiConnectptr.p->ndbapiBlockref = ref;
9926     apiConnectptr.p->ndbapiConnect = applOprec;
9927   }
9928 
9929   if (transStatus != LqhTransConf::Marker)
9930   {
9931     Uint32 instanceKey;
9932 
9933     if (unlikely(signal->getLength() < LqhTransConf::SignalLength_FRAG_ID))
9934     {
9935       jam();
9936       instanceKey = 0;
9937     }
9938     else
9939     {
9940       jam();
9941       instanceKey = getInstanceKey(tableId, fragId);
9942     }
9943     if (findTcConnectFail(signal, transid1, transid2, tcOprec))
9944     {
9945       jam();
9946       updateTcStateFail(signal,
9947                         instanceKey,
9948                         tcOprec,
9949                         reqinfo,
9950                         transStatus,
9951                         nodeId);
9952     }
9953     else
9954     {
9955       if (cfirstfreeTcConnectFail == RNIL)
9956       {
9957         /**
9958          * We failed to allocate a TC record, given that we can no longer
9959          * complete take over of this transaction we must handle the failed
9960          * transaction take over. We also set takeOverFailed to true to
9961          * ensure that we cannot start any new transaction take over after
9962          * this one. This is imperative to do since otherwise a new operation
9963          * on the failed transaction can come along and find free resources.
9964          * This would not be a correct behavior so we need to protect against
9965          * it by not starting any transactions after any seize failure.
9966          *
9967          * As long as we don't have transactions that are bigger than the
9968          * available number of TC records we should make progress at each
9969          * step and the algorithm should eventually complete.
9970          *
9971          * This could happen if the master node have fewer operation records
9972          * than the failed node had. This could happen but isn't
9973          * recommended.
9974          */
9975         Uint32 tcConnect = ctcConnectFilesize;
9976         jam();
9977         g_eventLogger->info("Need to do another round of TC takeover handling."
9978                             " The failed node had a higher setting of "
9979                             "MaxNoOfConcurrentOperations than this node has, "
9980                             "this node has MaxNoOfConcurrentOperations = %u",
9981                             tcConnect);
9982         tcNodeFailptr.p->takeOverFailed = true;
9983         remove_transaction_from_tc_fail_hash(signal);
9984         releaseMarker(apiConnectptr.p);
9985         remove_from_transid_fail_hash(signal, transid1);
9986         releaseTakeOver(signal);
9987       }
9988       else
9989       {
9990         jam();
9991         seizeTcConnectFail(signal);
9992         linkTcInConnectionlist(signal);
9993         insert_tc_fail_hash(transid1, tcOprec);
9994         initTcConnectFail(signal,
9995                           instanceKey,
9996                           tcOprec,
9997                           reqinfo,
9998                           transStatus,
9999                           nodeId);
10000       }
10001     }
10002   }
10003 }//Dbtc::execLQH_TRANSCONF()
10004 
10005 /*------------------------------------------------------------*/
10006 /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
10007 /*------------------------------------------------------------*/
nodeTakeOverCompletedLab(Signal * signal,NodeId nodeId,Uint32 maxInstanceId)10008 void Dbtc::nodeTakeOverCompletedLab(Signal* signal,
10009                                     NodeId nodeId,
10010                                     Uint32 maxInstanceId)
10011 {
10012   Uint32 guard0;
10013 
10014   CRASH_INSERTION(8061);
10015 
10016   if (unlikely(maxInstanceId >= NDBMT_MAX_BLOCK_INSTANCES))
10017   {
10018     /**
10019      * bug# 19193927 : LQH sends junk max instance id
10020      * Bug is fixed, but handle upgrade
10021      */
10022     maxInstanceId = NDBMT_MAX_BLOCK_INSTANCES - 1;
10023   }
10024   if (tcNodeFailptr.p->maxInstanceId < maxInstanceId)
10025   {
10026     jam();
10027     tcNodeFailptr.p->maxInstanceId = maxInstanceId;
10028   }
10029   hostptr.i = nodeId;
10030   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
10031   hostptr.p->lqhTransStatus = LTS_IDLE;
10032   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
10033     jam();
10034     ptrAss(hostptr, hostRecord);
10035     if (hostptr.p->hostStatus == HS_ALIVE) {
10036       if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
10037         jam();
10038         /*------------------------------------------------------------*/
10039         /*       NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE    */
10040         /*       TAKE OVER.                                           */
10041         /*------------------------------------------------------------*/
10042         return;
10043       }//if
10044     }//if
10045   }//for
10046   /*------------------------------------------------------------*/
10047   /*       ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
10048   /*       OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE  */
10049   /*       ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE       */
10050   /*       TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN     */
10051   /*       UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
10052   /*       TO THE APPLICATION IF THAT IS STILL ALIVE.           */
10053   /*------------------------------------------------------------*/
10054   tcNodeFailptr.p->currentHashIndexTakeOver = 0;
10055   tcNodeFailptr.p->completedTakeOver = 0;
10056   tcNodeFailptr.p->failStatus = FS_COMPLETING;
10057   guard0 = cnoParallelTakeOver - 1;
10058   /*------------------------------------------------------------*/
10059   /*       WE WILL COMPLETE THE TRANSACTIONS BY STARTING A      */
10060   /*       NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL    */
10061   /*       COMPLETE ONE TRANSACTION AT A TIME AND IN THAT       */
10062   /*       TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
10063   /*       WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
10064   /*       IS COMPLETED.                                        */
10065   /*------------------------------------------------------------*/
10066   arrGuard(guard0, MAX_NDB_NODES);
10067   for (tindex = 0; tindex <= guard0; tindex++) {
10068     jam();
10069     tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
10070     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
10071     signal->theData[1] = tcNodeFailptr.i;
10072     signal->theData[2] = tindex;
10073     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10074   }//for
10075 }//Dbtc::nodeTakeOverCompletedLab()
10076 
10077 /*------------------------------------------------------------*/
10078 /*       COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF    */
10079 /*       TRANSACTIONS TO COMPLETE.                            */
10080 /*------------------------------------------------------------*/
completeTransAtTakeOverLab(Signal * signal,UintR TtakeOverInd)10081 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
10082 {
10083   jam();
10084   while (tcNodeFailptr.p->currentHashIndexTakeOver < TRANSID_FAIL_HASH_SIZE)
10085   {
10086     jam();
10087     apiConnectptr.i =
10088         ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
10089     if (apiConnectptr.i != RNIL) {
10090       jam();
10091       /*------------------------------------------------------------*/
10092       /*       WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE         */
10093       /*       COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT   */
10094       /*       NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS     */
10095       /*       TRANSACTION.                                         */
10096       /*------------------------------------------------------------*/
10097       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10098       ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
10099         apiConnectptr.p->nextApiConnect;
10100       tcNodeFailptr.p->handledOneTransaction = true;
10101       completeTransAtTakeOverDoOne(signal, TtakeOverInd);
10102       // One transaction taken care of, return from this function
10103       // and wait for the next CONTINUEB to continue processing
10104       break;
10105 
10106     } else {
10107       if (tcNodeFailptr.p->currentHashIndexTakeOver <
10108           (TRANSID_FAIL_HASH_SIZE -1)){
10109         jam();
10110         tcNodeFailptr.p->currentHashIndexTakeOver++;
10111       } else {
10112         jam();
10113         completeTransAtTakeOverDoLast(signal, TtakeOverInd);
10114         tcNodeFailptr.p->currentHashIndexTakeOver++;
10115       }//if
10116     }//if
10117   }//while
10118 }//Dbtc::completeTransAtTakeOverLab()
10119 
10120 
completeTransAtTakeOverDoLast(Signal * signal,UintR TtakeOverInd)10121 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
10122 {
10123   Uint32 guard0;
10124   /*------------------------------------------------------------*/
10125   /*       THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS     */
10126   /*       ACTIVITY IS COMPLETED.                               */
10127   /*------------------------------------------------------------*/
10128   arrGuard(TtakeOverInd, MAX_NDB_NODES);
10129   if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
10130     jam();
10131     systemErrorLab(signal, __LINE__);
10132     return;
10133   }//if
10134   /**
10135    * If we need to continue with take over processing it will still be with
10136    * the same node.
10137    */
10138   if (tcNodeFailptr.p->takeOverFailed == ZTRUE)
10139   {
10140     /**
10141      * We performed a take over and it didn't complete, we will try
10142      * again. The reason it failed was due to this TC instance
10143      * not having sufficient resources to handle all transactions,
10144      * we should however make progress and thus eventually we should
10145      * be able to complete it. The only reason that it could completely
10146      * fail is if there is one transaction which is so big that we
10147      * cannot calculate its outcome.
10148      *
10149      * Given that we haven't completed this round, we continue with
10150      * one more attempt on the same TC instance.
10151      */
10152     jam();
10153     g_eventLogger->info("DBTC instance %u: Continuing take over of "
10154                         "DBTC instance %u in node %u",
10155                         instance(),
10156                         tcNodeFailptr.p->takeOverInstanceId,
10157                         tcNodeFailptr.p->takeOverNode);
10158     ndbrequire(tcNodeFailptr.p->handledOneTransaction);
10159     startTakeOverLab(signal,
10160                      tcNodeFailptr.p->takeOverInstanceId,
10161                      tcNodeFailptr.p->takeOverNode);
10162     return;
10163   }
10164   if (tcNodeFailptr.p->takeOverInstanceId < tcNodeFailptr.p->maxInstanceId)
10165   {
10166     /**
10167      * We deal with one TC instance at a time, we have completed one
10168      * instance and there are more instances to handle. Let's continue
10169      * with the next instance.
10170      */
10171     jam();
10172     g_eventLogger->info("DBTC instance %u: Completed take over of "
10173                         "DBTC instance %u in failed node %u,"
10174                         " continuing with the next instance",
10175                         instance(),
10176                         tcNodeFailptr.p->takeOverInstanceId,
10177                         tcNodeFailptr.p->takeOverNode);
10178     startTakeOverLab(signal,
10179                      tcNodeFailptr.p->takeOverInstanceId + 1,
10180                      tcNodeFailptr.p->takeOverNode);
10181     return;
10182   }
10183   /**
10184    * We have completed take over of this node for all its TC instances.
10185    * We will continue taking over other nodes if there are any more
10186    * nodes to take over.
10187    */
10188   tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
10189   tcNodeFailptr.p->completedTakeOver++;
10190 
10191   g_eventLogger->info("DBTC instance %u: Completed take over"
10192                       " of failed node %u",
10193                       instance(),
10194                       tcNodeFailptr.p->takeOverNode);
10195   CRASH_INSERTION(8062);
10196 
10197   if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
10198     jam();
10199     /*------------------------------------------------------------*/
10200     /*       WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
10201     /*       TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL     */
10202     /*       NODES THAT ARE ALIVE.                                */
10203     /*------------------------------------------------------------*/
10204     NodeReceiverGroup rg(DBTC, c_alive_nodes);
10205     signal->theData[0] = tcNodeFailptr.p->takeOverNode;
10206     signal->theData[1] = reference();
10207     sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 2, JBB);
10208 
10209     if (tcNodeFailptr.p->queueIndex > 0) {
10210       jam();
10211       /*------------------------------------------------------------*/
10212       /*       THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START  */
10213       /*       THE TAKE OVER.                                       */
10214       /*------------------------------------------------------------*/
10215       Uint32 failedNodeId = tcNodeFailptr.p->queueList[0];
10216       guard0 = tcNodeFailptr.p->queueIndex - 1;
10217       arrGuard(guard0 + 1, MAX_NDB_NODES);
10218       for (Uint32 i = 0; i <= guard0; i++) {
10219         jam();
10220         tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[i+1];
10221       }//for
10222       tcNodeFailptr.p->queueIndex--;
10223       g_eventLogger->info("DBTC instance %u: Starting next DBTC node"
10224                           " take over for failed node %u,"
10225                           " %u failed nodes remaining in takeover queue",
10226                           instance(),
10227                           failedNodeId,
10228                           tcNodeFailptr.p->queueIndex);
10229       startTakeOverLab(signal, 0, failedNodeId);
10230       return;
10231     } else {
10232       jam();
10233       tcNodeFailptr.p->failStatus = FS_IDLE;
10234     }//if
10235   }//if
10236   return;
10237 }//Dbtc::completeTransAtTakeOverDoLast()
10238 
completeTransAtTakeOverDoOne(Signal * signal,UintR TtakeOverInd)10239 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
10240 {
10241   apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
10242   apiConnectptr.p->takeOverInd = TtakeOverInd;
10243 
10244   switch (apiConnectptr.p->apiConnectstate) {
10245   case CS_FAIL_COMMITTED:
10246     jam();
10247     /*------------------------------------------------------------*/
10248     /*       ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
10249     /*       HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT  */
10250     /*       COMMITTED TO THE APPLICATION AND CONTINUE WITH THE   */
10251     /*       COMPLETE PHASE.                                      */
10252     /*------------------------------------------------------------*/
10253     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
10254     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10255     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10256     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
10257     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10258     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10259     commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
10260     toCompleteHandlingLab(signal);
10261     return;
10262   case CS_FAIL_COMMITTING:
10263     jam();
10264     /*------------------------------------------------------------*/
10265     /*       AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
10266     /*       PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
10267     /*       THEN CONTINUE AS AFTER COMMITTED.                    */
10268     /*------------------------------------------------------------*/
10269     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10270     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10271     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
10272     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10273     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10274     commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
10275     toCommitHandlingLab(signal);
10276     return;
10277   case CS_FAIL_ABORTING:
10278   case CS_FAIL_PREPARED:
10279     jam();
10280     /*------------------------------------------------------------*/
10281     /*       WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
10282     /*       STATE IN THIS VERSION. IN LATER VERSIONS WE WILL     */
10283     /*       HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT  */
10284     /*       TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
10285     /*       HAVE HEARD FROM THE TRANSACTION COORDINATOR.         */
10286     /*                                                            */
10287     /*       IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE       */
10288     /*       PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL  */
10289     /*       LATER VERSIONS.                                      */
10290     /*------------------------------------------------------------*/
10291     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10292     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10293     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
10294     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10295     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10296     toAbortHandlingLab(signal);
10297     return;
10298   case CS_FAIL_ABORTED:
10299     jam();
10300     sendTCKEY_FAILREF(signal, apiConnectptr.p);
10301 
10302     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
10303     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
10304     signal->theData[2] = apiConnectptr.p->takeOverInd;
10305     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10306     releaseTakeOver(signal);
10307     break;
10308   case CS_FAIL_COMPLETED:
10309     jam();
10310     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
10311 
10312     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
10313     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
10314     signal->theData[2] = apiConnectptr.p->takeOverInd;
10315     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10316     releaseApiConnectFail(signal);
10317     break;
10318   default:
10319     jam();
10320     systemErrorLab(signal, __LINE__);
10321     return;
10322   }//switch
10323 }//Dbtc::completeTransAtTakeOverDoOne()
10324 
10325 void
sendTCKEY_FAILREF(Signal * signal,ApiConnectRecord * regApiPtr)10326 Dbtc::sendTCKEY_FAILREF(Signal* signal, ApiConnectRecord * regApiPtr){
10327   jam();
10328 
10329   const Uint32 ref = regApiPtr->ndbapiBlockref;
10330   const NodeId nodeId = refToNode(ref);
10331   if(ref != 0)
10332   {
10333     jam();
10334     bool connectedToNode = getNodeInfo(nodeId).m_connected;
10335     signal->theData[0] = regApiPtr->ndbapiConnect;
10336     signal->theData[1] = regApiPtr->transid[0];
10337     signal->theData[2] = regApiPtr->transid[1];
10338 
10339     if (likely(connectedToNode))
10340     {
10341       jam();
10342       sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
10343     }
10344     else
10345     {
10346       routeTCKEY_FAILREFCONF(signal, regApiPtr, GSN_TCKEY_FAILREF, 3);
10347     }
10348   }
10349   releaseMarker(regApiPtr);
10350 }
10351 
10352 void
sendTCKEY_FAILCONF(Signal * signal,ApiConnectRecord * regApiPtr)10353 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
10354   jam();
10355   TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
10356 
10357   const Uint32 ref = regApiPtr->ndbapiBlockref;
10358   const Uint32 marker = regApiPtr->commitAckMarker;
10359   const NodeId nodeId = refToNode(ref);
10360   if(ref != 0)
10361   {
10362     jam();
10363     failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
10364     failConf->transId1 = regApiPtr->transid[0];
10365     failConf->transId2 = regApiPtr->transid[1];
10366 
10367     bool connectedToNode = getNodeInfo(nodeId).m_connected;
10368     if (likely(connectedToNode))
10369     {
10370       jam();
10371       sendSignal(ref, GSN_TCKEY_FAILCONF, signal,
10372 		 TcKeyFailConf::SignalLength, JBB);
10373     }
10374     else
10375     {
10376       routeTCKEY_FAILREFCONF(signal, regApiPtr,
10377 			     GSN_TCKEY_FAILCONF, TcKeyFailConf::SignalLength);
10378     }
10379   }
10380   regApiPtr->commitAckMarker = RNIL;
10381 }
10382 
10383 void
routeTCKEY_FAILREFCONF(Signal * signal,const ApiConnectRecord * regApiPtr,Uint32 gsn,Uint32 len)10384 Dbtc::routeTCKEY_FAILREFCONF(Signal* signal, const ApiConnectRecord* regApiPtr,
10385 			     Uint32 gsn, Uint32 len)
10386 {
10387   jam();
10388 
10389   Uint32 ref = regApiPtr->ndbapiBlockref;
10390 
10391   /**
10392    * We're not connected
10393    *   so we find another node in same node group as died node
10394    *   and send to it, so that it can forward
10395    */
10396   tcNodeFailptr.i = regApiPtr->takeOverRec;
10397   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
10398 
10399   /**
10400    * Save signal
10401    */
10402   Uint32 save[25];
10403   ndbrequire(len <= 25);
10404   memcpy(save, signal->theData, 4*len);
10405 
10406   Uint32 node = tcNodeFailptr.p->takeOverNode;
10407 
10408   CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
10409   sd->blockRef = reference();
10410   sd->requestType =
10411     CheckNodeGroups::Direct |
10412     CheckNodeGroups::GetNodeGroupMembers;
10413   sd->nodeId = node;
10414   EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
10415 		 CheckNodeGroups::SignalLength, 0);
10416   jamEntry();
10417 
10418   NdbNodeBitmask mask;
10419   mask.assign(sd->mask);
10420   mask.clear(getOwnNodeId());
10421   memcpy(signal->theData, save, 4*len);
10422 
10423   Uint32 i = 0;
10424   while((i = mask.find(i + 1)) != NdbNodeBitmask::NotFound)
10425   {
10426     jam();
10427     HostRecordPtr localHostptr;
10428     localHostptr.i = i;
10429     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
10430     if (localHostptr.p->hostStatus == HS_ALIVE)
10431     {
10432       jam();
10433       signal->theData[len] = gsn;
10434       signal->theData[len+1] = ref;
10435       sendSignal(calcTcBlockRef(i), GSN_TCKEY_FAILREFCONF_R,
10436 		 signal, len+2, JBB);
10437       return;
10438     }
10439   }
10440 
10441 
10442    /**
10443     * This code was 'unfinished' code for partially connected API's
10444     *   it does however not really work...
10445     *   and we seriously need to think about semantics for API connect
10446     */
10447 #if 0
10448   ndbrequire(getNodeInfo(refToNode(ref)).m_type == NodeInfo::DB);
10449 #endif
10450 }
10451 
10452 void
execTCKEY_FAILREFCONF_R(Signal * signal)10453 Dbtc::execTCKEY_FAILREFCONF_R(Signal* signal)
10454 {
10455   jamEntry();
10456   Uint32 len = signal->getLength();
10457   Uint32 gsn = signal->theData[len-2];
10458   Uint32 ref = signal->theData[len-1];
10459   sendSignal(ref, gsn, signal, len-2, JBB);
10460 }
10461 
10462 /*------------------------------------------------------------*/
10463 /*       THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A   */
10464 /*       NODE FAILURE BEFORE THE COMMIT DECISION.             */
10465 /*------------------------------------------------------------*/
10466 /*       ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID      */
10467 /*------------------------------------------------------------*/
execABORTCONF(Signal * signal)10468 void Dbtc::execABORTCONF(Signal* signal)
10469 {
10470   UintR compare_transid1, compare_transid2;
10471 
10472   jamEntry();
10473   tcConnectptr.i = signal->theData[0];
10474   NodeId nodeId = signal->theData[2];
10475   if (ERROR_INSERTED(8045)) {
10476     CLEAR_ERROR_INSERT_VALUE;
10477     sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
10478     return;
10479   }//if
10480   if (tcConnectptr.i >= ctcConnectFilesize) {
10481     errorReport(signal, 5);
10482     return;
10483   }//if
10484   ptrAss(tcConnectptr, tcConnectRecord);
10485   if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
10486     warningReport(signal, 16);
10487     return;
10488   }//if
10489   apiConnectptr.i = tcConnectptr.p->apiConnect;
10490   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10491   if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
10492     warningReport(signal, 17);
10493     return;
10494   }//if
10495   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
10496   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
10497   compare_transid1 = compare_transid1 | compare_transid2;
10498   if (compare_transid1 != 0) {
10499     warningReport(signal, 18);
10500     return;
10501   }//if
10502   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
10503   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
10504       nodeId) {
10505     warningReport(signal, 19);
10506     return;
10507   }//if
10508   tcurrentReplicaNo = (Uint8)Z8NIL;
10509   tcConnectptr.p->tcConnectstate = OS_ABORTING;
10510   toAbortHandlingLab(signal);
10511 }//Dbtc::execABORTCONF()
10512 
toAbortHandlingLab(Signal * signal)10513 void Dbtc::toAbortHandlingLab(Signal* signal)
10514 {
10515   do {
10516     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
10517       jam();
10518       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
10519       const LqhTransConf::OperationStatus stat =
10520 	(LqhTransConf::OperationStatus)
10521 	tcConnectptr.p->failData[tcurrentReplicaNo];
10522       switch(stat){
10523       case LqhTransConf::InvalidStatus:
10524       case LqhTransConf::Aborted:
10525         jam();
10526         /*empty*/;
10527         break;
10528       case LqhTransConf::Prepared:
10529         jam();
10530         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
10531         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
10532         if (hostptr.p->hostStatus == HS_ALIVE) {
10533           jam();
10534           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
10535           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
10536           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10537           tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
10538           apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
10539           apiConnectptr.p->timeOutCounter = 0;
10540           signal->theData[0] = tcConnectptr.i;
10541           signal->theData[1] = cownref;
10542           signal->theData[2] = apiConnectptr.p->transid[0];
10543           signal->theData[3] = apiConnectptr.p->transid[1];
10544           signal->theData[4] = apiConnectptr.p->tcBlockref;
10545           signal->theData[5] = tcConnectptr.p->tcOprec;
10546           sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
10547           return;
10548         }//if
10549         break;
10550       default:
10551         jam();
10552         systemErrorLab(signal, __LINE__);
10553         return;
10554       }//switch
10555     }//if
10556     if (apiConnectptr.p->currentReplicaNo > 0) {
10557       jam();
10558       /*------------------------------------------------------------*/
10559       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
10560       /*       ABORTED.                                             */
10561       /*------------------------------------------------------------*/
10562       apiConnectptr.p->currentReplicaNo--;
10563       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
10564     } else {
10565       /*------------------------------------------------------------*/
10566       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
10567       /*------------------------------------------------------------*/
10568       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
10569       if (tcConnectptr.i == RNIL) {
10570 	/*------------------------------------------------------------*/
10571 	/*       WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
10572 	/*       THE ABORT STATUS TO THE APPLICATION AND CONTINUE     */
10573 	/*       WITH THE NEXT TRANSACTION.                           */
10574 	/*------------------------------------------------------------*/
10575         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
10576           jam();
10577 	  sendTCKEY_FAILREF(signal, apiConnectptr.p);
10578 
10579 	  /*------------------------------------------------------------*/
10580 	  /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
10581 	  /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
10582 	  /*------------------------------------------------------------*/
10583           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
10584           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
10585           signal->theData[2] = apiConnectptr.p->takeOverInd;
10586           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10587           releaseTakeOver(signal);
10588         } else {
10589           jam();
10590           releaseAbortResources(signal);
10591         }//if
10592         return;
10593       }//if
10594       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
10595       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10596       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10597       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10598     }//if
10599   } while (1);
10600 }//Dbtc::toAbortHandlingLab()
10601 
10602 /*------------------------------------------------------------*/
10603 /*       THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A  */
10604 /*       NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE.      */
10605 /*------------------------------------------------------------*/
10606 /*       COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID     */
10607 /*------------------------------------------------------------*/
execCOMMITCONF(Signal * signal)10608 void Dbtc::execCOMMITCONF(Signal* signal)
10609 {
10610   UintR compare_transid1, compare_transid2;
10611 
10612   jamEntry();
10613   tcConnectptr.i = signal->theData[0];
10614   NodeId nodeId = signal->theData[1];
10615   if (ERROR_INSERTED(8046)) {
10616     CLEAR_ERROR_INSERT_VALUE;
10617     sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
10618     return;
10619   }//if
10620   if (tcConnectptr.i >= ctcConnectFilesize) {
10621     errorReport(signal, 4);
10622     return;
10623   }//if
10624   ptrAss(tcConnectptr, tcConnectRecord);
10625   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
10626     warningReport(signal, 8);
10627     return;
10628   }//if
10629   apiConnectptr.i = tcConnectptr.p->apiConnect;
10630   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10631   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
10632     warningReport(signal, 9);
10633     return;
10634   }//if
10635   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
10636   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
10637   compare_transid1 = compare_transid1 | compare_transid2;
10638   if (compare_transid1 != 0) {
10639     warningReport(signal, 10);
10640     return;
10641   }//if
10642   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
10643   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
10644       nodeId) {
10645     warningReport(signal, 11);
10646     return;
10647   }//if
10648   if (ERROR_INSERTED(8026)) {
10649     jam();
10650     systemErrorLab(signal, __LINE__);
10651   }//if
10652   tcurrentReplicaNo = (Uint8)Z8NIL;
10653   tcConnectptr.p->tcConnectstate = OS_COMMITTED;
10654   toCommitHandlingLab(signal);
10655 }//Dbtc::execCOMMITCONF()
10656 
toCommitHandlingLab(Signal * signal)10657 void Dbtc::toCommitHandlingLab(Signal* signal)
10658 {
10659   do {
10660     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
10661       jam();
10662       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
10663       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
10664       case LqhTransConf::InvalidStatus:
10665         jam();
10666         /*empty*/;
10667         break;
10668       case LqhTransConf::Committed:
10669         jam();
10670         /*empty*/;
10671         break;
10672       case LqhTransConf::Prepared:
10673         jam();
10674         /*------------------------------------------------------------*/
10675         /*       THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR    */
10676         /*       COMMIT REQUEST FROM TC.                              */
10677         /*------------------------------------------------------------*/
10678         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
10679         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
10680         if (hostptr.p->hostStatus == HS_ALIVE) {
10681           jam();
10682           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
10683           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
10684           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10685           apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
10686           apiConnectptr.p->timeOutCounter = 0;
10687           tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
10688           Uint64 gci = apiConnectptr.p->globalcheckpointid;
10689           signal->theData[0] = tcConnectptr.i;
10690           signal->theData[1] = cownref;
10691           signal->theData[2] = Uint32(gci >> 32); // XXX JON
10692           signal->theData[3] = apiConnectptr.p->transid[0];
10693           signal->theData[4] = apiConnectptr.p->transid[1];
10694           signal->theData[5] = apiConnectptr.p->tcBlockref;
10695           signal->theData[6] = tcConnectptr.p->tcOprec;
10696           signal->theData[7] = Uint32(gci);
10697           sendSignal(tblockref, GSN_COMMITREQ, signal, 8, JBB);
10698           return;
10699         }//if
10700         break;
10701       default:
10702         jam();
10703         systemErrorLab(signal, __LINE__);
10704         return;
10705         break;
10706       }//switch
10707     }//if
10708     if (apiConnectptr.p->currentReplicaNo > 0) {
10709       jam();
10710       /*------------------------------------------------------------*/
10711       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
10712       /*       COMMITTED.                                           */
10713       /*------------------------------------------------------------*/
10714       apiConnectptr.p->currentReplicaNo--;
10715       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
10716     } else {
10717       /*------------------------------------------------------------*/
10718       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
10719       /*------------------------------------------------------------*/
10720       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
10721       if (tcConnectptr.i == RNIL) {
10722 	/*------------------------------------------------------------*/
10723 	/*       WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
10724 	/*       THE COMMIT STATUS TO THE APPLICATION AND CONTINUE    */
10725 	/*       WITH THE COMPLETE PHASE.                             */
10726 	/*------------------------------------------------------------*/
10727         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
10728           jam();
10729 	  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
10730 	} else {
10731           jam();
10732           apiConnectptr = sendApiCommit(signal);
10733         }//if
10734         apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
10735         tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10736         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10737         tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10738         apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
10739         toCompleteHandlingLab(signal);
10740         return;
10741       }//if
10742       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
10743       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10744       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10745       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10746     }//if
10747   } while (1);
10748 }//Dbtc::toCommitHandlingLab()
10749 
10750 /*------------------------------------------------------------*/
10751 /*       COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE   */
10752 /*       HAVE FAILED.                                         */
10753 /*------------------------------------------------------------*/
10754 /*       THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION   */
10755 /*------------------------------------------------------------*/
execCOMPLETECONF(Signal * signal)10756 void Dbtc::execCOMPLETECONF(Signal* signal)
10757 {
10758   UintR compare_transid1, compare_transid2;
10759 
10760   jamEntry();
10761   tcConnectptr.i = signal->theData[0];
10762   NodeId nodeId = signal->theData[1];
10763   if (ERROR_INSERTED(8047)) {
10764     CLEAR_ERROR_INSERT_VALUE;
10765     sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
10766     return;
10767   }//if
10768   if (tcConnectptr.i >= ctcConnectFilesize) {
10769     errorReport(signal, 3);
10770     return;
10771   }//if
10772   ptrAss(tcConnectptr, tcConnectRecord);
10773   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
10774     warningReport(signal, 12);
10775     return;
10776   }//if
10777   apiConnectptr.i = tcConnectptr.p->apiConnect;
10778   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10779   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
10780     warningReport(signal, 13);
10781     return;
10782   }//if
10783   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
10784   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
10785   compare_transid1 = compare_transid1 | compare_transid2;
10786   if (compare_transid1 != 0) {
10787     warningReport(signal, 14);
10788     return;
10789   }//if
10790   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
10791   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
10792       nodeId) {
10793     warningReport(signal, 15);
10794     return;
10795   }//if
10796   if (ERROR_INSERTED(8028)) {
10797     jam();
10798     systemErrorLab(signal, __LINE__);
10799   }//if
10800   tcConnectptr.p->tcConnectstate = OS_COMPLETED;
10801   tcurrentReplicaNo = (Uint8)Z8NIL;
10802   toCompleteHandlingLab(signal);
10803 }//Dbtc::execCOMPLETECONF()
10804 
toCompleteHandlingLab(Signal * signal)10805 void Dbtc::toCompleteHandlingLab(Signal* signal)
10806 {
10807   do {
10808     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
10809       jam();
10810       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
10811       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
10812       case LqhTransConf::InvalidStatus:
10813         jam();
10814         /*empty*/;
10815         break;
10816       default:
10817         jam();
10818         /*------------------------------------------------------------*/
10819         /*       THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
10820         /*       IT MUST HAVE FAILED.                                 */
10821         /*------------------------------------------------------------*/
10822         /*------------------------------------------------------------*/
10823         /*       SEND COMPLETEREQ TO THE NEXT REPLICA.                */
10824         /*------------------------------------------------------------*/
10825         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
10826         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
10827         if (hostptr.p->hostStatus == HS_ALIVE) {
10828           jam();
10829           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
10830           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
10831           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10832           tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
10833           apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
10834           apiConnectptr.p->timeOutCounter = 0;
10835           tcConnectptr.p->apiConnect = apiConnectptr.i;
10836           signal->theData[0] = tcConnectptr.i;
10837           signal->theData[1] = cownref;
10838           signal->theData[2] = apiConnectptr.p->transid[0];
10839           signal->theData[3] = apiConnectptr.p->transid[1];
10840           signal->theData[4] = apiConnectptr.p->tcBlockref;
10841           signal->theData[5] = tcConnectptr.p->tcOprec;
10842           sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
10843           return;
10844         }//if
10845         break;
10846       }//switch
10847     }//if
10848     if (apiConnectptr.p->currentReplicaNo != 0) {
10849       jam();
10850       /*------------------------------------------------------------*/
10851       /*       THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE  */
10852       /*       NEED TO CONTINUE WITH THOSE REPLICAS.                */
10853       /*------------------------------------------------------------*/
10854       apiConnectptr.p->currentReplicaNo--;
10855       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
10856     } else {
10857       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
10858       if (tcConnectptr.i == RNIL) {
10859         /*------------------------------------------------------------*/
10860         /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
10861         /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
10862         /*------------------------------------------------------------*/
10863         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
10864           jam();
10865           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
10866           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
10867           signal->theData[2] = apiConnectptr.p->takeOverInd;
10868           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10869           handleGcp(signal, apiConnectptr);
10870           releaseTakeOver(signal);
10871         } else {
10872           jam();
10873           releaseTransResources(signal);
10874         }//if
10875         return;
10876       }//if
10877       /*------------------------------------------------------------*/
10878       /*       WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
10879       /*       COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
10880       /*       FIRST REPLICA SINCE IT IS THE COMPLETE PHASE.        */
10881       /*------------------------------------------------------------*/
10882       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
10883       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10884       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10885       apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
10886     }//if
10887   } while (1);
10888 }//Dbtc::toCompleteHandlingLab()
10889 
10890 /*----------------------------------------------------------*/
10891 /*       INITIALISE AN API CONNECT FAIL RECORD              */
10892 /*----------------------------------------------------------*/
initApiConnectFail(Signal * signal,Uint32 transid1,Uint32 transid2,LqhTransConf::OperationStatus transStatus,Uint32 reqinfo,BlockReference applRef,Uint64 gci,NodeId nodeId)10893 void Dbtc::initApiConnectFail(Signal* signal,
10894                               Uint32 transid1,
10895                               Uint32 transid2,
10896                               LqhTransConf::OperationStatus transStatus,
10897                               Uint32 reqinfo,
10898                               BlockReference applRef,
10899                               Uint64 gci,
10900                               NodeId nodeId)
10901 {
10902   apiConnectptr.p->transid[0] = transid1;
10903   apiConnectptr.p->transid[1] = transid2;
10904   apiConnectptr.p->firstTcConnect = RNIL;
10905   apiConnectptr.p->currSavePointId = 0;
10906   apiConnectptr.p->lastTcConnect = RNIL;
10907   BlockReference blockRef = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
10908 
10909   apiConnectptr.p->tcBlockref = blockRef;
10910   apiConnectptr.p->ndbapiBlockref = 0;
10911   apiConnectptr.p->ndbapiConnect = 0;
10912   apiConnectptr.p->buddyPtr = RNIL;
10913   apiConnectptr.p->m_transaction_nodes.clear();
10914   apiConnectptr.p->singleUserMode = 0;
10915   setApiConTimer(apiConnectptr.i, 0, __LINE__);
10916   switch(transStatus){
10917   case LqhTransConf::Committed:
10918     jam();
10919     apiConnectptr.p->globalcheckpointid = gci;
10920     apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
10921     break;
10922   case LqhTransConf::Prepared:
10923     jam();
10924     apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
10925     break;
10926   case LqhTransConf::Aborted:
10927     jam();
10928     apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
10929     break;
10930   case LqhTransConf::Marker:
10931     jam();
10932     apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
10933     break;
10934   default:
10935     jam();
10936     systemErrorLab(signal, __LINE__);
10937   }//if
10938   apiConnectptr.p->commitAckMarker = RNIL;
10939   if(LqhTransConf::getMarkerFlag(reqinfo)){
10940     jam();
10941     CommitAckMarkerPtr tmp;
10942 
10943     {
10944       CommitAckMarker key;
10945       key.transid1 = transid1;
10946       key.transid2 = transid2;
10947       if (m_commitAckMarkerHash.find(tmp, key))
10948       {
10949         /**
10950          * We found a "lingering" marker...
10951          *   most probably from earlier node failure
10952          *   check consistency using lots of it-statements
10953          */
10954         jam();
10955         if (tmp.p->apiConnectPtr == RNIL)
10956         {
10957           jam();
10958           // ok - marker had no transaction, use it...
10959         }
10960         else
10961         {
10962           ApiConnectRecordPtr transPtr;
10963           transPtr.i = tmp.p->apiConnectPtr;
10964           ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
10965           if (transPtr.p->commitAckMarker == RNIL)
10966           {
10967             jam();
10968             // ok - marker had a transaction that had moved on, use it...
10969           }
10970           else if (transPtr.p->commitAckMarker != tmp.i)
10971           {
10972             jam();
10973             // ok - marker had a transaction that had moved on, use it...
10974           }
10975           else
10976           {
10977             jam();
10978             /**
10979              * marker pointed to a transaction that was pointing to marker...
10980              *   i.e both transaction + marker lingering...
10981              *   treat this as an updateApiStateFail and release already seize trans
10982              */
10983             releaseApiConnectFail(signal);
10984             apiConnectptr = transPtr;
10985             updateApiStateFail(signal,
10986                                transid1,
10987                                transid2,
10988                                transStatus,
10989                                reqinfo,
10990                                applRef,
10991                                gci,
10992                                nodeId);
10993             return;
10994           }
10995         }
10996       }
10997       else
10998       {
10999         jam();
11000         m_commitAckMarkerHash.seize(tmp);
11001         ndbrequire(tmp.i != RNIL);
11002         new (tmp.p) CommitAckMarker();
11003         tmp.p->transid1      = transid1;
11004         tmp.p->transid2      = transid2;
11005         m_commitAckMarkerHash.add(tmp);
11006       }
11007     }
11008 
11009     apiConnectptr.p->commitAckMarker = tmp.i;
11010     tmp.p->apiNodeId     = refToNode(applRef);
11011     tmp.p->apiConnectPtr = apiConnectptr.i;
11012     ndbrequire(tmp.p->insert_in_commit_ack_marker_all(this, nodeId));
11013   }
11014 }//Dbtc::initApiConnectFail()
11015 
11016 /*------------------------------------------------------------*/
11017 /*       INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
11018 /*       THE TC CONNECT RECORD.                               */
11019 /*------------------------------------------------------------*/
initTcConnectFail(Signal * signal,Uint32 instanceKey,Uint32 tcOprec,Uint32 reqinfo,LqhTransConf::OperationStatus transStatus,NodeId nodeId)11020 void Dbtc::initTcConnectFail(Signal* signal,
11021                              Uint32 instanceKey,
11022                              Uint32 tcOprec,
11023                              Uint32 reqinfo,
11024                              LqhTransConf::OperationStatus transStatus,
11025                              NodeId nodeId)
11026 {
11027   TcConnectRecord * regTcPtr = tcConnectptr.p;
11028   regTcPtr->apiConnect = apiConnectptr.i;
11029   regTcPtr->tcOprec = tcOprec;
11030   Uint32 replicaNo = LqhTransConf::getReplicaNo(reqinfo);
11031   for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
11032     regTcPtr->failData[i] = LqhTransConf::InvalidStatus;
11033   }//for
11034   regTcPtr->tcNodedata[replicaNo] = nodeId;
11035   regTcPtr->failData[replicaNo] = transStatus;
11036   regTcPtr->lastReplicaNo = LqhTransConf::getLastReplicaNo(reqinfo);
11037   regTcPtr->dirtyOp = LqhTransConf::getDirtyFlag(reqinfo);
11038   regTcPtr->lqhInstanceKey = instanceKey;
11039 }//Dbtc::initTcConnectFail()
11040 
11041 /*----------------------------------------------------------*/
11042 /*       INITIALISE TC NODE FAIL RECORD.                    */
11043 /*----------------------------------------------------------*/
initTcFail(Signal * signal)11044 void Dbtc::initTcFail(Signal* signal)
11045 {
11046   tcNodeFailptr.i = 0;
11047   ptrAss(tcNodeFailptr, tcFailRecord);
11048   tcNodeFailptr.p->queueIndex = 0;
11049   tcNodeFailptr.p->failStatus = FS_IDLE;
11050 }//Dbtc::initTcFail()
11051 
11052 /*----------------------------------------------------------*/
11053 /*               RELEASE_TAKE_OVER                          */
11054 /*----------------------------------------------------------*/
releaseTakeOver(Signal * signal)11055 void Dbtc::releaseTakeOver(Signal* signal)
11056 {
11057   TcConnectRecordPtr rtoNextTcConnectptr;
11058 
11059   rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
11060   do {
11061     jam();
11062     tcConnectptr.i = rtoNextTcConnectptr.i;
11063     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11064     rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
11065     releaseTcConnectFail(signal);
11066   } while (rtoNextTcConnectptr.i != RNIL);
11067   releaseApiConnectFail(signal);
11068 }//Dbtc::releaseTakeOver()
11069 
11070 /*---------------------------------------------------------------------------*/
11071 /*                               SETUP_FAIL_DATA                             */
11072 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE      */
11073 /* FAILURE SITUATIONS.                                                       */
11074 /*---------------------------------------------------------------------------*/
setupFailData(Signal * signal)11075 void Dbtc::setupFailData(Signal* signal)
11076 {
11077   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
11078   do {
11079     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11080     switch (tcConnectptr.p->tcConnectstate) {
11081     case OS_PREPARED:
11082     case OS_COMMITTING:
11083       jam();
11084       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
11085       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
11086 	jam();
11087 	/*-------------------------------------------------------------------
11088 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
11089 	 * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
11090 	 * COMMIT/ABORT DECISION.
11091 	 *------------------------------------------------------------------*/
11092 	tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
11093       }//for
11094       break;
11095     case OS_COMMITTED:
11096     case OS_COMPLETING:
11097       jam();
11098       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
11099       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
11100 	jam();
11101 	/*-------------------------------------------------------------------
11102 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
11103 	 * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
11104 	 * COMPLETE MESSAGE.
11105 	 *------------------------------------------------------------------*/
11106 	tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
11107       }//for
11108       break;
11109     case OS_COMPLETED:
11110       jam();
11111       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
11112       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
11113 	jam();
11114 	/*-------------------------------------------------------------------
11115 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
11116 	 * IN THIS CASE ALL LQH'S ARE COMPLETED.
11117 	 *-------------------------------------------------------------------*/
11118 	tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
11119       }//for
11120       break;
11121     default:
11122       jam();
11123       sendSystemError(signal, __LINE__);
11124       break;
11125     }//switch
11126     if (tabortInd != ZCOMMIT_SETUP) {
11127       jam();
11128       for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
11129         hostptr.i = tcConnectptr.p->tcNodedata[Ti];
11130         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
11131         if (hostptr.p->hostStatus != HS_ALIVE) {
11132           jam();
11133 	  /*-----------------------------------------------------------------
11134 	   * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
11135 	   *-----------------------------------------------------------------*/
11136           tabortInd = ZTRUE;
11137         }//if
11138       }//for
11139     }//if
11140     tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
11141     tcConnectptr.p->tcOprec = tcConnectptr.i;
11142     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
11143   } while (tcConnectptr.i != RNIL);
11144   apiConnectptr.p->tcBlockref = cownref;
11145   apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
11146   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
11147   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11148   apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
11149   tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
11150 }//Dbtc::setupFailData()
11151 
11152 /*----------------------------------------------------------*/
11153 /*       UPDATE THE STATE OF THE API CONNECT FOR THIS PART.   */
11154 /*----------------------------------------------------------*/
updateApiStateFail(Signal * signal,Uint32 transid1,Uint32 transid2,LqhTransConf::OperationStatus transStatus,Uint32 reqinfo,BlockReference applRef,Uint64 gci,NodeId nodeId)11155 void Dbtc::updateApiStateFail(Signal* signal,
11156                               Uint32 transid1,
11157                               Uint32 transid2,
11158                               LqhTransConf::OperationStatus transStatus,
11159                               Uint32 reqinfo,
11160                               BlockReference applRef,
11161                               Uint64 gci,
11162                               NodeId nodeId)
11163 {
11164   if(LqhTransConf::getMarkerFlag(reqinfo))
11165   {
11166     CommitAckMarkerPtr tmp;
11167     const Uint32 marker = apiConnectptr.p->commitAckMarker;
11168     if (marker == RNIL)
11169     {
11170       jam();
11171 
11172       m_commitAckMarkerHash.seize(tmp);
11173       ndbrequire(tmp.i != RNIL);
11174 
11175       new (tmp.p) CommitAckMarker();
11176       apiConnectptr.p->commitAckMarker = tmp.i;
11177       tmp.p->transid1      = transid1;
11178       tmp.p->transid2      = transid2;
11179       tmp.p->apiNodeId     = refToNode(applRef);
11180       tmp.p->apiConnectPtr = apiConnectptr.i;
11181 #if defined VM_TRACE || defined ERROR_INSERT
11182       {
11183 	CommitAckMarkerPtr check;
11184 	ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
11185       }
11186 #endif
11187       m_commitAckMarkerHash.add(tmp);
11188     } else {
11189       jam();
11190       tmp.i = marker;
11191       tmp.p = m_commitAckMarkerHash.getPtr(marker);
11192 
11193       ndbrequire(tmp.p->transid1 == transid1);
11194       ndbrequire(tmp.p->transid2 == transid2);
11195     }
11196     ndbrequire(tmp.p->insert_in_commit_ack_marker_all(this, nodeId));
11197   }
11198 
11199   switch (transStatus) {
11200   case LqhTransConf::Committed:
11201     jam();
11202     switch (apiConnectptr.p->apiConnectstate) {
11203     case CS_FAIL_COMMITTING:
11204     case CS_FAIL_COMMITTED:
11205       jam();
11206       ndbrequire(gci == apiConnectptr.p->globalcheckpointid);
11207       break;
11208     case CS_FAIL_PREPARED:
11209       jam();
11210       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
11211       apiConnectptr.p->globalcheckpointid = gci;
11212       break;
11213     case CS_FAIL_COMPLETED:
11214       jam();
11215       apiConnectptr.p->globalcheckpointid = gci;
11216       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
11217       break;
11218     default:
11219       jam();
11220       systemErrorLab(signal, __LINE__);
11221       break;
11222     }//switch
11223     break;
11224   case LqhTransConf::Prepared:
11225     jam();
11226     switch (apiConnectptr.p->apiConnectstate) {
11227     case CS_FAIL_COMMITTED:
11228       jam();
11229       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
11230       break;
11231     case CS_FAIL_ABORTED:
11232       jam();
11233       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
11234       break;
11235     case CS_FAIL_COMMITTING:
11236     case CS_FAIL_PREPARED:
11237     case CS_FAIL_ABORTING:
11238       jam();
11239       /*empty*/;
11240       break;
11241     default:
11242       jam();
11243       systemErrorLab(signal, __LINE__);
11244       break;
11245     }//switch
11246     break;
11247   case LqhTransConf::Aborted:
11248     jam();
11249     switch (apiConnectptr.p->apiConnectstate) {
11250     case CS_FAIL_COMMITTING:
11251     case CS_FAIL_COMMITTED:
11252       jam();
11253       systemErrorLab(signal, __LINE__);
11254       break;
11255     case CS_FAIL_PREPARED:
11256       jam();
11257       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
11258       break;
11259     case CS_FAIL_ABORTING:
11260     case CS_FAIL_ABORTED:
11261       jam();
11262       /*empty*/;
11263       break;
11264     default:
11265       jam();
11266       systemErrorLab(signal, __LINE__);
11267       break;
11268     }//switch
11269     break;
11270   case LqhTransConf::Marker:
11271     jam();
11272     break;
11273   default:
11274     jam();
11275     systemErrorLab(signal, __LINE__);
11276     break;
11277   }//switch
11278 }//Dbtc::updateApiStateFail()
11279 
11280 /*------------------------------------------------------------*/
11281 /*               UPDATE_TC_STATE_FAIL                         */
11282 /*                                                            */
11283 /*       WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
11284 /*       WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY      */
11285 /*       BETWEEN THE DIFFERENT REPLICAS.                      */
11286 /*------------------------------------------------------------*/
updateTcStateFail(Signal * signal,Uint32 instanceKey,Uint32 tcOprec,Uint32 reqinfo,LqhTransConf::OperationStatus transStatus,NodeId nodeId)11287 void Dbtc::updateTcStateFail(Signal* signal,
11288                              Uint32 instanceKey,
11289                              Uint32 tcOprec,
11290                              Uint32 reqinfo,
11291                              LqhTransConf::OperationStatus transStatus,
11292                              NodeId nodeId)
11293 {
11294   const Uint8 replicaNo     = LqhTransConf::getReplicaNo(reqinfo);
11295   const Uint8 lastReplicaNo = LqhTransConf::getLastReplicaNo(reqinfo);
11296   const Uint8 dirtyOp       = LqhTransConf::getDirtyFlag(reqinfo);
11297 
11298   TcConnectRecord * regTcPtr = tcConnectptr.p;
11299 
11300   ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
11301   ndbrequire(regTcPtr->failData[replicaNo] == LqhTransConf::InvalidStatus);
11302   ndbrequire(regTcPtr->lastReplicaNo == lastReplicaNo);
11303   ndbrequire(regTcPtr->dirtyOp == dirtyOp);
11304 
11305   regTcPtr->tcNodedata[replicaNo] = nodeId;
11306   regTcPtr->failData[replicaNo] = transStatus;
11307   ndbrequire(regTcPtr->tcOprec == tcOprec);
11308   ndbrequire(regTcPtr->lqhInstanceKey == instanceKey)
11309 }//Dbtc::updateTcStateFail()
11310 
execTCGETOPSIZEREQ(Signal * signal)11311 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
11312 {
11313   jamEntry();
11314   CRASH_INSERTION(8000);
11315 
11316   UintR Tuserpointer = signal->theData[0];         /* DBDIH POINTER         */
11317   BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
11318   signal->theData[0] = Tuserpointer;
11319   signal->theData[1] = coperationsize;
11320   sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
11321 }//Dbtc::execTCGETOPSIZEREQ()
11322 
execTC_CLOPSIZEREQ(Signal * signal)11323 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
11324 {
11325   jamEntry();
11326   CRASH_INSERTION(8001);
11327 
11328   tuserpointer = signal->theData[0];
11329   tusersblkref = signal->theData[1];
11330                                             /* DBDIH BLOCK REFERENCE         */
11331   coperationsize = 0;
11332   signal->theData[0] = tuserpointer;
11333   sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
11334 }//Dbtc::execTC_CLOPSIZEREQ()
11335 
11336 /* ######################################################################### */
11337 /* #######                        ERROR MODULE                       ####### */
11338 /* ######################################################################### */
tabStateErrorLab(Signal * signal)11339 void Dbtc::tabStateErrorLab(Signal* signal)
11340 {
11341   terrorCode = ZSTATE_ERROR;
11342   releaseAtErrorLab(signal);
11343 }//Dbtc::tabStateErrorLab()
11344 
wrongSchemaVersionErrorLab(Signal * signal)11345 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
11346 {
11347   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
11348 
11349   TableRecordPtr tabPtr;
11350   tabPtr.i = tcKeyReq->tableId;
11351   const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
11352   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
11353 
11354   terrorCode = tabPtr.p->getErrorCode(schemVer);
11355 
11356   abortErrorLab(signal);
11357 }//Dbtc::wrongSchemaVersionErrorLab()
11358 
noFreeConnectionErrorLab(Signal * signal)11359 void Dbtc::noFreeConnectionErrorLab(Signal* signal)
11360 {
11361   terrorCode = ZNO_FREE_TC_CONNECTION;
11362   abortErrorLab(signal);        /* RECORD. OTHERWISE GOTO ERRORHANDLING  */
11363 }//Dbtc::noFreeConnectionErrorLab()
11364 
aiErrorLab(Signal * signal)11365 void Dbtc::aiErrorLab(Signal* signal)
11366 {
11367   terrorCode = ZLENGTH_ERROR;
11368   abortErrorLab(signal);
11369 }//Dbtc::aiErrorLab()
11370 
seizeDatabuferrorLab(Signal * signal)11371 void Dbtc::seizeDatabuferrorLab(Signal* signal)
11372 {
11373   terrorCode = ZGET_DATAREC_ERROR;
11374   releaseAtErrorLab(signal);
11375 }//Dbtc::seizeDatabuferrorLab()
11376 
appendToSectionErrorLab(Signal * signal)11377 void Dbtc::appendToSectionErrorLab(Signal* signal)
11378 {
11379   terrorCode = ZGET_DATAREC_ERROR;
11380   releaseAtErrorLab(signal);
11381 }//Dbtc::appendToSectionErrorLab
11382 
releaseAtErrorLab(Signal * signal)11383 void Dbtc::releaseAtErrorLab(Signal* signal)
11384 {
11385   ptrGuard(tcConnectptr);
11386   tcConnectptr.p->tcConnectstate = OS_ABORTING;
11387   /*-------------------------------------------------------------------------*
11388    * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
11389    * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
11390    * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
11391    * TO HANDLE THIS PROBLEM.
11392    * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
11393    * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
11394    * ANY SIGNALS.
11395    *-------------------------------------------------------------------------*/
11396   tcConnectptr.p->noOfNodes = 0;
11397   abortErrorLab(signal);
11398 }//Dbtc::releaseAtErrorLab()
11399 
warningHandlerLab(Signal * signal,int line)11400 void Dbtc::warningHandlerLab(Signal* signal, int line)
11401 {
11402   ndbassert(false);
11403 }//Dbtc::warningHandlerLab()
11404 
systemErrorLab(Signal * signal,int line)11405 void Dbtc::systemErrorLab(Signal* signal, int line)
11406 {
11407   progError(line, NDBD_EXIT_NDBREQUIRE);
11408 }//Dbtc::systemErrorLab()
11409 
11410 
11411 #ifdef ERROR_INSERT
testFragmentDrop(Signal * signal)11412 bool Dbtc::testFragmentDrop(Signal* signal)
11413 {
11414   Uint32 fragIdToDrop= ~0;
11415   /* Drop some fragments to test the dropped fragment handling code */
11416   if (ERROR_INSERTED(8074))
11417     fragIdToDrop= 1;
11418   else if (ERROR_INSERTED(8075))
11419     fragIdToDrop= 2;
11420   else if (ERROR_INSERTED(8076))
11421     fragIdToDrop= 3;
11422 
11423   if ((signal->header.m_fragmentInfo == fragIdToDrop) ||
11424       ERROR_INSERTED(8077)) // Drop all fragments
11425   {
11426     /* This signal fragment should be dropped
11427      * Let's throw away the sections, and call the
11428      * signal dropped report handler
11429      * This code is replicating the effect of the code in
11430      * TransporterCallback::deliver_signal()
11431      */
11432     SectionHandle handle(this, signal);
11433     Uint32 secCount= handle.m_cnt;
11434     releaseSections(handle);
11435     SignalDroppedRep* rep = (SignalDroppedRep*)signal->theData;
11436     Uint32 gsn = signal->header.theVerId_signalNumber;
11437     Uint32 len = signal->header.theLength;
11438     Uint32 newLen= (len > 22 ? 22 : len);
11439     memmove(rep->originalData, signal->theData, (4 * newLen));
11440     rep->originalGsn = gsn;
11441     rep->originalLength = len;
11442     rep->originalSectionCount = secCount;
11443     signal->header.theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
11444     signal->header.theLength = newLen + 3;
11445     signal->header.m_noOfSections = 0;
11446 
11447     executeFunction(GSN_SIGNAL_DROPPED_REP, signal);
11448     return true;
11449   }
11450   return false;
11451 }
11452 #endif
11453 
11454 /* ######################################################################### *
11455  * #######                        SCAN MODULE                        ####### *
11456  * ######################################################################### *
11457 
11458   The application orders a scan of a table.  We divide the scan into a scan on
11459   each fragment.  The scan uses the primary replicas since the scan might be
11460   used for an update in a separate transaction.
11461 
11462   Scans are always done as a separate transaction.  Locks from the scan
11463   can be overtaken by another transaction.  Scans can never lock the entire
11464   table.  Locks are released immediately after the read has been verified
11465   by the application. There is not even an option to leave the locks.
11466   The reason is that this would hurt real-time behaviour too much.
11467 
11468   -#  The first step in handling a scan of a table is to receive all signals
11469       defining the scan. If failures occur during this step we release all
11470       resource and reply with SCAN_TABREF providing the error code.
11471       If system load is too high, the request will not be allowed.
11472 
11473   -#  The second step retrieves the number of fragments that exist in the
11474       table. It also ensures that the table actually exist.  After this,
11475       the scan is ready to be parallelised.  The idea is that the receiving
11476       process (hereafter called delivery process) will start up a number
11477       of scan processes.  Each of these scan processes will
11478       independently scan one fragment at a time.  The delivery
11479       process object is the scan record and the scan process object is
11480       the scan fragment record plus the scan operation record.
11481 
11482   -#  The third step is thus performed in parallel. In the third step each
11483       scan process retrieves the primary replica of the fragment it will
11484       scan.  Then it starts the scan as soon as the load on that node permits.
11485 
11486   The LQH returns either when it retrieved the maximum number of tuples or
11487   when it has retrived at least one tuple and is hindered by a lock to
11488   retrieve the next tuple.  This is to ensure that a scan process never
11489   can be involved in a deadlock situation.
11490 
11491   Tuples from each fragment scan are sent directly to API from TUP, and tuples
11492   from different fragments are delivered in parallel (so will be interleaved
11493   when received).
11494 
11495   When a batch of tuples from one fragment has been fully fetched, the scan of
11496   that fragment will not continue until the previous batch has been
11497   acknowledged by API with a SCAN_NEXTREQ signal.
11498 
11499 
11500   ERROR HANDLING
11501 
11502   As already mentioned it is rather easy to handle errors before the scan
11503   processes have started.  In this case it is enough to release the resources
11504   and send SCAN_TAB_REF.
11505 
11506   If an error occurs in any of the scan processes then we have to stop all
11507   scan processes. We do however only stop the delivery process and ask
11508   the api to order us to close the scan.  The reason is that we can easily
11509   enter into difficult timing problems since the application and this
11510   block is out of synch we will thus always start by report the error to
11511   the application and wait for a close request. This error report uses the
11512   SCAN_TABREF signal with a special error code that the api must check for.
11513 
11514 
11515   CLOSING AN ACTIVE SCAN
11516 
11517   The application can close a scan for several reasons before it is completed.
11518   One reason was mentioned above where an error in a scan process led to a
11519   request to close the scan. Another reason could simply be that the
11520   application found what it looked for and is thus not interested in the
11521   rest of the scan.
11522 
11523   IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
11524 
11525   When a close scan request is received, all scan processes are stopped and all
11526   resources belonging to those scan processes are released. Stopping the scan
11527   processes most often includes communication with an LQH where the local scan
11528   is controlled. Finally all resources belonging to the scan is released and
11529   the SCAN_TABCONF is sent with an indication of that the scan is closed.
11530 
11531 
11532   CLOSING A COMPLETED SCAN
11533 
11534   When all scan processes are completed then a report is sent to the
11535   application which indicates that no more tuples can be fetched.
11536   The application will send a close scan and the same action as when
11537   closing an active scan is performed.
11538   In this case it will of course not find any active scan processes.
11539   It will even find all scan processes already released.
11540 
11541   The reason for requiring the api to close the scan is the same as above.
11542   It is to avoid any timing problems due to that the api and this block
11543   is out of synch.
11544 
11545   * ######################################################################## */
execSCAN_TABREQ(Signal * signal)11546 void Dbtc::execSCAN_TABREQ(Signal* signal)
11547 {
11548   jamEntry();
11549 
11550 #ifdef ERROR_INSERT
11551   /* Test fragmented + dropped signal handling */
11552   if (ERROR_INSERTED(8074) ||
11553       ERROR_INSERTED(8075) ||
11554       ERROR_INSERTED(8076) ||
11555       ERROR_INSERTED(8077))
11556   {
11557     jam();
11558     if (testFragmentDrop(signal)) {
11559       jam();
11560       return;
11561     }
11562   } /* End of test fragmented + dropped signal handling */
11563 #endif
11564 
11565   /* Reassemble if the request was fragmented */
11566   if (!assembleFragments(signal)){
11567     jam();
11568     return;
11569   }
11570 
11571   const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
11572   const Uint32 ri = scanTabReq->requestInfo;
11573   const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
11574   const Uint32 transid1 = scanTabReq->transId1;
11575   const Uint32 transid2 = scanTabReq->transId2;
11576   const Uint32 tmpXX = scanTabReq->buddyConPtr;
11577   const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
11578   Uint32 currSavePointId = 0;
11579 
11580   Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
11581   Uint32 errCode;
11582   ScanRecordPtr scanptr;
11583 
11584   /* Short SCANTABREQ has 1 section, Long has 2 or 3.
11585    * Section 0 : NDBAPI receiver ids (Mandatory)
11586    * Section 1 : ATTRINFO section (Mandatory for long SCAN_TABREQ
11587    * Section 2 : KEYINFO section (Optional for long SCAN_TABREQ
11588    */
11589   Uint32 numSections= signal->getNoOfSections();
11590   ndbassert( numSections >= 1 );
11591   bool isLongReq= numSections >= 2;
11592 
11593   SectionHandle handle(this, signal);
11594   SegmentedSectionPtr api_op_ptr;
11595   handle.getSection(api_op_ptr, 0);
11596   // Scan parallelism is determined by the number of receiver ids sent
11597   Uint32 scanParallel = api_op_ptr.sz;
11598   Uint32 scanConcurrency = scanParallel;
11599   Uint32 * apiPtr = signal->theData+25; // temp storage
11600   copy(apiPtr, api_op_ptr);
11601 
11602   Uint32 aiLength= 0;
11603   Uint32 keyLen= 0;
11604 
11605   if (likely(isLongReq))
11606   {
11607     SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
11608     /* Long SCANTABREQ, determine Ai and Key length from sections */
11609     handle.getSection(attrInfoPtr, ScanTabReq::AttrInfoSectionNum);
11610     aiLength= attrInfoPtr.sz;
11611     if (numSections == 3)
11612     {
11613       handle.getSection(keyInfoPtr, ScanTabReq::KeyInfoSectionNum);
11614       keyLen= keyInfoPtr.sz;
11615     }
11616   }
11617   else
11618   {
11619     /* Short SCANTABREQ, get Ai and Key length from signal */
11620     aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
11621     keyLen = scanTabReq->attrLenKeyLen >> 16;
11622   }
11623 
11624   apiConnectptr.i = scanTabReq->apiConnectPtr;
11625   tabptr.i = scanTabReq->tableId;
11626 
11627   if (apiConnectptr.i >= capiConnectFilesize)
11628   {
11629     jam();
11630     releaseSections(handle);
11631     warningHandlerLab(signal, __LINE__);
11632     return;
11633   }//if
11634 
11635   ptrAss(apiConnectptr, apiConnectRecord);
11636   ApiConnectRecord * transP = apiConnectptr.p;
11637 
11638   if (transP->apiConnectstate != CS_CONNECTED) {
11639     jam();
11640     // could be left over from TCKEYREQ rollback
11641     if (transP->apiConnectstate == CS_ABORTING &&
11642 	transP->abortState == AS_IDLE) {
11643       jam();
11644     } else if(transP->apiConnectstate == CS_STARTED &&
11645 	      transP->firstTcConnect == RNIL){
11646       jam();
11647       // left over from simple/dirty read
11648     } else {
11649       jam();
11650       jamLine(transP->apiConnectstate);
11651       errCode = ZSTATE_ERROR;
11652       goto SCAN_TAB_error_no_state_change;
11653     }
11654   }
11655 
11656   if(tabptr.i >= ctabrecFilesize)
11657   {
11658     errCode = ZUNKNOWN_TABLE_ERROR;
11659     goto SCAN_TAB_error;
11660   }
11661 
11662   if (unlikely (ScanTabReq::getViaSPJFlag(ri) &&
11663                 /* Check that all nodes can handle SPJ requests. */
11664                 !ndb_join_pushdown(getNodeVersionInfo().m_type[NodeInfo::DB]
11665                                    .m_min_version)))
11666   {
11667     jam();
11668     errCode = 4003; // Function not implemented
11669     goto SCAN_TAB_error;
11670   }
11671 
11672   ptrAss(tabptr, tableRecord);
11673   if ((aiLength == 0) ||
11674       (!tabptr.p->checkTable(schemaVersion)) ||
11675       (scanConcurrency == 0) ||
11676       (cfirstfreeScanrec == RNIL)) {
11677     goto SCAN_error_check;
11678   }
11679   if (buddyPtr != RNIL) {
11680     jam();
11681     ApiConnectRecordPtr buddyApiPtr;
11682     buddyApiPtr.i = buddyPtr;
11683     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
11684     if ((transid1 == buddyApiPtr.p->transid[0]) &&
11685 	(transid2 == buddyApiPtr.p->transid[1])) {
11686       jam();
11687 
11688       if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
11689 	// transaction has been aborted
11690 	jam();
11691 	errCode = buddyApiPtr.p->returncode;
11692 	goto SCAN_TAB_error;
11693       }//if
11694       currSavePointId = buddyApiPtr.p->currSavePointId;
11695       buddyApiPtr.p->currSavePointId++;
11696     }
11697   }
11698 
11699   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
11700       getNodeState().getSingleUserApi() !=
11701       refToNode(apiConnectptr.p->ndbapiBlockref))
11702   {
11703     errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
11704     goto SCAN_TAB_error;
11705   }
11706 
11707   scanptr = seizeScanrec(signal);
11708   ndbrequire(transP->apiScanRec == RNIL);
11709   ndbrequire(scanptr.p->scanApiRec == RNIL);
11710 
11711   errCode = initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag,
11712                         apiPtr);
11713   if (unlikely(errCode))
11714   {
11715     jam();
11716     transP->apiScanRec = scanptr.i;
11717     releaseScanResources(signal, scanptr, true /* NotStarted */);
11718     goto SCAN_TAB_error;
11719   }
11720 
11721   releaseSection(handle.m_ptr[ScanTabReq::ReceiverIdSectionNum].i);
11722   if (likely(isLongReq))
11723   {
11724     jam();
11725     /* We keep the AttrInfo and KeyInfo sections */
11726     scanptr.p->scanAttrInfoPtr = handle.m_ptr[ScanTabReq::AttrInfoSectionNum].i;
11727     if (keyLen)
11728     {
11729       jam();
11730       scanptr.p->scanKeyInfoPtr = handle.m_ptr[ScanTabReq::KeyInfoSectionNum].i;
11731     }
11732   }
11733   else
11734   {
11735     jam();
11736     seizeCacheRecord(signal);
11737     cachePtr.p->attrlength = aiLength;
11738     cachePtr.p->keylen = keyLen;
11739     cachePtr.p->save1 = 0;
11740   }
11741   handle.clear();
11742 
11743   scanptr.p->m_scan_dist_key = scanTabReq->distributionKey;
11744   scanptr.p->m_scan_dist_key_flag = ScanTabReq::getDistributionKeyFlag(ri);
11745 
11746   transP->apiScanRec = scanptr.i;
11747   transP->returncode = 0;
11748   transP->transid[0] = transid1;
11749   transP->transid[1] = transid2;
11750   transP->buddyPtr   = buddyPtr;
11751 
11752   // The scan is started
11753   transP->apiConnectstate = CS_START_SCAN;
11754   transP->currSavePointId = currSavePointId;
11755 
11756   /**********************************************************
11757   * We start the timer on scanRec to be able to discover a
11758   * timeout in the API the API now is in charge!
11759   ***********************************************************/
11760   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
11761   updateBuddyTimer(apiConnectptr);
11762 
11763   /***********************************************************
11764    * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
11765    * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
11766    * IF ANY TO RECEIVE.
11767    **********************************************************/
11768   scanptr.p->scanState = ScanRecord::WAIT_AI;
11769 
11770   if (ERROR_INSERTED(8038))
11771   {
11772     /**
11773      * Force API_FAILREQ
11774      */
11775     signal->theData[0] = refToNode(apiConnectptr.p->ndbapiBlockref);
11776     sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBA);
11777     CLEAR_ERROR_INSERT_VALUE;
11778   }
11779 
11780   if (isLongReq)
11781   {
11782     /* All AttrInfo (and KeyInfo) has been received, continue
11783      * processing
11784      */
11785     diFcountReqLab(signal, scanptr);
11786   }
11787 
11788   return;
11789 
11790  SCAN_error_check:
11791   if (aiLength == 0) {
11792     jam();
11793     errCode = ZSCAN_AI_LEN_ERROR;
11794     goto SCAN_TAB_error;
11795   }//if
11796   if (!tabptr.p->checkTable(schemaVersion)){
11797     jam();
11798     errCode = tabptr.p->getErrorCode(schemaVersion);
11799     goto SCAN_TAB_error;
11800   }//if
11801   if (scanConcurrency == 0) {
11802     jam();
11803     errCode = ZNO_CONCURRENCY_ERROR;
11804     goto SCAN_TAB_error;
11805   }//if
11806   ndbrequire(cfirstfreeScanrec == RNIL);
11807   ndbrequire(cConcScanCount == cscanrecFileSize);
11808   jam();
11809   errCode = ZNO_SCANREC_ERROR;
11810   goto SCAN_TAB_error;
11811 
11812 SCAN_TAB_error:
11813   jam();
11814   /**
11815    * Prepare for up coming ATTRINFO/KEYINFO
11816    */
11817   transP->apiConnectstate = CS_ABORTING;
11818   transP->abortState = AS_IDLE;
11819   transP->transid[0] = transid1;
11820   transP->transid[1] = transid2;
11821 
11822 SCAN_TAB_error_no_state_change:
11823 
11824   releaseSections(handle);
11825 
11826   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11827   ref->apiConnectPtr = transP->ndbapiConnect;
11828   ref->transId1 = transid1;
11829   ref->transId2 = transid2;
11830   ref->errorCode  = errCode;
11831   ref->closeNeeded = 0;
11832   sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
11833 	     signal, ScanTabRef::SignalLength, JBB);
11834   return;
11835 }//Dbtc::execSCAN_TABREQ()
11836 
11837 Uint32
initScanrec(ScanRecordPtr scanptr,const ScanTabReq * scanTabReq,UintR scanParallel,UintR noOprecPerFrag,const Uint32 apiPtr[])11838 Dbtc::initScanrec(ScanRecordPtr scanptr,
11839 		  const ScanTabReq * scanTabReq,
11840 		  UintR scanParallel,
11841 		  UintR noOprecPerFrag,
11842                   const Uint32 apiPtr[])
11843 {
11844   const UintR ri = scanTabReq->requestInfo;
11845   scanptr.p->scanApiRec = apiConnectptr.i;
11846   scanptr.p->scanTableref = tabptr.i;
11847   scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
11848   scanptr.p->scanParallel = scanParallel;
11849   scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
11850   scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
11851   scanptr.p->batch_size_rows = noOprecPerFrag;
11852   scanptr.p->m_scan_block_no = DBLQH;
11853   scanptr.p->m_scan_dist_key_flag = 0;
11854 
11855   Uint32 tmp = 0;
11856   ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
11857   ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
11858   ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
11859   ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
11860   ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
11861   ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
11862   ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
11863   ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
11864   if (ScanTabReq::getViaSPJFlag(ri))
11865   {
11866     jam();
11867     scanptr.p->m_scan_block_no = DBSPJ;
11868   }
11869 
11870   scanptr.p->scanRequestInfo = tmp;
11871   scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
11872   scanptr.p->scanState = ScanRecord::RUNNING;
11873   scanptr.p->m_queued_count = 0;
11874   scanptr.p->m_booked_fragments_count = 0;
11875   scanptr.p->m_scan_cookie = DihScanTabConf::InvalidCookie;
11876   scanptr.p->m_close_scan_req = false;
11877   scanptr.p->m_pass_all_confs =  ScanTabReq::getPassAllConfsFlag(ri);
11878   scanptr.p->m_4word_conf = ScanTabReq::get4WordConf(ri);
11879   scanptr.p->scanKeyInfoPtr = RNIL;
11880   scanptr.p->scanAttrInfoPtr = RNIL;
11881 
11882   ScanFragList list(c_scan_frag_pool,
11883 		    scanptr.p->m_running_scan_frags);
11884   for (Uint32 i = 0; i < scanParallel; i++) {
11885     jam();
11886     ScanFragRecPtr ptr;
11887     if (unlikely((list.seizeFirst(ptr) == false) ||
11888                  ERROR_INSERTED(8093)))
11889     {
11890       jam();
11891       goto errout;
11892     }
11893     ptr.p->scanFragState = ScanFragRec::IDLE;
11894     ptr.p->scanRec = scanptr.i;
11895     ptr.p->scanFragId = 0;
11896     ptr.p->m_apiPtr = apiPtr[i];
11897   }//for
11898 
11899   (* (ScanTabReq::getRangeScanFlag(ri) ?
11900       &c_counters.c_range_scan_count :
11901       &c_counters.c_scan_count))++;
11902   return 0;
11903 errout:
11904   {
11905     ScanFragRecPtr ptr;
11906     bool found = list.first(ptr);
11907     while (found)
11908     {
11909       ScanFragRecPtr old_ptr = ptr;
11910       ptr.p->scanFragState = ScanFragRec::COMPLETED;
11911       found = list.next(ptr);
11912       list.release(old_ptr);
11913     }
11914   }
11915   return ZSCAN_FRAGREC_ERROR;
11916 }//Dbtc::initScanrec()
11917 
scanTabRefLab(Signal * signal,Uint32 errCode)11918 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
11919 {
11920   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11921   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11922   ref->transId1 = apiConnectptr.p->transid[0];
11923   ref->transId2 = apiConnectptr.p->transid[1];
11924   ref->errorCode  = errCode;
11925   ref->closeNeeded = 0;
11926   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
11927 	     signal, ScanTabRef::SignalLength, JBB);
11928 }//Dbtc::scanTabRefLab()
11929 
11930 /**
11931  * scanKeyinfoLab
11932  * Handle reception of KeyInfo for a Scan
11933  */
scanKeyinfoLab(Signal * signal)11934 void Dbtc::scanKeyinfoLab(Signal* signal)
11935 {
11936   /* Receive KEYINFO for a SCAN operation
11937    * Note that old NDBAPI nodes sometimes send header-only KEYINFO signals
11938    */
11939   CacheRecord * const regCachePtr = cachePtr.p;
11940   UintR TkeyLen = regCachePtr->keylen;
11941   UintR Tlen = regCachePtr->save1;
11942 
11943   Uint32 wordsInSignal= MIN(KeyInfo::DataLength,
11944                             (TkeyLen - Tlen));
11945 
11946   ndbassert( signal->getLength() ==
11947              (KeyInfo::HeaderLength + wordsInSignal) );
11948 
11949   if (unlikely ((! appendToSection(regCachePtr->keyInfoSectionI,
11950                                    &signal->theData[KeyInfo::HeaderLength],
11951                                    wordsInSignal)) ||
11952                  ERROR_INSERTED(8094)))
11953   {
11954     jam();
11955     Uint32 transid0 = apiConnectptr.p->transid[0];
11956     Uint32 transid1 = apiConnectptr.p->transid[1];
11957     ndbrequire(apiConnectptr.p->apiScanRec != RNIL);
11958     ScanRecordPtr scanPtr;
11959     scanPtr.i = apiConnectptr.p->apiScanRec;
11960     ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
11961     abortScanLab(signal,
11962                  scanPtr,
11963                  ZGET_DATAREC_ERROR,
11964                  true /* Not started */);
11965 
11966     /* Prepare for up coming ATTRINFO/KEYINFO */
11967     apiConnectptr.p->apiConnectstate = CS_ABORTING;
11968     apiConnectptr.p->abortState = AS_IDLE;
11969     apiConnectptr.p->transid[0] = transid0;
11970     apiConnectptr.p->transid[1] = transid1;
11971 
11972     return;
11973   }
11974 
11975   Tlen+= wordsInSignal;
11976   regCachePtr->save1 = Tlen;
11977 
11978   if (Tlen < TkeyLen)
11979   {
11980     jam();
11981     /* More KeyInfo still to come - continue waiting */
11982     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
11983     return;
11984   }
11985 
11986   /* All KeyInfo has been received, we will now start receiving
11987    * ATTRINFO
11988    */
11989   jam();
11990   ndbassert(Tlen == TkeyLen);
11991   return;
11992 } // scanKeyinfoLab
11993 
11994 /*---------------------------------------------------------------------------*/
11995 /*                                                                           */
11996 /*       RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST.                       */
11997 /*---------------------------------------------------------------------------*/
scanAttrinfoLab(Signal * signal,UintR Tlen)11998 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
11999 {
12000   ScanRecordPtr scanptr;
12001   scanptr.i = apiConnectptr.p->apiScanRec;
12002   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12003   cachePtr.i = apiConnectptr.p->cachePtr;
12004   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12005   CacheRecord * const regCachePtr = cachePtr.p;
12006   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
12007 
12008   regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
12009 
12010   if (unlikely(! appendToSection(regCachePtr->attrInfoSectionI,
12011                                  &signal->theData[AttrInfo::HeaderLength],
12012                                  Tlen)))
12013   {
12014     jam();
12015     abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
12016     return;
12017   }
12018 
12019   if (regCachePtr->currReclenAi == regCachePtr->attrlength)
12020   {
12021     jam();
12022     /* We have now received all the signals defining this
12023      * scan.  We are ready to start executing the scan
12024      */
12025     scanptr.p->scanAttrInfoPtr = regCachePtr->attrInfoSectionI;
12026     scanptr.p->scanKeyInfoPtr = regCachePtr->keyInfoSectionI;
12027     releaseCacheRecord(apiConnectptr, regCachePtr);
12028     diFcountReqLab(signal, scanptr);
12029     return;
12030   }
12031   else if (unlikely (regCachePtr->currReclenAi > regCachePtr->attrlength))
12032   {
12033     jam();
12034     abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
12035     return;
12036   }
12037 
12038   /* Still some ATTRINFO to arrive...*/
12039   return;
12040 }//Dbtc::scanAttrinfoLab()
12041 
diFcountReqLab(Signal * signal,ScanRecordPtr scanptr)12042 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
12043 {
12044   /**
12045    * Check so that the table is not being dropped
12046    */
12047   TableRecordPtr tabPtr;
12048   tabPtr.i = scanptr.p->scanTableref;
12049   tabPtr.p = &tableRecord[tabPtr.i];
12050   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
12051     ;
12052   } else {
12053     abortScanLab(signal, scanptr,
12054 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
12055 		 true);
12056     return;
12057   }
12058 
12059   scanptr.p->scanNextFragId = 0;
12060   scanptr.p->m_booked_fragments_count= 0;
12061   scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
12062 
12063   /*************************************************
12064    * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
12065    ***************************************************/
12066   ndbassert(scanptr.p->m_scan_cookie == DihScanTabConf::InvalidCookie);
12067   DihScanTabReq * req = (DihScanTabReq*)signal->getDataPtrSend();
12068   req->senderRef = reference();
12069   req->senderData = scanptr.p->scanApiRec;
12070   req->tableId = scanptr.p->scanTableref;
12071   req->schemaTransId = 0;
12072   sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_REQ, signal,
12073              DihScanTabReq::SignalLength, JBB);
12074   return;
12075 }//Dbtc::diFcountReqLab()
12076 
12077 /********************************************************************
12078  * execDIH_SCAN_TAB_CONF
12079  *
12080  * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
12081  * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
12082  * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
12083  * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
12084  * CLOSES THE SCAN.
12085  ********************************************************************/
execDIH_SCAN_TAB_CONF(Signal * signal)12086 void Dbtc::execDIH_SCAN_TAB_CONF(Signal* signal)
12087 {
12088   jamEntry();
12089   DihScanTabConf * conf = (DihScanTabConf*)signal->getDataPtr();
12090   Uint32 tfragCount = conf->fragmentCount;
12091   apiConnectptr.i = conf->senderData;
12092   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12093   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
12094   ScanRecordPtr scanptr;
12095   scanptr.i = regApiPtr->apiScanRec;
12096   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12097   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
12098   scanptr.p->m_scan_cookie = conf->scanCookie;
12099   ndbrequire(scanptr.p->m_scan_cookie != DihScanTabConf::InvalidCookie);
12100 
12101   if (conf->reorgFlag)
12102   {
12103     jam();
12104     ScanFragReq::setReorgFlag(scanptr.p->scanRequestInfo, ScanFragReq::REORG_NOT_MOVED);
12105   }
12106   if (regApiPtr->apiFailState == ZTRUE) {
12107     jam();
12108     releaseScanResources(signal, scanptr, true);
12109     handleApiFailState(signal, apiConnectptr.i);
12110     return;
12111   }//if
12112   if (tfragCount == 0) {
12113     jam();
12114     abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
12115     return;
12116   }//if
12117 
12118   /**
12119    * Check so that the table is not being dropped
12120    */
12121   TableRecordPtr tabPtr;
12122   tabPtr.i = scanptr.p->scanTableref;
12123   tabPtr.p = &tableRecord[tabPtr.i];
12124   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
12125     ;
12126   } else {
12127     abortScanLab(signal, scanptr,
12128 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
12129 		 true);
12130     return;
12131   }
12132 
12133   if (scanptr.p->m_scan_dist_key_flag)
12134   {
12135     jam();
12136     ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType) ||
12137                tabPtr.p->get_user_defined_partitioning());
12138 
12139     DiGetNodesReq * req = (DiGetNodesReq *)&signal->theData[0];
12140     const DiGetNodesConf * get_conf = (DiGetNodesConf *)&signal->theData[0];
12141     req->tableId = tabPtr.i;
12142     req->hashValue = scanptr.p->m_scan_dist_key;
12143     req->distr_key_indicator = tabPtr.p->get_user_defined_partitioning();
12144     req->jamBufferPtr = jamBuffer();
12145     EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
12146                    DiGetNodesReq::SignalLength, 0);
12147     UintR TerrorIndicator = signal->theData[0];
12148     jamEntry();
12149     if (TerrorIndicator != 0)
12150     {
12151       jam();
12152       abortScanLab(signal, scanptr,
12153                    signal->theData[1],
12154                    true);
12155       return;
12156     }
12157 
12158     scanptr.p->scanNextFragId = get_conf->fragId;
12159     tfragCount = 1;
12160   }
12161 
12162   scanptr.p->scanParallel = tfragCount;
12163   scanptr.p->scanNoFrag = tfragCount;
12164   scanptr.p->scanState = ScanRecord::RUNNING;
12165 
12166   setApiConTimer(apiConnectptr.i, 0, __LINE__);
12167   updateBuddyTimer(apiConnectptr);
12168 
12169   /** Need own local scope of list(...,m_running_scan_frags) */
12170   {
12171     ScanFragRecPtr ptr;
12172     ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12173 
12174     /**
12175      * Initially list(...,m_running_scan_frags) contains an 'IDLE' entry
12176      * for all fragments. Now assign fragId to those 'tfragCount' fragments
12177      * to execute in parallel.
12178      */
12179     for (list.first(ptr); !ptr.isNull() && tfragCount;
12180          list.next(ptr), tfragCount--){
12181       jam();
12182 
12183       ndbassert(ptr.p->scanFragState == ScanFragRec::IDLE);
12184       ptr.p->lqhBlockref = 0;
12185       ptr.p->scanFragId = scanptr.p->scanNextFragId++;
12186     }//for
12187 
12188     /**
12189      * Any remaining fragments, not allowed to execute in parallel, are
12190      * put into the 'queued-list' until they can be executed.
12191      */
12192     ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
12193     for (; !ptr.isNull();)
12194     {
12195       jam();
12196       ptr.p->m_ops = 0;
12197       ptr.p->m_totalLen = 0;
12198       ptr.p->m_scan_frag_conf_status = 1;
12199       ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
12200       ptr.p->stopFragTimer();
12201 
12202       ScanFragRecPtr tmp;
12203       tmp.i = ptr.i;
12204       tmp.p = ptr.p;
12205       list.next(ptr);
12206       list.remove(tmp);
12207       queued.addFirst(tmp);
12208       scanptr.p->m_queued_count++;
12209     }
12210   }
12211 
12212   /**
12213    * Start by requesting fragment info from DIH.
12214    * Max MAX_DIH_FRAG_REQS fragments can be requested at once.
12215    * If needed we will send more requests after CONF is received.
12216    */
12217   jam();
12218   sendDihGetNodesReq(signal, scanptr);
12219 
12220 }//Dbtc::execDIH_SCAN_TAB_CONF()
12221 
12222 /********************************************************************
12223  * sendDihGetNodesReq
12224  *
12225  * Will check the 'm_running_scan_frags' list for fragments which
12226  * are still 'IDLE'. These should be started by requesting
12227  * node info in a DIH_SCAN_GET_NODES_REQ.
12228  *
12229  * In order to avoid CPU starvation, or unmanagable huge FragItem[],
12230  * max MAX_DIH_FRAG_REQS are requested in a single signal.
12231  * If there are more fragments, we have to repeatable call this
12232  * function when CONF for the first fragment set is received.
12233  ********************************************************************/
sendDihGetNodesReq(Signal * signal,ScanRecordPtr scanptr)12234 void Dbtc::sendDihGetNodesReq(Signal* signal, ScanRecordPtr scanptr)
12235 {
12236   jam();
12237   ScanFragRecPtr ptr;
12238   DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
12239   Uint32 fragCnt = 0;
12240 
12241   { // running-list scope
12242     ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12243 
12244     for (list.first(ptr);
12245          !ptr.isNull() && fragCnt < DihScanGetNodesReq::MAX_DIH_FRAG_REQS;
12246          list.next(ptr))
12247     {
12248       jam();
12249 
12250       /**
12251        * Check correct CONTINUEB(ZSTART_FRAG_SCAN) handling in
12252        * combination with multiple DIH_SCAN_GET_NODES_REQ /_CONF.
12253        * Setup such that we will have a one fragment REQ
12254        * pending after this REQ.
12255        * ::startFragScans executed when first _CONF arrives
12256        * will be delayed with CONTINUEB in order to possibly
12257        * bring it out of sequence with last (remaining) _CONF.
12258        */
12259       if (ERROR_INSERTED(8097) &&
12260           fragCnt > 0 &&
12261           ptr.p->scanFragId == scanptr.p->scanNoFrag-1) //Last FragId
12262       {
12263         jam();
12264         break;
12265       }
12266 
12267       if (ptr.p->scanFragState == ScanFragRec::IDLE) // Start it NOW!.
12268       {
12269         jam();
12270         ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
12271         ptr.p->startFragTimer(ctcTimer);
12272         req->fragItem[fragCnt].senderData = ptr.i;
12273         req->fragItem[fragCnt].fragId = ptr.p->scanFragId;
12274 
12275         fragCnt++;
12276       } // if IDLE
12277     }
12278   } // running-list scope
12279 
12280   if (fragCnt > 0)
12281   {
12282     jam();
12283     req->senderRef = reference();
12284     req->tableId = scanptr.p->scanTableref;
12285     req->scanCookie = scanptr.p->m_scan_cookie;
12286     req->fragCnt = fragCnt;
12287 
12288     /** Always send as a long signal, even if a short would
12289      *  have been sufficient in the (rare) case of 'fragCnt==1'
12290      */
12291     Ptr<SectionSegment> fragReq;
12292     const Uint32 len = fragCnt*DihScanGetNodesReq::FragItem::Length;
12293 
12294     if (ERROR_INSERTED_CLEAR(8095) ||  // Fail once
12295         unlikely(!import(fragReq, (Uint32*)req->fragItem, len)))
12296     {
12297       jam();
12298 
12299       /** Handling of failed REQ is similar to :execDIH_SCAN_GET_NODES_REF */
12300       for (Uint32 i = 0; i < fragCnt; i++)
12301       {
12302         jam();
12303         ptr.i = req->fragItem[i].senderData;
12304         c_scan_frag_pool.getPtr(ptr);
12305 
12306         ndbrequire(ptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
12307         ptr.p->scanFragState = ScanFragRec::COMPLETED;
12308         ptr.p->stopFragTimer();
12309         {
12310           ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12311           run.release(ptr);
12312         }
12313       }
12314       scanError(signal, scanptr, ZGET_DATAREC_ERROR);
12315       return;
12316     }
12317     SectionHandle handle(this, fragReq.i);
12318     sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
12319                DihScanGetNodesReq::FixedSignalLength,
12320                JBB, &handle);
12321   }
12322 }//Dbtc::sendDihGetNodesReq
12323 
12324 /******************************************************
12325  * execDIH_SCAN_TAB_REF
12326  ******************************************************/
execDIH_SCAN_TAB_REF(Signal * signal)12327 void Dbtc::execDIH_SCAN_TAB_REF(Signal* signal)
12328 {
12329   jamEntry();
12330   DihScanTabRef * ref = (DihScanTabRef*)signal->getDataPtr();
12331   const Uint32 errCode = ref->error;
12332   apiConnectptr.i = ref->senderData;
12333   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12334   ScanRecordPtr scanptr;
12335   scanptr.i = apiConnectptr.p->apiScanRec;
12336   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12337   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
12338   if (apiConnectptr.p->apiFailState == ZTRUE) {
12339     jam();
12340     releaseScanResources(signal, scanptr, true);
12341     handleApiFailState(signal, apiConnectptr.i);
12342     return;
12343   }//if
12344   abortScanLab(signal, scanptr, errCode, true);
12345 }//Dbtc::execDIH_SCAN_TAB_REF()
12346 
abortScanLab(Signal * signal,ScanRecordPtr scanptr,Uint32 errCode,bool not_started)12347 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
12348 			bool not_started)
12349 {
12350   scanTabRefLab(signal, errCode);
12351   releaseScanResources(signal, scanptr, not_started);
12352 }//Dbtc::abortScanLab()
12353 
releaseScanResources(Signal * signal,ScanRecordPtr scanPtr,bool not_started)12354 void Dbtc::releaseScanResources(Signal* signal,
12355                                 ScanRecordPtr scanPtr,
12356 				bool not_started)
12357 {
12358   if (apiConnectptr.p->cachePtr != RNIL) {
12359     cachePtr.i = apiConnectptr.p->cachePtr;
12360     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12361     releaseKeys();
12362     releaseAttrinfo();
12363   }//if
12364 
12365   if (not_started)
12366   {
12367     jam();
12368     ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
12369     ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
12370     ScanFragRecPtr ptr;
12371     bool found = run.first(ptr);
12372     while (found)
12373     {
12374       ScanFragRecPtr old_ptr = ptr;
12375       ptr.p->scanFragState = ScanFragRec::COMPLETED;
12376       found = run.next(ptr);
12377       run.release(old_ptr);
12378     }
12379     found = queue.first(ptr);
12380     while (found)
12381     {
12382       ScanFragRecPtr old_ptr = ptr;
12383       ptr.p->scanFragState = ScanFragRec::COMPLETED;
12384       found = queue.next(ptr);
12385       queue.release(old_ptr);
12386     }
12387   }
12388 
12389   if (scanPtr.p->scanKeyInfoPtr != RNIL)
12390   {
12391     releaseSection(scanPtr.p->scanKeyInfoPtr);
12392     scanPtr.p->scanKeyInfoPtr = RNIL;
12393   }
12394 
12395   if (scanPtr.p->scanAttrInfoPtr != RNIL)
12396   {
12397     releaseSection(scanPtr.p->scanAttrInfoPtr);
12398     scanPtr.p->scanAttrInfoPtr = RNIL;
12399   }
12400 
12401   ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
12402   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
12403   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
12404 
12405   ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
12406   ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
12407 
12408   if (scanPtr.p->m_scan_cookie != DihScanTabConf::InvalidCookie)
12409   {
12410     /* Cookie was requested, 'return' it */
12411     DihScanTabCompleteRep* rep = (DihScanTabCompleteRep*)signal->getDataPtrSend();
12412     rep->tableId = scanPtr.p->scanTableref;
12413     rep->scanCookie = scanPtr.p->m_scan_cookie;
12414     sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_COMPLETE_REP,
12415                signal, DihScanTabCompleteRep::SignalLength, JBB);
12416     scanPtr.p->m_scan_cookie = DihScanTabConf::InvalidCookie;
12417   }
12418 
12419   // link into free list
12420   scanPtr.p->nextScan = cfirstfreeScanrec;
12421   scanPtr.p->scanState = ScanRecord::IDLE;
12422   scanPtr.p->scanApiRec = RNIL;
12423   cfirstfreeScanrec = scanPtr.i;
12424   ndbassert(cConcScanCount > 0);
12425   cConcScanCount--;
12426 
12427   apiConnectptr.p->apiScanRec = RNIL;
12428   apiConnectptr.p->apiConnectstate = CS_CONNECTED;
12429   setApiConTimer(apiConnectptr.i, 0, __LINE__);
12430 }//Dbtc::releaseScanResources()
12431 
12432 
12433 /****************************************************************
12434  * execDIH_SCAN_GET_NODES_CONF
12435  *
12436  * WE HAVE RECEIVED THE PRIMARY NODES OF ALL FRAGMENTS.
12437  * WE ARE NOW READY TO ASK FOR PERMISSION TO LOAD THESE
12438  * NODES WITH A SCAN OPERATIONS.
12439  ****************************************************************/
execDIH_SCAN_GET_NODES_CONF(Signal * signal)12440 void Dbtc::execDIH_SCAN_GET_NODES_CONF(Signal* signal)
12441 {
12442   jamEntry();
12443   DihScanGetNodesConf * conf = (DihScanGetNodesConf*)signal->getDataPtr();
12444   const Uint32 tableId = conf->tableId;
12445 
12446   if (signal->getNoOfSections() > 0)
12447   {
12448     // Long signal: FragItems listed in first section
12449     jam();
12450     SectionHandle handle(this, signal);
12451     ndbassert(handle.m_cnt==1);
12452     startFragScansLab(signal, tableId, handle, 0);
12453 
12454     /**
12455      * NOTE: No sendDihGetNodesReq() as part of this branch!
12456      * startFragScansLab() will, when required, sendDihGetNodesReq()
12457      * after it has completed without a CONTINUEB, or after
12458      * CONTINUEB(ZSTART_FRAG_SCAN) completed last fragment.
12459      */
12460   }
12461   else   // Short signal, with single FragItem
12462   {
12463     jam();
12464     ndbassert(conf->fragCnt == 1);
12465     ndbassert(signal->getLength()
12466               == DihScanGetNodesConf::FixedSignalLength + DihScanGetNodesConf::FragItem::Length);
12467 
12468     DihScanGetNodesConf::FragItem fragConf[1];
12469     memcpy(fragConf, conf->fragItem, 4 * DihScanGetNodesConf::FragItem::Length);
12470     startFragScanLab(signal, tableId, fragConf[0]);
12471 
12472     /**
12473      * As MAX_DIH_FRAG_REQS fragments can be requested at once,
12474      * we may have to send more DIH_SCAN_GET_NODES_REQ now
12475      */
12476     ScanRecordPtr scanptr;
12477     scanptr.i = scanFragptr.p->scanRec;
12478     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12479     sendDihGetNodesReq(signal, scanptr);
12480   }
12481 }//Dbtc::execDIH_SCAN_GET_NODES_CONF
12482 
12483 /****************************************************************
12484  * startFragScansLab
12485  *
12486  * PROCESS THE LIST OF DihScanGetNodesConf::FragItem RECEIVED
12487  * FROM ::execDIH_SCAN_GET_NODES_CONF. SEND A 'SCAN_FRAGREQ'
12488  * FOR EACH OF THESE.
12489  * AVOID PRODUCING TOO MANY LOCAL SIGNALS WHICH MAY RESULT IN
12490  * A 'Out of SendBuffers' ERROR. IN THESE CASES WE TAKE A BREAK
12491  * AND CONTINUEB LATER.
12492  ****************************************************************/
startFragScansLab(Signal * signal,Uint32 tableId,SectionHandle & handle,Uint32 secOffs)12493 void Dbtc::startFragScansLab(Signal* signal, Uint32 tableId,
12494                             SectionHandle& handle, Uint32 secOffs)
12495 {
12496   Uint32 cntLocalSignals = 0;
12497   const NodeId ownNodeId = getOwnNodeId();
12498   SectionReader fragReader(handle.m_ptr[0], getSectionSegmentPool());
12499   ndbassert((fragReader.getSize() % DihScanGetNodesConf::FragItem::Length) == 0);
12500   ndbrequire(fragReader.step(secOffs));
12501 
12502   DihScanGetNodesConf::FragItem fragConf;
12503   while (fragReader.getWords((Uint32*)&fragConf,DihScanGetNodesConf::FragItem::Length))
12504   {
12505     jam();
12506 
12507     /**
12508      * ::startFragScans() should be allowed to take a CONTINUEB break
12509      * at any point. Execution of that CONTINUEB may be delayed
12510      * due to job buffer scheduling policy.
12511      * Check that such delay will not be harmfull.
12512      */
12513     if (ERROR_INSERTED_CLEAR(8097))
12514     {
12515       jam();
12516       signal->theData[0] = TcContinueB::ZSTART_FRAG_SCANS;
12517       signal->theData[1] = tableId;
12518       signal->theData[2] = secOffs;
12519       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 3, 10, &handle);
12520       return;
12521     }
12522 
12523     if (fragConf.nodes[0] == ownNodeId)
12524     {
12525       cntLocalSignals++;
12526 
12527       /**
12528        * A max fanout of 1::4 of consumed::produced signals are allowed.
12529        * If we are about to produce more, we have to contine later.
12530        */
12531       if (cntLocalSignals >= 4)
12532       {
12533         jam();
12534         signal->theData[0] = TcContinueB::ZSTART_FRAG_SCANS;
12535         signal->theData[1] = tableId;
12536         signal->theData[2] = secOffs;
12537         sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB, &handle);
12538         return;
12539       }
12540     }
12541 
12542     startFragScanLab(signal, tableId, fragConf);
12543     secOffs += DihScanGetNodesConf::FragItem::Length;
12544   } //while
12545 
12546   jam();
12547   releaseSections(handle);
12548 
12549   /**
12550    * Scan for all fragments in current DIH_SCAN_GET_NODES_CONF
12551    * completed. Send more DIH_SCAN_GET_NODES_REQ if required:
12552    * (As MAX_DIH_FRAG_REQS fragments can be requested at once)
12553    */
12554   ScanRecordPtr scanptr;
12555   scanptr.i = scanFragptr.p->scanRec;
12556   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12557   sendDihGetNodesReq(signal, scanptr);
12558 }//Dbtc::startFragScansLab
12559 
startFragScanLab(Signal * signal,Uint32 tableId,const DihScanGetNodesConf::FragItem & fragConf)12560 void Dbtc::startFragScanLab(Signal* signal, Uint32 tableId,
12561                             const DihScanGetNodesConf::FragItem& fragConf)
12562 {
12563   jam();
12564   const NodeId ownNodeId = getOwnNodeId();
12565 
12566   scanFragptr.i = fragConf.senderData;
12567   c_scan_frag_pool.getPtr(scanFragptr);
12568 
12569   NodeId nodeId = fragConf.nodes[0];
12570   arrGuard(nodeId, MAX_NDB_NODES);
12571 
12572   if (ERROR_INSERTED(8050) && nodeId != ownNodeId)
12573   {
12574     /* Asked to scan a fragment which is not on the same node as the
12575      * TC - transaction hinting / scan partition pruning has failed
12576      * Used by testPartitioning.cpp
12577      */
12578     CRASH_INSERTION(8050);
12579   }
12580 
12581   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
12582   scanFragptr.p->stopFragTimer();
12583 
12584   ScanRecordPtr scanptr;
12585   scanptr.i = scanFragptr.p->scanRec;
12586   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12587 
12588   /**
12589    * This must be false as select count(*) otherwise
12590    *   can "pass" committing on backup fragments and
12591    *   get incorrect row count
12592    */
12593   if (false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
12594   {
12595     jam();
12596     for (Uint32 i = 1; i<fragConf.count; i++)
12597     {
12598       if (fragConf.nodes[i] == ownNodeId)
12599       {
12600 	jam();
12601 	nodeId = ownNodeId;
12602 	break;
12603       }
12604     }
12605   }
12606 
12607   {
12608     /**
12609      * Check table
12610      */
12611     TableRecordPtr tabPtr;
12612     tabPtr.i = scanptr.p->scanTableref;
12613     ptrAss(tabPtr, tableRecord);
12614     Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
12615     if (ERROR_INSERTED(8081) || tabPtr.p->checkTable(schemaVersion) == false)
12616     {
12617       jam();
12618       Uint32 err;
12619       if (ERROR_INSERTED(8081))
12620       {
12621         err = ZTIME_OUT_ERROR;
12622         CLEAR_ERROR_INSERT_VALUE;
12623       }
12624       else
12625       {
12626         err = tabPtr.p->getErrorCode(schemaVersion);
12627       }
12628       {
12629         scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
12630         ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12631         run.release(scanFragptr);
12632       }
12633       scanError(signal, scanptr, err);
12634       return;
12635     }
12636   }
12637 
12638   apiConnectptr.i = scanptr.p->scanApiRec;
12639   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12640   switch (scanptr.p->scanState) {
12641   case ScanRecord::CLOSING_SCAN:
12642     jam();
12643     updateBuddyTimer(apiConnectptr);
12644     {
12645       scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
12646       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12647       run.release(scanFragptr);
12648     }
12649     close_scan_req_send_conf(signal, scanptr);
12650     return;
12651   default:
12652     jam();
12653     /*empty*/;
12654     break;
12655   }//switch
12656 
12657   /* Send SCANFRAGREQ to LQH block
12658    * SCANFRAGREQ with optional KEYINFO and mandatory ATTRINFO are
12659    * now sent to LQH
12660    * This starts the scan on the given fragment.
12661    * If this is the last SCANFRAGREQ, sendScanFragReq will release
12662    * the KeyInfo and AttrInfo sections when sending.
12663    */
12664   Uint32 instanceKey = fragConf.instanceKey;
12665   scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
12666                                            instanceKey, nodeId);
12667 
12668   scanFragptr.p->m_connectCount = getNodeInfo(nodeId).m_connectCount;
12669 
12670   /* Determine whether this is the last scanFragReq
12671    * Handle normal scan-all-fragments and partition pruned
12672    * scan-one-fragment cases.
12673    *
12674    * (Note that this assumes that fragments are processed in order,
12675    * and that DIH_SCAN_GET_NODES_CONF signals are received in the
12676    * order that the DIH_SCAN_GET_NODES_REQs were sent)
12677    */
12678   bool isLastScanFragReq= ((scanptr.p->scanNextFragId >=
12679                             scanptr.p->scanNoFrag) &&
12680                            (scanFragptr.p->scanFragId ==
12681                             (scanptr.p->scanNextFragId - 1)));
12682 
12683   sendScanFragReq(signal, scanptr.p, scanFragptr.p, isLastScanFragReq);
12684 
12685   scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
12686   scanFragptr.p->startFragTimer(ctcTimer);
12687   updateBuddyTimer(apiConnectptr);
12688   /*********************************************
12689    * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
12690    * WAIT FOR THE FIRST SCANNED RECORDS
12691    *********************************************/
12692 }//Dbtc::startFragScanLab
12693 
12694 
12695 /***************************************************
12696  * execDIH_SCAN_GET_NODES_REF
12697  *
12698  * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
12699  * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
12700  * FINDING A PRIMARY REPLICA OF SOME FRAGMENT(s).
12701  ***************************************************/
execDIH_SCAN_GET_NODES_REF(Signal * signal)12702 void Dbtc::execDIH_SCAN_GET_NODES_REF(Signal* signal)
12703 {
12704   jamEntry();
12705   const DihScanGetNodesRef* ref = (DihScanGetNodesRef*)signal->getDataPtr();
12706 //const Uint32 tableId = ref->tableId;
12707   const Uint32 fragCnt = ref->fragCnt;
12708   const Uint32 errCode = ref->errCode;
12709 
12710   if (signal->getNoOfSections() > 0)
12711   {
12712     // Long signal: FragItems listed in first section
12713     jam();
12714     SectionHandle handle(this, signal);
12715     ndbassert(handle.m_cnt==1);
12716 
12717     SegmentedSectionPtr fragRefSection;
12718     ndbrequire(handle.getSection(fragRefSection,0));
12719     ndbassert(fragRefSection.p->m_sz == (fragCnt*DihScanGetNodesRef::FragItem::Length));
12720     ndbassert(fragCnt <= DihScanGetNodesReq::MAX_DIH_FRAG_REQS);
12721     copy((Uint32*)ref->fragItem, fragRefSection);
12722     releaseSections(handle);
12723   }
12724   else                  // Short signal, single frag in ref->fragItem[0]
12725   {
12726     ndbassert(fragCnt == 1);
12727     ndbassert(signal->getLength()
12728               == DihScanGetNodesRef::FixedSignalLength + DihScanGetNodesRef::FragItem::Length);
12729   }
12730 
12731   ScanRecordPtr scanptr;
12732   scanptr.setNull();
12733 
12734   for (Uint32 i = 0; i < fragCnt; i++)
12735   {
12736     jam();
12737     scanFragptr.i = ref->fragItem[i].senderData;
12738     c_scan_frag_pool.getPtr(scanFragptr);
12739 
12740     ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
12741     scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
12742     scanFragptr.p->stopFragTimer();
12743 
12744     // All scanFrags should belong to the same table scan
12745     ndbassert(scanptr.isNull() || scanptr.i==scanFragptr.p->scanRec);
12746     if (scanptr.isNull())
12747     {
12748       jam();
12749       scanptr.i = scanFragptr.p->scanRec;
12750       ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12751     }
12752     {
12753       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12754       run.release(scanFragptr);
12755     }
12756   }
12757 
12758   scanError(signal, scanptr, errCode);
12759 }//Dbtc::execDIH_SCAN_GET_NODES_REF()
12760 
12761 /**
12762  * Dbtc::execSCAN_FRAGREF
12763  *  Our attempt to scan a fragment was refused
12764  *  set error code and close all other fragment
12765  *  scan's belonging to this scan
12766  */
execSCAN_FRAGREF(Signal * signal)12767 void Dbtc::execSCAN_FRAGREF(Signal* signal)
12768 {
12769   const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
12770 
12771   jamEntry();
12772   const Uint32 errCode = ref->errorCode;
12773 
12774   scanFragptr.i = ref->senderData;
12775   c_scan_frag_pool.getPtr(scanFragptr);
12776 
12777   ScanRecordPtr scanptr;
12778   scanptr.i = scanFragptr.p->scanRec;
12779   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12780 
12781   apiConnectptr.i = scanptr.p->scanApiRec;
12782   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12783 
12784   Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
12785   Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
12786   transid1 = transid1 | transid2;
12787   if (transid1 != 0) {
12788     jam();
12789     systemErrorLab(signal, __LINE__);
12790   }//if
12791 
12792   /**
12793    * Set errorcode, close connection to this lqh fragment,
12794    * stop fragment timer and call scanFragError to start
12795    * close of the other fragment scans
12796    */
12797   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
12798   scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
12799   scanFragptr.p->stopFragTimer();
12800   {
12801     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12802     run.release(scanFragptr);
12803   }
12804   scanError(signal, scanptr, errCode);
12805 }//Dbtc::execSCAN_FRAGREF()
12806 
12807 /**
12808  * Dbtc::scanError
12809  *
12810  * Called when an error occurs during
12811  */
scanError(Signal * signal,ScanRecordPtr scanptr,Uint32 errorCode)12812 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
12813 {
12814   jam();
12815   ScanRecord* scanP = scanptr.p;
12816 
12817   DEBUG("scanError, errorCode = "<< errorCode <<
12818 	", scanState = " << scanptr.p->scanState);
12819 
12820   apiConnectptr.i = scanP->scanApiRec;
12821   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12822   ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
12823 
12824   if(scanP->scanState == ScanRecord::CLOSING_SCAN){
12825     jam();
12826     close_scan_req_send_conf(signal, scanptr);
12827     return;
12828   }
12829 
12830   ndbrequire(scanP->scanState == ScanRecord::RUNNING);
12831 
12832   /**
12833    * Close scan wo/ having received an order to do so
12834    */
12835   close_scan_req(signal, scanptr, false);
12836 
12837   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
12838   if(apiFail){
12839     jam();
12840     return;
12841   }
12842 
12843   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
12844   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
12845   ref->transId1 = apiConnectptr.p->transid[0];
12846   ref->transId2 = apiConnectptr.p->transid[1];
12847   ref->errorCode  = errorCode;
12848   ref->closeNeeded = 1;
12849   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
12850 	     signal, ScanTabRef::SignalLength, JBB);
12851 }//Dbtc::scanError()
12852 
12853 /************************************************************
12854  * execSCAN_FRAGCONF
12855  *
12856  * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
12857  * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
12858  ************************************************************/
execSCAN_FRAGCONF(Signal * signal)12859 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
12860 {
12861   Uint32 transid1, transid2, total_len;
12862   jamEntry();
12863 
12864   const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
12865   const Uint32 noCompletedOps = conf->completedOps;
12866   const Uint32 status = conf->fragmentCompleted;
12867 
12868   scanFragptr.i = conf->senderData;
12869   c_scan_frag_pool.getPtr(scanFragptr);
12870 
12871   ScanRecordPtr scanptr;
12872   scanptr.i = scanFragptr.p->scanRec;
12873   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
12874 
12875   apiConnectptr.i = scanptr.p->scanApiRec;
12876   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12877 
12878   transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
12879   transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
12880   total_len= conf->total_len;
12881   transid1 = transid1 | transid2;
12882   if (transid1 != 0) {
12883     jam();
12884     systemErrorLab(signal, __LINE__);
12885   }//if
12886 
12887   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
12888 
12889   if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
12890     jam();
12891     if(status == 0){
12892       /**
12893        * We have started closing = we sent a close -> ignore this
12894        */
12895       return;
12896     } else {
12897       jam();
12898       scanFragptr.p->stopFragTimer();
12899       scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
12900       {
12901         ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12902         run.release(scanFragptr);
12903       }
12904     }
12905     close_scan_req_send_conf(signal, scanptr);
12906     return;
12907   }
12908 
12909   if(noCompletedOps == 0 && status != 0 &&
12910      !scanptr.p->m_pass_all_confs &&
12911      scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
12912     /**
12913      * Start on next fragment. Don't do this if we scan via the SPJ block. In
12914      * that case, dropping the last SCAN_TABCONF message for a fragment would
12915      * mean dropping the 'nodeMask' (which is sent in ScanFragConf::total_len).
12916      * This would confuse the API with respect to which pushed operations that
12917      * would get new tuples in the next batch. If we use SPJ, we must thus
12918      * send SCAN_TABCONF and let the API ask for the next batch.
12919      */
12920     scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
12921     scanFragptr.p->startFragTimer(ctcTimer);
12922 
12923     scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
12924     DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
12925     req->senderRef = reference();
12926     req->tableId = scanptr.p->scanTableref;
12927     req->scanCookie = scanptr.p->m_scan_cookie;
12928     req->fragCnt = 1;
12929     req->fragItem[0].senderData = scanFragptr.i;
12930     req->fragItem[0].fragId = scanFragptr.p->scanFragId;
12931     sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
12932                DihScanGetNodesReq::FixedSignalLength
12933                + DihScanGetNodesReq::FragItem::Length,
12934                JBB);
12935     return;
12936   }
12937  /*
12938   Uint32 totalLen = 0;
12939   for(Uint32 i = 0; i<noCompletedOps; i++){
12940     Uint32 tmp = conf->opReturnDataLen[i];
12941     totalLen += tmp;
12942   }
12943  */
12944   {
12945     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
12946     ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
12947 
12948     run.remove(scanFragptr);
12949     queued.addFirst(scanFragptr);
12950     scanptr.p->m_queued_count++;
12951   }
12952 
12953   if (status != 0 &&
12954       scanptr.p->m_pass_all_confs &&
12955       scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count
12956       < scanptr.p->scanNoFrag){
12957     /**
12958      * nodeMask(=total_len) should be zero since there will be no more
12959      * rows from this fragment.
12960      */
12961     ndbrequire(total_len==0);
12962     /**
12963      * Now set it to one to tell the API that there may be more rows from
12964      * the next fragment.
12965      */
12966     total_len  = 1;
12967   }
12968 
12969   scanFragptr.p->m_scan_frag_conf_status = status;
12970   scanFragptr.p->m_ops = noCompletedOps;
12971   scanFragptr.p->m_totalLen = total_len;
12972   scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
12973   scanFragptr.p->stopFragTimer();
12974 
12975   if(scanptr.p->m_queued_count > /** Min */ 0){
12976     jam();
12977     sendScanTabConf(signal, scanptr);
12978   }
12979 }//Dbtc::execSCAN_FRAGCONF()
12980 
12981 /****************************************************************************
12982  * execSCAN_NEXTREQ
12983  *
12984  * THE APPLICATION HAS PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
12985  * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
12986  ****************************************************************************/
execSCAN_NEXTREQ(Signal * signal)12987 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
12988 {
12989   const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
12990   const UintR transid1 = req->transId1;
12991   const UintR transid2 = req->transId2;
12992   const UintR stopScan = req->stopScan;
12993 
12994   jamEntry();
12995 
12996   SectionHandle handle(this, signal);
12997   apiConnectptr.i = req->apiConnectPtr;
12998   if (apiConnectptr.i >= capiConnectFilesize) {
12999     jam();
13000     releaseSections(handle);
13001     warningHandlerLab(signal, __LINE__);
13002     return;
13003   }//if
13004   ptrAss(apiConnectptr, apiConnectRecord);
13005 
13006   /**
13007    * Check transid
13008    */
13009   const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
13010   const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
13011   if ((ctransid1 | ctransid2) != 0){
13012     releaseSections(handle);
13013     ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
13014     ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
13015     ref->transId1 = transid1;
13016     ref->transId2 = transid2;
13017     ref->errorCode  = ZSTATE_ERROR;
13018     ref->closeNeeded = 0;
13019     sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
13020 	       signal, ScanTabRef::SignalLength, JBB);
13021     DEBUG("Wrong transid");
13022     return;
13023   }
13024 
13025   /**
13026    * Check state of API connection
13027    */
13028   if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
13029     jam();
13030     releaseSections(handle);
13031     if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
13032       jam();
13033       /*********************************************************************
13034        * The application sends a SCAN_NEXTREQ after experiencing a time-out.
13035        *  We will send a SCAN_TABREF to indicate a time-out occurred.
13036        *********************************************************************/
13037       DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
13038       ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
13039       ndbrequire(false); //B2 indication of strange things going on
13040       scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
13041       return;
13042     }
13043     DEBUG("scanTabRefLab: ZSTATE_ERROR");
13044     DEBUG("  apiConnectstate="<<apiConnectptr.p->apiConnectstate);
13045     ndbrequire(false); //B2 indication of strange things going on
13046     scanTabRefLab(signal, ZSTATE_ERROR);
13047     return;
13048   }//if
13049 
13050   /*******************************************************
13051    * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
13052    ********************************************************/
13053   // Stop the timer that is used to check for timeout in the API
13054   setApiConTimer(apiConnectptr.i, 0, __LINE__);
13055   ScanRecordPtr scanptr;
13056   scanptr.i = apiConnectptr.p->apiScanRec;
13057   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
13058   ScanRecord* scanP = scanptr.p;
13059 
13060   /* Copy ReceiverIds to working space past end of signal
13061    * so that we don't overwrite them when sending signals
13062    */
13063   Uint32 len = 0;
13064   if (handle.m_cnt > 0)
13065   {
13066     jam();
13067     /* TODO : Add Dropped signal handling for SCAN_NEXTREQ */
13068     /* Receiver ids are in a long section */
13069     ndbrequire(signal->getLength() == ScanNextReq::SignalLength);
13070     ndbrequire(handle.m_cnt == 1);
13071     SegmentedSectionPtr receiverIdsSection;
13072     ndbrequire(handle.getSection(receiverIdsSection,
13073                                  ScanNextReq::ReceiverIdsSectionNum));
13074     len= receiverIdsSection.p->m_sz;
13075     ndbassert(len < (8192 - 25));
13076 
13077     copy(signal->getDataPtrSend()+25, receiverIdsSection);
13078     releaseSections(handle);
13079   }
13080   else
13081   {
13082     jam();
13083     len= signal->getLength() - ScanNextReq::SignalLength;
13084     memcpy(signal->getDataPtrSend()+25,
13085            signal->getDataPtr()+ ScanNextReq::SignalLength,
13086            4 * len);
13087   }
13088 
13089   if (stopScan == ZTRUE) {
13090     jam();
13091     /*********************************************************************
13092      * APPLICATION IS CLOSING THE SCAN.
13093      **********************************************************************/
13094     close_scan_req(signal, scanptr, true);
13095     return;
13096   }//if
13097 
13098   if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
13099     jam();
13100     /**
13101      * The scan is closing (typically due to error)
13102      *   but the API hasn't understood it yet
13103      *
13104      * Wait for API close request
13105      */
13106     return;
13107   }
13108 
13109   ScanFragNextReq tmp;
13110   tmp.requestInfo = 0;
13111   tmp.transId1 = apiConnectptr.p->transid[0];
13112   tmp.transId2 = apiConnectptr.p->transid[1];
13113   tmp.batch_size_rows = scanP->batch_size_rows;
13114   tmp.batch_size_bytes = scanP->batch_byte_size;
13115 
13116   ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
13117   ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
13118   for(Uint32 i = 0 ; i<len; i++){
13119     jam();
13120     scanFragptr.i = signal->theData[i+25];
13121     c_scan_frag_pool.getPtr(scanFragptr);
13122     ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
13123 
13124     scanFragptr.p->startFragTimer(ctcTimer);
13125     scanFragptr.p->m_ops = 0;
13126 
13127     if(scanFragptr.p->m_scan_frag_conf_status)
13128     {
13129       /**
13130        * last scan was complete
13131        */
13132       jam();
13133       ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
13134       ndbassert(scanptr.p->m_booked_fragments_count);
13135       scanptr.p->m_booked_fragments_count--;
13136       scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
13137 
13138       scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
13139 
13140       DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
13141       req->senderRef = reference();
13142       req->tableId = scanptr.p->scanTableref;
13143       req->scanCookie = scanptr.p->m_scan_cookie;
13144       req->fragCnt = 1;
13145       req->fragItem[0].senderData = scanFragptr.i;
13146       req->fragItem[0].fragId = scanFragptr.p->scanFragId;
13147       sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
13148                  DihScanGetNodesReq::FixedSignalLength
13149                  + DihScanGetNodesReq::FragItem::Length,
13150                  JBB);
13151     }
13152     else
13153     {
13154       jam();
13155       scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
13156       ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
13157       * req = tmp;
13158       req->senderData = scanFragptr.i;
13159       sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
13160 		 ScanFragNextReq::SignalLength, JBB);
13161     }
13162     delivered.remove(scanFragptr);
13163     running.addFirst(scanFragptr);
13164   }//for
13165 
13166 }//Dbtc::execSCAN_NEXTREQ()
13167 
13168 void
close_scan_req(Signal * signal,ScanRecordPtr scanPtr,bool req_received)13169 Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
13170 
13171   ScanRecord* scanP = scanPtr.p;
13172   ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
13173   ScanRecord::ScanState old = scanPtr.p->scanState;
13174   scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
13175   scanPtr.p->m_close_scan_req = req_received;
13176 
13177   if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
13178   {
13179     jam();
13180     scanPtr.p->scanState = old;
13181     return; // Will continue on execDI_FCOUNTCONF
13182   }
13183 
13184   /**
13185    * Queue         : Action
13186    * ============= : =================
13187    * completed     : -
13188    * running       : close -> LQH
13189    * delivered w/  : close -> LQH
13190    * delivered wo/ : move to completed
13191    * queued w/     : close -> LQH
13192    * queued wo/    : move to completed
13193    */
13194 
13195   ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
13196   nextReq->requestInfo = 0;
13197   ScanFragNextReq::setCloseFlag(nextReq->requestInfo, 1);
13198   nextReq->transId1 = apiConnectptr.p->transid[0];
13199   nextReq->transId2 = apiConnectptr.p->transid[1];
13200 
13201   {
13202     ScanFragRecPtr ptr;
13203     ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
13204     ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
13205     ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
13206 
13207     // Close running
13208     for(running.first(ptr); !ptr.isNull(); ){
13209       ScanFragRecPtr curr = ptr; // Remove while iterating...
13210       running.next(ptr);
13211 
13212       switch(curr.p->scanFragState){
13213       case ScanFragRec::IDLE:
13214 	jam(); // real early abort
13215 	ndbrequire(old == ScanRecord::WAIT_AI || old == ScanRecord::RUNNING);
13216         curr.p->scanFragState = ScanFragRec::COMPLETED;
13217 	running.release(curr);
13218 	continue;
13219       case ScanFragRec::WAIT_GET_PRIMCONF:
13220 	jam();
13221 	continue;
13222       case ScanFragRec::LQH_ACTIVE:
13223 	jam();
13224 	break;
13225       default:
13226 	jamLine(curr.p->scanFragState);
13227 	ndbrequire(false);
13228       }
13229 
13230       curr.p->startFragTimer(ctcTimer);
13231       curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
13232       nextReq->senderData = curr.i;
13233       sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
13234 		 ScanFragNextReq::SignalLength, JBB);
13235     }
13236 
13237     // Close delivered
13238     for(delivered.first(ptr); !ptr.isNull(); ){
13239       jam();
13240       ScanFragRecPtr curr = ptr; // Remove while iterating...
13241       delivered.next(ptr);
13242 
13243       ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
13244       delivered.remove(curr);
13245 
13246       if (curr.p->m_scan_frag_conf_status == 0)
13247       {
13248 	jam();
13249         running.addFirst(curr);
13250 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
13251 	curr.p->startFragTimer(ctcTimer);
13252 	nextReq->senderData = curr.i;
13253 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
13254 		   ScanFragNextReq::SignalLength, JBB);
13255 
13256       }
13257       else
13258       {
13259 	jam();
13260 	c_scan_frag_pool.release(curr);
13261 	curr.p->scanFragState = ScanFragRec::COMPLETED;
13262 	curr.p->stopFragTimer();
13263       }
13264     }//for
13265 
13266     /**
13267      * All queued with data should be closed
13268      */
13269     for(queued.first(ptr); !ptr.isNull(); ){
13270       jam();
13271       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
13272       ScanFragRecPtr curr = ptr; // Remove while iterating...
13273       queued.next(ptr);
13274 
13275       queued.remove(curr);
13276       scanP->m_queued_count--;
13277 
13278       if (curr.p->m_scan_frag_conf_status == 0)
13279       {
13280 	jam();
13281         running.addFirst(curr);
13282 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
13283 	curr.p->startFragTimer(ctcTimer);
13284 	nextReq->senderData = curr.i;
13285 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
13286 		   ScanFragNextReq::SignalLength, JBB);
13287       }
13288       else
13289       {
13290 	jam();
13291 	c_scan_frag_pool.release(curr);
13292 	curr.p->scanFragState = ScanFragRec::COMPLETED;
13293 	curr.p->stopFragTimer();
13294       }
13295     }
13296   }
13297   close_scan_req_send_conf(signal, scanPtr);
13298 }
13299 
13300 void
close_scan_req_send_conf(Signal * signal,ScanRecordPtr scanPtr)13301 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
13302 
13303   jam();
13304 
13305   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
13306   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
13307   //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
13308 
13309   if(!scanPtr.p->m_running_scan_frags.isEmpty()){
13310     jam();
13311     return;
13312   }
13313 
13314   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
13315 
13316   if(!scanPtr.p->m_close_scan_req){
13317     jam();
13318     /**
13319      * The API hasn't order closing yet
13320      */
13321     return;
13322   }
13323 
13324   Uint32 ref = apiConnectptr.p->ndbapiBlockref;
13325   if(!apiFail && ref){
13326     jam();
13327     ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
13328     conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
13329     conf->requestInfo = ScanTabConf::EndOfData;
13330     conf->transId1 = apiConnectptr.p->transid[0];
13331     conf->transId2 = apiConnectptr.p->transid[1];
13332     sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
13333   }
13334 
13335   releaseScanResources(signal, scanPtr);
13336 
13337   if(apiFail){
13338     jam();
13339     /**
13340      * API has failed
13341      */
13342     handleApiFailState(signal, apiConnectptr.i);
13343   }
13344 }
13345 
13346 Dbtc::ScanRecordPtr
seizeScanrec(Signal * signal)13347 Dbtc::seizeScanrec(Signal* signal) {
13348   ScanRecordPtr scanptr;
13349   scanptr.i = cfirstfreeScanrec;
13350   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
13351   cfirstfreeScanrec = scanptr.p->nextScan;
13352   scanptr.p->nextScan = RNIL;
13353   cConcScanCount++;
13354   ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
13355   return scanptr;
13356 }//Dbtc::seizeScanrec()
13357 
sendScanFragReq(Signal * signal,ScanRecord * scanP,ScanFragRec * scanFragP,bool isLastReq)13358 void Dbtc::sendScanFragReq(Signal* signal,
13359 			   ScanRecord* scanP,
13360 			   ScanFragRec* scanFragP,
13361                            bool isLastReq)
13362 {
13363   Uint32 version= getNodeInfo(refToNode(scanFragP->lqhBlockref)).m_version;
13364   bool longFragReq= ((version >= NDBD_LONG_SCANFRAGREQ) &&
13365                      (! ERROR_INSERTED(8070) &&
13366 		      ! ERROR_INSERTED(8088)));
13367 
13368   SectionHandle sections(this);
13369   sections.m_ptr[0].i = scanP->scanAttrInfoPtr;
13370   sections.m_ptr[1].i = scanP->scanKeyInfoPtr;
13371 
13372   sections.m_cnt = 1; // there is always attrInfo
13373 
13374   if (scanP->scanKeyInfoPtr != RNIL)
13375   {
13376     jam();
13377     sections.m_cnt = 2; // and sometimes keyinfo
13378   }
13379 
13380   if (isLastReq)
13381   {
13382     /* This send will release these sections, remove our
13383      * references to them
13384      */
13385     scanP->scanKeyInfoPtr = RNIL;
13386     scanP->scanAttrInfoPtr = RNIL;
13387   }
13388 
13389   getSections(sections.m_cnt, sections.m_ptr);
13390 
13391   ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
13392   Uint32 requestInfo = scanP->scanRequestInfo;
13393   ScanFragReq::setScanPrio(requestInfo, 1);
13394   apiConnectptr.i = scanP->scanApiRec;
13395   req->tableId = scanP->scanTableref;
13396   req->schemaVersion = scanP->scanSchemaVersion;
13397   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
13398   req->senderData = scanFragptr.i;
13399   req->requestInfo = requestInfo;
13400   req->fragmentNoKeyLen = scanFragP->scanFragId;
13401   req->resultRef = apiConnectptr.p->ndbapiBlockref;
13402   req->savePointId = apiConnectptr.p->currSavePointId;
13403   req->transId1 = apiConnectptr.p->transid[0];
13404   req->transId2 = apiConnectptr.p->transid[1];
13405   req->clientOpPtr = scanFragP->m_apiPtr;
13406   req->batch_size_rows= scanP->batch_size_rows;
13407   req->batch_size_bytes= scanP->batch_byte_size;
13408 
13409   if (likely(longFragReq))
13410   {
13411     jam();
13412     /* Send long, possibly fragmented SCAN_FRAGREQ */
13413 
13414     // TODO :
13415     //   1) Consider whether to adjust fragmentation threshold
13416     //      a) When to fragment signal vs fragment size
13417     //      b) Fragment size
13418     /* To reduce the copy burden we want to keep hold of the
13419      * AttrInfo and KeyInfo sections after sending them to
13420      * LQH.  To do this we perform the fragmented send inline,
13421      * so that all fragments are sent *now*.  This avoids any
13422      * problems with the fragmented send CONTINUE 'thread' using
13423      * the section while we hold or even release it.  The
13424      * signal receiver can still take realtime breaks when
13425      * receiving.
13426      *
13427      * Indicate to sendFirstFragment that we want to keep the
13428      * fragments, so it must not free them, unless this is the
13429      * last request in which case they can be freed.  If the
13430      * last request is a local send then a copy is avoided.
13431      */
13432     FragmentSendInfo fragSendInfo;
13433 
13434     sendFirstFragment(fragSendInfo,
13435                       NodeReceiverGroup(scanFragP->lqhBlockref),
13436                       GSN_SCAN_FRAGREQ,
13437                       signal,
13438                       ScanFragReq::SignalLength,
13439                       JBB,
13440                       &sections,
13441                       !isLastReq); // Keep sent sections unless
13442                                    // last send
13443 
13444     while (fragSendInfo.m_status != FragmentSendInfo::SendComplete)
13445     {
13446       jam();
13447       /* Send remaining fragments */
13448       sendNextSegmentedFragment(signal, fragSendInfo);
13449     }
13450 
13451     /* Clear handle, section deallocation handled elsewhere. */
13452     sections.clear();
13453   }
13454   else
13455   {
13456     jam();
13457     /* Short SCANFRAGREQ with separate KeyInfo and AttrInfo trains
13458      * Sent to older NDBD nodes during upgrade
13459      */
13460     Uint32 reqAttrLen = sections.m_ptr[0].sz;
13461     ScanFragReq::setAttrLen(req->requestInfo, reqAttrLen);
13462     if (sections.m_cnt > 1)
13463     {
13464       jam();
13465       /*
13466        * bug#13834481 missing shift, causing fragment not found
13467        * (error 1231) on 6.3 node.
13468        */
13469       req->fragmentNoKeyLen |= (sections.m_ptr[1].sz << 16);
13470     }
13471     sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
13472                ScanFragReq::SignalLength, JBB);
13473     if (sections.m_cnt > 1)
13474     {
13475       jam();
13476       /* Build KeyInfo train from KeyInfo long signal section */
13477       sendKeyInfoTrain(signal,
13478                        scanFragP->lqhBlockref,
13479                        scanFragptr.i,
13480                        0, // Offset 0
13481                        sections.m_ptr[1].i);
13482     }
13483 
13484     if(ERROR_INSERTED(8035))
13485       globalTransporterRegistry.performSend();
13486 
13487     if (!ERROR_INSERTED(8088))
13488     {
13489       ndbrequire(sendAttrInfoTrain(signal,
13490                                    scanFragP->lqhBlockref,
13491                                    scanFragptr.i,
13492                                    0, // Offset 0
13493                                    sections.m_ptr[0].i));
13494     }
13495 
13496     if(ERROR_INSERTED(8035))
13497       globalTransporterRegistry.performSend();
13498 
13499     if (isLastReq)
13500     {
13501       /* Free the sections here */
13502       releaseSections(sections);
13503     }
13504     else
13505     {
13506       sections.clear();
13507     }
13508   }
13509 
13510   if (ERROR_INSERTED(8088))
13511   {
13512     signal->theData[0] = 9999;
13513     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
13514   }
13515 }//Dbtc::sendScanFragReq()
13516 
13517 
sendScanTabConf(Signal * signal,ScanRecordPtr scanPtr)13518 void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
13519   jam();
13520   Uint32* ops = signal->getDataPtrSend()+4;
13521   Uint32 op_count = scanPtr.p->m_queued_count;
13522 
13523   Uint32 words_per_op = 4;
13524   const Uint32 ref = apiConnectptr.p->ndbapiBlockref;
13525   if (!scanPtr.p->m_4word_conf)
13526   {
13527     jam();
13528     words_per_op = 3;
13529   }
13530 
13531   if (4 + words_per_op * op_count > 25)
13532   {
13533     jam();
13534     ops += 21;
13535   }
13536 
13537   int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
13538   Uint32 booked = scanPtr.p->m_booked_fragments_count;
13539 
13540   ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
13541   conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
13542   conf->requestInfo = op_count;
13543   conf->transId1 = apiConnectptr.p->transid[0];
13544   conf->transId2 = apiConnectptr.p->transid[1];
13545   ScanFragRecPtr ptr;
13546   {
13547     ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
13548     ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
13549     for(queued.first(ptr); !ptr.isNull(); ){
13550       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
13551       ScanFragRecPtr curr = ptr; // Remove while iterating...
13552       queued.next(ptr);
13553 
13554       bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
13555       if(curr.p->m_scan_frag_conf_status)
13556 	booked++;
13557 
13558       * ops++ = curr.p->m_apiPtr;
13559       * ops++ = done ? RNIL : curr.i;
13560       if (words_per_op == 4)
13561       {
13562         * ops++ = curr.p->m_ops;
13563         * ops++ = curr.p->m_totalLen;
13564       }
13565       else
13566       {
13567         * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
13568       }
13569 
13570       queued.remove(curr);
13571       if(!done){
13572         delivered.addFirst(curr);
13573 	curr.p->scanFragState = ScanFragRec::DELIVERED;
13574 	curr.p->stopFragTimer();
13575       } else {
13576 	c_scan_frag_pool.release(curr);
13577 	curr.p->scanFragState = ScanFragRec::COMPLETED;
13578 	curr.p->stopFragTimer();
13579       }
13580     }
13581   }
13582 
13583   bool release = false;
13584   scanPtr.p->m_booked_fragments_count = booked;
13585   if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
13586      scanPtr.p->m_running_scan_frags.isEmpty())
13587   {
13588     jam();
13589     release = true;
13590     conf->requestInfo = op_count | ScanTabConf::EndOfData;
13591   }
13592   else
13593   {
13594     if (scanPtr.p->m_running_scan_frags.isEmpty())
13595     {
13596       jam();
13597       /**
13598        * All scan frags delivered...waiting for API
13599        */
13600       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
13601     }
13602   }
13603 
13604   if (4 + words_per_op * op_count > 25)
13605   {
13606     jam();
13607     LinearSectionPtr ptr[3];
13608     ptr[0].p = signal->getDataPtrSend()+25;
13609     ptr[0].sz = words_per_op * op_count;
13610     sendSignal(ref, GSN_SCAN_TABCONF, signal,
13611                ScanTabConf::SignalLength, JBB, ptr, 1);
13612   }
13613   else
13614   {
13615     jam();
13616     sendSignal(ref, GSN_SCAN_TABCONF, signal,
13617 	       ScanTabConf::SignalLength + words_per_op * op_count, JBB);
13618   }
13619   scanPtr.p->m_queued_count = 0;
13620 
13621   if (release)
13622   {
13623     jam();
13624     releaseScanResources(signal, scanPtr);
13625   }
13626 
13627 }//Dbtc::sendScanTabConf()
13628 
13629 
gcpTcfinished(Signal * signal,Uint64 gci)13630 void Dbtc::gcpTcfinished(Signal* signal, Uint64 gci)
13631 {
13632   GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
13633   conf->senderData = c_gcp_data;
13634   conf->gci_hi = Uint32(gci >> 32);
13635   conf->gci_lo = Uint32(gci);
13636   conf->tcFailNo = cfailure_nr; /* Indicate highest handled failno in GCP */
13637 
13638 #ifdef ERROR_INSERT
13639   if (ERROR_INSERTED(8098))
13640   {
13641     if (cmasterNodeId == getOwnNodeId())
13642     {
13643       bool multi = ((gci&1) == 1);
13644       bool kill_me = ((gci&3) == 1);
13645       /* Kill multi 'assumes' NoOfReplicas=2, and skipping one
13646        * live node at a time avoids taking out a nodegroup
13647        */
13648       ndbout_c("TC killing multi : %u  me : %u", multi, kill_me);
13649       Uint32 start = getOwnNodeId();
13650       bool skip = !kill_me;
13651       Uint32 pos = start;
13652       do
13653       {
13654         NodeInfo ni = getNodeInfo(pos);
13655         if ((ni.getType() == NODE_TYPE_DB) &&
13656             ni.m_connected)
13657         {
13658           /* Found a db node... */
13659           if (!skip)
13660           {
13661             ndbout_c("TC : Killing node %u", pos);
13662             signal->theData[0] = 9999;
13663             sendSignal(numberToRef(CMVMI, pos), GSN_DUMP_STATE_ORD, signal,
13664                        1, JBA);
13665             if (!multi)
13666               break;
13667             skip = true;
13668           }
13669           else
13670           {
13671             ndbout_c("TC : Skipping node %u", pos);
13672             skip = false;
13673           }
13674         }
13675 
13676         pos++;
13677         if (pos == MAX_NDB_NODES)
13678           pos = 1;
13679       } while (pos != start);
13680     }
13681 
13682     /* Keep delaying GCP_TCFINISHED, but don't kill anymore */
13683     SET_ERROR_INSERT_VALUE(8099);
13684   }
13685 
13686   if (ERROR_INSERTED(8099))
13687   {
13688     /* Slow it down */
13689     ndbout_c("TC : Sending delayed GCP_TCFINISHED (%u/%u), failNo %u to local DIH(%x)",
13690              conf->gci_hi, conf->gci_lo, cfailure_nr, cdihblockref);
13691     sendSignalWithDelay(cdihblockref, GSN_GCP_TCFINISHED, signal,
13692                         2000, GCPTCFinished::SignalLength);
13693     return;
13694   }
13695 #endif
13696   sendSignal(c_gcp_ref, GSN_GCP_TCFINISHED, signal,
13697              GCPTCFinished::SignalLength, JBB);
13698 }//Dbtc::gcpTcfinished()
13699 
initApiConnect(Signal * signal)13700 void Dbtc::initApiConnect(Signal* signal)
13701 {
13702   Uint32 tiacTmp;
13703   Uint32 guard4;
13704 
13705   tiacTmp = capiConnectFilesize / 3;
13706   ndbrequire(tiacTmp > 0);
13707   guard4 = tiacTmp + 1;
13708   for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
13709     refresh_watch_dog();
13710     ptrAss(cachePtr, cacheRecord);
13711     cachePtr.p->nextCacheRec = cachePtr.i + 1;
13712   }//for
13713   cachePtr.i = tiacTmp;
13714   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
13715   cachePtr.p->nextCacheRec = RNIL;
13716   cfirstfreeCacheRec = 0;
13717 
13718   guard4 = tiacTmp - 1;
13719   for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
13720     refresh_watch_dog();
13721     jam();
13722     ptrAss(apiConnectptr, apiConnectRecord);
13723     apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
13724     apiConnectptr.p->apiFailState = ZFALSE;
13725     setApiConTimer(apiConnectptr.i, 0, __LINE__);
13726     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
13727     apiConnectptr.p->cachePtr = RNIL;
13728     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
13729     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
13730     apiConnectptr.p->commitAckMarker = RNIL;
13731     apiConnectptr.p->num_commit_ack_markers = 0;
13732     apiConnectptr.p->firstTcConnect = RNIL;
13733     apiConnectptr.p->lastTcConnect = RNIL;
13734     apiConnectptr.p->m_flags = 0;
13735     apiConnectptr.p->m_special_op_flags = 0;
13736     apiConnectptr.p->accumulatingIndexOp = RNIL;
13737     apiConnectptr.p->executingIndexOp = RNIL;
13738     apiConnectptr.p->buddyPtr = RNIL;
13739     apiConnectptr.p->currSavePointId = 0;
13740     apiConnectptr.p->m_transaction_nodes.clear();
13741     apiConnectptr.p->singleUserMode = 0;
13742     apiConnectptr.p->apiCopyRecord = RNIL;
13743   }//for
13744   apiConnectptr.i = tiacTmp - 1;
13745   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
13746   apiConnectptr.p->nextApiConnect = RNIL;
13747   cfirstfreeApiConnect = 0;
13748   guard4 = (2 * tiacTmp) - 1;
13749   for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
13750     {
13751       refresh_watch_dog();
13752       jam();
13753       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
13754       apiConnectptr.p->apiConnectstate = CS_RESTART;
13755       apiConnectptr.p->apiFailState = ZFALSE;
13756       setApiConTimer(apiConnectptr.i, 0, __LINE__);
13757       apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
13758       apiConnectptr.p->cachePtr = RNIL;
13759       apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
13760       apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
13761       apiConnectptr.p->commitAckMarker = RNIL;
13762       apiConnectptr.p->num_commit_ack_markers = 0;
13763       apiConnectptr.p->firstTcConnect = RNIL;
13764       apiConnectptr.p->lastTcConnect = RNIL;
13765       apiConnectptr.p->m_flags = 0;
13766       apiConnectptr.p->m_special_op_flags = 0;
13767       apiConnectptr.p->accumulatingIndexOp = RNIL;
13768       apiConnectptr.p->executingIndexOp = RNIL;
13769       apiConnectptr.p->buddyPtr = RNIL;
13770       apiConnectptr.p->currSavePointId = 0;
13771       apiConnectptr.p->m_transaction_nodes.clear();
13772       apiConnectptr.p->singleUserMode = 0;
13773       apiConnectptr.p->apiCopyRecord = RNIL;
13774     }//for
13775   apiConnectptr.i = (2 * tiacTmp) - 1;
13776   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
13777   apiConnectptr.p->nextApiConnect = RNIL;
13778   cfirstfreeApiConnectCopy = tiacTmp;
13779   guard4 = (3 * tiacTmp) - 1;
13780   for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
13781        apiConnectptr.i++) {
13782     refresh_watch_dog();
13783     jam();
13784     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
13785     setApiConTimer(apiConnectptr.i, 0, __LINE__);
13786     apiConnectptr.p->apiFailState = ZFALSE;
13787     apiConnectptr.p->apiConnectstate = CS_RESTART;
13788     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
13789     apiConnectptr.p->cachePtr = RNIL;
13790     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
13791     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
13792     apiConnectptr.p->commitAckMarker = RNIL;
13793     apiConnectptr.p->num_commit_ack_markers = 0;
13794     apiConnectptr.p->firstTcConnect = RNIL;
13795     apiConnectptr.p->lastTcConnect = RNIL;
13796     apiConnectptr.p->m_flags = 0;
13797     apiConnectptr.p->m_special_op_flags = 0;
13798     apiConnectptr.p->accumulatingIndexOp = RNIL;
13799     apiConnectptr.p->executingIndexOp = RNIL;
13800     apiConnectptr.p->buddyPtr = RNIL;
13801     apiConnectptr.p->currSavePointId = 0;
13802     apiConnectptr.p->m_transaction_nodes.clear();
13803     apiConnectptr.p->singleUserMode = 0;
13804     apiConnectptr.p->apiCopyRecord = RNIL;
13805   }//for
13806   apiConnectptr.i = (3 * tiacTmp) - 1;
13807   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
13808   apiConnectptr.p->nextApiConnect = RNIL;
13809   cfirstfreeApiConnectFail = 2 * tiacTmp;
13810 }//Dbtc::initApiConnect()
13811 
initgcp(Signal * signal)13812 void Dbtc::initgcp(Signal* signal)
13813 {
13814   Ptr<GcpRecord> gcpPtr;
13815   ndbrequire(cgcpFilesize > 0);
13816   for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
13817     ptrAss(gcpPtr, gcpRecord);
13818     gcpPtr.p->nextGcp = gcpPtr.i + 1;
13819   }//for
13820   gcpPtr.i = cgcpFilesize - 1;
13821   ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
13822   gcpPtr.p->nextGcp = RNIL;
13823   cfirstfreeGcp = 0;
13824   cfirstgcp = RNIL;
13825   clastgcp = RNIL;
13826 }//Dbtc::initgcp()
13827 
inithost(Signal * signal)13828 void Dbtc::inithost(Signal* signal)
13829 {
13830   cpackedListIndex = 0;
13831   ndbrequire(chostFilesize > 0);
13832   for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
13833     jam();
13834     ptrAss(hostptr, hostRecord);
13835     hostptr.p->hostStatus = HS_DEAD;
13836     hostptr.p->inPackedList = false;
13837     hostptr.p->lqhTransStatus = LTS_IDLE;
13838     struct PackedWordsContainer * containerTCKEYCONF =
13839       &hostptr.p->packTCKEYCONF;
13840     containerTCKEYCONF->noOfPackedWords = 0;
13841     for (Uint32 i = 0; i < NDB_ARRAY_SIZE(hostptr.p->lqh_pack); i++)
13842     {
13843       struct PackedWordsContainer * container = &hostptr.p->lqh_pack[i];
13844       container->noOfPackedWords = 0;
13845       container->hostBlockRef = numberToRef(DBLQH, i, hostptr.i);
13846     }
13847     hostptr.p->m_nf_bits = 0;
13848   }//for
13849   c_alive_nodes.clear();
13850 }//Dbtc::inithost()
13851 
initialiseRecordsLab(Signal * signal,UintR Tdata0,Uint32 retRef,Uint32 retData)13852 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
13853 				Uint32 retRef, Uint32 retData)
13854 {
13855   switch (Tdata0) {
13856   case 0:
13857     jam();
13858     initApiConnect(signal);
13859     break;
13860   case 1:
13861     jam();
13862     // UNUSED Free to initialise something
13863     break;
13864   case 2:
13865     jam();
13866     // UNUSED Free to initialise something
13867     break;
13868   case 3:
13869     jam();
13870     initgcp(signal);
13871     break;
13872   case 4:
13873     jam();
13874     inithost(signal);
13875     break;
13876   case 5:
13877     jam();
13878     // UNUSED Free to initialise something
13879     break;
13880   case 6:
13881     jam();
13882     initTable(signal);
13883     break;
13884   case 7:
13885     jam();
13886     initialiseScanrec(signal);
13887     break;
13888   case 8:
13889     jam();
13890     initialiseScanOprec(signal);
13891     break;
13892   case 9:
13893     jam();
13894     initialiseScanFragrec(signal);
13895     break;
13896   case 10:
13897     jam();
13898     initialiseTcConnect(signal);
13899     break;
13900   case 11:
13901     jam();
13902     initTcFail(signal);
13903 
13904     {
13905       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
13906       conf->senderRef = reference();
13907       conf->senderData = retData;
13908       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
13909 		 ReadConfigConf::SignalLength, JBB);
13910     }
13911     return;
13912     break;
13913   default:
13914     jam();
13915     systemErrorLab(signal, __LINE__);
13916     return;
13917     break;
13918   }//switch
13919 
13920   signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
13921   signal->theData[1] = Tdata0 + 1;
13922   signal->theData[2] = 0;
13923   signal->theData[3] = retRef;
13924   signal->theData[4] = retData;
13925   sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
13926 }
13927 
13928 /* ========================================================================= */
13929 /* =======                       INITIALISE_SCANREC                  ======= */
13930 /*                                                                           */
13931 /* ========================================================================= */
initialiseScanrec(Signal * signal)13932 void Dbtc::initialiseScanrec(Signal* signal)
13933 {
13934   ScanRecordPtr scanptr;
13935   ndbrequire(cscanrecFileSize > 0);
13936   for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
13937     refresh_watch_dog();
13938     jam();
13939     ptrAss(scanptr, scanRecord);
13940     new (scanptr.p) ScanRecord();
13941     scanptr.p->scanState = ScanRecord::IDLE;
13942     scanptr.p->scanApiRec = RNIL;
13943     scanptr.p->nextScan = scanptr.i + 1;
13944   }//for
13945   scanptr.i = cscanrecFileSize - 1;
13946   ptrAss(scanptr, scanRecord);
13947   scanptr.p->nextScan = RNIL;
13948   cfirstfreeScanrec = 0;
13949   cConcScanCount = 0;
13950 }//Dbtc::initialiseScanrec()
13951 
initialiseScanFragrec(Signal * signal)13952 void Dbtc::initialiseScanFragrec(Signal* signal)
13953 {
13954 }//Dbtc::initialiseScanFragrec()
13955 
initialiseScanOprec(Signal * signal)13956 void Dbtc::initialiseScanOprec(Signal* signal)
13957 {
13958 }//Dbtc::initialiseScanOprec()
13959 
initTable(Signal * signal)13960 void Dbtc::initTable(Signal* signal)
13961 {
13962 
13963   ndbrequire(ctabrecFilesize > 0);
13964   for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
13965     refresh_watch_dog();
13966     ptrAss(tabptr, tableRecord);
13967     tabptr.p->currentSchemaVersion = 0;
13968     tabptr.p->m_flags = 0;
13969     tabptr.p->set_storedTable(true);
13970     tabptr.p->tableType = 0;
13971     tabptr.p->set_enabled(false);
13972     tabptr.p->set_dropping(false);
13973     tabptr.p->noOfKeyAttr = 0;
13974     tabptr.p->hasCharAttr = 0;
13975     tabptr.p->noOfDistrKeys = 0;
13976     tabptr.p->hasVarKeys = 0;
13977   }//for
13978 }//Dbtc::initTable()
13979 
initialiseTcConnect(Signal * signal)13980 void Dbtc::initialiseTcConnect(Signal* signal)
13981 {
13982   ndbrequire(ctcConnectFilesize >= 2);
13983 
13984   // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
13985   Uint32 titcTmp = ctcConnectFilesize / 2;
13986   for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
13987     refresh_watch_dog();
13988     jam();
13989     ptrAss(tcConnectptr, tcConnectRecord);
13990     new (tcConnectptr.p) TcConnectRecord();
13991     tcConnectptr.p->tcConnectstate = OS_CONNECTED;
13992     tcConnectptr.p->apiConnect = RNIL;
13993     tcConnectptr.p->noOfNodes = 0;
13994     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
13995     tcConnectptr.p->commitAckMarker = RNIL;
13996   }//for
13997   tcConnectptr.i = titcTmp - 1;
13998   ptrAss(tcConnectptr, tcConnectRecord);
13999   tcConnectptr.p->nextTcConnect = RNIL;
14000   cfirstfreeTcConnectFail = 0;
14001 
14002   // Place other half in cfirstfreeTcConnect list
14003   for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
14004        tcConnectptr.i++) {
14005     refresh_watch_dog();
14006     jam();
14007     ptrAss(tcConnectptr, tcConnectRecord);
14008     new (tcConnectptr.p) TcConnectRecord();
14009     tcConnectptr.p->tcConnectstate = OS_CONNECTED;
14010     tcConnectptr.p->apiConnect = RNIL;
14011     tcConnectptr.p->noOfNodes = 0;
14012     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
14013     tcConnectptr.p->commitAckMarker = RNIL;
14014   }//for
14015   tcConnectptr.i = ctcConnectFilesize - 1;
14016   ptrAss(tcConnectptr, tcConnectRecord);
14017   tcConnectptr.p->nextTcConnect = RNIL;
14018   cfirstfreeTcConnect = titcTmp;
14019   c_counters.cconcurrentOp = 0;
14020 }//Dbtc::initialiseTcConnect()
14021 
14022 /* ------------------------------------------------------------------------- */
14023 /* ----     LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS  */
14024 /*          WAITING FOR COMPLETION.                                          */
14025 /* ------------------------------------------------------------------------- */
linkGciInGcilist(Ptr<GcpRecord> gcpPtr)14026 void Dbtc::linkGciInGcilist(Ptr<GcpRecord> gcpPtr)
14027 {
14028   GcpRecordPtr tmpGcpPointer;
14029   if (cfirstgcp == RNIL) {
14030     jam();
14031     cfirstgcp = gcpPtr.i;
14032   } else {
14033     jam();
14034     tmpGcpPointer.i = clastgcp;
14035     ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
14036     tmpGcpPointer.p->nextGcp = gcpPtr.i;
14037   }//if
14038   clastgcp = gcpPtr.i;
14039 }//Dbtc::linkGciInGcilist()
14040 
14041 /* ------------------------------------------------------------------------- */
14042 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS  --- */
14043 /* ------------------------------------------------------------------------- */
linkTcInConnectionlist(Signal * signal)14044 void Dbtc::linkTcInConnectionlist(Signal* signal)
14045 {
14046   /* POINTER FOR THE CONNECT_RECORD */
14047   TcConnectRecordPtr ltcTcConnectptr;
14048 
14049   tcConnectptr.p->nextTcConnect = RNIL;
14050   ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
14051   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
14052   if (ltcTcConnectptr.i == RNIL) {
14053     jam();
14054     apiConnectptr.p->firstTcConnect = tcConnectptr.i;
14055   } else {
14056     jam();
14057     ptrCheckGuard(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
14058     ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
14059   }//if
14060 }//Dbtc::linkTcInConnectionlist()
14061 
14062 /*---------------------------------------------------------------------------*/
14063 /*                    RELEASE_ABORT_RESOURCES                                */
14064 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
14065 /* SENDS THE ABORT DECISION TO THE APPLICATION.                              */
14066 /*---------------------------------------------------------------------------*/
releaseAbortResources(Signal * signal)14067 void Dbtc::releaseAbortResources(Signal* signal)
14068 {
14069   TcConnectRecordPtr rarTcConnectptr;
14070 
14071   c_counters.cabortCount++;
14072   if (apiConnectptr.p->apiCopyRecord != RNIL)
14073   {
14074     // Put apiCopyRecord back in free list.
14075     jam();
14076     ApiConnectRecordPtr copyPtr;
14077     copyPtr.i = apiConnectptr.p->apiCopyRecord;
14078     ptrCheckGuard(copyPtr, capiConnectFilesize, apiConnectRecord);
14079     ndbassert(copyPtr.p->apiCopyRecord == RNIL);
14080     ndbassert(copyPtr.p->nextApiConnect == RNIL);
14081     copyPtr.p->nextApiConnect = cfirstfreeApiConnectCopy;
14082     cfirstfreeApiConnectCopy = copyPtr.i;
14083     apiConnectptr.p->apiCopyRecord = RNIL;
14084   }
14085   if (apiConnectptr.p->cachePtr != RNIL) {
14086     cachePtr.i = apiConnectptr.p->cachePtr;
14087     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
14088     releaseAttrinfo();
14089     releaseKeys();
14090   }//if
14091   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
14092   while (tcConnectptr.i != RNIL) {
14093     jam();
14094     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
14095     // Clear any markers that have not already been cleared
14096     clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
14097     rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
14098     releaseTcCon();
14099     tcConnectptr.i = rarTcConnectptr.i;
14100   }//while
14101 
14102   ndbrequire(apiConnectptr.p->num_commit_ack_markers == 0);
14103   releaseMarker(apiConnectptr.p);
14104 
14105   apiConnectptr.p->firstTcConnect = RNIL;
14106   apiConnectptr.p->lastTcConnect = RNIL;
14107   apiConnectptr.p->m_transaction_nodes.clear();
14108   apiConnectptr.p->singleUserMode = 0;
14109 
14110   // MASV let state be CS_ABORTING until all
14111   // signals in the "air" have been received. Reset to CS_CONNECTED
14112   // will be done when a TCKEYREQ with start flag is received
14113   // or releaseApiCon is called
14114   // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
14115   apiConnectptr.p->apiConnectstate = CS_ABORTING;
14116   apiConnectptr.p->abortState = AS_IDLE;
14117   releaseAllSeizedIndexOperations(apiConnectptr.p);
14118   releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
14119 
14120   if (tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG) ||
14121       apiConnectptr.p->apiFailState == ZTRUE)
14122   {
14123     jam();
14124     bool ok = false;
14125     Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
14126     ReturnSignal ret = apiConnectptr.p->returnsignal;
14127     apiConnectptr.p->returnsignal = RS_NO_RETURN;
14128     tc_clearbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
14129     switch(ret){
14130     case RS_TCROLLBACKCONF:
14131       jam();
14132       ok = true;
14133       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
14134       signal->theData[1] = apiConnectptr.p->transid[0];
14135       signal->theData[2] = apiConnectptr.p->transid[1];
14136       sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
14137       break;
14138     case RS_TCROLLBACKREP:{
14139       jam();
14140       ok = true;
14141 #ifdef ERROR_INSERT
14142       if (ERROR_INSERTED(8101))
14143       {
14144         char buf[128];
14145         BaseString::snprintf(buf, sizeof(buf), "Sending CONTINUEB:ZDEBUG_DELAY_TCROLLBACKREP");
14146         warningEvent("%s", buf);
14147 
14148         jam();
14149         signal->theData[0] = TcContinueB::ZDEBUG_DELAY_TCROLLBACKREP;
14150         signal->theData[1] = apiConnectptr.p->ndbapiConnect;
14151         signal->theData[2] = apiConnectptr.p->transid[0];
14152         signal->theData[3] = apiConnectptr.p->transid[1];
14153         signal->theData[4] = apiConnectptr.p->returncode;
14154         signal->theData[5] = apiConnectptr.p->errorData;
14155         signal->theData[6] = blockRef;
14156 
14157         sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 7);
14158         break;
14159       }
14160 #endif
14161       TcRollbackRep * const tcRollbackRep =
14162 	(TcRollbackRep *) signal->getDataPtr();
14163 
14164       tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
14165       tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
14166       tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
14167       tcRollbackRep->returnCode = apiConnectptr.p->returncode;
14168       tcRollbackRep->errorData = apiConnectptr.p->errorData;
14169       sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
14170 		 TcRollbackRep::SignalLength, JBB);
14171     }
14172       break;
14173     case RS_NO_RETURN:
14174       jam();
14175       ok = true;
14176       break;
14177     case RS_TCKEYCONF:
14178     case RS_TC_COMMITCONF:
14179       break;
14180     }
14181     if(!ok){
14182       jam();
14183       ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
14184       sendSystemError(signal, __LINE__);
14185     }//if
14186 
14187   }
14188   setApiConTimer(apiConnectptr.i, 0,
14189 		 100000+c_apiConTimer_line[apiConnectptr.i]);
14190   if (apiConnectptr.p->apiFailState == ZTRUE) {
14191     jam();
14192     handleApiFailState(signal, apiConnectptr.i);
14193     return;
14194   }//if
14195 }//Dbtc::releaseAbortResources()
14196 
releaseApiCon(Signal * signal,UintR TapiConnectPtr)14197 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
14198 {
14199   ApiConnectRecordPtr TlocalApiConnectptr;
14200 
14201   TlocalApiConnectptr.i = TapiConnectPtr;
14202   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
14203   ndbassert(TlocalApiConnectptr.p->apiCopyRecord == RNIL);
14204   ndbassert(TlocalApiConnectptr.p->nextApiConnect == RNIL);
14205   TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
14206   cfirstfreeApiConnect = TlocalApiConnectptr.i;
14207   setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
14208   TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
14209   ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
14210   ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
14211   ndbassert(TlocalApiConnectptr.p->cascading_scans_count == 0);
14212   TlocalApiConnectptr.p->ndbapiBlockref = 0;
14213   TlocalApiConnectptr.p->transid[0] = 0;
14214   TlocalApiConnectptr.p->transid[1] = 0;
14215 }//Dbtc::releaseApiCon()
14216 
releaseApiConnectFail(Signal * signal)14217 void Dbtc::releaseApiConnectFail(Signal* signal)
14218 {
14219   apiConnectptr.p->apiConnectstate = CS_RESTART;
14220   apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
14221   setApiConTimer(apiConnectptr.i, 0, __LINE__);
14222   apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
14223   cfirstfreeApiConnectFail = apiConnectptr.i;
14224   ndbrequire(apiConnectptr.p->commitAckMarker == RNIL);
14225 }//Dbtc::releaseApiConnectFail()
14226 
releaseKeys()14227 void Dbtc::releaseKeys()
14228 {
14229   Uint32 keyInfoSectionI= cachePtr.p->keyInfoSectionI;
14230 
14231   /* Release KeyInfo section if there is one */
14232   releaseSection(keyInfoSectionI);
14233   cachePtr.p->keyInfoSectionI= RNIL;
14234 
14235 }//Dbtc::releaseKeys()
14236 
releaseTcConnectFail(Signal * signal)14237 void Dbtc::releaseTcConnectFail(Signal* signal)
14238 {
14239   ptrGuard(tcConnectptr);
14240   tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
14241   tcConnectptr.p->tcConnectstate = OS_CONNECTED;
14242   cfirstfreeTcConnectFail = tcConnectptr.i;
14243 }//Dbtc::releaseTcConnectFail()
14244 
seizeApiConnect(Signal * signal)14245 void Dbtc::seizeApiConnect(Signal* signal)
14246 {
14247   if (cfirstfreeApiConnect != RNIL) {
14248     jam();
14249     terrorCode = ZOK;
14250     apiConnectptr.i = cfirstfreeApiConnect;     /* ASSIGN A FREE RECORD FROM */
14251     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14252     cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
14253     apiConnectptr.p->nextApiConnect = RNIL;
14254     setApiConTimer(apiConnectptr.i, 0, __LINE__);
14255     apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
14256     tc_clearbit(apiConnectptr.p->m_flags,
14257                 ApiConnectRecord::TF_TRIGGER_PENDING);
14258     apiConnectptr.p->m_special_op_flags = 0;
14259   } else {
14260     jam();
14261     terrorCode = ZNO_FREE_API_CONNECTION;
14262   }//if
14263 }//Dbtc::seizeApiConnect()
14264 
seizeApiConnectFail(Signal * signal)14265 void Dbtc::seizeApiConnectFail(Signal* signal)
14266 {
14267   apiConnectptr.i = cfirstfreeApiConnectFail;
14268   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14269   cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
14270   apiConnectptr.p->nextApiConnect = RNIL;
14271 }//Dbtc::seizeApiConnectFail()
14272 
seizeTcConnect(Signal * signal)14273 void Dbtc::seizeTcConnect(Signal* signal)
14274 {
14275   tcConnectptr.i = cfirstfreeTcConnect;
14276   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
14277   cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
14278   c_counters.cconcurrentOp++;
14279   tcConnectptr.p->m_special_op_flags = 0;
14280   tcConnectptr.p->tcConnectstate = OS_ABORTING;
14281   tcConnectptr.p->noOfNodes = 0;
14282 }//Dbtc::seizeTcConnect()
14283 
seizeTcConnectFail(Signal * signal)14284 void Dbtc::seizeTcConnectFail(Signal* signal)
14285 {
14286   tcConnectptr.i = cfirstfreeTcConnectFail;
14287   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
14288   cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
14289 }//Dbtc::seizeTcConnectFail()
14290 
14291 /**
14292  * sendAttrInfoTrain
14293  * This method sends an ATTRINFO signal train using AttrInfo
14294  * from the section passed, starting at the supplied offset
14295  */
sendAttrInfoTrain(Signal * signal,UintR TBRef,Uint32 connectPtr,Uint32 offset,Uint32 attrInfoIVal)14296 bool Dbtc::sendAttrInfoTrain(Signal* signal,
14297                              UintR TBRef,
14298                              Uint32 connectPtr,
14299                              Uint32 offset,
14300                              Uint32 attrInfoIVal)
14301 {
14302   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
14303 
14304   ndbassert( attrInfoIVal != RNIL );
14305   SectionReader attrInfoReader(attrInfoIVal, getSectionSegmentPool());
14306   Uint32 attrInfoLength= attrInfoReader.getSize();
14307 
14308   ndbassert( offset < attrInfoLength );
14309   if (unlikely(! attrInfoReader.step( offset )))
14310     return false;
14311   attrInfoLength-= offset;
14312 
14313   signal->theData[0] = connectPtr;
14314   signal->theData[1] = regApiPtr->transid[0];
14315   signal->theData[2] = regApiPtr->transid[1];
14316 
14317   while (attrInfoLength != 0)
14318   {
14319     Uint32 dataInSignal= MIN(AttrInfo::DataLength, attrInfoLength);
14320 
14321     if (unlikely(! attrInfoReader.getWords(&signal->theData[3],
14322                                            dataInSignal)))
14323       return false;
14324 
14325     sendSignal(TBRef, GSN_ATTRINFO, signal,
14326                AttrInfo::HeaderLength + dataInSignal, JBB);
14327 
14328     attrInfoLength-= dataInSignal;
14329   }
14330   return true;
14331 } //Dbtc::sendAttrInfoTrain()
14332 
sendContinueTimeOutControl(Signal * signal,Uint32 TapiConPtr)14333 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
14334 {
14335   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
14336   signal->theData[1] = TapiConPtr;
14337   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
14338 }//Dbtc::sendContinueTimeOutControl()
14339 
sendSystemError(Signal * signal,int line)14340 void Dbtc::sendSystemError(Signal* signal, int line)
14341 {
14342   progError(line, NDBD_EXIT_NDBREQUIRE);
14343 }//Dbtc::sendSystemError()
14344 
14345 /* ========================================================================= */
14346 /* -------             LINK ACTUAL GCP OUT OF LIST                   ------- */
14347 /* ------------------------------------------------------------------------- */
unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)14348 void Dbtc::unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)
14349 {
14350   ndbrequire(cfirstgcp == tmpGcpPtr.i);
14351 
14352   cfirstgcp = tmpGcpPtr.p->nextGcp;
14353   if (tmpGcpPtr.i == clastgcp) {
14354     jam();
14355     clastgcp = RNIL;
14356   }//if
14357 
14358   tmpGcpPtr.p->nextGcp = cfirstfreeGcp;
14359   cfirstfreeGcp = tmpGcpPtr.i;
14360 }//Dbtc::unlinkGcp()
14361 
14362 void
execDUMP_STATE_ORD(Signal * signal)14363 Dbtc::execDUMP_STATE_ORD(Signal* signal)
14364 {
14365   const Uint32 MAX_RECORDS_AT_A_TIME = 16;
14366 
14367   jamEntry();
14368   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
14369   Uint32 arg = signal->theData[0];
14370 
14371   // Dump set of ScanFragRecs
14372   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfScanFragRec){
14373     /**
14374      * DUMP 2500 12 10 1 1
14375      * Prints ScanFrag records 12 through 21 in instance 1.
14376      * The last parameter indicates whether to only print active instances.
14377      * If the parameter is missing it is set to 1 indicating printing only
14378      * active instances.
14379      *
14380      * Output to cluster log.
14381      */
14382     jam();
14383     Uint32 recordNo = 0;
14384     Uint32 numRecords = 0;
14385     Uint32 instanceId = 0;
14386     Uint32 includeOnlyActive = 1;
14387 
14388     if (signal->getLength() >= 4)
14389     {
14390       recordNo = dumpState->args[1];
14391       numRecords = dumpState->args[2];
14392       instanceId = dumpState->args[3];
14393       if (signal->getLength() >= 5)
14394       {
14395         includeOnlyActive = dumpState->args[4];
14396       }
14397     }
14398     else
14399     {
14400       return;
14401     }
14402     if (instance() != instanceId)
14403     {
14404       return;
14405     }
14406     if (numRecords > MAX_RECORDS_AT_A_TIME)
14407     {
14408       numRecords = MAX_RECORDS_AT_A_TIME;
14409     }
14410     if (recordNo >= cscanFragrecFileSize)
14411     {
14412       return;
14413     }
14414 
14415     ScanFragRecPtr sfp;
14416     sfp.i = recordNo;
14417     c_scan_frag_pool.getPtr(sfp);
14418     if (sfp.p->scanFragState != ScanFragRec::COMPLETED ||
14419         !includeOnlyActive)
14420     {
14421       dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
14422       dumpState->args[1] = recordNo;
14423       dumpState->args[2] = instance();
14424       signal->setLength(3);
14425       execDUMP_STATE_ORD(signal);
14426     }
14427     numRecords--;
14428     recordNo++;
14429 
14430     if (recordNo < cscanFragrecFileSize && numRecords > 0)
14431     {
14432       dumpState->args[0] = DumpStateOrd::TcDumpSetOfScanFragRec;
14433       dumpState->args[1] = recordNo;
14434       dumpState->args[2] = numRecords;
14435       dumpState->args[3] = instance();
14436       dumpState->args[4] = includeOnlyActive;
14437       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
14438     }
14439     return;
14440   }
14441 
14442   // Dump one ScanFragRec
14443   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
14444     /**
14445      * DUMP 2501 12 1
14446      * Print ScanFrag record 12 in instance 1
14447      *
14448      * Output to cluster log.
14449      */
14450     jam();
14451     Uint32 recordNo = RNIL;
14452     Uint32 instanceId = RNIL;
14453     if (signal->getLength() == 3)
14454     {
14455       recordNo = dumpState->args[1];
14456       instanceId = dumpState->args[2];
14457     }
14458     else
14459     {
14460       return;
14461     }
14462     if (instanceId != instance())
14463     {
14464       return;
14465     }
14466     if (recordNo >= cscanFragrecFileSize)
14467     {
14468       return;
14469     }
14470 
14471     ScanFragRecPtr sfp;
14472     sfp.i = recordNo;
14473     c_scan_frag_pool.getPtr(sfp);
14474     infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
14475 	      sfp.i,
14476 	      sfp.p->scanFragState,
14477 	      sfp.p->scanFragId);
14478     infoEvent(" nodeid=%d, timer=%d",
14479 	      refToNode(sfp.p->lqhBlockref),
14480 	      sfp.p->scanFragTimer);
14481     return;
14482   }
14483 
14484   // Dump set of ScanRecords
14485   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfScanRec){
14486     /**
14487      * DUMP 2502 12 10 1 1
14488      * Print Scan records 12 through 21 in instance 1
14489      * Last parameter == 0 indicates that we will print all
14490      * records, otherwise we will only print active scan records.
14491      * Last parameter is defaulting to 1 if not provided
14492      *
14493      * Output to the cluster log
14494      */
14495     jam();
14496     Uint32 recordNo = 0;
14497     Uint32 numRecords = 0;
14498     Uint32 instanceId = 0;
14499     Uint32 includeOnlyActive = 1;
14500 
14501     if (signal->getLength() >= 4)
14502     {
14503       recordNo = dumpState->args[1];
14504       numRecords = dumpState->args[2];
14505       instanceId = dumpState->args[3];
14506       if (signal->getLength() >= 5)
14507       {
14508         includeOnlyActive = dumpState->args[4];
14509       }
14510     }
14511     else
14512     {
14513       return;
14514     }
14515     if (instance() != instanceId)
14516     {
14517       return;
14518     }
14519     if (numRecords > MAX_RECORDS_AT_A_TIME)
14520     {
14521       numRecords = MAX_RECORDS_AT_A_TIME;
14522     }
14523     if (recordNo >= cscanrecFileSize)
14524     {
14525       return;
14526     }
14527 
14528     ScanRecordPtr sp;
14529     sp.i = recordNo;
14530     ptrAss(sp, scanRecord);
14531     if (sp.p->scanState != ScanRecord::IDLE ||
14532         !includeOnlyActive)
14533     {
14534       dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
14535       dumpState->args[1] = recordNo;
14536       dumpState->args[2] = instance();
14537       signal->setLength(3);
14538       execDUMP_STATE_ORD(signal);
14539     }
14540 
14541     numRecords--;
14542     recordNo++;
14543     if (recordNo < cscanrecFileSize && numRecords > 0)
14544     {
14545       dumpState->args[0] = DumpStateOrd::TcDumpSetOfScanRec;
14546       dumpState->args[1] = recordNo;
14547       dumpState->args[2] = numRecords;
14548       dumpState->args[3] = instance();
14549       dumpState->args[4] = includeOnlyActive;
14550       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
14551     }
14552     return;
14553   }
14554 
14555   // Dump one ScanRecord
14556   // and associated ScanFragRec and ApiConnectRecord
14557   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
14558     /**
14559      * DUMP 2504 12 1
14560      * This will print ScanRecord 12 in instance 1 and all associated
14561      * ScanFrag records and ApiConnect records.
14562      *
14563      * It is necessary to provide both record number and instance id
14564      * to get anything printed using this dump command.
14565      */
14566     jam();
14567     Uint32 recordNo = RNIL;
14568     Uint32 instanceId = 0;
14569     if (signal->getLength() == 3)
14570     {
14571       recordNo = dumpState->args[1];
14572       instanceId = dumpState->args[2];
14573     }
14574     else
14575     {
14576       return;
14577     }
14578     if (instanceId != instance())
14579     {
14580       return;
14581     }
14582     if (recordNo >= cscanrecFileSize)
14583     {
14584       return;
14585     }
14586 
14587     ScanRecordPtr sp;
14588     sp.i = recordNo;
14589     ptrAss(sp, scanRecord);
14590     infoEvent("Dbtc::ScanRecord[%d]: state=%d, "
14591 	      "nextfrag=%d, nofrag=%d",
14592 	      sp.i,
14593 	      sp.p->scanState,
14594 	      sp.p->scanNextFragId,
14595 	      sp.p->scanNoFrag);
14596     infoEvent(" para=%d, receivedop=%d, noOprecPerFrag=%d",
14597 	      sp.p->scanParallel,
14598 	      sp.p->scanReceivedOperations,
14599 	      sp.p->batch_size_rows);
14600     infoEvent(" schv=%d, tab=%d, sproc=%d",
14601 	      sp.p->scanSchemaVersion,
14602 	      sp.p->scanTableref,
14603 	      sp.p->scanStoredProcId);
14604     infoEvent(" apiRec=%d, next=%d",
14605 	      sp.p->scanApiRec, sp.p->nextScan);
14606 
14607     if (sp.p->scanState != ScanRecord::IDLE){
14608       // Request dump of ScanFragRec
14609       ScanFragRecPtr sfptr;
14610 #define DUMP_SFR(x){\
14611       ScanFragList list(c_scan_frag_pool, x);\
14612       for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
14613 	dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
14614 	dumpState->args[1] = sfptr.i;\
14615         dumpState->args[2] = instance(); \
14616         signal->setLength(3); \
14617 	execDUMP_STATE_ORD(signal);\
14618       }}
14619 
14620       DUMP_SFR(sp.p->m_running_scan_frags);
14621       DUMP_SFR(sp.p->m_queued_scan_frags);
14622       DUMP_SFR(sp.p->m_delivered_scan_frags);
14623 
14624       // Request dump of ApiConnectRecord
14625       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
14626       dumpState->args[1] = sp.p->scanApiRec;
14627       dumpState->args[2] = instance();
14628       signal->setLength(3);
14629       execDUMP_STATE_ORD(signal);
14630     }
14631     return;
14632   }
14633 
14634   // Dump Set of TcConnectRecord(s)
14635   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfTcConnectRec)
14636   {
14637     /**
14638      * DUMP 2517 12 10 1 1
14639      * This will print recordNo from 12 to 21 in instance 1 (first
14640      * instance is number since instance 0 is the DBTC Proxy instance).
14641      * We will not print records that doesn't exist. The last parameter
14642      * indicates whether to include only active records or if we should
14643      * include all records. This last parameter defaults to 1 which means
14644      * we are only printing information about active records.
14645      *
14646      * It is necessary to specify record number, number of records
14647      * and instance id to get anything printed.
14648      *
14649      * Use this DUMP command with care and avoid printing more than
14650      * 10 records per dump command in production systems to avoid
14651      * overloading any parts of the system. Also print from instance
14652      * at a time since otherwise it will be almost impossible to know
14653      * which instance have generated what printout.
14654      *
14655      * The printouts will end up in the cluster log.
14656      */
14657     jam();
14658     Uint32 recordNo = RNIL;
14659     Uint32 instanceId = RNIL;
14660     Uint32 numRecords = 1;
14661     Uint32 includeOnlyActive = 1;
14662 
14663     if (signal->getLength() >= 4)
14664     {
14665       recordNo = dumpState->args[1];
14666       numRecords = dumpState->args[2];
14667       instanceId = dumpState->args[3];
14668       if (signal->getLength() >= 5)
14669       {
14670         includeOnlyActive = dumpState->args[4];
14671       }
14672     }
14673     else
14674     {
14675       return;
14676     }
14677     if (instanceId != instance())
14678     {
14679       return;
14680     }
14681     if (numRecords > MAX_RECORDS_AT_A_TIME)
14682     {
14683       numRecords = MAX_RECORDS_AT_A_TIME;
14684     }
14685     if (recordNo >= ctcConnectFilesize)
14686     {
14687       return;
14688     }
14689 
14690     TcConnectRecordPtr tc;
14691     tc.i = recordNo;
14692     ptrAss(tc, tcConnectRecord);
14693     if (tc.p->tcConnectstate == OS_CONNECTED ||
14694         !includeOnlyActive)
14695     {
14696       dumpState->args[0] = DumpStateOrd::TcDumpOneTcConnectRec;
14697       dumpState->args[1] = recordNo;
14698       dumpState->args[2] = instanceId;
14699       signal->setLength(3);
14700       execDUMP_STATE_ORD(signal);
14701     }
14702 
14703     numRecords--;
14704     recordNo++;
14705     if (recordNo < ctcConnectFilesize && numRecords > 0)
14706     {
14707       dumpState->args[0] = DumpStateOrd::TcDumpSetOfTcConnectRec;
14708       dumpState->args[1] = recordNo;
14709       dumpState->args[2] = numRecords;
14710       dumpState->args[3] = instanceId;
14711       dumpState->args[4] = includeOnlyActive;
14712       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
14713     }
14714     return;
14715   }
14716 
14717   // Dump one TcConnectRecord
14718   if (dumpState->args[0] == DumpStateOrd::TcDumpOneTcConnectRec)
14719   {
14720     /**
14721      * This part is mostly used as an assistant function to dump a range
14722      * of TcConnect records. It can also be invoked directly in
14723      * the following manner.
14724      *
14725      * DUMP 2516 12 1
14726      * Record 12 will be printed in instance 1
14727      */
14728     jam();
14729     Uint32 recordNo = RNIL;
14730     Uint32 instanceId = RNIL;
14731     if (signal->getLength() == 3)
14732     {
14733       recordNo = dumpState->args[1];
14734       instanceId = dumpState->args[2];
14735     }
14736     else
14737     {
14738       return;
14739     }
14740     if (recordNo >= ctcConnectFilesize)
14741     {
14742       return;
14743     }
14744     if (instanceId != instance())
14745     {
14746       return;
14747     }
14748 
14749     TcConnectRecordPtr tc;
14750     tc.i = recordNo;
14751     ptrAss(tc, tcConnectRecord);
14752     infoEvent("Dbtc::TcConnectRecord[%d]: state=%d, apiCon=%d, "
14753 	      "commitAckMarker=%d",
14754 	      tc.i,
14755 	      tc.p->tcConnectstate,
14756 	      tc.p->apiConnect,
14757 	      tc.p->commitAckMarker);
14758     infoEvent(" special flags=%x, noOfNodes=%d, operation=%d",
14759 	      tc.p->m_special_op_flags,
14760 	      tc.p->noOfNodes,
14761 	      tc.p->operation);
14762     infoEvent(" clientData=%d, savePointId=%d, nodes(%d,%d,%d,%d), ",
14763 	      tc.p->clientData,
14764 	      tc.p->savePointId,
14765               tc.p->tcNodedata[0],
14766               tc.p->tcNodedata[1],
14767               tc.p->tcNodedata[2],
14768               tc.p->tcNodedata[3]);
14769     infoEvent(" next=%d, instance=%u ",
14770 	      tc.p->nextTcConnect,
14771               instance());
14772     return;
14773   }
14774 
14775   // Dump Set of ApiConnectRecord(s)
14776   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfApiConnectRec)
14777   {
14778     /**
14779      * Print a range of ApiConnect records
14780      * This command is invoked by the following DUMP command:
14781      * DUMP 2515 12 2 1
14782      * Print ApiConnect record 12 through 13 in instance 1
14783      *
14784      * The output will end up in the cluster log.
14785      *
14786      * WARNING: Don't print more than at most 10 records at a time
14787      * in a production system.
14788      * Use the full set of parameters such that we also specify the
14789      * instance id. This is necessary to know what is actually printed
14790      * since the printout from instance 1 and instance 2 doesn't
14791      * differ.
14792      */
14793     jam();
14794     Uint32 recordNo = RNIL;
14795     Uint32 instanceId = RNIL;
14796     Uint32 numRecords = 1;
14797     Uint32 includeOnlyActive = 1;
14798 
14799     if (signal->getLength() >= 4)
14800     {
14801       recordNo = dumpState->args[1];
14802       numRecords = dumpState->args[2];
14803       instanceId = dumpState->args[3];
14804       if (signal->getLength() >= 5)
14805       {
14806         includeOnlyActive = dumpState->args[4];
14807       }
14808     }
14809     else
14810     {
14811       return;
14812     }
14813     if (instanceId != instance())
14814     {
14815       return;
14816     }
14817     if (recordNo >= capiConnectFilesize)
14818     {
14819       return;
14820     }
14821 
14822     ApiConnectRecordPtr ap;
14823     ap.i = recordNo;
14824     ptrAss(ap, apiConnectRecord);
14825 
14826     if (!includeOnlyActive ||
14827         ((ap.p->apiConnectstate != CS_CONNECTED) &&
14828            (ap.p->apiConnectstate != CS_ABORTING ||
14829             ap.p->abortState != AS_IDLE)))
14830     {
14831       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
14832       dumpState->args[1] = recordNo;
14833       dumpState->args[2] = instanceId;
14834       signal->setLength(3);
14835       execDUMP_STATE_ORD(signal);
14836     }
14837 
14838     numRecords--;
14839     recordNo++;
14840     if (recordNo < capiConnectFilesize && numRecords > 0)
14841     {
14842       dumpState->args[0] = DumpStateOrd::TcDumpSetOfApiConnectRec;
14843       dumpState->args[1] = recordNo;
14844       dumpState->args[2] = numRecords;
14845       dumpState->args[3] = instanceId;
14846       dumpState->args[4] = includeOnlyActive;
14847       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
14848     }
14849     return;
14850   }
14851 
14852   // Dump one ApiConnectRecord
14853   if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
14854     /**
14855      * Print one ApiConnect record.
14856      * This is a support function to DUMP 2515. It can also
14857      * be used directly using the following command.
14858      *
14859      * DUMP 2505 12 1
14860      * Print ApiConnect record 12 in instance 1
14861      *
14862      * The output will be printed to the cluster log.
14863      */
14864     jam();
14865     Uint32 recordNo = RNIL;
14866     Uint32 instanceId = RNIL;
14867     if (signal->getLength() == 3)
14868     {
14869       recordNo = dumpState->args[1];
14870       instanceId = dumpState->args[2];
14871     }
14872     else
14873     {
14874       return;
14875     }
14876 
14877     if (recordNo >= capiConnectFilesize)
14878     {
14879       return;
14880     }
14881     if (instanceId != instance())
14882     {
14883       return;
14884     }
14885 
14886     ApiConnectRecordPtr ap;
14887     ap.i = recordNo;
14888     ptrAss(ap, apiConnectRecord);
14889     infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
14890 	      "apiFailState=%d",
14891 	      ap.i,
14892 	      ap.p->apiConnectstate,
14893 	      ap.p->abortState,
14894 	      ap.p->apiFailState);
14895     infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
14896 	      ap.p->transid[0],
14897 	      ap.p->transid[1],
14898 	      ap.p->ndbapiBlockref,
14899 	      ap.p->apiScanRec);
14900     infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
14901 	      "retsig=%d",
14902 	      ctcTimer, getApiConTimer(ap.i),
14903 	      ap.p->counter,
14904 	      ap.p->returncode,
14905 	      ap.p->returnsignal);
14906     infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
14907 	      "tckeyrec=%d",
14908 	      ap.p->lqhkeyconfrec,
14909 	      ap.p->lqhkeyreqrec,
14910 	      ap.p->tckeyrec);
14911     infoEvent(" next=%d, instance=%u, firstTc=%d ",
14912 	      ap.p->nextApiConnect,
14913               instance(),
14914               ap.p->firstTcConnect);
14915     return;
14916   }
14917 
14918   if (dumpState->args[0] == DumpStateOrd::TcDumpApiConnectRecSummary)
14919   {
14920     /**
14921      * This DUMP command is used to print a summary of ApiConnect record
14922      * connected to API nodes.
14923      * The following use of it is allowed:
14924      * DUMP 2514 1
14925      * This will print a summary of all ApiConnect records in instance 1
14926      *
14927      * Output is to the node log.
14928      */
14929     jam();
14930     Uint32 apiNode = 1;
14931     Uint32 pos = 0;
14932 
14933     Uint32 seized_count = 0;      /* Number seized by an Api */
14934     Uint32 stateless_count = 0;   /* Number 'started' with no ops */
14935     Uint32 stateful_count = 0;    /* Number running */
14936     Uint32 scan_count = 0;        /* Number used for scans */
14937     const Uint32 userVisibleConnectFilesize = capiConnectFilesize / 3;
14938 
14939     if (signal->getLength() == 2)
14940     {
14941       if (instance() != dumpState->args[1])
14942       {
14943         return;
14944       }
14945       ndbout_c("Start of ApiConnectRec summary (%u total allocated)",
14946                userVisibleConnectFilesize);
14947       /*
14948        * total allocated = MaxNoOfConcurrentTransactions
14949        * total allocated = unseized + SUM_over_Api_nodes(seized)
14950        *   unseized can be seized by any Api node
14951        *   seized are 'owned' by a particular api node, can't be used
14952        *     by others until they are manually released.
14953        * seized = seized_unused + stateless + stateful + scan
14954        *   seized_unused are 'idle' connection objects owned by an
14955        *     api node.
14956        *   stateless are potentially idle connection objects, last
14957        *     used in a TC-stateless operation (e.g. read committed)
14958        *   stateful are in use, handling some transaction
14959        *   scan are in use, handling a table or index scan
14960        */
14961     }
14962     else if (signal->getLength() == 7)
14963     {
14964       apiNode = dumpState->args[1];
14965       pos = dumpState->args[2];
14966       seized_count = dumpState->args[3];
14967       stateless_count = dumpState->args[4];
14968       stateful_count = dumpState->args[5];
14969       scan_count = dumpState->args[6];
14970     }
14971     else
14972     {
14973       return;
14974     }
14975 
14976     if (apiNode == 0)
14977       return;
14978 
14979     while (apiNode < MAX_NODES)
14980     {
14981       if (getNodeInfo(apiNode).getType() == NODE_TYPE_API &&
14982           getNodeInfo(apiNode).m_version != 0)
14983       {
14984         break;
14985       }
14986       apiNode ++;
14987     }
14988 
14989     if (apiNode >= MAX_NODES)
14990     {
14991       ndbout_c("End of ApiConnectRec summary");
14992       return;
14993     }
14994 
14995     Uint32 limit = MIN(pos + 16, userVisibleConnectFilesize);
14996 
14997     while(pos < limit)
14998     {
14999       apiConnectptr.i = pos;
15000       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
15001       /* Following code mostly similar to that for NdbInfo transactions table */
15002       Uint32 conState = apiConnectptr.p->apiConnectstate;
15003 
15004       if (conState == CS_ABORTING && apiConnectptr.p->abortState == AS_IDLE)
15005       {
15006         /**
15007          * These is for all practical purposes equal
15008          */
15009         conState = CS_CONNECTED;
15010       }
15011 
15012       if ((refToNode(apiConnectptr.p->ndbapiBlockref) == apiNode) &&
15013           (conState != CS_DISCONNECTED))
15014       {
15015         seized_count++;
15016 
15017         if (conState == CS_STARTED &&
15018             apiConnectptr.p->lqhkeyreqrec == 0)
15019         {
15020           stateless_count++;
15021         }
15022         else if (conState == CS_START_SCAN)
15023         {
15024           scan_count++;
15025         }
15026         else if (conState != CS_CONNECTED)
15027         {
15028           stateful_count++;
15029         }
15030       }
15031 
15032       pos++;
15033     }
15034 
15035     if (pos >= userVisibleConnectFilesize)
15036     {
15037       /* Finished with this apiNode, output info, if any */
15038 //      if (seized_count > 0)
15039       {
15040         ndbout_c("  Api node %u connect records seized : %u stateless : %u stateful : %u scan : %u",
15041                  apiNode, seized_count, stateless_count, stateful_count, scan_count);
15042         seized_count = 0;
15043         stateless_count = 0;
15044         stateful_count = 0;
15045         scan_count = 0;
15046       }
15047 
15048       apiNode++;
15049       pos = 0;
15050     }
15051 
15052     signal->theData[0] = DumpStateOrd::TcDumpApiConnectRecSummary;
15053     signal->theData[1] = apiNode;
15054     signal->theData[2] = pos;
15055     signal->theData[3] = seized_count;
15056     signal->theData[4] = stateless_count;
15057     signal->theData[5] = stateful_count;
15058     signal->theData[6] = scan_count;
15059 
15060     sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 7, JBB);
15061     return;
15062   }
15063 
15064   if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
15065     jam();
15066     if(signal->getLength() > 1){
15067       set_timeout_value(signal->theData[1]);
15068     }
15069   }
15070 
15071   if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
15072     jam();
15073     if(signal->getLength() > 1){
15074       set_appl_timeout_value(signal->theData[1]);
15075     }
15076   }
15077 
15078   if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
15079   {
15080     static int frequency = 1;
15081     if (signal->getLength() > 1)
15082       frequency = signal->theData[1];
15083     else
15084       if (refToBlock(signal->getSendersBlockRef()) != DBTC)
15085 	frequency = 1;
15086 
15087     if (frequency)
15088     {
15089       dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
15090       execDUMP_STATE_ORD(signal);
15091       dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
15092 
15093       Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
15094       sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
15095     }
15096   }
15097 
15098   if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
15099   {
15100     infoEvent("instance: %u, IndexOpCount: pool: %d free: %d",
15101               instance(),
15102 	      c_theIndexOperationPool.getSize(),
15103 	      c_theIndexOperationPool.getNoOfFree());
15104     return;
15105   }
15106 
15107   if (arg == 2550)
15108   {
15109     jam();
15110     Uint32 len = signal->getLength() - 1;
15111     if (len + 2 > 25)
15112     {
15113       jam();
15114       infoEvent("Too long filter");
15115       return;
15116     }
15117     if (validate_filter(signal))
15118     {
15119       jam();
15120       memmove(signal->theData + 2, signal->theData + 1, 4 * len);
15121       signal->theData[0] = 2551;
15122       signal->theData[1] = 0;    // record
15123       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 2, JBB);
15124 
15125       infoEvent("Starting dump of transactions");
15126     }
15127     return;
15128   }
15129 
15130   if (arg == 2551)
15131   {
15132     jam();
15133     Uint32 record = signal->theData[1];
15134     Uint32 len = signal->getLength();
15135     ndbassert(len > 1);
15136 
15137     ApiConnectRecordPtr ap;
15138     ap.i = record;
15139     ptrAss(ap, apiConnectRecord);
15140 
15141     bool print = false;
15142     for (Uint32 i = 0; i<32; i++)
15143     {
15144       jam();
15145       print = match_and_print(signal, ap);
15146 
15147       ap.i++;
15148       if (ap.i == capiConnectFilesize || print)
15149       {
15150 	jam();
15151 	break;
15152       }
15153 
15154       ptrAss(ap, apiConnectRecord);
15155     }
15156 
15157     if (ap.i == capiConnectFilesize)
15158     {
15159       jam();
15160       infoEvent("End of transaction dump");
15161       return;
15162     }
15163 
15164     signal->theData[1] = ap.i;
15165     if (print)
15166     {
15167       jam();
15168       sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
15169     }
15170     else
15171     {
15172       jam();
15173       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
15174     }
15175     return;
15176   }
15177 #ifdef ERROR_INSERT
15178   if (arg == 2552 || arg == 4002 || arg == 4003)
15179   {
15180     ndbrequire(m_commitAckMarkerPool.getNoOfFree() == m_commitAckMarkerPool.getSize());
15181     return;
15182   }
15183 #endif
15184 
15185   if (arg == DumpStateOrd::DihTcSumaNodeFailCompleted &&
15186       signal->getLength() == 2)
15187   {
15188     jam();
15189     NodeId nodeId = signal->theData[1];
15190     if (nodeId < MAX_NODES && nodeId < NDB_ARRAY_SIZE(capiConnectClosing))
15191     {
15192       warningEvent(" DBTC: capiConnectClosing[%u]: %u",
15193                    nodeId, capiConnectClosing[nodeId]);
15194     }
15195     else
15196     {
15197       warningEvent(" DBTC: dump-%u to unknown node: %u", arg, nodeId);
15198     }
15199   }
15200 
15201   if (arg == DumpStateOrd::TcResourceSnapshot)
15202   {
15203     RSS_OP_SNAPSHOT_SAVE(cConcScanCount);
15204     RSS_AP_SNAPSHOT_SAVE(c_scan_frag_pool);
15205     RSS_AP_SNAPSHOT_SAVE(c_theDefinedTriggerPool);
15206     RSS_AP_SNAPSHOT_SAVE(c_theFiredTriggerPool);
15207     RSS_AP_SNAPSHOT_SAVE(c_theIndexPool);
15208     RSS_AP_SNAPSHOT_SAVE(m_commitAckMarkerPool);
15209     RSS_AP_SNAPSHOT_SAVE(c_theIndexOperationPool);
15210 #ifdef ERROR_INSERT
15211     rss_cconcurrentOp = c_counters.cconcurrentOp;
15212 #endif
15213   }
15214   if (arg == DumpStateOrd::TcResourceCheckLeak)
15215   {
15216     RSS_OP_SNAPSHOT_CHECK(cConcScanCount);
15217     RSS_AP_SNAPSHOT_CHECK(c_scan_frag_pool);
15218     RSS_AP_SNAPSHOT_CHECK(c_theDefinedTriggerPool);
15219     RSS_AP_SNAPSHOT_CHECK(c_theFiredTriggerPool);
15220     RSS_AP_SNAPSHOT_CHECK(c_theIndexPool);
15221     RSS_AP_SNAPSHOT_CHECK(m_commitAckMarkerPool);
15222     RSS_AP_SNAPSHOT_CHECK(c_theIndexOperationPool);
15223 #ifdef ERROR_INSERT
15224     ndbrequire(rss_cconcurrentOp == c_counters.cconcurrentOp);
15225 #endif
15226   }
15227 
15228   if (arg == DumpStateOrd::TcDumpPoolLevels)
15229   {
15230     /**
15231      * DUMP 2555 1
15232      * Prints pool levels for instance 1 to cluster log
15233      */
15234     if (signal->getLength() == 2)
15235     {
15236       if (signal->theData[1] != instance())
15237       {
15238         return;
15239       }
15240       infoEvent("TC: instance: %u, Print pool levels", instance());
15241       signal->theData[4] = signal->theData[1];
15242       signal->theData[1] = 1;
15243       signal->theData[2] = 0;
15244       signal->theData[3] = 0;
15245       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
15246       return;
15247     }
15248     if (signal->getLength() != 5)
15249     {
15250       ndbout_c("DUMP TcDumpPoolLevels : Bad signal length : %u", signal->getLength());
15251       return;
15252     }
15253     if (signal->theData[4] != instance())
15254     {
15255       return;
15256     }
15257 
15258     Uint32 resource = signal->theData[1];
15259     Uint32 position = signal->theData[2];
15260     Uint32 sum = signal->theData[3];
15261     /* const Uint32 MAX_ITER = 200; */
15262 
15263     switch(resource)
15264     {
15265     case 1:
15266       infoEvent("TC : Concurrent operations in use/total : %u/%u (%u bytes each)",
15267                 c_counters.cconcurrentOp,
15268                 ctcConnectFilesize,
15269                 (Uint32) sizeof(TcConnectRecord));
15270       resource++;
15271       position = 0;
15272       sum = 0;
15273       break;
15274     case 2:
15275       infoEvent("TC : Concurrent scans in use/total : %u/%u (%u bytes each)",
15276                 cConcScanCount,
15277                 cscanrecFileSize,
15278                 (Uint32) sizeof(ScanRecord));
15279       resource++;
15280       position = 0;
15281       sum = 0;
15282       break;
15283     case 3:
15284       infoEvent("TC : Scan Frag records in use/total : %u/%u (%u bytes each)",
15285                 c_scan_frag_pool.getSize() -
15286                 c_scan_frag_pool.getNoOfFree(),
15287                 c_scan_frag_pool.getSize(),
15288                 (Uint32) sizeof(ScanFragRec));
15289       resource++;
15290       position = 0;
15291       sum = 0;
15292       break;
15293     default:
15294       return;
15295     }
15296 
15297     signal->theData[0] = DumpStateOrd::TcDumpPoolLevels;
15298     signal->theData[1] = resource;
15299     signal->theData[2] = position;
15300     signal->theData[3] = sum;
15301     signal->theData[4] = instance();
15302     sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
15303     return;
15304   }
15305 }//Dbtc::execDUMP_STATE_ORD()
15306 
execDBINFO_SCANREQ(Signal * signal)15307 void Dbtc::execDBINFO_SCANREQ(Signal *signal)
15308 {
15309   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
15310   const Ndbinfo::ScanCursor* cursor =
15311     CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
15312   Ndbinfo::Ratelimit rl;
15313 
15314   jamEntry();
15315 
15316   switch(req.tableId){
15317   case Ndbinfo::POOLS_TABLEID:
15318   {
15319     Ndbinfo::pool_entry pools[] =
15320     {
15321       { "Defined Trigger",
15322         c_theDefinedTriggerPool.getUsed(),
15323         c_theDefinedTriggerPool.getSize(),
15324         c_theDefinedTriggerPool.getEntrySize(),
15325         c_theDefinedTriggerPool.getUsedHi(),
15326         { CFG_DB_NO_TRIGGERS,0,0,0 }},
15327       { "Fired Trigger",
15328         c_theFiredTriggerPool.getUsed(),
15329         c_theFiredTriggerPool.getSize(),
15330         c_theFiredTriggerPool.getEntrySize(),
15331         c_theFiredTriggerPool.getUsedHi(),
15332         { CFG_DB_NO_TRIGGER_OPS,0,0,0 }},
15333       { "Index",
15334         c_theIndexPool.getUsed(),
15335         c_theIndexPool.getSize(),
15336         c_theIndexPool.getEntrySize(),
15337         c_theIndexPool.getUsedHi(),
15338         { CFG_DB_NO_TABLES,
15339           CFG_DB_NO_ORDERED_INDEXES,
15340           CFG_DB_NO_UNIQUE_HASH_INDEXES,0 }},
15341       { "Scan Fragment",
15342         c_scan_frag_pool.getUsed(),
15343         c_scan_frag_pool.getSize(),
15344         c_scan_frag_pool.getEntrySize(),
15345         c_scan_frag_pool.getUsedHi(),
15346         { CFG_DB_NO_LOCAL_SCANS,0,0,0 }},
15347       { "Commit ACK Marker",
15348         m_commitAckMarkerPool.getUsed(),
15349         m_commitAckMarkerPool.getSize(),
15350         m_commitAckMarkerPool.getEntrySize(),
15351         m_commitAckMarkerPool.getUsedHi(),
15352         { CFG_DB_NO_TRANSACTIONS,0,0,0 }},
15353       { "Index Op",
15354         c_theIndexOperationPool.getUsed(),
15355         c_theIndexOperationPool.getSize(),
15356         c_theIndexOperationPool.getEntrySize(),
15357         c_theIndexOperationPool.getUsedHi(),
15358         { CFG_DB_NO_INDEX_OPS,0,0,0 }},
15359       { "Operations",
15360         c_counters.cconcurrentOp,
15361         ctcConnectFilesize,
15362         sizeof(TcConnectRecord),
15363         0,
15364         { CFG_DB_NO_TRANSACTIONS,
15365           CFG_DB_NO_OPS,0,0 }},
15366       { "TC Scan Record",  /* TC redundantly included to improve readability */
15367         cConcScanCount,
15368         cscanrecFileSize,
15369         sizeof(ScanRecord),
15370         0, /* No HWM */
15371         {CFG_DB_NO_SCANS, 0, 0, 0}},
15372       { NULL, 0,0,0,0,{0,0,0,0} }
15373     };
15374 
15375    const size_t num_config_params =
15376       sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
15377     Uint32 pool = cursor->data[0];
15378     BlockNumber bn = blockToMain(number());
15379     while(pools[pool].poolname)
15380     {
15381       jam();
15382       Ndbinfo::Row row(signal, req);
15383       row.write_uint32(getOwnNodeId());
15384       row.write_uint32(bn);           // block number
15385       row.write_uint32(instance());   // block instance
15386       row.write_string(pools[pool].poolname);
15387 
15388       row.write_uint64(pools[pool].used);
15389       row.write_uint64(pools[pool].total);
15390       row.write_uint64(pools[pool].used_hi);
15391       row.write_uint64(pools[pool].entry_size);
15392       for (size_t i = 0; i < num_config_params; i++)
15393         row.write_uint32(pools[pool].config_params[i]);
15394       ndbinfo_send_row(signal, req, row, rl);
15395       pool++;
15396       if (rl.need_break(req))
15397       {
15398         jam();
15399         ndbinfo_send_scan_break(signal, req, rl, pool);
15400         return;
15401       }
15402     }
15403     break;
15404   }
15405 
15406   case Ndbinfo::COUNTERS_TABLEID:
15407   {
15408     Ndbinfo::counter_entry counters[] = {
15409       { Ndbinfo::ATTRINFO_COUNTER, c_counters.cattrinfoCount },
15410       { Ndbinfo::TRANSACTIONS_COUNTER, c_counters.ctransCount },
15411       { Ndbinfo::COMMITS_COUNTER, c_counters.ccommitCount },
15412       { Ndbinfo::READS_COUNTER, c_counters.creadCount },
15413       { Ndbinfo::SIMPLE_READS_COUNTER, c_counters.csimpleReadCount },
15414       { Ndbinfo::WRITES_COUNTER, c_counters.cwriteCount },
15415       { Ndbinfo::ABORTS_COUNTER, c_counters.cabortCount },
15416       { Ndbinfo::TABLE_SCANS_COUNTER, c_counters.c_scan_count },
15417       { Ndbinfo::RANGE_SCANS_COUNTER, c_counters.c_range_scan_count },
15418       { Ndbinfo::LOCAL_READ_COUNTER, c_counters.clocalReadCount },
15419       { Ndbinfo::LOCAL_WRITE_COUNTER, c_counters.clocalWriteCount }
15420     };
15421     const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
15422 
15423     Uint32 i = cursor->data[0];
15424     BlockNumber bn = blockToMain(number());
15425     while(i < num_counters)
15426     {
15427       jam();
15428       Ndbinfo::Row row(signal, req);
15429       row.write_uint32(getOwnNodeId());
15430       row.write_uint32(bn);           // block number
15431       row.write_uint32(instance());   // block instance
15432       row.write_uint32(counters[i].id);
15433 
15434       row.write_uint64(counters[i].val);
15435       ndbinfo_send_row(signal, req, row, rl);
15436       i++;
15437       if (rl.need_break(req))
15438       {
15439         jam();
15440         ndbinfo_send_scan_break(signal, req, rl, i);
15441         return;
15442       }
15443     }
15444 
15445     break;
15446   }
15447   case Ndbinfo::TRANSACTIONS_TABLEID:{
15448     ApiConnectRecordPtr ptr;
15449     ptr.i = cursor->data[0];
15450     const Uint32 maxloop = 256;
15451     for (Uint32 i = 0; i < maxloop; i++)
15452     {
15453       ptrCheckGuard(ptr, capiConnectFilesize, apiConnectRecord);
15454       Ndbinfo::Row row(signal, req);
15455       if (ndbinfo_write_trans(row, ptr))
15456       {
15457         jam();
15458         ndbinfo_send_row(signal, req, row, rl);
15459       }
15460 
15461       ptr.i ++;
15462       if (ptr.i == capiConnectFilesize)
15463       {
15464         goto done;
15465       }
15466       else if (rl.need_break(req))
15467       {
15468         break;
15469       }
15470     }
15471     ndbinfo_send_scan_break(signal, req, rl, ptr.i);
15472     return;
15473   }
15474   default:
15475     break;
15476   }
15477 
15478 done:
15479   ndbinfo_send_scan_conf(signal, req, rl);
15480 }
15481 
15482 bool
ndbinfo_write_trans(Ndbinfo::Row & row,ApiConnectRecordPtr transPtr)15483 Dbtc::ndbinfo_write_trans(Ndbinfo::Row & row, ApiConnectRecordPtr transPtr)
15484 {
15485   Uint32 conState = transPtr.p->apiConnectstate;
15486 
15487   if (conState == CS_ABORTING && transPtr.p->abortState == AS_IDLE)
15488   {
15489     /**
15490      * These is for all practical purposes equal
15491      */
15492     conState = CS_CONNECTED;
15493   }
15494 
15495   if (conState == CS_CONNECTED ||
15496       conState == CS_DISCONNECTED ||
15497       conState == CS_RESTART)
15498   {
15499     return false;
15500   }
15501 
15502   row.write_uint32(getOwnNodeId());
15503   row.write_uint32(instance());   // block instance
15504   row.write_uint32(transPtr.i);
15505   row.write_uint32(transPtr.p->ndbapiBlockref);
15506   row.write_uint32(transPtr.p->transid[0]);
15507   row.write_uint32(transPtr.p->transid[1]);
15508   row.write_uint32(conState);
15509   row.write_uint32(transPtr.p->m_flags);
15510   row.write_uint32(transPtr.p->lqhkeyreqrec);
15511   Uint32 outstanding = 0;
15512   switch((ConnectionState)conState) {
15513   case CS_CONNECTED:
15514   case CS_DISCONNECTED:
15515     break;
15516   case CS_STARTED:
15517   case CS_RECEIVING:
15518   case CS_REC_COMMITTING:
15519   case CS_START_COMMITTING:
15520   case CS_SEND_FIRE_TRIG_REQ:
15521   case CS_WAIT_FIRE_TRIG_REQ:
15522     outstanding = transPtr.p->lqhkeyreqrec - transPtr.p->lqhkeyconfrec;
15523     break;
15524   case CS_COMMITTING:
15525   case CS_COMPLETING:
15526   case CS_COMMIT_SENT:
15527   case CS_COMPLETE_SENT:
15528   case CS_ABORTING:
15529     outstanding = transPtr.p->counter;
15530     break;
15531   case CS_PREPARE_TO_COMMIT:
15532     break;
15533   case CS_START_SCAN:
15534     // TODO
15535     break;
15536   case CS_WAIT_ABORT_CONF:
15537   case CS_WAIT_COMMIT_CONF:
15538   case CS_WAIT_COMPLETE_CONF:
15539     // not easily computed :-(
15540     break;
15541   case CS_FAIL_PREPARED:
15542   case CS_FAIL_ABORTED:
15543     // we're assembling a state...
15544     break;
15545   case CS_FAIL_COMMITTING:
15546   case CS_FAIL_COMMITTED:
15547   case CS_FAIL_ABORTING:
15548   case CS_FAIL_COMPLETED:
15549     // not easily computed :_(
15550     break;
15551   case CS_RESTART:
15552     break;
15553   }
15554 
15555   row.write_uint32(outstanding);
15556 
15557   Uint32 apiTimer = getApiConTimer(transPtr.i);
15558   row.write_uint32(apiTimer ? (ctcTimer - apiTimer) / 100 : 0);
15559   return true;
15560 }
15561 
15562 bool
validate_filter(Signal * signal)15563 Dbtc::validate_filter(Signal* signal)
15564 {
15565   Uint32 * start = signal->theData + 1;
15566   Uint32 * end = signal->theData + signal->getLength();
15567   if (start == end)
15568   {
15569     infoEvent("No filter specified, not listing...");
15570     return false;
15571   }
15572 
15573   while(start < end)
15574   {
15575     switch(* start){
15576     case 1: // API Node
15577     case 4: // Inactive time
15578       start += 2;
15579       break;
15580     case 2: // Transid
15581       start += 3;
15582       break;
15583     default:
15584       infoEvent("Invalid filter op: 0x%x pos: %ld",
15585 		* start,
15586 		(long int)(start - (signal->theData + 1)));
15587       return false;
15588     }
15589   }
15590 
15591   if (start != end)
15592   {
15593     infoEvent("Invalid filter, unexpected end");
15594     return false;
15595   }
15596 
15597   return true;
15598 }
15599 
15600 bool
match_and_print(Signal * signal,ApiConnectRecordPtr apiPtr)15601 Dbtc::match_and_print(Signal* signal, ApiConnectRecordPtr apiPtr)
15602 {
15603   Uint32 conState = apiPtr.p->apiConnectstate;
15604   if (conState == CS_CONNECTED ||
15605       conState == CS_DISCONNECTED ||
15606       conState == CS_RESTART)
15607     return false;
15608 
15609   Uint32 len = signal->getLength();
15610   Uint32* start = signal->theData + 2;
15611   Uint32* end = signal->theData + len;
15612   Uint32 apiTimer = getApiConTimer(apiPtr.i);
15613   while (start < end)
15614   {
15615     jam();
15616     switch(* start){
15617     case 1:
15618       jam();
15619       if (refToNode(apiPtr.p->ndbapiBlockref) != * (start + 1))
15620 	return false;
15621       start += 2;
15622       break;
15623     case 2:
15624       jam();
15625       if (apiPtr.p->transid[0] != * (start + 1) ||
15626 	  apiPtr.p->transid[1] != * (start + 2))
15627 	return false;
15628       start += 3;
15629       break;
15630     case 4:{
15631       jam();
15632       if (apiTimer == 0 || ((ctcTimer - apiTimer) / 100) < * (start + 1))
15633 	return false;
15634       start += 2;
15635       break;
15636     }
15637     default:
15638       ndbassert(false);
15639       return false;
15640     }
15641   }
15642 
15643   if (start != end)
15644   {
15645     ndbassert(false);
15646     return false;
15647   }
15648 
15649   /**
15650    * Do print
15651    */
15652   Uint32 *temp = signal->theData + 25;
15653   memcpy(temp, signal->theData, 4 * len);
15654 
15655   char state[10];
15656   const char *stateptr = "";
15657 
15658   switch(apiPtr.p->apiConnectstate){
15659   case CS_STARTED:
15660     stateptr = "Prepared";
15661     break;
15662   case CS_RECEIVING:
15663   case CS_REC_COMMITTING:
15664   case CS_START_COMMITTING:
15665     stateptr = "Running";
15666     break;
15667   case CS_COMMITTING:
15668     stateptr = "Committing";
15669     break;
15670   case CS_COMPLETING:
15671     stateptr = "Completing";
15672     break;
15673   case CS_PREPARE_TO_COMMIT:
15674     stateptr = "Prepare to commit";
15675     break;
15676   case CS_COMMIT_SENT:
15677     stateptr = "Commit sent";
15678     break;
15679   case CS_COMPLETE_SENT:
15680     stateptr = "Complete sent";
15681     break;
15682   case CS_ABORTING:
15683     stateptr = "Aborting";
15684     break;
15685   case CS_START_SCAN:
15686     stateptr = "Scanning";
15687     break;
15688   case CS_WAIT_ABORT_CONF:
15689   case CS_WAIT_COMMIT_CONF:
15690   case CS_WAIT_COMPLETE_CONF:
15691   case CS_FAIL_PREPARED:
15692   case CS_FAIL_COMMITTING:
15693   case CS_FAIL_COMMITTED:
15694   case CS_RESTART:
15695   case CS_FAIL_ABORTED:
15696   case CS_DISCONNECTED:
15697   default:
15698     BaseString::snprintf(state, sizeof(state),
15699 			 "%u", apiPtr.p->apiConnectstate);
15700     stateptr = state;
15701     break;
15702   }
15703 
15704   char buf[100];
15705   BaseString::snprintf(buf, sizeof(buf),
15706 		       "TRX[%u]: API: %d(0x%x)"
15707 		       "transid: 0x%x 0x%x inactive: %u(%d) state: %s",
15708 		       apiPtr.i,
15709 		       refToNode(apiPtr.p->ndbapiBlockref),
15710 		       refToBlock(apiPtr.p->ndbapiBlockref),
15711 		       apiPtr.p->transid[0],
15712 		       apiPtr.p->transid[1],
15713 		       apiTimer ? (ctcTimer - apiTimer) / 100 : 0,
15714 		       c_apiConTimer_line[apiPtr.i],
15715 		       stateptr);
15716   infoEvent("%s", buf);
15717 
15718   memcpy(signal->theData, temp, 4*len);
15719   return true;
15720 }
15721 
execABORT_ALL_REQ(Signal * signal)15722 void Dbtc::execABORT_ALL_REQ(Signal* signal)
15723 {
15724   jamEntry();
15725   AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
15726   AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
15727 
15728   const Uint32 senderData = req->senderData;
15729   const BlockReference senderRef = req->senderRef;
15730 
15731   if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
15732     jam();
15733 
15734     ref->senderData = senderData;
15735     ref->errorCode = AbortAllRef::InvalidState;
15736     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
15737 	       AbortAllRef::SignalLength, JBB);
15738     return;
15739   }
15740 
15741   if(c_abortRec.clientRef != 0){
15742     jam();
15743 
15744     ref->senderData = senderData;
15745     ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
15746     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
15747 	       AbortAllRef::SignalLength, JBB);
15748     return;
15749   }
15750 
15751   if(refToNode(senderRef) != getOwnNodeId()){
15752     jam();
15753 
15754     ref->senderData = senderData;
15755     ref->errorCode = AbortAllRef::FunctionNotImplemented;
15756     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
15757 	       AbortAllRef::SignalLength, JBB);
15758     return;
15759   }
15760 
15761   c_abortRec.clientRef = senderRef;
15762   c_abortRec.clientData = senderData;
15763   c_abortRec.oldTimeOutValue = ctimeOutValue;
15764 
15765   ctimeOutValue = 0;
15766   const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
15767 
15768   checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
15769 }
15770 
checkAbortAllTimeout(Signal * signal,Uint32 sleepTime)15771 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
15772 {
15773 
15774   ndbrequire(c_abortRec.clientRef != 0);
15775 
15776   if(sleepTime > 0){
15777     jam();
15778 
15779     sleepTime -= 1;
15780     signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
15781     signal->theData[1] = sleepTime;
15782     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
15783     return;
15784   }
15785 
15786   AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
15787   conf->senderData = c_abortRec.clientData;
15788   sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
15789 	     AbortAllConf::SignalLength, JBB);
15790 
15791   ctimeOutValue = c_abortRec.oldTimeOutValue;
15792   c_abortRec.clientRef = 0;
15793 }
15794 
15795 /* **************************************************************** */
15796 /* ---------------------------------------------------------------- */
15797 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
15798 /* ---------------------------------------------------------------- */
15799 /* **************************************************************** */
15800 
execCREATE_TRIG_IMPL_REQ(Signal * signal)15801 void Dbtc::execCREATE_TRIG_IMPL_REQ(Signal* signal)
15802 {
15803   jamEntry();
15804   if (!assembleFragments(signal))
15805   {
15806     jam();
15807     return;
15808   }
15809 
15810   const CreateTrigImplReq* req = (const CreateTrigImplReq*)signal->getDataPtr();
15811   const Uint32 senderRef = req->senderRef;
15812   const Uint32 senderData = req->senderData;
15813 
15814   SectionHandle handle(this, signal);
15815   releaseSections(handle); // Not using mask
15816 
15817   TcDefinedTriggerData* triggerData;
15818   DefinedTriggerPtr triggerPtr;
15819 
15820   triggerPtr.i = req->triggerId;
15821   if (ERROR_INSERTED(8033) ||
15822       !c_theDefinedTriggers.getPool().seizeId(triggerPtr, req->triggerId)) {
15823     jam();
15824     CLEAR_ERROR_INSERT_VALUE;
15825     // Failed to allocate trigger record
15826 ref:
15827     CreateTrigImplRef* ref =  (CreateTrigImplRef*)signal->getDataPtrSend();
15828 
15829     ref->senderRef = reference();
15830     ref->senderData = senderData;
15831     ref->errorCode = CreateTrigImplRef::InconsistentTC;
15832     ref->errorLine = __LINE__;
15833     sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_REF,
15834                signal, CreateTrigImplRef::SignalLength, JBB);
15835     return;
15836   }
15837   c_theDefinedTriggers.addFirst(triggerPtr);
15838 
15839   triggerData = triggerPtr.p;
15840   triggerData->triggerId = req->triggerId;
15841   triggerData->triggerType = TriggerInfo::getTriggerType(req->triggerInfo);
15842   triggerData->triggerEvent = TriggerInfo::getTriggerEvent(req->triggerInfo);
15843   triggerData->oldTriggerIds[0] = RNIL;
15844   triggerData->oldTriggerIds[1] = RNIL;
15845   triggerData->refCount = 0;
15846 
15847   switch(triggerData->triggerType){
15848   case TriggerType::SECONDARY_INDEX:
15849     jam();
15850     triggerData->indexId = req->indexId;
15851     break;
15852   case TriggerType::REORG_TRIGGER:
15853     jam();
15854     triggerData->tableId = req->tableId;
15855     break;
15856   case TriggerType::FK_PARENT:
15857   case TriggerType::FK_CHILD:
15858     triggerData->fkId = req->indexId;
15859     break;
15860   default:
15861     c_theDefinedTriggers.release(triggerPtr);
15862     goto ref;
15863   }
15864 
15865   if (unlikely(req->triggerId != req->upgradeExtra[1]))
15866   {
15867     /**
15868      * This is nasty upgrade for unique indexes
15869      */
15870     jam();
15871     ndbrequire(req->triggerId == req->upgradeExtra[0]);
15872     ndbrequire(triggerData->triggerType == TriggerType::SECONDARY_INDEX);
15873 
15874     DefinedTriggerPtr insertPtr = triggerPtr;
15875     DefinedTriggerPtr updatePtr;
15876     DefinedTriggerPtr deletePtr;
15877     if (c_theDefinedTriggers.getPool().seizeId(updatePtr, req->upgradeExtra[1]) == false)
15878     {
15879       jam();
15880       c_theDefinedTriggers.release(insertPtr);
15881       goto ref;
15882     }
15883     c_theDefinedTriggers.addFirst(updatePtr);
15884 
15885     if (c_theDefinedTriggers.getPool().seizeId(deletePtr, req->upgradeExtra[2]) == false)
15886     {
15887       jam();
15888       c_theDefinedTriggers.release(insertPtr);
15889       c_theDefinedTriggers.release(updatePtr);
15890       goto ref;
15891     }
15892     c_theDefinedTriggers.addFirst(deletePtr);
15893 
15894     insertPtr.p->triggerEvent = TriggerEvent::TE_INSERT;
15895 
15896     updatePtr.p->triggerId = req->upgradeExtra[1];
15897     updatePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
15898     updatePtr.p->triggerEvent = TriggerEvent::TE_UPDATE;
15899     updatePtr.p->oldTriggerIds[0] = RNIL;
15900     updatePtr.p->oldTriggerIds[1] = RNIL;
15901     updatePtr.p->indexId = req->indexId;
15902     updatePtr.p->refCount = 0;
15903 
15904     deletePtr.p->triggerId = req->upgradeExtra[2];
15905     deletePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
15906     deletePtr.p->triggerEvent = TriggerEvent::TE_DELETE;
15907     deletePtr.p->oldTriggerIds[0] = RNIL;
15908     deletePtr.p->oldTriggerIds[1] = RNIL;
15909     deletePtr.p->indexId = req->indexId;
15910     deletePtr.p->refCount = 0;
15911   }
15912 
15913   CreateTrigImplConf* conf = (CreateTrigImplConf*)signal->getDataPtrSend();
15914   conf->senderRef = reference();
15915   conf->senderData = senderData;
15916   sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_CONF,
15917              signal, CreateTrigImplConf::SignalLength, JBB);
15918 }
15919 
execDROP_TRIG_IMPL_REQ(Signal * signal)15920 void Dbtc::execDROP_TRIG_IMPL_REQ(Signal* signal)
15921 {
15922   jamEntry();
15923   const DropTrigImplReq* req = (const DropTrigImplReq*)signal->getDataPtr();
15924   const Uint32 senderRef = req->senderRef;
15925   const Uint32 senderData = req->senderData;
15926 
15927   DefinedTriggerPtr triggerPtr;
15928   triggerPtr.i = req->triggerId;
15929 
15930   if (ERROR_INSERTED(8035) ||
15931       ((triggerPtr.p = c_theDefinedTriggers.getPtr(req->triggerId)) == NULL))
15932   {
15933     jam();
15934     CLEAR_ERROR_INSERT_VALUE;
15935     // Failed to find find trigger record
15936     DropTrigImplRef* ref = (DropTrigImplRef*)signal->getDataPtrSend();
15937 
15938     ref->senderRef = reference();
15939     ref->senderData = senderData;
15940     ref->errorCode = DropTrigImplRef::InconsistentTC;
15941     ref->errorLine = __LINE__;
15942     sendSignal(senderRef, GSN_DROP_TRIG_IMPL_REF,
15943                signal, DropTrigImplRef::SignalLength, JBB);
15944     return;
15945   }
15946 
15947   if (triggerPtr.p->refCount > 0)
15948   {
15949     jam();
15950     sendSignalWithDelay(reference(), GSN_DROP_TRIG_IMPL_REQ,
15951                         signal, 100, signal->getLength());
15952     return;
15953   }
15954 
15955   if (unlikely(triggerPtr.p->oldTriggerIds[0] != RNIL))
15956   {
15957     jam();
15958 
15959     const Uint32 * oldId = triggerPtr.p->oldTriggerIds;
15960     if (c_theDefinedTriggers.getPtr(oldId[0])->refCount > 0 ||
15961         c_theDefinedTriggers.getPtr(oldId[1])->refCount > 0)
15962     {
15963       jam();
15964       sendSignalWithDelay(reference(), GSN_DROP_TRIG_IMPL_REQ,
15965                           signal, 100, signal->getLength());
15966       return;
15967     }
15968 
15969     c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[0]);
15970     c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[1]);
15971   }
15972 
15973   // Release trigger record
15974   c_theDefinedTriggers.release(triggerPtr);
15975 
15976   DropTrigImplConf* conf = (DropTrigImplConf*)signal->getDataPtrSend();
15977 
15978   conf->senderRef = reference();
15979   conf->senderData = senderData;
15980 
15981   sendSignal(senderRef, GSN_DROP_TRIG_IMPL_CONF,
15982              signal, DropTrigImplConf::SignalLength, JBB);
15983 }
15984 
execCREATE_INDX_IMPL_REQ(Signal * signal)15985 void Dbtc::execCREATE_INDX_IMPL_REQ(Signal* signal)
15986 {
15987   jamEntry();
15988   const CreateIndxImplReq * const req =
15989     (const CreateIndxImplReq *)signal->getDataPtr();
15990   const Uint32 senderRef = req->senderRef;
15991   const Uint32 senderData = req->senderData;
15992   TcIndexData* indexData;
15993   TcIndexDataPtr indexPtr;
15994 
15995   SectionHandle handle(this, signal);
15996   if (ERROR_INSERTED(8034) ||
15997       !c_theIndexes.getPool().seizeId(indexPtr, req->indexId)) {
15998     jam();
15999     CLEAR_ERROR_INSERT_VALUE;
16000     // Failed to allocate index record
16001      CreateIndxImplRef * const ref =
16002        (CreateIndxImplRef *)signal->getDataPtrSend();
16003 
16004      ref->senderRef = reference();
16005      ref->senderData = senderData;
16006      ref->errorCode = CreateIndxImplRef::InconsistentTC;
16007      ref->errorLine = __LINE__;
16008      releaseSections(handle);
16009      sendSignal(senderRef, GSN_CREATE_INDX_IMPL_REF,
16010                 signal, CreateIndxImplRef::SignalLength, JBB);
16011      return;
16012   }
16013   c_theIndexes.addFirst(indexPtr);
16014   indexData = indexPtr.p;
16015   // Indexes always start in state IS_BUILDING
16016   // Will become IS_ONLINE in execALTER_INDX_IMPL_REQ
16017   indexData->indexState = IS_BUILDING;
16018   indexData->indexId = indexPtr.i;
16019   indexData->primaryTableId = req->tableId;
16020 
16021   // So far need only attribute count
16022   SegmentedSectionPtr ssPtr;
16023   handle.getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
16024   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
16025   r0.reset(); // undo implicit first()
16026   if (!r0.getWord(&indexData->attributeList.sz) ||
16027       !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
16028     ndbrequire(false);
16029   }
16030   indexData->primaryKeyPos = indexData->attributeList.sz;
16031 
16032   releaseSections(handle);
16033 
16034   CreateIndxImplConf * const conf =
16035     (CreateIndxImplConf *)signal->getDataPtrSend();
16036 
16037   conf->senderRef = reference();
16038   conf->senderData = senderData;
16039   sendSignal(senderRef, GSN_CREATE_INDX_IMPL_CONF,
16040              signal, CreateIndxImplConf::SignalLength, JBB);
16041 }
16042 
execALTER_INDX_IMPL_REQ(Signal * signal)16043 void Dbtc::execALTER_INDX_IMPL_REQ(Signal* signal)
16044 {
16045   jamEntry();
16046   const AlterIndxImplReq * const req =
16047     (const AlterIndxImplReq *)signal->getDataPtr();
16048   const Uint32 senderRef = req->senderRef;
16049   const Uint32 senderData = req->senderData;
16050   TcIndexData* indexData;
16051   const Uint32 requestType = req->requestType;
16052   const Uint32 indexId = req->indexId;
16053 
16054   if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
16055     jam();
16056     // Failed to find index record
16057     AlterIndxImplRef * const ref =
16058       (AlterIndxImplRef *)signal->getDataPtrSend();
16059 
16060     ref->senderRef = reference();
16061     ref->senderData = senderData;
16062     ref->errorCode = AlterIndxImplRef::InconsistentTC;
16063     ref->errorLine = __LINE__;
16064 
16065     sendSignal(senderRef, GSN_ALTER_INDX_IMPL_REF,
16066 	       signal, AlterIndxImplRef::SignalLength, JBB);
16067     return;
16068   }
16069   // Found index record, alter it's state
16070   switch (requestType) {
16071   case AlterIndxImplReq::AlterIndexOnline:
16072     jam();
16073     indexData->indexState = IS_ONLINE;
16074     break;
16075   case AlterIndxImplReq::AlterIndexOffline:
16076     jam();
16077     indexData->indexState = IS_BUILDING; // wl3600_todo ??
16078     break;
16079   default:
16080     ndbrequire(false);
16081     break;
16082   }
16083   AlterIndxImplConf * const conf =
16084     (AlterIndxImplConf *)signal->getDataPtrSend();
16085 
16086   conf->senderRef = reference();
16087   conf->senderData = senderData;
16088   sendSignal(senderRef, GSN_ALTER_INDX_IMPL_CONF,
16089 	     signal, AlterIndxImplConf::SignalLength, JBB);
16090 }
16091 
16092 void
execCREATE_FK_IMPL_REQ(Signal * signal)16093 Dbtc::execCREATE_FK_IMPL_REQ(Signal* signal)
16094 {
16095   jamEntry();
16096   CreateFKImplReq reqCopy = * CAST_CONSTPTR(CreateFKImplReq,
16097                                             signal->getDataPtr());
16098   CreateFKImplReq * req = &reqCopy;
16099 
16100   Uint32 errCode = 0;
16101   SectionHandle handle(this, signal);
16102 
16103   if (req->requestType == CreateFKImplReq::RT_PREPARE)
16104   {
16105     jam();
16106     Ptr<TcFKData> fkPtr;
16107     if (c_fk_hash.find(fkPtr, req->fkId))
16108     {
16109       jam();
16110       errCode = CreateFKImplRef::ObjectAlreadyExist;
16111       goto error;
16112     }
16113     if (!c_fk_pool.seize(fkPtr))
16114     {
16115       jam();
16116       errCode = CreateFKImplRef::NoMoreObjectRecords;
16117       goto error;
16118     }
16119 
16120     fkPtr.p->fkId = req->fkId;
16121     fkPtr.p->bits = req->bits;
16122     fkPtr.p->parentTableId = req->parentTableId;
16123     fkPtr.p->childTableId = req->childTableId;
16124     fkPtr.p->childIndexId = req->childIndexId;
16125 
16126     if (req->parentIndexId != RNIL)
16127     {
16128       /**
16129        * Ignore base-table here...we'll only use the index anyway
16130        */
16131       jam();
16132       fkPtr.p->parentTableId = req->parentIndexId;
16133     }
16134 
16135     if (req->childIndexId == RNIL)
16136     {
16137       jam();
16138       fkPtr.p->childIndexId = req->childTableId;
16139     }
16140 
16141     {
16142       SegmentedSectionPtr ssPtr;
16143       handle.getSection(ssPtr, CreateFKImplReq::PARENT_COLUMNS);
16144       fkPtr.p->parentTableColumns.sz = ssPtr.sz;
16145       if (ssPtr.sz > NDB_ARRAY_SIZE(fkPtr.p->parentTableColumns.id))
16146       {
16147         errCode = CreateFKImplRef::InvalidFormat;
16148         goto error;
16149       }
16150       copy(fkPtr.p->parentTableColumns.id, ssPtr);
16151     }
16152 
16153     {
16154       SegmentedSectionPtr ssPtr;
16155       handle.getSection(ssPtr, CreateFKImplReq::CHILD_COLUMNS);
16156       fkPtr.p->childTableColumns.sz = ssPtr.sz;
16157       if (ssPtr.sz > NDB_ARRAY_SIZE(fkPtr.p->childTableColumns.id))
16158       {
16159         errCode = CreateFKImplRef::InvalidFormat;
16160         goto error;
16161       }
16162       copy(fkPtr.p->childTableColumns.id, ssPtr);
16163     }
16164 
16165     c_fk_hash.add(fkPtr);
16166   }
16167   else if (req->requestType == CreateFKImplReq::RT_ABORT)
16168   {
16169     jam();
16170     Ptr<TcFKData> fkPtr;
16171     ndbassert(c_fk_hash.find(fkPtr, req->fkId));
16172     if (c_fk_hash.find(fkPtr, req->fkId))
16173     {
16174       jam();
16175       c_fk_hash.release(fkPtr);
16176     }
16177   }
16178   else
16179   {
16180     ndbrequire(false); // No other request should reach TC
16181   }
16182 
16183   releaseSections(handle);
16184   {
16185     CreateFKImplConf * conf = CAST_PTR(CreateFKImplConf,
16186                                        signal->getDataPtrSend());
16187     conf->senderRef = reference();
16188     conf->senderData = req->senderData;
16189     sendSignal(req->senderRef, GSN_CREATE_FK_IMPL_CONF,
16190                signal, CreateFKImplConf::SignalLength, JBB);
16191   }
16192   return;
16193 error:
16194   releaseSections(handle);
16195   CreateFKImplRef * ref = CAST_PTR(CreateFKImplRef,
16196                                    signal->getDataPtrSend());
16197   ref->senderRef = reference();
16198   ref->senderData = req->senderData;
16199   ref->errorCode = errCode;
16200   sendSignal(req->senderRef, GSN_CREATE_FK_IMPL_REF,
16201              signal, CreateFKImplRef::SignalLength, JBB);
16202 }
16203 
16204 void
execDROP_FK_IMPL_REQ(Signal * signal)16205 Dbtc::execDROP_FK_IMPL_REQ(Signal* signal)
16206 {
16207   jamEntry();
16208   DropFKImplReq reqCopy = * CAST_CONSTPTR(DropFKImplReq,
16209                                           signal->getDataPtr());
16210   DropFKImplReq * req = &reqCopy;
16211 
16212   SectionHandle handle(this, signal);
16213   releaseSections(handle);
16214 
16215   Ptr<TcFKData> fkPtr;
16216   ndbassert(c_fk_hash.find(fkPtr, req->fkId));
16217   if (c_fk_hash.find(fkPtr, req->fkId))
16218   {
16219     jam();
16220     c_fk_hash.release(fkPtr);
16221 
16222     DropFKImplConf * conf = CAST_PTR(DropFKImplConf,
16223                                      signal->getDataPtrSend());
16224     conf->senderRef = reference();
16225     conf->senderData = req->senderData;
16226     sendSignal(req->senderRef, GSN_DROP_FK_IMPL_CONF,
16227                signal, DropFKImplConf::SignalLength, JBB);
16228   }
16229   else
16230   {
16231     jam();
16232     DropFKImplRef * ref = CAST_PTR(DropFKImplRef,
16233                                    signal->getDataPtrSend());
16234     ref->senderRef = reference();
16235     ref->senderData = req->senderData;
16236     ref->errorCode = DropFKImplRef::NoSuchObject;
16237     sendSignal(req->senderRef, GSN_DROP_FK_IMPL_REF,
16238                signal, DropFKImplRef::SignalLength, JBB);
16239   }
16240 }
16241 
execFIRE_TRIG_ORD(Signal * signal)16242 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
16243 {
16244   jamEntry();
16245   FireTrigOrd * const fireOrd =  (FireTrigOrd *)signal->getDataPtr();
16246   SectionHandle handle(this, signal);
16247   const bool longsignal = handle.m_cnt > 0;
16248 
16249   ApiConnectRecordPtr transPtr;
16250   TcConnectRecordPtr opPtr;
16251   bool transIdOk = true;
16252   /* Check the received transaction id
16253    * Older nodes do not send transid info in FIRE_TRIG_ORD
16254    */
16255   const Uint32 sourceNode = refToNode(signal->getSendersBlockRef());
16256   const Uint32 sourceNodeVersion = getNodeInfo(sourceNode).m_version;
16257   bool sigContainsTransId = ndb_fire_trig_ord_transid(sourceNodeVersion);
16258 
16259   /* Get triggering operation record */
16260   opPtr.i = fireOrd->getConnectionPtr();
16261   ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
16262 
16263   /* Get transaction record */
16264   transPtr.i = opPtr.p->apiConnect;
16265   if (unlikely(transPtr.i == RNIL))
16266   {
16267     /* Looks like the connect record was released
16268      * Treat as a bad transid
16269      */
16270     transIdOk = false;
16271   }
16272   else
16273   {
16274     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
16275 
16276     /* Check if signal's trans id and operation's transid are aligned */
16277     transIdOk = (! sigContainsTransId) |
16278       (! ((fireOrd->m_transId1 ^ transPtr.p->transid[0]) |
16279           (fireOrd->m_transId2 ^ transPtr.p->transid[1])));
16280   }
16281 
16282   TcFiredTriggerData key;
16283   key.fireingOperation = opPtr.i;
16284   key.nodeId = refToNode(signal->getSendersBlockRef());
16285   FiredTriggerPtr trigPtr;
16286   bool ok = transIdOk;
16287 
16288   if (likely(longsignal && transIdOk))
16289   {
16290     jam();
16291     if (likely(c_theFiredTriggerPool.seize(trigPtr)))
16292     {
16293       jam();
16294       trigPtr.p->nodeId = key.nodeId;
16295       trigPtr.p->fireingOperation = key.fireingOperation;
16296       trigPtr.p->triggerId = fireOrd->m_triggerId;
16297     }
16298     else
16299     {
16300       jam();
16301       ok = false;
16302     }
16303   }
16304 
16305   Uint32 errorCode = ZTOO_MANY_FIRED_TRIGGERS;
16306   if (likely((longsignal && ok) ||
16307              c_firedTriggerHash.find(trigPtr, key)))
16308   {
16309     jam();
16310     if (!longsignal)
16311     {
16312       jam();
16313       c_firedTriggerHash.remove(trigPtr);
16314     }
16315 
16316     trigPtr.p->triggerType = (TriggerType::Value)fireOrd->m_triggerType;
16317     trigPtr.p->triggerEvent = (TriggerEvent::Value)fireOrd->m_triggerEvent;
16318 
16319     if (unlikely(signal->getLength() < FireTrigOrd::SignalLength))
16320     {
16321       jam();
16322       ndbrequire(! sigContainsTransId );
16323       Ptr<TcDefinedTriggerData> ptr;
16324       c_theDefinedTriggers.getPtr(ptr, trigPtr.p->triggerId);
16325       trigPtr.p->triggerType = ptr.p->triggerType;
16326       trigPtr.p->triggerEvent = ptr.p->triggerEvent;
16327     }
16328     trigPtr.p->fragId= fireOrd->fragId;
16329     if (longsignal)
16330     {
16331       jam();
16332       AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
16333       {
16334         //TODO: error insert to make e.g middle append fail
16335         LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
16336         LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
16337         LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
16338         append(tmp1, handle.m_ptr[0], getSectionSegmentPool());
16339         append(tmp2, handle.m_ptr[1], getSectionSegmentPool());
16340         append(tmp3, handle.m_ptr[2], getSectionSegmentPool());
16341       }
16342       releaseSections(handle);
16343     }
16344 
16345     ok &= trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
16346     ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
16347     ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
16348 
16349     if (ERROR_INSERTED(8085))
16350     {
16351       ok = false;
16352     }
16353 
16354     if(likely( ok ))
16355     {
16356       jam();
16357       setApiConTimer(transPtr.i, ctcTimer, __LINE__);
16358       opPtr.p->numReceivedTriggers++;
16359       opPtr.p->triggerExecutionCount++; // Default 1 LQHKEYREQ per trigger
16360 
16361       // Insert fired trigger in execution queue
16362       {
16363         LocalDLFifoList<TcFiredTriggerData>
16364           list(c_theFiredTriggerPool, opPtr.p->thePendingTriggers);
16365         list.addLast(trigPtr);
16366       }
16367 
16368       if (opPtr.p->numReceivedTriggers == opPtr.p->numFiredTriggers ||
16369           transPtr.p->isExecutingDeferredTriggers())
16370       {
16371         jam();
16372         transPtr.p->theFiredTriggers.appendList(opPtr.p->thePendingTriggers);
16373 	executeTriggers(signal, &transPtr);
16374       }
16375       return;
16376     }
16377 
16378     /* Trigger entry found but either :
16379      *   - Overload resulted in loss of Trig_Attrinfo
16380      *     : Release resources + Abort transaction
16381      *   - Bad transaction id due to concurrent abort?
16382      *     : Release resources
16383      */
16384     jam();
16385     errorCode = ZINCONSISTENT_TRIGGER_STATE;
16386     // Release trigger records
16387     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
16388     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
16389     tmp1.release();
16390     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
16391     tmp2.release();
16392     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
16393     tmp3.release();
16394     c_theFiredTriggerPool.release(trigPtr);
16395   }
16396 
16397   releaseSections(handle);
16398 
16399   /* Either no trigger entry found, or overload, or
16400    * bad transid
16401    * If transid is ok, abort the transaction.
16402    * else, return.
16403    * (Note small risk of 'abort of innocent' in upgrade
16404    *  scenario with no transid in FIRE_TRIG_ORD)
16405    */
16406   jam();
16407   if (transIdOk)
16408   {
16409     jam();
16410     abortTransFromTrigger(signal, transPtr, errorCode);
16411   }
16412 
16413   return;
16414 }
16415 
execTRIG_ATTRINFO(Signal * signal)16416 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
16417 {
16418   jamEntry();
16419   TrigAttrInfo * const trigAttrInfo =  (TrigAttrInfo *)signal->getDataPtr();
16420   Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
16421   const Uint32 *src = trigAttrInfo->getData();
16422   FiredTriggerPtr firedTrigPtr;
16423 
16424   TcFiredTriggerData key;
16425   key.fireingOperation = trigAttrInfo->getConnectionPtr();
16426   key.nodeId = refToNode(signal->getSendersBlockRef());
16427   if(!c_firedTriggerHash.find(firedTrigPtr, key)){
16428     jam();
16429     /* TODO : Node failure handling (use sig-train assembly) */
16430     if(!c_firedTriggerHash.seize(firedTrigPtr)){
16431       jam();
16432       /**
16433        * Will be handled when FIRE_TRIG_ORD arrives
16434        */
16435       ndbout_c("op: %d node: %d failed to seize",
16436 	       key.fireingOperation, key.nodeId);
16437       return;
16438     }
16439     ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
16440 	       firedTrigPtr.p->beforeValues.getSize() == 0 &&
16441 	       firedTrigPtr.p->afterValues.getSize() == 0);
16442 
16443     firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
16444     firedTrigPtr.p->fireingOperation = key.fireingOperation;
16445     firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
16446     c_firedTriggerHash.add(firedTrigPtr);
16447   }
16448 
16449   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
16450   switch (trigAttrInfo->getAttrInfoType()) {
16451   case(TrigAttrInfo::PRIMARY_KEY):
16452     jam();
16453     {
16454       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
16455       buf.append(src, attrInfoLength);
16456     }
16457     break;
16458   case(TrigAttrInfo::BEFORE_VALUES):
16459     jam();
16460     {
16461       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
16462       buf.append(src, attrInfoLength);
16463     }
16464     break;
16465   case(TrigAttrInfo::AFTER_VALUES):
16466     jam();
16467     {
16468       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
16469       buf.append(src, attrInfoLength);
16470     }
16471     break;
16472   default:
16473     ndbrequire(false);
16474   }
16475 }
16476 
execDROP_INDX_IMPL_REQ(Signal * signal)16477 void Dbtc::execDROP_INDX_IMPL_REQ(Signal* signal)
16478 {
16479   jamEntry();
16480   const DropIndxImplReq * const req =
16481     (const DropIndxImplReq *)signal->getDataPtr();
16482   const Uint32 senderRef = req->senderRef;
16483   const Uint32 senderData = req->senderData;
16484   TcIndexData* indexData;
16485 
16486   if (ERROR_INSERTED(8036) ||
16487       (indexData = c_theIndexes.getPtr(req->indexId)) == NULL) {
16488     jam();
16489     CLEAR_ERROR_INSERT_VALUE;
16490     // Failed to find index record
16491     DropIndxImplRef * const ref =
16492       (DropIndxImplRef *)signal->getDataPtrSend();
16493 
16494     ref->senderRef = reference();
16495     ref->senderData = senderData;
16496     ref->errorCode = DropIndxImplRef::InconsistentTC;
16497     ref->errorLine = __LINE__;
16498     sendSignal(senderRef, GSN_DROP_INDX_IMPL_REF,
16499                signal, DropIndxImplRef::SignalLength, JBB);
16500     return;
16501   }
16502   // Release index record
16503   c_theIndexes.release(req->indexId);
16504 
16505   DropIndxImplConf * const conf =
16506     (DropIndxImplConf *)signal->getDataPtrSend();
16507 
16508   conf->senderRef = reference();
16509   conf->senderData = senderData;
16510   sendSignal(senderRef, GSN_DROP_INDX_IMPL_CONF,
16511              signal, DropIndxImplConf::SignalLength, JBB);
16512 }
16513 
execTCINDXREQ(Signal * signal)16514 void Dbtc::execTCINDXREQ(Signal* signal)
16515 {
16516   jamEntry();
16517 
16518   TcKeyReq * const tcIndxReq =  (TcKeyReq *)signal->getDataPtr();
16519   const UintR TapiIndex = tcIndxReq->apiConnectPtr;
16520   Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
16521   Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
16522   ApiConnectRecordPtr transPtr;
16523   bool isLongTcIndxReq= (signal->getNoOfSections() != 0);
16524   SectionHandle handle(this, signal);
16525 
16526   transPtr.i = TapiIndex;
16527   if (transPtr.i >= capiConnectFilesize) {
16528     jam();
16529     warningHandlerLab(signal, __LINE__);
16530     releaseSections(handle);
16531     return;
16532   }//if
16533   ptrAss(transPtr, apiConnectRecord);
16534   ApiConnectRecord * const regApiPtr = transPtr.p;
16535   // Seize index operation
16536   TcIndexOperationPtr indexOpPtr;
16537 
16538 #ifdef ERROR_INSERT
16539   if (ERROR_INSERTED(8100))
16540   {
16541     char buf[128];
16542     BaseString::snprintf(buf, sizeof(buf), "Inserted 8100, startFlag %u, regApiPtr->apiConnectstate %u, regApiPtr->abortState %u", startFlag, regApiPtr->apiConnectstate, regApiPtr->abortState);
16543     warningEvent("%s", buf);
16544 
16545     if (startFlag == 1)
16546     {
16547       jam();
16548       /*
16549         Phase 1:
16550         Abort the transaction by simulating a fake node failure.
16551         Don't send any TCROLLBACKREP until in next TCINDXREQ call
16552         to simulate a slow signal still in the air.
16553       */
16554       Signal s = *signal;
16555       signal->theData[0] = TcContinueB::ZDEBUG_DELAYED_ABORT;
16556       signal->theData[1] = transPtr.i;
16557       signal->theData[2] = regApiPtr->transid[0];
16558       signal->theData[3] = regApiPtr->transid[1];
16559       signal->theData[4] = ZNODEFAIL_BEFORE_COMMIT;
16560       signal->theData[5] = RS_TCROLLBACKREP;
16561       signal->theData[6] = 8101;
16562       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 6);
16563       *signal = s;
16564     }
16565   }
16566   else if (ERROR_INSERTED(8101))
16567   {
16568     char buf[128];
16569     BaseString::snprintf(buf, sizeof(buf), "Inserted 8101, startFlag %u, regApiPtr->apiConnectstate %u, regApiPtr->abortState %u", startFlag, regApiPtr->apiConnectstate, regApiPtr->abortState);
16570     warningEvent("%s", buf);
16571 
16572     jam();
16573     /*
16574       Phase 2:
16575       Transaction has been aborted by a fake node failure,
16576       but the API hasn't been informed yet. Force the state
16577       into waiting for pending signals.
16578     */
16579     if (regApiPtr->returncode != ZNODEFAIL_BEFORE_COMMIT ||
16580         regApiPtr->apiConnectstate != CS_ABORTING ||
16581         regApiPtr->abortState != AS_IDLE)
16582     {
16583       /*
16584         We are waiting for abort to complete, but have not reached
16585         the transaction state we want to test. Try again.
16586       */
16587       jam();
16588       sendSignalWithDelay(reference(), GSN_TCINDXREQ, signal, 100,
16589                           TcKeyReq::StaticLength, &handle);
16590       return;
16591     }
16592     CLEAR_ERROR_INSERT_VALUE;
16593   }
16594 #endif
16595 
16596    if (startFlag == 1 &&
16597        (regApiPtr->apiConnectstate == CS_CONNECTED ||
16598         (regApiPtr->apiConnectstate == CS_STARTED &&
16599          regApiPtr->firstTcConnect == RNIL) ||
16600         (regApiPtr->apiConnectstate == CS_ABORTING &&
16601          regApiPtr->abortState == AS_IDLE)))
16602   {
16603     jam();
16604     // This is a newly started transaction, clean-up from any
16605     // previous transaction.
16606     releaseAllSeizedIndexOperations(regApiPtr);
16607 
16608     regApiPtr->apiConnectstate = CS_STARTED;
16609     regApiPtr->transid[0] = tcIndxReq->transId1;
16610     regApiPtr->transid[1] = tcIndxReq->transId2;
16611   }//if (startFlag == 1 && ...
16612   else if (regApiPtr->apiConnectstate == CS_ABORTING)
16613   {
16614     jam();
16615     /*
16616       Transaction has been aborted and we have to do error
16617       handling, but since when we read the index table
16618       the generated TCKEYREQ will do the proper error
16619       handling. Any received TCKEYREF will be forwarded
16620       to the original sender as a TCINDXREF.
16621      */
16622   }//if (regApiPtr->apiConnectstate == CS_ABORTING)
16623 
16624   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
16625       getNodeState().getSingleUserApi() !=
16626       refToNode(regApiPtr->ndbapiBlockref))
16627   {
16628     jam();
16629     releaseSections(handle);
16630     terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
16631     regApiPtr->m_flags |=
16632       TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
16633       ApiConnectRecord::TF_EXEC_FLAG : 0;
16634     apiConnectptr = transPtr;
16635     abortErrorLab(signal);
16636     return;
16637   }
16638 
16639   if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
16640     jam();
16641     releaseSections(handle);
16642     // Failed to allocate index operation
16643     terrorCode = 288;
16644     regApiPtr->m_flags |=
16645       TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
16646       ApiConnectRecord::TF_EXEC_FLAG : 0;
16647     apiConnectptr = transPtr;
16648     abortErrorLab(signal);
16649     return;
16650   }
16651   TcIndexOperation* indexOp = indexOpPtr.p;
16652   indexOp->indexOpId = indexOpPtr.i;
16653 
16654   // Save original signal
16655   indexOp->tcIndxReq = *tcIndxReq;
16656   indexOp->connectionIndex = TapiIndex;
16657   regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
16658 
16659   if (isLongTcIndxReq)
16660   {
16661     jam();
16662     /* KeyInfo and AttrInfo already received into sections */
16663     SegmentedSectionPtr keyInfoSection, attrInfoSection;
16664 
16665     /* Store i value for first long section of KeyInfo
16666      * and AttrInfo in Index operation
16667      */
16668     handle.getSection(keyInfoSection,
16669                       TcKeyReq::KeyInfoSectionNum);
16670 
16671     indexOp->keyInfoSectionIVal= keyInfoSection.i;
16672 
16673     if (handle.m_cnt == 2)
16674     {
16675       handle.getSection(attrInfoSection,
16676                         TcKeyReq::AttrInfoSectionNum);
16677       indexOp->attrInfoSectionIVal= attrInfoSection.i;
16678     }
16679 
16680     if (TcKeyReq::getDeferredConstraints(tcIndxRequestInfo))
16681     {
16682       regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
16683     }
16684 
16685     if (TcKeyReq::getDisableFkConstraints(tcIndxRequestInfo))
16686     {
16687       regApiPtr->m_flags |= ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS;
16688     }
16689     indexOp->savedFlags = regApiPtr->m_flags;
16690 
16691     /* Detach sections from the handle
16692      * Success path code, or index operation cleanup is
16693      * now responsible for freeing the sections
16694      */
16695     handle.clear();
16696 
16697     /* All data received, process */
16698     readIndexTable(signal, regApiPtr, indexOp, 0);
16699     return;
16700   }
16701   else
16702   {
16703     jam();
16704     /* Short TcIndxReq, build up KeyInfo and AttrInfo
16705      * sections from separate signals
16706      */
16707     Uint32 * dataPtr = &tcIndxReq->scanInfo;
16708     Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
16709     Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
16710 
16711     indexOp->pendingKeyInfo = indexLength;
16712     indexOp->pendingAttrInfo = attrLength;
16713 
16714     const Uint32 includedIndexLength = MIN(indexLength, TcKeyReq::MaxKeyInfo);
16715     const Uint32 includedAttrLength = MIN(attrLength, TcKeyReq::MaxAttrInfo);
16716     int ret;
16717 
16718     if ((ret = saveINDXKEYINFO(signal,
16719                                indexOp,
16720                                dataPtr,
16721                                includedIndexLength)) == 0)
16722     {
16723       jam();
16724       /* All KI + no AI received, process */
16725       readIndexTable(signal, regApiPtr, indexOp, 0);
16726       return;
16727     }
16728     else if (ret == -1)
16729     {
16730       jam();
16731       return;
16732     }
16733 
16734     dataPtr += includedIndexLength;
16735 
16736     if (saveINDXATTRINFO(signal,
16737                          indexOp,
16738                          dataPtr,
16739                          includedAttrLength) == 0) {
16740       jam();
16741       /* All KI and AI received, process */
16742       readIndexTable(signal, regApiPtr, indexOp, 0);
16743       return;
16744     }
16745   }
16746 }
16747 
execINDXKEYINFO(Signal * signal)16748 void Dbtc::execINDXKEYINFO(Signal* signal)
16749 {
16750   jamEntry();
16751   Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
16752   IndxKeyInfo * const indxKeyInfo =  (IndxKeyInfo *)signal->getDataPtr();
16753   const Uint32 *src = indxKeyInfo->getData();
16754   const UintR TconnectIndex = indxKeyInfo->connectPtr;
16755   ApiConnectRecordPtr transPtr;
16756   transPtr.i = TconnectIndex;
16757   if (transPtr.i >= capiConnectFilesize) {
16758     jam();
16759     warningHandlerLab(signal, __LINE__);
16760     return;
16761   }//if
16762   ptrAss(transPtr, apiConnectRecord);
16763   ApiConnectRecord * const regApiPtr = transPtr.p;
16764   TcIndexOperationPtr indexOpPtr;
16765   TcIndexOperation* indexOp;
16766 
16767   if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
16768   {
16769     TCKEY_abort(signal, 19);
16770     return;
16771   }
16772 
16773   if (regApiPtr->apiConnectstate == CS_ABORTING)
16774   {
16775     jam();
16776     return;
16777   }
16778 
16779   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
16780   {
16781     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
16782 
16783     ndbassert( indexOp->pendingKeyInfo > 0 );
16784 
16785     if (saveINDXKEYINFO(signal,
16786 			indexOp,
16787 			src,
16788 			keyInfoLength) == 0) {
16789       jam();
16790       /* All KI + AI received, process */
16791       readIndexTable(signal, regApiPtr, indexOp, 0);
16792     }
16793   }
16794 }
16795 
execINDXATTRINFO(Signal * signal)16796 void Dbtc::execINDXATTRINFO(Signal* signal)
16797 {
16798   jamEntry();
16799   Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
16800   IndxAttrInfo * const indxAttrInfo =  (IndxAttrInfo *)signal->getDataPtr();
16801   const Uint32 *src = indxAttrInfo->getData();
16802   const UintR TconnectIndex = indxAttrInfo->connectPtr;
16803   ApiConnectRecordPtr transPtr;
16804   transPtr.i = TconnectIndex;
16805   if (transPtr.i >= capiConnectFilesize) {
16806     jam();
16807     warningHandlerLab(signal, __LINE__);
16808     return;
16809   }//if
16810   ptrAss(transPtr, apiConnectRecord);
16811   ApiConnectRecord * const regApiPtr = transPtr.p;
16812   TcIndexOperationPtr indexOpPtr;
16813   TcIndexOperation* indexOp;
16814 
16815   if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
16816   {
16817     TCKEY_abort(signal, 19);
16818     return;
16819   }
16820 
16821   if (regApiPtr->apiConnectstate == CS_ABORTING)
16822   {
16823     jam();
16824     return;
16825   }
16826 
16827   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
16828   {
16829     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
16830 
16831     ndbassert( indexOp->pendingAttrInfo > 0 );
16832 
16833     if (saveINDXATTRINFO(signal,
16834 			 indexOp,
16835 			 src,
16836 			 attrInfoLength) == 0) {
16837       jam();
16838       /* All KI + AI received, process */
16839       readIndexTable(signal, regApiPtr, indexOp, 0);
16840       return;
16841     }
16842     return;
16843   }
16844 }
16845 
16846 /**
16847  * Save received KeyInfo
16848  * Return true if we have received all needed data
16849  */
16850 int
saveINDXKEYINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)16851 Dbtc::saveINDXKEYINFO(Signal* signal,
16852                       TcIndexOperation* indexOp,
16853                       const Uint32 *src,
16854                       Uint32 len)
16855 {
16856   if (ERROR_INSERTED(8052) ||
16857       ! appendToSection(indexOp->keyInfoSectionIVal,
16858                         src,
16859                         len))
16860   {
16861     jam();
16862     // Failed to seize keyInfo, abort transaction
16863 #ifdef VM_TRACE
16864     ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize buffer for KeyInfo\n");
16865 #endif
16866     // Abort transaction
16867     apiConnectptr.i = indexOp->connectionIndex;
16868     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
16869     releaseIndexOperation(apiConnectptr.p, indexOp);
16870     terrorCode = 289;
16871     if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
16872       apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
16873     abortErrorLab(signal);
16874     return -1;
16875   }
16876   indexOp->pendingKeyInfo-= len;
16877 
16878   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
16879     jam();
16880     return 0;
16881   }
16882   return 1;
16883 }
16884 
receivedAllINDXKEYINFO(TcIndexOperation * indexOp)16885 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
16886 {
16887   return (indexOp->pendingKeyInfo == 0);
16888 }
16889 
16890 /**
16891  * Save signal INDXATTRINFO
16892  * Return true if we have received all needed data
16893  */
16894 int
saveINDXATTRINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)16895 Dbtc::saveINDXATTRINFO(Signal* signal,
16896                        TcIndexOperation* indexOp,
16897                        const Uint32 *src,
16898                        Uint32 len)
16899 {
16900   if (ERROR_INSERTED(8051) ||
16901       ! appendToSection(indexOp->attrInfoSectionIVal,
16902                         src,
16903                         len))
16904   {
16905     jam();
16906 #ifdef VM_TRACE
16907     ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize buffer for attrInfo\n");
16908 #endif
16909     apiConnectptr.i = indexOp->connectionIndex;
16910     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
16911     releaseIndexOperation(apiConnectptr.p, indexOp);
16912     terrorCode = 289;
16913     if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
16914       apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
16915     abortErrorLab(signal);
16916     return -1;
16917   }
16918 
16919   indexOp->pendingAttrInfo-= len;
16920 
16921   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
16922     jam();
16923     return 0;
16924   }
16925   return 1;
16926 }
16927 
receivedAllINDXATTRINFO(TcIndexOperation * indexOp)16928 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
16929 {
16930   return (indexOp->pendingAttrInfo == 0);
16931 }
16932 
16933 #ifdef ERROR_INSERT
16934 extern bool ErrorImportActive;
16935 #endif
16936 
saveTRANSID_AI(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)16937 Uint32 Dbtc::saveTRANSID_AI(Signal* signal,
16938                             TcIndexOperation* indexOp,
16939                             const Uint32 *src,
16940                             Uint32 len)
16941 {
16942   /* TransID_AI is received as a result of looking up a
16943    * unique index table
16944    * The unique index table is looked up using the index
16945    * key to receive a single attribute containing the
16946    * fragment holding the base table row and the base
16947    * table primary key.
16948    * This is later used to build a TCKEYREQ against the
16949    * base table.
16950    * In this method, we prepare a KEYINFO section for the
16951    * TCKEYREQ as we receive TRANSID_AI words.
16952    *
16953    * Expected TRANSID_AI words :
16954    *
16955    *   Word(s)  Description           States
16956    *
16957    *   0        Attribute header      ITAS_WAIT_HEADER
16958    *             containing length     -> ITAS_WAIT_FRAGID
16959    *
16960    *   1        Fragment Id           ITAS_WAIT_FRAGID
16961    *                                   -> ITAS_WAIT_KEY
16962    *
16963    *   [2..N]   Base table primary    ITAS_WAIT_KEY
16964    *            key info               -> [ ITAS_WAIT_KEY |
16965    *                                        ITAS_WAIT_KEY_FAIL ]
16966    *                                   -> ITAS_ALL_RECEIVED
16967    *
16968    * The outgoing KeyInfo section contains the base
16969    * table primary key info, with the fragment id passed
16970    * as the distribution key.
16971    * ITAS_WAIT_KEY_FAIL state is entered when there is no
16972    * space to store received TRANSID_AI information and
16973    * key collection must fail.  Transaction abort is performed
16974    * once all TRANSID_AI is received, and the system waits in
16975    * ITAS_WAIT_KEY_FAIL state until then.
16976    *
16977    */
16978   Uint32 remain= len;
16979 
16980   while (remain != 0)
16981   {
16982     switch(indexOp->transIdAIState) {
16983     case ITAS_WAIT_HEADER:
16984     {
16985       jam();
16986       ndbassert(indexOp->transIdAISectionIVal == RNIL);
16987       /* Look at the first AttributeHeader to get the
16988        * expected size of the primary key attribute
16989        */
16990       AttributeHeader* head = (AttributeHeader *) src;
16991       ndbassert(head->getHeaderSize() == 1);
16992       indexOp->pendingTransIdAI = 1 + head->getDataSize();
16993 
16994       src++;
16995       remain--;
16996       indexOp->transIdAIState = ITAS_WAIT_FRAGID;
16997       break;
16998     }
16999     case ITAS_WAIT_FRAGID:
17000     {
17001       jam();
17002       ndbassert(indexOp->transIdAISectionIVal == RNIL);
17003       /* Grab the fragment Id word */
17004       indexOp->fragmentId= *src;
17005 
17006       src++;
17007       remain--;
17008       indexOp->transIdAIState = ITAS_WAIT_KEY;
17009       break;
17010     }
17011     case ITAS_WAIT_KEY:
17012     {
17013       jam();
17014       /* Add key information to long section */
17015 #ifdef ERROR_INSERT
17016       if (ERROR_INSERTED(8066))
17017       {
17018         ErrorImportActive = true;
17019       }
17020 #endif
17021 
17022       bool res = appendToSection(indexOp->transIdAISectionIVal, src, remain);
17023 #ifdef ERROR_INSERT
17024       if (ERROR_INSERTED(8066))
17025       {
17026         ErrorImportActive = false;
17027       }
17028 #endif
17029 
17030       if (res)
17031       {
17032         jam();
17033         remain= 0;
17034         break;
17035       }
17036       else
17037       {
17038         jam();
17039 #ifdef VM_TRACE
17040         ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize buffer for TRANSID_AI\n");
17041 #endif
17042         indexOp->transIdAIState= ITAS_WAIT_KEY_FAIL;
17043         /* Fall through to ITAS_WAIT_KEY_FAIL state handling */
17044       }
17045     }
17046 
17047     case ITAS_WAIT_KEY_FAIL:
17048     {
17049       /* Failed when collecting key previously - if we have all the
17050        * TRANSID_AI now then we abort
17051        */
17052       if (indexOp->pendingTransIdAI > len)
17053       {
17054         /* Still some TransIdAI to arrive, keep waiting as if we had
17055          * stored it
17056          */
17057         remain= 0;
17058         break;
17059       }
17060 
17061       /* All TransIdAI has arrived, abort */
17062       apiConnectptr.i = indexOp->connectionIndex;
17063       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
17064       releaseIndexOperation(apiConnectptr.p, indexOp);
17065       terrorCode = ZGET_DATAREC_ERROR;
17066       abortErrorLab(signal);
17067       return ZGET_DATAREC_ERROR;
17068     }
17069 
17070     case ITAS_ALL_RECEIVED:
17071       jam();
17072       // Fall through
17073     default:
17074       jam();
17075       /* Bad state, or bad state to receive TransId_Ai in */
17076       // Todo : Check error handling here.
17077 #ifdef VM_TRACE
17078       ndbout_c("Dbtc::saveTRANSID_AI: Bad state when receiving\n");
17079 #endif
17080       apiConnectptr.i = indexOp->connectionIndex;
17081       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
17082       releaseIndexOperation(apiConnectptr.p, indexOp);
17083       terrorCode = ZINCONSISTENT_INDEX_USE;
17084       abortErrorLab(signal);
17085       return ZINCONSISTENT_INDEX_USE;
17086     } // switch
17087   } // while
17088 
17089   if ((indexOp->pendingTransIdAI-= len) == 0)
17090     indexOp->transIdAIState = ITAS_ALL_RECEIVED;
17091 
17092   return ZOK;
17093 }
17094 
receivedAllTRANSID_AI(TcIndexOperation * indexOp)17095 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
17096 {
17097   return (indexOp->transIdAIState == ITAS_ALL_RECEIVED);
17098 }
17099 
17100 /**
17101  * Receive signal TCINDXCONF
17102  * This can be either the return of reading an index table
17103  * or performing an index operation
17104  */
execTCKEYCONF(Signal * signal)17105 void Dbtc::execTCKEYCONF(Signal* signal)
17106 {
17107   TcKeyConf * const tcKeyConf =  (TcKeyConf *)signal->getDataPtr();
17108   TcIndexOperationPtr indexOpPtr;
17109 
17110   jamEntry();
17111   indexOpPtr.i = tcKeyConf->apiConnectPtr;
17112   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
17113 
17114   /**
17115    * Check on TCKEYCONF whether the the transaction was committed
17116    */
17117   ndbassert(TcKeyConf::getCommitFlag(tcKeyConf->confInfo) == false);
17118 
17119   indexOpPtr.p = indexOp;
17120   if (!indexOp) {
17121     jam();
17122     // Missing index operation
17123     return;
17124   }
17125   const UintR TconnectIndex = indexOp->connectionIndex;
17126   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
17127   apiConnectptr.p = regApiPtr;
17128   apiConnectptr.i = TconnectIndex;
17129   switch(indexOp->indexOpState) {
17130   case(IOS_NOOP): {
17131     jam();
17132     // Should never happen, abort
17133     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17134 
17135     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
17136     tcIndxRef->transId[0] = regApiPtr->transid[0];
17137     tcIndxRef->transId[1] = regApiPtr->transid[1];
17138     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
17139     tcIndxRef->errorData = 0;
17140     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17141 	       TcKeyRef::SignalLength, JBB);
17142     return;
17143   }
17144   case(IOS_INDEX_ACCESS): {
17145     jam();
17146     // Just waiting for the TRANSID_AI now
17147     indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
17148     break;
17149   }
17150   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
17151     jam();
17152     // Double TCKEYCONF, should never happen, abort
17153     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17154 
17155     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
17156     tcIndxRef->transId[0] = regApiPtr->transid[0];
17157     tcIndxRef->transId[1] = regApiPtr->transid[1];
17158     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
17159     tcIndxRef->errorData = 0;
17160     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17161 	       TcKeyRef::SignalLength, JBB);
17162     return;
17163   }
17164   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
17165     jam();
17166     // Continue with index operation
17167     executeIndexOperation(signal, regApiPtr, indexOp);
17168     break;
17169   }
17170   }
17171 }
17172 
execTCKEYREF(Signal * signal)17173 void Dbtc::execTCKEYREF(Signal* signal)
17174 {
17175   TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
17176   TcIndexOperationPtr indexOpPtr;
17177 
17178   jamEntry();
17179   indexOpPtr.i = tcKeyRef->connectPtr;
17180   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
17181   indexOpPtr.p = indexOp;
17182   if (!indexOp) {
17183     jam();
17184     // Missing index operation
17185     return;
17186   }
17187   const UintR TconnectIndex = indexOp->connectionIndex;
17188   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
17189 
17190   switch(indexOp->indexOpState) {
17191   case(IOS_NOOP): {
17192     jam();
17193     // Should never happen, abort
17194     break;
17195   }
17196   case(IOS_INDEX_ACCESS):
17197   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
17198   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
17199     jam();
17200     // Send TCINDXREF
17201 
17202     TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
17203     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17204 
17205     tcIndxRef->connectPtr = tcIndxReq->senderData;
17206     tcIndxRef->transId[0] = tcKeyRef->transId[0];
17207     tcIndxRef->transId[1] = tcKeyRef->transId[1];
17208     tcIndxRef->errorCode = tcKeyRef->errorCode;
17209     tcIndxRef->errorData = 0;
17210 
17211     releaseIndexOperation(regApiPtr, indexOp);
17212 
17213     sendSignal(regApiPtr->ndbapiBlockref,
17214                GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
17215     return;
17216   }
17217   }
17218 }
17219 
execTRANSID_AI_R(Signal * signal)17220 void Dbtc::execTRANSID_AI_R(Signal* signal){
17221   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
17222   Uint32 sigLen = signal->length();
17223   Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
17224   Uint32 recBlockref = transIdAI->attrData[dataLen];
17225 
17226   jamEntry();
17227 
17228   SectionHandle handle(this, signal);
17229 
17230   /**
17231    * Forward signal to final destination
17232    * Truncate last word since that was used to hold the final dest.
17233    */
17234   sendSignal(recBlockref, GSN_TRANSID_AI,
17235 	     signal, sigLen - 1, JBB,
17236 	     &handle);
17237 }
17238 
execKEYINFO20_R(Signal * signal)17239 void Dbtc::execKEYINFO20_R(Signal* signal){
17240   KeyInfo20 * const keyInfo =  (KeyInfo20 *)signal->getDataPtr();
17241   Uint32 sigLen = signal->length();
17242   Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
17243   Uint32 recBlockref = keyInfo->keyData[dataLen];
17244 
17245   jamEntry();
17246 
17247   SectionHandle handle(this, signal);
17248 
17249   /**
17250    * Forward signal to final destination
17251    * Truncate last word since that was used to hold the final dest.
17252    */
17253   sendSignal(recBlockref, GSN_KEYINFO20,
17254 	     signal, sigLen - 1, JBB,
17255 	     &handle);
17256 }
17257 
17258 
17259 /**
17260  * execTRANSID_AI
17261  *
17262  * TRANSID_AI are received as a result of performing a read on
17263  * the index table as part of a (unique) index operation.
17264  * The data received is the primary key of the base table
17265  * which is then used to perform the index operation on the
17266  * base table.
17267  */
execTRANSID_AI(Signal * signal)17268 void Dbtc::execTRANSID_AI(Signal* signal)
17269 {
17270   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
17271 
17272   jamEntry();
17273   TcIndexOperationPtr indexOpPtr;
17274   indexOpPtr.i = transIdAI->connectPtr;
17275   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
17276   indexOpPtr.p = indexOp;
17277   if (!indexOp) {
17278     jam();
17279     // Missing index operation
17280   }
17281   const UintR TconnectIndex = indexOp->connectionIndex;
17282   ApiConnectRecordPtr transPtr;
17283 
17284   transPtr.i = TconnectIndex;
17285   ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
17286   ApiConnectRecord * const regApiPtr = transPtr.p;
17287 
17288   // Acccumulate attribute data
17289   SectionHandle handle(this, signal);
17290   bool longSignal = (handle.m_cnt == 1);
17291   Uint32 errorCode = ZOK;
17292   if (longSignal)
17293   {
17294     SegmentedSectionPtr dataPtr;
17295     Uint32 dataLen;
17296     ndbrequire(handle.getSection(dataPtr, 0));
17297     dataLen = dataPtr.sz;
17298 
17299     SectionSegment * ptrP = dataPtr.p;
17300     while (dataLen > NDB_SECTION_SEGMENT_SZ)
17301     {
17302       errorCode = saveTRANSID_AI(signal, indexOp, &ptrP->theData[0],
17303                                  NDB_SECTION_SEGMENT_SZ);
17304       if (errorCode != ZOK)
17305       {
17306         releaseSections(handle);
17307         goto save_error;
17308       }
17309       dataLen -= NDB_SECTION_SEGMENT_SZ;
17310       ptrP = g_sectionSegmentPool.getPtr(ptrP->m_nextSegment);
17311     }
17312     errorCode = saveTRANSID_AI(signal, indexOp, &ptrP->theData[0], dataLen);
17313     if (errorCode != ZOK)
17314     {
17315       releaseSections(handle);
17316       goto save_error;
17317     }
17318 
17319     releaseSections(handle);
17320   }
17321   else
17322   {
17323     /* Short TransId_AI signal */
17324     errorCode = saveTRANSID_AI(signal,
17325                                indexOp,
17326                                transIdAI->getData(),
17327                                signal->getLength() - TransIdAI::HeaderLength);
17328     if (errorCode != ZOK) {
17329     save_error:
17330       jam();
17331       // Failed to allocate space for TransIdAI
17332       // Todo : How will this behave when transaction already aborted
17333       // in saveTRANSID_AI call?
17334       TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17335 
17336       tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
17337       tcIndxRef->transId[0] = regApiPtr->transid[0];
17338       tcIndxRef->transId[1] = regApiPtr->transid[1];
17339       tcIndxRef->errorCode = errorCode;
17340       tcIndxRef->errorData = 0;
17341       sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17342                  TcKeyRef::SignalLength, JBB);
17343       return;
17344     }
17345   }
17346 
17347   switch(indexOp->indexOpState) {
17348   case(IOS_NOOP): {
17349     jam();
17350     // Should never happen, abort
17351     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17352 
17353     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
17354     tcIndxRef->transId[0] = regApiPtr->transid[0];
17355     tcIndxRef->transId[1] = regApiPtr->transid[1];
17356     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
17357     tcIndxRef->errorData = 0;
17358     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17359 	       TcKeyRef::SignalLength, JBB);
17360     return;
17361     break;
17362   }
17363   case(IOS_INDEX_ACCESS): {
17364     jam();
17365     // Check if all TRANSID_AI have been received
17366     if (receivedAllTRANSID_AI(indexOp)) {
17367       jam();
17368       // Just waiting for a TCKEYCONF now
17369       indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
17370     }
17371     // else waiting for either TRANSID_AI or TCKEYCONF
17372     break;
17373     }
17374   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
17375     jam();
17376 #ifdef VM_TRACE
17377     ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
17378 #endif
17379     /*
17380     // Too many TRANSID_AI
17381     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17382 
17383     tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
17384     tcIndxRef->transId[0] = regApiPtr->transid[0];
17385     tcIndxRef->transId[1] = regApiPtr->transid[1];
17386     tcIndxRef->errorCode = 4349;
17387     tcIndxRef->errorData = 0;
17388     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17389                TcKeyRef::SignalLength, JBB);
17390     */
17391     break;
17392   }
17393   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
17394     jam();
17395     // Check if all TRANSID_AI have been received
17396     if (receivedAllTRANSID_AI(indexOp)) {
17397       jam();
17398       // Continue with index operation
17399       executeIndexOperation(signal, regApiPtr, indexOp);
17400     }
17401     // else continue waiting for more TRANSID_AI
17402     break;
17403   }
17404   }
17405 }
17406 
execTCROLLBACKREP(Signal * signal)17407 void Dbtc::execTCROLLBACKREP(Signal* signal)
17408 {
17409   TcRollbackRep* tcRollbackRep =  (TcRollbackRep *)signal->getDataPtr();
17410   jamEntry();
17411   TcIndexOperationPtr indexOpPtr;
17412   indexOpPtr.i = tcRollbackRep->connectPtr;
17413   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
17414   indexOpPtr.p = indexOp;
17415   tcRollbackRep =  (TcRollbackRep *)signal->getDataPtrSend();
17416   tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
17417   sendSignal(apiConnectptr.p->ndbapiBlockref,
17418 	     GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
17419 }
17420 
17421 /**
17422  * Read index table with the index attributes as PK
17423  */
readIndexTable(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp,Uint32 special_op_flags)17424 void Dbtc::readIndexTable(Signal* signal,
17425 			  ApiConnectRecord* regApiPtr,
17426 			  TcIndexOperation* indexOp,
17427                           Uint32 special_op_flags)
17428 {
17429   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
17430   Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
17431   TcIndexData* indexData;
17432   Uint32 transId1 = indexOp->tcIndxReq.transId1;
17433   Uint32 transId2 = indexOp->tcIndxReq.transId2;
17434 
17435   const Operation_t opType =
17436     (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
17437 
17438   // Find index table
17439   if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
17440     // TODO : Free KeyInfo and AttrInfo sections here if necessary
17441     // How is this operation cleaned up?
17442     jam();
17443     // Failed to find index record
17444     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17445 
17446     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
17447     tcIndxRef->transId[0] = regApiPtr->transid[0];
17448     tcIndxRef->transId[1] = regApiPtr->transid[1];
17449     tcIndxRef->errorCode = 4000;
17450     // tcIndxRef->errorData = ??; Where to find indexId
17451     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17452 	       TcKeyRef::SignalLength, JBB);
17453     return;
17454   }
17455   tcKeyReq->transId1 = transId1;
17456   tcKeyReq->transId2 = transId2;
17457   tcKeyReq->tableId = indexData->indexId;
17458   tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
17459   TcKeyReq::setOperationType(tcKeyRequestInfo,
17460 			     opType == ZREAD ? ZREAD : ZREAD_EX);
17461   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0); // No AI in long TCKEYREQ
17462   TcKeyReq::setInterpretedFlag(tcKeyRequestInfo, 0);
17463   tcKeyReq->senderData = indexOp->indexOpId;
17464   indexOp->indexOpState = IOS_INDEX_ACCESS;
17465   regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
17466   regApiPtr->accumulatingIndexOp = RNIL;
17467   regApiPtr->m_special_op_flags =
17468     TcConnectRecord::SOF_INDEX_TABLE_READ | special_op_flags;
17469 
17470   if (ERROR_INSERTED(8037))
17471   {
17472     ndbout_c("shifting index version");
17473     tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
17474   }
17475   tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
17476   tcKeyReq->requestInfo = tcKeyRequestInfo;
17477 
17478   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
17479   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
17480 
17481   /* Long TCKEYREQ Signal sections
17482    * We attach the KeyInfo section received from the user, and
17483    * create a new AttrInfo section with just one AttributeHeader
17484    * to retrieve the base table primary key
17485    */
17486   Ptr<SectionSegment> indexLookupAttrInfoSection;
17487   Uint32 singleAIWord;
17488 
17489   AttributeHeader::init(&singleAIWord, indexData->primaryKeyPos, 0);
17490   if (! import(indexLookupAttrInfoSection,
17491                &singleAIWord,
17492                1))
17493   {
17494     jam();
17495     /* Error creating AttrInfo section to request primary
17496      * key from index table.
17497      */
17498     // TODO - verify error handling
17499 #ifdef VM_TRACE
17500     ndbout_c("Dbtc::readIndexTable: Failed to create AttrInfo section");
17501 #endif
17502     apiConnectptr.i = indexOp->connectionIndex;
17503     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
17504     releaseIndexOperation(apiConnectptr.p, indexOp);
17505     terrorCode = 4000;
17506     abortErrorLab(signal);
17507     return;
17508   }
17509 
17510   ndbassert(signal->header.m_noOfSections == 0);
17511 
17512   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
17513     = indexOp->keyInfoSectionIVal;
17514 
17515   /* We pass this section to TCKEYREQ next */
17516   indexOp->keyInfoSectionIVal= RNIL;
17517 
17518   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
17519     = indexLookupAttrInfoSection.i;
17520   signal->header.m_noOfSections= 2;
17521 
17522   /* Direct execute of long TCKEYREQ
17523    * TCKEYREQ is responsible for freeing the KeyInfo and
17524    * AttrInfo sections passed to it
17525    */
17526   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
17527   jamEntry();
17528 
17529   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
17530   {
17531     jam();
17532   }
17533   else
17534   {
17535     jam();
17536     /**
17537      * "Fool" TC not to start commiting transaction since it always will
17538      *   have one outstanding lqhkeyreq
17539      * This is later decreased when the index read is complete
17540      */
17541     regApiPtr->lqhkeyreqrec++;
17542 
17543     /**
17544      * Remember ptr to index read operation
17545      *   (used to set correct save point id on index operation later)
17546      */
17547     indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
17548   }
17549 
17550   return;
17551 }
17552 
17553 /**
17554  * Execute the index operation with the result from
17555  * the index table read as PK
17556  */
executeIndexOperation(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)17557 void Dbtc::executeIndexOperation(Signal* signal,
17558 				 ApiConnectRecord* regApiPtr,
17559 				 TcIndexOperation* indexOp) {
17560 
17561   TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
17562   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
17563   Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
17564   TcIndexData* indexData;
17565 
17566   // Find index table
17567   if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
17568     jam();
17569     // Failed to find index record
17570     // TODO : How is this operation cleaned up?
17571     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
17572 
17573     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
17574     tcIndxRef->transId[0] = regApiPtr->transid[0];
17575     tcIndxRef->transId[1] = regApiPtr->transid[1];
17576     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
17577     tcIndxRef->errorData = 0;
17578     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
17579 	       TcKeyRef::SignalLength, JBB);
17580     return;
17581   }
17582 
17583   // Find schema version of primary table
17584   TableRecordPtr tabPtr;
17585   tabPtr.i = indexData->primaryTableId;
17586   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
17587 
17588   tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
17589   tcKeyReq->attrLen = tcIndxReq->attrLen;
17590   tcKeyReq->tableId = indexData->primaryTableId;
17591   tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
17592   tcKeyReq->transId1 = regApiPtr->transid[0];
17593   tcKeyReq->transId2 = regApiPtr->transid[1];
17594   tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
17595 
17596   if (tabPtr.p->get_user_defined_partitioning())
17597   {
17598     jam();
17599     tcKeyReq->scanInfo = indexOp->fragmentId; // As read from Index table
17600     TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
17601   }
17602   regApiPtr->m_special_op_flags = 0;
17603   regApiPtr->executingIndexOp = 0;
17604 
17605   /* KeyInfo section
17606    * Get the KeyInfo we received from the index table lookup
17607    */
17608   SegmentedSectionPtr keyInfoFromTransIdAI;
17609 
17610   ndbassert( indexOp->transIdAISectionIVal != RNIL );
17611   getSection(keyInfoFromTransIdAI, indexOp->transIdAISectionIVal);
17612 
17613   ndbassert( signal->header.m_noOfSections == 0 );
17614   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
17615     = indexOp->transIdAISectionIVal;
17616   signal->header.m_noOfSections = 1;
17617 
17618   indexOp->transIdAISectionIVal = RNIL;
17619 
17620   /* AttrInfo section
17621    * Attach any AttrInfo section from original TCINDXREQ
17622    */
17623   if ( indexOp->attrInfoSectionIVal != RNIL )
17624   {
17625     jam();
17626     SegmentedSectionPtr attrInfoFromInitialReq;
17627 
17628     getSection(attrInfoFromInitialReq, indexOp->attrInfoSectionIVal);
17629     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
17630       = indexOp->attrInfoSectionIVal;
17631     signal->header.m_noOfSections = 2;
17632     indexOp->attrInfoSectionIVal = RNIL;
17633   }
17634 
17635   releaseIndexOperation(regApiPtr, indexOp);
17636 
17637   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyInfoFromTransIdAI.sz);
17638   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
17639   TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
17640   TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
17641   tcKeyReq->requestInfo = tcKeyRequestInfo;
17642 
17643   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
17644   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
17645 
17646   /**
17647    * Decrease lqhkeyreqrec to compensate for addition
17648    *   during read of index table
17649    * I.e. let TC start committing when other operations has completed
17650    */
17651   regApiPtr->lqhkeyreqrec--;
17652 
17653   /**
17654    * Fix savepoint id -
17655    *   fix so that index operation has the same savepoint id
17656    *   as the read of the index table (TCINDXREQ)
17657    */
17658   TcConnectRecordPtr tmp;
17659   tmp.i = indexOp->indexReadTcConnect;
17660   ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
17661   const Uint32 currSavePointId = regApiPtr->currSavePointId;
17662   const Uint32 triggeringOp = tmp.p->triggeringOperation;
17663   const Uint32 triggerId = tmp.p->currentTriggerId;
17664   regApiPtr->currSavePointId = tmp.p->savePointId;
17665 
17666 #ifdef ERROR_INSERT
17667   bool err8072 = ERROR_INSERTED(8072);
17668   if (err8072)
17669   {
17670     CLEAR_ERROR_INSERT_VALUE;
17671   }
17672 #endif
17673 
17674   if (triggeringOp != RNIL)
17675   {
17676     jam();
17677     /**
17678      * Carry forward info that this was caused by trigger
17679      *   (used by FK)
17680      */
17681     ndbassert(triggerId != RNIL);
17682     ndbassert(tcIndxReq->senderData == triggeringOp);
17683     regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
17684     regApiPtr->immediateTriggerId = triggerId;
17685   }
17686 
17687   /* Execute TCKEYREQ now - it is now responsible for freeing
17688    * the KeyInfo and AttrInfo sections
17689    */
17690   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
17691   jamEntry();
17692 
17693 #ifdef ERROR_INSERT
17694   if (err8072)
17695   {
17696     SET_ERROR_INSERT_VALUE(8072);
17697   }
17698 #endif
17699 
17700   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
17701   {
17702     // TODO : Presumably the abort cleans up the operation
17703     jam();
17704     return;
17705   }
17706 
17707   regApiPtr->currSavePointId = currSavePointId;
17708   regApiPtr->immediateTriggerId = RNIL;
17709 }
17710 
seizeIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperationPtr & indexOpPtr)17711 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
17712 			       TcIndexOperationPtr& indexOpPtr)
17713 {
17714   if (regApiPtr->theSeizedIndexOperations.seizeFirst(indexOpPtr))
17715   {
17716     jam();
17717     ndbassert(indexOpPtr.p->pendingKeyInfo == 0);
17718     ndbassert(indexOpPtr.p->keyInfoSectionIVal == RNIL);
17719     ndbassert(indexOpPtr.p->pendingAttrInfo == 0);
17720     ndbassert(indexOpPtr.p->attrInfoSectionIVal == RNIL);
17721     ndbassert(indexOpPtr.p->transIdAIState == ITAS_WAIT_HEADER);
17722     ndbassert(indexOpPtr.p->pendingTransIdAI == 0);
17723     ndbassert(indexOpPtr.p->transIdAISectionIVal == RNIL);
17724     return true;
17725   }
17726   jam();
17727   return false;
17728 }
17729 
releaseIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)17730 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
17731 				 TcIndexOperation* indexOp)
17732 {
17733   indexOp->indexOpState = IOS_NOOP;
17734   indexOp->pendingKeyInfo = 0;
17735   releaseSection(indexOp->keyInfoSectionIVal);
17736   indexOp->keyInfoSectionIVal= RNIL;
17737   indexOp->pendingAttrInfo = 0;
17738   releaseSection(indexOp->attrInfoSectionIVal);
17739   indexOp->attrInfoSectionIVal= RNIL;
17740   indexOp->transIdAIState = ITAS_WAIT_HEADER;
17741   indexOp->pendingTransIdAI = 0;
17742   releaseSection(indexOp->transIdAISectionIVal);
17743   indexOp->transIdAISectionIVal= RNIL;
17744   regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
17745 }
17746 
releaseAllSeizedIndexOperations(ApiConnectRecord * regApiPtr)17747 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
17748 {
17749   TcIndexOperationPtr seizedIndexOpPtr;
17750 
17751   regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
17752   while(seizedIndexOpPtr.i != RNIL) {
17753     jam();
17754     TcIndexOperation* indexOp = seizedIndexOpPtr.p;
17755 
17756     indexOp->indexOpState = IOS_NOOP;
17757     indexOp->pendingKeyInfo = 0;
17758     releaseSection(indexOp->keyInfoSectionIVal);
17759     indexOp->keyInfoSectionIVal = RNIL;
17760     indexOp->pendingAttrInfo = 0;
17761     releaseSection(indexOp->attrInfoSectionIVal);
17762     indexOp->attrInfoSectionIVal = RNIL;
17763     indexOp->transIdAIState = ITAS_WAIT_HEADER;
17764     indexOp->pendingTransIdAI = 0;
17765     releaseSection(indexOp->transIdAISectionIVal);
17766     indexOp->transIdAISectionIVal = RNIL;
17767     regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
17768   }
17769   jam();
17770   while (regApiPtr->theSeizedIndexOperations.releaseFirst())
17771   {
17772     ;
17773   }
17774   jam();
17775 }
17776 
saveTriggeringOpState(Signal * signal,TcConnectRecord * trigOp)17777 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
17778 {
17779   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
17780   copyFromToLen((UintR*)lqhKeyConf,
17781 		&trigOp->savedState[0],
17782                 LqhKeyConf::SignalLength);
17783 }
17784 
17785 void
trigger_op_finished(Signal * signal,ApiConnectRecordPtr regApiPtr,Uint32 trigPtrI,TcConnectRecord * triggeringOp,Uint32 errCode)17786 Dbtc::trigger_op_finished(Signal* signal,
17787                           ApiConnectRecordPtr regApiPtr,
17788                           Uint32 trigPtrI,
17789                           TcConnectRecord* triggeringOp,
17790                           Uint32 errCode)
17791 {
17792   if (trigPtrI != RNIL)
17793   {
17794     jam();
17795     Ptr<TcDefinedTriggerData> trigPtr;
17796     c_theDefinedTriggers.getPtr(trigPtr, trigPtrI);
17797     switch(trigPtr.p->triggerType){
17798     case TriggerType::FK_PARENT:
17799     {
17800       if (errCode == ZNOT_FOUND)
17801       {
17802         jam();
17803         break; // good!
17804       }
17805 
17806       Ptr<TcFKData> fkPtr;
17807       // TODO make it a pool.getPtr() instead
17808       // by also adding fk_ptr_i to definedTriggerData
17809       ndbrequire(c_fk_hash.find(fkPtr, trigPtr.p->fkId));
17810       if (errCode == 0 && ((fkPtr.p->bits&CreateFKImplReq::FK_ON_ACTION) == 0))
17811       {
17812         jam();
17813         // Only restrict
17814         terrorCode = ZFK_CHILD_ROW_EXISTS;
17815       }
17816       else if (errCode == 0)
17817       {
17818         /**
17819          * Check action performed against expected result...
17820          */
17821         if (triggeringOp->operation == ZDELETE &&
17822             (fkPtr.p->bits & CreateFKImplReq::FK_DELETE_ACTION))
17823         {
17824           jam();
17825           // the on action succeeded, good!
17826           break;
17827         }
17828         else if ((triggeringOp->operation == ZUPDATE || triggeringOp->operation == ZWRITE) &&
17829                  (fkPtr.p->bits & CreateFKImplReq::FK_UPDATE_ACTION))
17830         {
17831           jam();
17832           // the on action succeeded, good!
17833           break;
17834         }
17835         jam();
17836         terrorCode = ZFK_CHILD_ROW_EXISTS;
17837       }
17838       else
17839       {
17840         jam();
17841         jamLine(errCode);
17842         terrorCode = errCode;
17843       }
17844       apiConnectptr = regApiPtr;
17845       abortErrorLab(signal);
17846       return;
17847     }
17848     default:
17849       (void)1;
17850     }
17851   }
17852   if (!regApiPtr.p->isExecutingDeferredTriggers())
17853   {
17854     jam();
17855     if (unlikely((triggeringOp->triggerExecutionCount == 0)))
17856     {
17857       printf("%u : 0x%x->triggerExecutionCount == 0\n",
17858              __LINE__,
17859              Uint32(triggeringOp - this->tcConnectRecord));
17860       dump_trans(regApiPtr);
17861     }
17862     ndbrequire(triggeringOp->triggerExecutionCount > 0);
17863     triggeringOp->triggerExecutionCount--;
17864     if (triggeringOp->triggerExecutionCount == 0)
17865     {
17866       /**
17867        * We have completed current trigger execution
17868        * Continue triggering operation
17869        */
17870       jam();
17871       continueTriggeringOp(signal, triggeringOp);
17872     }
17873   }
17874   else
17875   {
17876     jam();
17877     lqhKeyConf_checkTransactionState(signal, regApiPtr);
17878   }
17879 }
17880 
continueTriggeringOp(Signal * signal,TcConnectRecord * trigOp)17881 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
17882 {
17883   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
17884   copyFromToLen(&trigOp->savedState[0],
17885                 (UintR*)lqhKeyConf,
17886 		LqhKeyConf::SignalLength);
17887 
17888   ndbassert(trigOp->savedState[LqhKeyConf::SignalLength-1] != ~Uint32(0));
17889   trigOp->savedState[LqhKeyConf::SignalLength-1] = ~Uint32(0);
17890 
17891   lqhKeyConf->numFiredTriggers = 0;
17892   trigOp->numReceivedTriggers = 0;
17893 
17894   /**
17895    * All triggers executed successfully, continue operation
17896    *
17897    * We have to be careful here not sending too many direct signals in a row.
17898    * This has two consequences, first we are breaking the coding rules if we
17899    * do and thus other signals have a hard time to get their piece of the
17900    * CPU.
17901    * Secondly we can easily run out of stack which can cause all sorts of
17902    * weird errors. We cannot allow any type of completely recursive behaviour
17903    * in the NDB code.
17904    */
17905   c_lqhkeyconf_direct_sent++;
17906   if (c_lqhkeyconf_direct_sent <= 5)
17907   {
17908     jam();
17909     execLQHKEYCONF(signal);
17910   }
17911   else
17912   {
17913     jam();
17914     c_lqhkeyconf_direct_sent = 0;
17915     sendSignal(reference(),
17916                GSN_LQHKEYCONF,
17917                signal,
17918                LqhKeyConf::SignalLength,
17919                JBB);
17920   }
17921 }
17922 
executeTriggers(Signal * signal,ApiConnectRecordPtr * transPtr)17923 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
17924 {
17925   ApiConnectRecord* regApiPtr = transPtr->p;
17926   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
17927   TcConnectRecordPtr opPtr;
17928   FiredTriggerPtr trigPtr;
17929 
17930   if (!regApiPtr->theFiredTriggers.isEmpty()) {
17931     jam();
17932     if ((regApiPtr->apiConnectstate == CS_STARTED) ||
17933         (regApiPtr->apiConnectstate == CS_START_COMMITTING) ||
17934         (regApiPtr->apiConnectstate == CS_SEND_FIRE_TRIG_REQ) ||
17935         (regApiPtr->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ))
17936     {
17937       jam();
17938       regApiPtr->theFiredTriggers.first(trigPtr);
17939       while (trigPtr.i != RNIL) {
17940         jam();
17941         if (regApiPtr->cascading_scans_count >=
17942             MaxCascadingScansPerTransaction)
17943         {
17944           jam();
17945           D("trans: cascading scans " << regApiPtr->cascading_scans_count);
17946           waitToExecutePendingTrigger(signal, *transPtr);
17947           // pause all trigger execution
17948           break;
17949         }
17950         // Execute all ready triggers in parallel
17951         opPtr.i = trigPtr.p->fireingOperation;
17952         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
17953 	FiredTriggerPtr nextTrigPtr = trigPtr;
17954 	regApiPtr->theFiredTriggers.next(nextTrigPtr);
17955         ndbrequire(opPtr.p->apiConnect == transPtr->i);
17956         if (opPtr.p->numReceivedTriggers == opPtr.p->numFiredTriggers ||
17957             regApiPtr->isExecutingDeferredTriggers()) {
17958           jam();
17959           // Fireing operation is ready to have a trigger executing
17960           executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
17961           // Should allow for interleaving here by sending a CONTINUEB and
17962 	  // return
17963           // Release trigger records
17964 	  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
17965 	  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
17966 	  tmp1.release();
17967 	  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
17968 	  tmp2.release();
17969 	  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
17970 	  tmp3.release();
17971           regApiPtr->theFiredTriggers.release(trigPtr);
17972         }
17973 	trigPtr = nextTrigPtr;
17974       }
17975       return;
17976     // No more triggers, continue transaction after last executed trigger has
17977     // reurned (in execLQHKEYCONF or execLQHKEYREF)
17978     } else {
17979 
17980       jam();
17981       /* Not in correct state to fire triggers yet, need to wait
17982        * (or keep waiting)
17983        */
17984 
17985       if ((regApiPtr->apiConnectstate == CS_RECEIVING) ||
17986           (regApiPtr->apiConnectstate == CS_REC_COMMITTING))
17987       {
17988         // Wait until transaction is ready to execute a trigger
17989         jam();
17990         D("trans: apiConnectstate " << regApiPtr->apiConnectstate);
17991         waitToExecutePendingTrigger(signal, *transPtr);
17992       }
17993       else
17994       {
17995         /* Transaction has started aborting.
17996          * Forget about unprocessed triggers
17997          */
17998         ndbrequire(regApiPtr->apiConnectstate == CS_ABORTING);
17999       }
18000     }
18001   }
18002 }
18003 
18004 void
waitToExecutePendingTrigger(Signal * signal,ApiConnectRecordPtr transPtr)18005 Dbtc::waitToExecutePendingTrigger(Signal* signal, ApiConnectRecordPtr transPtr)
18006 {
18007   if (!tc_testbit(transPtr.p->m_flags,
18008                   ApiConnectRecord::TF_TRIGGER_PENDING))
18009   {
18010     jam();
18011     D("trans: send trigger pending");
18012     c_lqhkeyconf_direct_sent = 0;
18013     transPtr.p->m_flags |= ApiConnectRecord::TF_TRIGGER_PENDING;
18014     signal->theData[0] = TcContinueB::TRIGGER_PENDING;
18015     signal->theData[1] = transPtr.i;
18016     signal->theData[2] = transPtr.p->transid[0];
18017     signal->theData[3] = transPtr.p->transid[1];
18018     sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
18019   }
18020   else
18021   {
18022     // We are already waiting for a pending trigger (CONTINUEB)
18023     D("trans: trigger pending already");
18024   }
18025 }
18026 
executeTrigger(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)18027 void Dbtc::executeTrigger(Signal* signal,
18028                           TcFiredTriggerData* firedTriggerData,
18029                           ApiConnectRecordPtr* transPtr,
18030                           TcConnectRecordPtr* opPtr)
18031 {
18032   TcDefinedTriggerData* definedTriggerData;
18033 
18034   if ((definedTriggerData =
18035        c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
18036       != NULL)
18037   {
18038     transPtr->p->pendingTriggers--;
18039     switch(firedTriggerData->triggerType) {
18040     case(TriggerType::SECONDARY_INDEX):
18041       jam();
18042       executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
18043                           transPtr, opPtr);
18044       break;
18045     case TriggerType::REORG_TRIGGER:
18046       jam();
18047       executeReorgTrigger(signal, definedTriggerData, firedTriggerData,
18048                           transPtr, opPtr);
18049       break;
18050     case TriggerType::FK_PARENT:
18051       jam();
18052       executeFKParentTrigger(signal, definedTriggerData, firedTriggerData,
18053                              transPtr, opPtr);
18054       break;
18055     case TriggerType::FK_CHILD:
18056       jam();
18057       executeFKChildTrigger(signal, definedTriggerData, firedTriggerData,
18058                             transPtr, opPtr);
18059       break;
18060     default:
18061       ndbrequire(false);
18062     }
18063   }
18064 }
18065 
executeIndexTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)18066 void Dbtc::executeIndexTrigger(Signal* signal,
18067                                TcDefinedTriggerData* definedTriggerData,
18068                                TcFiredTriggerData* firedTriggerData,
18069                                ApiConnectRecordPtr* transPtr,
18070                                TcConnectRecordPtr* opPtr)
18071 {
18072   TcIndexData* indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
18073   ndbassert(indexData != NULL);
18074 
18075   switch (firedTriggerData->triggerEvent) {
18076   case(TriggerEvent::TE_INSERT): {
18077     jam();
18078     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
18079     break;
18080   }
18081   case(TriggerEvent::TE_DELETE): {
18082     jam();
18083     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
18084     break;
18085   }
18086   case(TriggerEvent::TE_UPDATE): {
18087     jam();
18088     opPtr->p->triggerExecutionCount++; // One is already added...and this is 2
18089     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
18090     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
18091     break;
18092   }
18093   default:
18094     ndbrequire(false);
18095   }
18096 }
18097 
18098 Uint32
fk_constructAttrInfoSetNull(const TcFKData * fkPtrP)18099 Dbtc::fk_constructAttrInfoSetNull(const TcFKData * fkPtrP)
18100 {
18101   Uint32 attrInfo[MAX_ATTRIBUTES_IN_INDEX];
18102   for (Uint32 i = 0; i<fkPtrP->childTableColumns.sz; i++)
18103   {
18104     AttributeHeader::init(attrInfo + i, fkPtrP->childTableColumns.id[i],
18105                           0 /* setNull */);
18106   }
18107 
18108   Uint32 tmp = RNIL;
18109   if (ERROR_INSERTED(8106))
18110   {
18111     return tmp;
18112   }
18113 
18114   appendToSection(tmp, attrInfo, fkPtrP->childTableColumns.sz);
18115   return tmp;
18116 }
18117 
18118 Uint32
fk_constructAttrInfoUpdateCascade(const TcFKData * fkPtrP,DataBuffer<11>::Head & srchead)18119 Dbtc::fk_constructAttrInfoUpdateCascade(const TcFKData * fkPtrP,
18120                                         DataBuffer<11>::Head & srchead)
18121 {
18122   Uint32 tmp = RNIL;
18123   if (ERROR_INSERTED(8103))
18124   {
18125     return tmp;
18126   }
18127 
18128   /**
18129    * Construct an update based on the src-data
18130    *
18131    * NOTE: this assumes same order...
18132    */
18133   Uint32 pos = 0;
18134   AttributeBuffer::DataBufferIterator iter;
18135   LocalDataBuffer<11> src(c_theAttributeBufferPool, srchead);
18136   bool moreData= src.first(iter);
18137   const Uint32 segSize= src.getSegmentSize(); // 11
18138 
18139   while (moreData)
18140   {
18141     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
18142     Uint32 dataSize = attrHeader->getDataSize();
18143 
18144     AttributeHeader ah(*iter.data);
18145     ah.setAttributeId(fkPtrP->childTableColumns.id[pos++]);// Renumber AttrIds
18146     if (unlikely(!appendToSection(tmp, &ah.m_value, 1)))
18147     {
18148       releaseSection(tmp);
18149       return RNIL;
18150     }
18151 
18152     moreData = src.next(iter, 1);
18153     while (dataSize)
18154     {
18155       ndbrequire(moreData);
18156       /* Copy as many contiguous words as possible */
18157       Uint32 contigLeft = segSize - iter.ind;
18158       ndbassert(contigLeft);
18159       Uint32 contigValid = MIN(dataSize, contigLeft);
18160 
18161       if (unlikely(!appendToSection(tmp, iter.data, contigValid)))
18162       {
18163         releaseSection(tmp);
18164         return RNIL;
18165       }
18166       moreData = src.next(iter, contigValid);
18167       dataSize -= contigValid;
18168     }
18169   }
18170 
18171   return tmp;
18172 }
18173 
18174 void
executeFKParentTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)18175 Dbtc::executeFKParentTrigger(Signal* signal,
18176                              TcDefinedTriggerData* definedTriggerData,
18177                              TcFiredTriggerData* firedTriggerData,
18178                              ApiConnectRecordPtr* transPtr,
18179                              TcConnectRecordPtr* opPtr)
18180 {
18181   Ptr<TcFKData> fkPtr;
18182   // TODO make it a pool.getPtr() instead
18183   // by also adding fk_ptr_i to definedTriggerData
18184   ndbrequire(c_fk_hash.find(fkPtr, definedTriggerData->fkId));
18185 
18186   switch (firedTriggerData->triggerEvent) {
18187   case(TriggerEvent::TE_DELETE):
18188     jam();
18189     /**
18190      * Check that before values does not exist in child-table
18191      */
18192     break;
18193   case(TriggerEvent::TE_UPDATE):
18194     jam();
18195     /**
18196      * Check that before values does not exist in child-table
18197      */
18198     break;
18199   default:
18200     ndbrequire(false);
18201   }
18202 
18203   Uint32 op = ZREAD;
18204   Uint32 attrValuesPtrI = RNIL; // for cascascade update/setnull
18205   switch(firedTriggerData->triggerEvent){
18206   case TriggerEvent::TE_UPDATE:
18207     if (fkPtr.p->bits & CreateFKImplReq::FK_UPDATE_CASCADE)
18208     {
18209       jam();
18210       /**
18211        * Update child table with after values of parent
18212        */
18213       op = ZUPDATE;
18214       attrValuesPtrI =
18215         fk_constructAttrInfoUpdateCascade(fkPtr.p,
18216                                           firedTriggerData->afterValues);
18217 
18218       if (unlikely(attrValuesPtrI == RNIL))
18219         goto oom;
18220     }
18221     else if (fkPtr.p->bits & CreateFKImplReq::FK_UPDATE_SET_NULL)
18222     {
18223       jam();
18224       /**
18225        * Update child table set null
18226        */
18227       goto setnull;
18228     }
18229     break;
18230   case TriggerEvent::TE_DELETE:
18231     if (fkPtr.p->bits & CreateFKImplReq::FK_DELETE_CASCADE)
18232     {
18233       jam();
18234       /**
18235        * Delete from child table
18236        */
18237       op = ZDELETE;
18238     }
18239     else if (fkPtr.p->bits & CreateFKImplReq::FK_DELETE_SET_NULL)
18240     {
18241       jam();
18242       /**
18243        * Update child table set null
18244        */
18245       goto setnull;
18246     }
18247     break;
18248   default:
18249     ndbrequire(false);
18250   setnull:{
18251       op = ZUPDATE;
18252       attrValuesPtrI = fk_constructAttrInfoSetNull(fkPtr.p);
18253       if (unlikely(attrValuesPtrI == RNIL))
18254         goto oom;
18255     }
18256   }
18257 
18258   if (! (fkPtr.p->bits & CreateFKImplReq::FK_CHILD_OI))
18259   {
18260     jam();
18261     fk_readFromChildTable(signal, firedTriggerData, transPtr, opPtr,
18262                           fkPtr.p, op, attrValuesPtrI);
18263   }
18264   else
18265   {
18266     jam();
18267     fk_scanFromChildTable(signal, firedTriggerData, transPtr, opPtr,
18268                           fkPtr.p, op, attrValuesPtrI);
18269   }
18270   return;
18271 oom:
18272   abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
18273 }
18274 
18275 void
fk_readFromChildTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcFKData * fkData,Uint32 op,Uint32 attrValuesPtrI)18276 Dbtc::fk_readFromChildTable(Signal* signal,
18277                             TcFiredTriggerData* firedTriggerData,
18278                             ApiConnectRecordPtr* transPtr,
18279                             TcConnectRecordPtr* opPtr,
18280                             TcFKData* fkData,
18281                             Uint32 op,
18282                             Uint32 attrValuesPtrI)
18283 {
18284   ApiConnectRecord* regApiPtr = transPtr->p;
18285   TcConnectRecord* opRecord = opPtr->p;
18286   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
18287   Uint32 tcKeyRequestInfo = 0;
18288   TableRecordPtr childIndexPtr;
18289 
18290   childIndexPtr.i = fkData->childIndexId;
18291   ptrCheckGuard(childIndexPtr, ctabrecFilesize, tableRecord);
18292   tcKeyReq->apiConnectPtr = transPtr->i;
18293   tcKeyReq->senderData = opPtr->i;
18294 
18295   // Calculate key length and renumber attribute id:s
18296   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
18297   LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
18298 
18299   SegmentedSectionGuard guard(this, attrValuesPtrI);
18300   if (beforeValues.getSize() == 0)
18301   {
18302     jam();
18303     ndbrequire(tc_testbit(regApiPtr->m_flags,
18304                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
18305     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
18306     return;
18307   }
18308 
18309   Uint32 keyIVal= RNIL;
18310   bool hasNull= false;
18311   Uint32 err = fk_buildKeyInfo(keyIVal, hasNull, beforeValues, fkData, false);
18312   guard.add(keyIVal);
18313   if (unlikely(err != 0))
18314   {
18315     abortTransFromTrigger(signal, *transPtr, err);
18316     return;
18317   }
18318 
18319   /* If there's Nulls in the values that become the index table's
18320    * PK then we skip this delete
18321    */
18322   if (hasNull)
18323   {
18324     jam();
18325     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
18326     return;
18327   }
18328 
18329   /**
18330    * Access child does never need lock...
18331    *   as parent is read with lock
18332    */
18333   Uint16 flags = TcConnectRecord::SOF_TRIGGER;
18334   const Uint32 currSavePointId = regApiPtr->currSavePointId;
18335   Uint32 usedSavePointId = currSavePointId;
18336   Uint32 gsn = GSN_TCKEYREQ;
18337   if (op == ZREAD)
18338   {
18339     jam();
18340     flags |= TcConnectRecord::SOF_FK_READ_COMMITTED;
18341     TcKeyReq::setSimpleFlag(tcKeyRequestInfo, 1);
18342   }
18343   else
18344   {
18345     jam();
18346     /**
18347      * Let any DML be made with same save point
18348      *   as original DML...but ZREAD reads latest
18349      */
18350     usedSavePointId = opRecord->savePointId;
18351     if (fkData->childTableId != fkData->childIndexId)
18352     {
18353       jam();
18354       gsn = GSN_TCINDXREQ;
18355     }
18356   }
18357   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
18358   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
18359   tcKeyReq->attrLen = 0;
18360   tcKeyReq->tableId = childIndexPtr.i;
18361   TcKeyReq::setOperationType(tcKeyRequestInfo, op);
18362   tcKeyReq->tableSchemaVersion = childIndexPtr.p->currentSchemaVersion;
18363   tcKeyReq->transId1 = regApiPtr->transid[0];
18364   tcKeyReq->transId2 = regApiPtr->transid[1];
18365   tcKeyReq->requestInfo = tcKeyRequestInfo;
18366 
18367   /* Attach KeyInfo section to signal */
18368   ndbrequire(signal->header.m_noOfSections == 0);
18369   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
18370   signal->header.m_noOfSections = 1;
18371 
18372   if (attrValuesPtrI != RNIL)
18373   {
18374     jam();
18375     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrValuesPtrI;
18376     signal->header.m_noOfSections = 2;
18377   }
18378 
18379   guard.clear(); // now sections will be handled...
18380 
18381   /**
18382    * Handle savepoint id - (see above)
18383    */
18384   regApiPtr->currSavePointId = usedSavePointId;
18385   regApiPtr->m_special_op_flags = flags;
18386   /* Pass trigger Id via ApiConnectRecord (nasty) */
18387   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
18388   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
18389   if (gsn == GSN_TCKEYREQ)
18390   {
18391     EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
18392   }
18393   else
18394   {
18395     fk_execTCINDXREQ(signal, * transPtr, * opPtr, op);
18396   }
18397   jamEntry();
18398 
18399   /*
18400    * Restore ApiConnectRecord state
18401    */
18402   regApiPtr->immediateTriggerId = RNIL;
18403   regApiPtr->currSavePointId = currSavePointId;
18404 }
18405 
18406 void
fk_execTCINDXREQ(Signal * signal,ApiConnectRecordPtr transPtr,TcConnectRecordPtr opPtr,Uint32 operation)18407 Dbtc::fk_execTCINDXREQ(Signal* signal,
18408                        ApiConnectRecordPtr transPtr,
18409                        TcConnectRecordPtr opPtr,
18410                        Uint32 operation)
18411 {
18412   jam();
18413   SectionHandle handle(this, signal);
18414   const TcKeyReq * tcIndxReq =  CAST_CONSTPTR(TcKeyReq,
18415                                               signal->getDataPtr());
18416 
18417   /**
18418    * this is a mockup of execTCINDXREQ...
18419    */
18420   TcIndexOperationPtr indexOpPtr;
18421   if (unlikely(!seizeIndexOperation(transPtr.p, indexOpPtr)))
18422   {
18423     releaseSections(handle);
18424     abortTransFromTrigger(signal, transPtr, 288);
18425     return;
18426   }
18427 
18428   indexOpPtr.p->indexOpId = indexOpPtr.i;
18429 
18430   // Save original signal
18431   indexOpPtr.p->tcIndxReq = *tcIndxReq;
18432   indexOpPtr.p->connectionIndex = transPtr.i;
18433   transPtr.p->accumulatingIndexOp = indexOpPtr.i;
18434 
18435   /* KeyInfo and AttrInfo already received into sections */
18436   SegmentedSectionPtr keyInfoSection, attrInfoSection;
18437 
18438   /* Store i value for first long section of KeyInfo
18439    * and AttrInfo in Index operation
18440    */
18441   handle.getSection(keyInfoSection, TcKeyReq::KeyInfoSectionNum);
18442   indexOpPtr.p->keyInfoSectionIVal = keyInfoSection.i;
18443 
18444   if (handle.m_cnt == 2)
18445   {
18446     handle.getSection(attrInfoSection, TcKeyReq::AttrInfoSectionNum);
18447     indexOpPtr.p->attrInfoSectionIVal = attrInfoSection.i;
18448   }
18449 
18450   /* Detach sections from the handle
18451    * Success path code, or index operation cleanup is
18452    * now responsible for freeing the sections
18453    */
18454   handle.clear();
18455 
18456   /* All data received, process */
18457   readIndexTable(signal, transPtr.p, indexOpPtr.p,
18458                  transPtr.p->m_special_op_flags);
18459 
18460   if (unlikely(transPtr.p->apiConnectstate == CS_ABORTING))
18461   {
18462     jam();
18463   }
18464   else
18465   {
18466     /**
18467      * readIndexTable() sets senderData to indexOpPtr.i
18468      * and SOF_TRIGGER assumes triggerOperation is stored in senderData
18469      *   so set it correct afterwards...
18470      */
18471     jam();
18472     TcConnectRecordPtr tcPtr;
18473     tcPtr.i = indexOpPtr.p->indexReadTcConnect;
18474     ptrCheckGuard(tcPtr, ctcConnectFilesize, tcConnectRecord);
18475     tcPtr.p->triggeringOperation = opPtr.i;
18476     ndbrequire(hasOp(transPtr, opPtr.i));
18477   }
18478   return;
18479 }
18480 
18481 Uint32
fk_buildKeyInfo(Uint32 & keyIVal,bool & hasNull,LocalDataBuffer<11> & values,TcFKData * fkPtrP,bool parent)18482 Dbtc::fk_buildKeyInfo(Uint32& keyIVal, bool& hasNull,
18483                       LocalDataBuffer<11> & values,
18484                       TcFKData * fkPtrP,
18485                       bool parent)
18486 {
18487   if (ERROR_INSERTED(8104))
18488   {
18489     return ZGET_DATAREC_ERROR;
18490   }
18491 
18492   IndexAttributeList * list = 0;
18493   if (parent == true)
18494   {
18495     jam();
18496     list = &fkPtrP->childTableColumns;
18497   }
18498   else
18499   {
18500     jam();
18501     list = &fkPtrP->parentTableColumns;
18502   }
18503 
18504   AttributeBuffer::DataBufferIterator iter;
18505   bool eof = !values.first(iter);
18506   for (Uint32 i = 0; i < list->sz; i++)
18507   {
18508     Uint32 col = list->id[i];
18509     if (!eof && AttributeHeader(* iter.data).getAttributeId() == col)
18510     {
18511   found:
18512       Uint32 len = AttributeHeader(* iter.data).getDataSize();
18513       if (len == 0)
18514       {
18515         hasNull = true;
18516         return 0;
18517       }
18518       eof = !values.next(iter);
18519       Uint32 err = appendDataToSection(keyIVal, values, iter,
18520                                        len);
18521       if (unlikely(err != 0))
18522         return err;
18523 
18524       eof = iter.isNull();
18525     }
18526     else
18527     {
18528       /**
18529        * Search for column...
18530        */
18531       eof = !values.first(iter);
18532       while (!eof && AttributeHeader(* iter.data).getAttributeId() != col)
18533       {
18534         eof = !values.next(iter,
18535                            1 + AttributeHeader(* iter.data).getDataSize());
18536       }
18537       if (unlikely(eof))
18538       {
18539         return ZMISSING_TRIGGER_DATA;
18540       }
18541       ndbassert(AttributeHeader(* iter.data).getAttributeId() == col);
18542       goto found;
18543     }
18544   }
18545 
18546   return 0;
18547 }
18548 
18549 #define SCAN_FROM_CHILD_PARALLELISM 4
18550 
18551 void
fk_scanFromChildTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcFKData * fkData,Uint32 op,Uint32 attrValuesPtrI)18552 Dbtc::fk_scanFromChildTable(Signal* signal,
18553                             TcFiredTriggerData* firedTriggerData,
18554                             ApiConnectRecordPtr* transPtr,
18555                             TcConnectRecordPtr* opPtr,
18556                             TcFKData* fkData,
18557                             Uint32 op,
18558                             Uint32 attrValuesPtrI)
18559 {
18560   ApiConnectRecord* regApiPtr = transPtr->p;
18561 
18562   SegmentedSectionGuard guard(this, attrValuesPtrI);
18563 
18564   if (unlikely(cfirstfreeScanrec == RNIL))
18565   {
18566     jam();
18567     abortTransFromTrigger(signal, *transPtr, ZNO_SCANREC_ERROR);
18568     return;
18569   }
18570 
18571   if (unlikely(cfirstfreeTcConnect == RNIL))
18572   {
18573     jam();
18574     abortTransFromTrigger(signal, *transPtr, ZNO_FREE_TC_CONNECTION);
18575     return;
18576   }
18577 
18578   seizeApiConnect(signal);
18579   if (unlikely(terrorCode != ZOK))
18580   {
18581     jam();
18582     abortTransFromTrigger(signal, *transPtr, terrorCode);
18583     return;
18584   }
18585 
18586   // seize a TcConnectRecord to keep track of trigger stuff
18587   seizeTcConnect(0);
18588   TcConnectRecordPtr tcPtr = tcConnectptr;
18589 
18590   ApiConnectRecordPtr scanApiConnectPtr = apiConnectptr;
18591   scanApiConnectPtr.p->ndbapiBlockref = reference();
18592   scanApiConnectPtr.p->ndbapiConnect = tcPtr.i;
18593 
18594   tcPtr.p->apiConnect = scanApiConnectPtr.i;
18595   tcPtr.p->triggeringOperation = opPtr->i;
18596   ndbrequire(hasOp(* transPtr, opPtr->i));
18597   tcPtr.p->currentTriggerId = firedTriggerData->triggerId;
18598   tcPtr.p->triggerErrorCode = ZNOT_FOUND;
18599   tcPtr.p->operation = op;
18600   tcPtr.p->indexOp = attrValuesPtrI;     // NOTE! 0x187
18601   tcPtr.p->nextTcFailHash = transPtr->i; // NOTE! 0x188
18602 
18603   {
18604     Ptr<TcDefinedTriggerData> trigPtr;
18605     c_theDefinedTriggers.getPtr(trigPtr, tcPtr.p->currentTriggerId);
18606     trigPtr.p->refCount++;
18607   }
18608 
18609   TableRecordPtr childIndexPtr;
18610   childIndexPtr.i = fkData->childIndexId;
18611   ptrCheckGuard(childIndexPtr, ctabrecFilesize, tableRecord);
18612 
18613   /**
18614    * Construct a index-scan
18615    */
18616   const Uint32 parallelism = SCAN_FROM_CHILD_PARALLELISM;
18617   ScanTabReq * req = CAST_PTR(ScanTabReq, signal->getDataPtrSend());
18618   Uint32 ri = 0;
18619   ScanTabReq::setParallelism(ri, parallelism);
18620   ScanTabReq::setDescendingFlag(ri, 0);
18621   ScanTabReq::setRangeScanFlag(ri, 1);
18622   ScanTabReq::setTupScanFlag(ri, 0);
18623   ScanTabReq::setNoDiskFlag(ri, 1);
18624   if (op == ZREAD)
18625   {
18626     ScanTabReq::setScanBatch(ri, 1);
18627     ScanTabReq::setLockMode(ri, 0);
18628     ScanTabReq::setHoldLockFlag(ri, 0);
18629     ScanTabReq::setReadCommittedFlag(ri, 1);
18630     ScanTabReq::setKeyinfoFlag(ri, 0);
18631   }
18632   else
18633   {
18634     ScanTabReq::setScanBatch(ri, 16);
18635     ScanTabReq::setLockMode(ri, 1);
18636     ScanTabReq::setHoldLockFlag(ri, 1);
18637     ScanTabReq::setReadCommittedFlag(ri, 0);
18638     ScanTabReq::setKeyinfoFlag(ri, 1);
18639   }
18640   ScanTabReq::setDistributionKeyFlag(ri, 0);
18641   ScanTabReq::setViaSPJFlag(ri, 0);
18642   ScanTabReq::setPassAllConfsFlag(ri, 0);
18643   ScanTabReq::set4WordConf(ri, 0);
18644   req->requestInfo = ri;
18645   req->transId1 = regApiPtr->transid[0];
18646   req->transId2 = regApiPtr->transid[1];
18647   req->buddyConPtr = transPtr->i;
18648   req->tableId = childIndexPtr.i;
18649   req->tableSchemaVersion = childIndexPtr.p->currentSchemaVersion;
18650   req->apiConnectPtr = scanApiConnectPtr.i;
18651   req->storedProcId = 0xFFFF;
18652   req->batch_byte_size = 0;
18653   req->first_batch_size = 0;
18654 
18655   SegmentedSectionPtr ptr[3];
18656   ptr[0].i = ptr[1].i = ptr[2].i = RNIL;
18657 
18658   Uint32 optrs[parallelism];
18659   for (Uint32 i = 0; i<parallelism; i++)
18660     optrs[i] = tcPtr.i;
18661 
18662   Uint32 program[] = {
18663     0, 1, 0, 0, 0, Interpreter::ExitLastOK()
18664   };
18665 
18666   if (op != ZREAD)
18667   {
18668     program[5] = Interpreter::ExitOK();
18669   }
18670 
18671   Uint32 errorCode = ZGET_DATAREC_ERROR;
18672   if (ERROR_INSERTED(8102))
18673   {
18674     goto oom;
18675   }
18676   if (unlikely( !import(ptr[0], optrs, NDB_ARRAY_SIZE(optrs))))
18677   {
18678     jam();
18679     goto oom;
18680   }
18681 
18682   if (unlikely( !import(ptr[1], program, NDB_ARRAY_SIZE(program))))
18683   {
18684     jam();
18685     goto oom;
18686   }
18687 
18688   {
18689     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
18690     LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
18691     if (unlikely((errorCode=fk_buildBounds(ptr[2], beforeValues, fkData)) != 0))
18692     {
18693       jam();
18694       goto oom;
18695     }
18696   }
18697 
18698   guard.clear(); // now sections will be handled...
18699 
18700   signal->header.m_noOfSections= 3;
18701   signal->m_sectionPtrI[0] = ptr[0].i;
18702   signal->m_sectionPtrI[1] = ptr[1].i;
18703   signal->m_sectionPtrI[2] = ptr[2].i;
18704   execSCAN_TABREQ(signal);
18705 
18706   transPtr->p->lqhkeyreqrec++; // Make sure that execution is stalled
18707   D("trans: cascading scans++ " << transPtr->p->cascading_scans_count);
18708   ndbrequire(transPtr->p->cascading_scans_count < MaxCascadingScansPerTransaction);
18709   transPtr->p->cascading_scans_count++;
18710   return;
18711 
18712 oom:
18713   for (Uint32 i = 0; i < 3; i++)
18714   {
18715     if (ptr[i].i != RNIL)
18716     {
18717       release(ptr[i]);
18718     }
18719   }
18720   tcConnectptr = tcPtr;
18721   releaseTcCon();
18722   releaseApiCon(signal, scanApiConnectPtr.i);
18723   abortTransFromTrigger(signal, *transPtr, errorCode);
18724   return;
18725 }
18726 
18727 void
execKEYINFO20(Signal * signal)18728 Dbtc::execKEYINFO20(Signal* signal)
18729 {
18730   jamEntry();
18731   const KeyInfo20 * conf = CAST_CONSTPTR(KeyInfo20, signal->getDataPtr());
18732 
18733   Uint32 transId[] = {
18734     conf->transId1,
18735     conf->transId2
18736   };
18737 
18738   Uint32 keyLen = conf->keyLen;
18739   Uint32 scanInfo = conf->scanInfo_Node;
18740 
18741   TcConnectRecordPtr tcPtr;
18742   tcPtr.i = conf->clientOpPtr;
18743   ptrCheckGuard(tcPtr, ctcConnectFilesize, tcConnectRecord);
18744 
18745   ApiConnectRecordPtr scanApiConnectPtr;
18746   scanApiConnectPtr.i = tcPtr.p->apiConnect;
18747   ptrCheckGuard(scanApiConnectPtr, capiConnectFilesize, apiConnectRecord);
18748 
18749   if (! (transId[0] == scanApiConnectPtr.p->transid[0] &&
18750          transId[1] == scanApiConnectPtr.p->transid[1]))
18751   {
18752     jam();
18753 
18754     /**
18755      * incorrect transid...no known scenario where this can happen
18756      */
18757     ndbassert(false);
18758     return;
18759   }
18760 
18761   /**
18762    * Validate base transaction
18763    */
18764   Uint32 orgTransPtrI = tcPtr.p->nextTcFailHash; // NOTE: 0x188
18765   ApiConnectRecordPtr transPtr;
18766   transPtr.i = orgTransPtrI;
18767   ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
18768 
18769   if (unlikely(! (transId[0] == transPtr.p->transid[0] &&
18770                   transId[1] == transPtr.p->transid[1] &&
18771                   transPtr.p->apiConnectstate != CS_ABORTING)))
18772   {
18773     jam();
18774 
18775     /**
18776      * The "base" transaction has been aborted...
18777      *   terminate scan directly
18778      */
18779     fk_scanFromChildTable_abort(signal, tcPtr);
18780     return;
18781   }
18782 
18783   Ptr<TcDefinedTriggerData> trigPtr;
18784   c_theDefinedTriggers.getPtr(trigPtr, tcPtr.p->currentTriggerId);
18785 
18786   /* Extract KeyData */
18787   Uint32 keyInfoPtrI = RNIL;
18788   if (signal->header.m_noOfSections == 0)
18789   {
18790     jam();
18791     Ptr<SectionSegment> keyInfo;
18792     if (unlikely(! import(keyInfo, conf->keyData, keyLen)))
18793     {
18794       abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
18795       return;
18796     }
18797     keyInfoPtrI = keyInfo.i;
18798   }
18799   else
18800   {
18801     jam();
18802     ndbrequire(signal->header.m_noOfSections == 1); // key is already here...
18803     keyInfoPtrI = signal->m_sectionPtrI[0];
18804     signal->header.m_noOfSections = 0;
18805   }
18806 
18807   Ptr<TcFKData> fkPtr;
18808   // TODO make it a pool.getPtr() instead
18809   // by also adding fk_ptr_i to definedTriggerData
18810   ndbrequire(c_fk_hash.find(fkPtr, trigPtr.p->fkId));
18811 
18812   /**
18813    * Construct a DELETE/UPDATE
18814    * NOTE: on table...not index
18815    */
18816   Uint32 op = tcPtr.p->operation;
18817   TcKeyReq * const tcKeyReq =  CAST_PTR(TcKeyReq, signal->getDataPtrSend());
18818   TableRecordPtr childTabPtr;
18819 
18820   childTabPtr.i = fkPtr.p->childTableId;
18821   ptrCheckGuard(childTabPtr, ctabrecFilesize, tableRecord);
18822   tcKeyReq->apiConnectPtr = orgTransPtrI;
18823   tcKeyReq->senderData = tcPtr.p->triggeringOperation;
18824 
18825   tcKeyReq->attrLen = 0;
18826   tcKeyReq->tableId = childTabPtr.i;
18827   tcKeyReq->tableSchemaVersion = childTabPtr.p->currentSchemaVersion;
18828   tcKeyReq->transId1 = transPtr.p->transid[0];
18829   tcKeyReq->transId2 = transPtr.p->transid[1];
18830   Uint32 tcKeyRequestInfo = 0;
18831   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
18832   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
18833   TcKeyReq::setOperationType(tcKeyRequestInfo, op);
18834   const bool use_scan_takeover = false;
18835   if (use_scan_takeover)
18836   {
18837     TcKeyReq::setScanIndFlag(tcKeyRequestInfo, 1);
18838   }
18839   tcKeyReq->requestInfo = tcKeyRequestInfo;
18840   if (use_scan_takeover)
18841   {
18842     tcKeyReq->scanInfo = (scanInfo << 1) + 1; // TODO cleanup
18843   }
18844   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyInfoPtrI;
18845   signal->header.m_noOfSections= 1;
18846 
18847   if (tcPtr.p->indexOp != RNIL)
18848   {
18849     /**
18850      * attrValues save in indexOp
18851      */
18852     Uint32 tmp = RNIL;
18853     if (unlikely( !dupSection(tmp, tcPtr.p->indexOp)))
18854     {
18855       jam();
18856       releaseSection(keyInfoPtrI);
18857       signal->header.m_noOfSections = 0;
18858       abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
18859       return;
18860     }
18861     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = tmp;
18862     signal->header.m_noOfSections= 2;
18863   }
18864 
18865   TcConnectRecordPtr opPtr; // triggering operation
18866   opPtr.i = tcPtr.p->triggeringOperation;
18867   ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
18868 
18869   /**
18870    * Fix savepoint id -
18871    *   fix so that op has same savepoint id as triggering operation
18872    */
18873   Uint32 currSavePointId = transPtr.p->currSavePointId;
18874   transPtr.p->currSavePointId = opPtr.p->savePointId;
18875   transPtr.p->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
18876   /* Pass trigger Id via ApiConnectRecord (nasty) */
18877   ndbrequire(transPtr.p->immediateTriggerId == RNIL);
18878   transPtr.p->immediateTriggerId = tcPtr.p->currentTriggerId;
18879   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength +
18880                  (use_scan_takeover ? 1 : 0));
18881   jamEntry();
18882 
18883   /*
18884    * Restore ApiConnectRecord state
18885    */
18886   transPtr.p->immediateTriggerId = RNIL;
18887   transPtr.p->currSavePointId = currSavePointId;
18888 
18889   /**
18890    * Update counter of how many trigger executed...
18891    */
18892   opPtr.p->triggerExecutionCount++;
18893  }
18894 
18895 void
execSCAN_TABCONF(Signal * signal)18896 Dbtc::execSCAN_TABCONF(Signal* signal)
18897 {
18898   jamEntry();
18899   const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, signal->getDataPtr());
18900 
18901   Uint32 transId[] = {
18902     conf->transId1,
18903     conf->transId2
18904   };
18905 
18906   TcConnectRecordPtr tcPtr;
18907   tcPtr.i = conf->apiConnectPtr;
18908   ptrCheckGuard(tcPtr, ctcConnectFilesize, tcConnectRecord);
18909 
18910   ApiConnectRecordPtr scanApiConnectPtr;
18911   scanApiConnectPtr.i = tcPtr.p->apiConnect;
18912   ptrCheckGuard(scanApiConnectPtr, capiConnectFilesize, apiConnectRecord);
18913 
18914   if (! (transId[0] == scanApiConnectPtr.p->transid[0] &&
18915          transId[1] == scanApiConnectPtr.p->transid[1]))
18916   {
18917     jam();
18918 
18919     /**
18920      * incorrect transid...no known scenario where this can happen
18921      */
18922     ndbassert(false);
18923     return;
18924   }
18925 
18926   /**
18927    * Validate base transaction
18928    */
18929   Uint32 orgTransPtrI = tcPtr.p->nextTcFailHash; // NOTE: 0x188
18930   ApiConnectRecordPtr orgApiConnectPtr;
18931   orgApiConnectPtr.i = orgTransPtrI;
18932   ptrCheckGuard(orgApiConnectPtr, capiConnectFilesize, apiConnectRecord);
18933 
18934   if (unlikely(! (transId[0] == orgApiConnectPtr.p->transid[0] &&
18935                   transId[1] == orgApiConnectPtr.p->transid[1] &&
18936                   orgApiConnectPtr.p->apiConnectstate != CS_ABORTING)))
18937   {
18938     jam();
18939 
18940     /**
18941      * The "base" transaction has been aborted...
18942      *   terminate scan directly
18943      */
18944     if (conf->requestInfo & ScanTabConf::EndOfData)
18945     {
18946       jam();
18947       fk_scanFromChildTable_done(signal, tcPtr);
18948     }
18949     else
18950     {
18951       jam();
18952       fk_scanFromChildTable_abort(signal, tcPtr);
18953     }
18954     return;
18955   }
18956 
18957   Ptr<TcDefinedTriggerData> trigPtr;
18958   c_theDefinedTriggers.getPtr(trigPtr, tcPtr.p->currentTriggerId);
18959 
18960   Ptr<TcFKData> fkPtr;
18961   // TODO make it a pool.getPtr() instead
18962   // by also adding fk_ptr_i to definedTriggerData
18963   ndbrequire(c_fk_hash.find(fkPtr, trigPtr.p->fkId));
18964 
18965   Uint32 rows = 0;
18966   const Uint32 ops = (conf->requestInfo >> OPERATIONS_SHIFT) & OPERATIONS_MASK;
18967   for (Uint32 i = 0; i<ops; i++)
18968   {
18969     jam();
18970     ScanTabConf::OpData * op = (ScanTabConf::OpData*)
18971       (signal->getDataPtr() + ScanTabConf::SignalLength + 3 * i);
18972     rows += ScanTabConf::getRows(op->rows);
18973   }
18974 
18975   if (rows && tcPtr.p->operation != ZREAD)
18976   {
18977     jam();
18978     TcConnectRecordPtr opPtr; // triggering operation
18979     opPtr.i = tcPtr.p->triggeringOperation;
18980     ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
18981     TcConnectRecord * triggeringOp = opPtr.p;
18982     if (triggeringOp->operation == ZDELETE &&
18983         (fkPtr.p->bits & (CreateFKImplReq::FK_DELETE_CASCADE | CreateFKImplReq::FK_DELETE_SET_NULL)))
18984     {
18985       /**
18986        * don't abort scan
18987        */
18988       jam();
18989       rows = 0;
18990     }
18991     else if ((triggeringOp->operation == ZUPDATE || triggeringOp->operation == ZWRITE) &&
18992              (fkPtr.p->bits & (CreateFKImplReq::FK_UPDATE_CASCADE | CreateFKImplReq::FK_UPDATE_SET_NULL)))
18993     {
18994       /**
18995        * don't abort scan
18996        */
18997       jam();
18998       rows = 0;
18999     }
19000   }
19001 
19002   if (rows)
19003   {
19004     jam();
19005     tcPtr.p->triggerErrorCode = ZFK_CHILD_ROW_EXISTS;
19006   }
19007 
19008   if (conf->requestInfo & ScanTabConf::EndOfData)
19009   {
19010     jam();
19011     fk_scanFromChildTable_done(signal, tcPtr);
19012   }
19013   else if (rows)
19014   {
19015     jam();
19016     /**
19017      * Abort scan...we already know that ZFK_CHILD_ROW_EXISTS
19018      */
19019     fk_scanFromChildTable_abort(signal, tcPtr);
19020   }
19021   else
19022   {
19023     jam();
19024     /**
19025      * Continue scanning...
19026      */
19027     const Uint32 parallelism = SCAN_FROM_CHILD_PARALLELISM;
19028     Uint32 cnt = 0;
19029     Uint32 operations[parallelism];
19030     for (Uint32 i = 0; i<ops; i++)
19031     {
19032       jam();
19033       ScanTabConf::OpData * op = (ScanTabConf::OpData*)
19034         (signal->getDataPtr() + ScanTabConf::SignalLength + 3 * i);
19035       if (op->tcPtrI != RNIL)
19036       {
19037         ndbrequire(cnt < NDB_ARRAY_SIZE(operations));
19038         operations[cnt++] = op->tcPtrI;
19039       }
19040     }
19041     if (cnt)
19042     {
19043       jam();
19044       ScanNextReq* req = CAST_PTR(ScanNextReq, signal->getDataPtrSend());
19045       req->apiConnectPtr = scanApiConnectPtr.i;
19046       req->stopScan = 0;
19047       req->transId1 = scanApiConnectPtr.p->transid[0];
19048       req->transId2 = scanApiConnectPtr.p->transid[1];
19049       memcpy(signal->getDataPtrSend() + ScanNextReq::SignalLength,
19050              operations, 4 * cnt);
19051       sendSignal(reference(), GSN_SCAN_NEXTREQ, signal,
19052                  ScanNextReq::SignalLength + cnt, JBB);
19053     }
19054   }
19055 }
19056 
19057 void
fk_scanFromChildTable_abort(Signal * signal,TcConnectRecordPtr tcPtr)19058 Dbtc::fk_scanFromChildTable_abort(Signal* signal, TcConnectRecordPtr tcPtr)
19059 {
19060   ApiConnectRecordPtr scanApiConnectPtr;
19061   scanApiConnectPtr.i = tcPtr.p->apiConnect;
19062   ptrCheckGuard(scanApiConnectPtr, capiConnectFilesize, apiConnectRecord);
19063 
19064   /**
19065    * Check that the scan has not already completed
19066    * - so we can abort aggresively
19067    */
19068   if (scanApiConnectPtr.p->apiConnectstate != CS_START_SCAN)
19069   {
19070     jam();
19071     /**
19072      * Scan has already completed...we just haven't received the EOD yet
19073      *
19074      *   wait for it...
19075      */
19076     return;
19077   }
19078 
19079   ScanNextReq* req = CAST_PTR(ScanNextReq, signal->getDataPtrSend());
19080   req->apiConnectPtr = scanApiConnectPtr.i;
19081   req->stopScan = 1;
19082   req->transId1 = scanApiConnectPtr.p->transid[0];
19083   req->transId2 = scanApiConnectPtr.p->transid[1];
19084 
19085   /**
19086    * Here we need to use EXECUTE_DIRECT
19087    *   or this signal will race with state-changes in scan-record
19088    *
19089    * NOTE: A better alternative would be to fix Dbtc/protocol to handle
19090    *       these races...
19091    */
19092   EXECUTE_DIRECT(DBTC, GSN_SCAN_NEXTREQ, signal, ScanNextReq::SignalLength);
19093 }
19094 
19095 void
fk_scanFromChildTable_done(Signal * signal,TcConnectRecordPtr tcPtr)19096 Dbtc::fk_scanFromChildTable_done(Signal* signal, TcConnectRecordPtr tcPtr)
19097 {
19098   ApiConnectRecordPtr scanApiConnectPtr;
19099   scanApiConnectPtr.i = tcPtr.p->apiConnect;
19100   ptrCheckGuard(scanApiConnectPtr, capiConnectFilesize, apiConnectRecord);
19101 
19102   ndbrequire(scanApiConnectPtr.p->ndbapiConnect == tcPtr.i);
19103 
19104   /**
19105    * save things needed to finish this trigger op
19106    */
19107   Uint32 transId[] = {
19108     scanApiConnectPtr.p->transid[0],
19109     scanApiConnectPtr.p->transid[1]
19110   };
19111 
19112   Uint32 errCode = tcPtr.p->triggerErrorCode;
19113   Uint32 triggerId = tcPtr.p->currentTriggerId;
19114   Uint32 orgTransPtrI = tcPtr.p->nextTcFailHash; // NOTE: 0x188
19115 
19116   TcConnectRecordPtr opPtr; // triggering operation
19117   opPtr.i = tcPtr.p->triggeringOperation;
19118 
19119   /**
19120    * release extra allocated resources
19121    */
19122   if (tcPtr.p->indexOp != RNIL) // NOTE: 0x187
19123   {
19124     releaseSection(tcPtr.p->indexOp);
19125   }
19126   tcConnectptr = tcPtr;
19127   releaseTcCon();
19128   releaseApiCon(signal, scanApiConnectPtr.i);
19129 
19130   ApiConnectRecordPtr orgApiConnectPtr;
19131   orgApiConnectPtr.i = orgTransPtrI;
19132   ptrCheckGuard(orgApiConnectPtr, capiConnectFilesize, apiConnectRecord);
19133 
19134   if (! (transId[0] == orgApiConnectPtr.p->transid[0] &&
19135          transId[1] == orgApiConnectPtr.p->transid[1] &&
19136          orgApiConnectPtr.p->apiConnectstate != CS_ABORTING))
19137   {
19138     jam();
19139     /**
19140      * The "base" transaction has been aborted...
19141      *   we need just throw away our scan...
19142      *   any DML caused by it...is anyway put onto "real" transaction
19143      */
19144     return;
19145   }
19146 
19147   ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
19148   if (opPtr.p->apiConnect != orgApiConnectPtr.i)
19149   {
19150     jam();
19151     ndbassert(false);
19152     /**
19153      * this should not happen :-)
19154      *
19155      * triggering operation has been moved to different transaction...
19156      * this should not happen since then the original trans should be aborted
19157      *   (or aborted and restarted) this is checked above...
19158      *
19159      */
19160     return;
19161   }
19162 
19163   ndbrequire(orgApiConnectPtr.p->lqhkeyreqrec > 0);
19164   ndbrequire(orgApiConnectPtr.p->lqhkeyreqrec > orgApiConnectPtr.p->lqhkeyconfrec);
19165   orgApiConnectPtr.p->lqhkeyreqrec--;
19166 
19167   D("trans: cascading scans-- " << orgApiConnectPtr.p->cascading_scans_count);
19168   ndbrequire(orgApiConnectPtr.p->cascading_scans_count > 0);
19169   orgApiConnectPtr.p->cascading_scans_count--;
19170 
19171   trigger_op_finished(signal, orgApiConnectPtr, triggerId, opPtr.p, errCode);
19172 }
19173 
19174 void
execSCAN_TABREF(Signal * signal)19175 Dbtc::execSCAN_TABREF(Signal* signal)
19176 {
19177   jamEntry();
19178 
19179   const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, signal->getDataPtr());
19180 
19181   Uint32 transId[] = {
19182     ref->transId1,
19183     ref->transId2
19184   };
19185 
19186   TcConnectRecordPtr tcPtr;
19187   tcPtr.i = ref->apiConnectPtr;
19188   ptrCheckGuard(tcPtr, ctcConnectFilesize, tcConnectRecord);
19189 
19190   ApiConnectRecordPtr scanApiConnectPtr;
19191   scanApiConnectPtr.i = tcPtr.p->apiConnect;
19192   ptrCheckGuard(scanApiConnectPtr, capiConnectFilesize, apiConnectRecord);
19193 
19194   if (! (transId[0] == scanApiConnectPtr.p->transid[0] &&
19195          transId[1] == scanApiConnectPtr.p->transid[1]))
19196   {
19197     jam();
19198 
19199     /**
19200      * incorrect transid...no known scenario where this can happen
19201      */
19202     ndbassert(false);
19203     return;
19204   }
19205 
19206   tcPtr.p->triggerErrorCode = ref->errorCode;
19207   if (ref->closeNeeded)
19208   {
19209     jam();
19210     fk_scanFromChildTable_abort(signal, tcPtr);
19211   }
19212   else
19213   {
19214     jam();
19215     fk_scanFromChildTable_done(signal, tcPtr);
19216   }
19217 }
19218 
19219 Uint32
fk_buildBounds(SegmentedSectionPtr & dst,LocalDataBuffer<11> & src,TcFKData * fkData)19220 Dbtc::fk_buildBounds(SegmentedSectionPtr & dst,
19221                      LocalDataBuffer<11> & src,
19222                      TcFKData* fkData)
19223 {
19224   dst.i = RNIL;
19225   Uint32 dstPtrI = RNIL;
19226 
19227   IndexAttributeList * list = &fkData->parentTableColumns;
19228 
19229   AttributeBuffer::DataBufferIterator iter;
19230   bool eof = !src.first(iter);
19231   for (Uint32 i = 0; i < list->sz; i++)
19232   {
19233     Uint32 col = list->id[i];
19234     if (!eof && AttributeHeader(* iter.data).getAttributeId() == col)
19235     {
19236   found:
19237       Uint32 byteSize = AttributeHeader(* iter.data).getByteSize();
19238       Uint32 len32 = (byteSize + 3) / 4;
19239       if (len32 == 0)
19240       {
19241         // ?? TODO what to do
19242       }
19243       eof = !src.next(iter);
19244 
19245       Uint32 data[2];
19246       data[0] = TuxBoundInfo::BoundEQ;
19247       AttributeHeader::init(data+1, i, byteSize);
19248       if (unlikely(!appendToSection(dstPtrI, data, NDB_ARRAY_SIZE(data))))
19249       {
19250         dst.i = dstPtrI;
19251         return ZGET_DATAREC_ERROR;
19252       }
19253 
19254       Uint32 err = appendDataToSection(dstPtrI, src, iter,
19255                                        len32);
19256       if (unlikely(err != 0))
19257       {
19258         dst.i = dstPtrI;
19259         return err;
19260       }
19261 
19262       eof = iter.isNull();
19263     }
19264     else
19265     {
19266       /**
19267        * Search for column...
19268        */
19269       eof = !src.first(iter);
19270       while (!eof && AttributeHeader(* iter.data).getAttributeId() != col)
19271       {
19272         eof = !src.next(iter,
19273                            1 + AttributeHeader(* iter.data).getDataSize());
19274       }
19275       if (unlikely(eof))
19276       {
19277         dst.i = dstPtrI;
19278         return ZMISSING_TRIGGER_DATA;
19279       }
19280       ndbassert(AttributeHeader(* iter.data).getAttributeId() == col);
19281       goto found;
19282     }
19283   }
19284 
19285   dst.i = dstPtrI;
19286   return 0;
19287 }
19288 
19289 void
executeFKChildTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)19290 Dbtc::executeFKChildTrigger(Signal* signal,
19291                             TcDefinedTriggerData* definedTriggerData,
19292                             TcFiredTriggerData* firedTriggerData,
19293                             ApiConnectRecordPtr* transPtr,
19294                             TcConnectRecordPtr* opPtr)
19295 {
19296   Ptr<TcFKData> fkPtr;
19297   // TODO make it a pool.getPtr() instead
19298   // by also adding fk_ptr_i to definedTriggerData
19299   ndbrequire(c_fk_hash.find(fkPtr, definedTriggerData->fkId));
19300 
19301   switch (firedTriggerData->triggerEvent) {
19302   case(TriggerEvent::TE_INSERT):
19303     jam();
19304     /**
19305      * Check that after values exists in parent table
19306      */
19307     fk_readFromParentTable(signal, firedTriggerData, transPtr, opPtr, fkPtr.p);
19308     break;
19309   case(TriggerEvent::TE_UPDATE):
19310     jam();
19311     /**
19312      * Check that after values exists in parent table
19313      */
19314     fk_readFromParentTable(signal, firedTriggerData, transPtr, opPtr, fkPtr.p);
19315     break;
19316   default:
19317     ndbrequire(false);
19318   }
19319 }
19320 
19321 void
fk_readFromParentTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcFKData * fkData)19322 Dbtc::fk_readFromParentTable(Signal* signal,
19323                              TcFiredTriggerData* firedTriggerData,
19324                              ApiConnectRecordPtr* transPtr,
19325                              TcConnectRecordPtr* opPtr,
19326                              TcFKData* fkData)
19327 {
19328   ApiConnectRecord* regApiPtr = transPtr->p;
19329   TcConnectRecord* opRecord = opPtr->p;
19330   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
19331   Uint32 tcKeyRequestInfo = 0;
19332   TableRecordPtr parentTabPtr;
19333 
19334   parentTabPtr.i = fkData->parentTableId;
19335   ptrCheckGuard(parentTabPtr, ctabrecFilesize, tableRecord);
19336   tcKeyReq->apiConnectPtr = transPtr->i;
19337   tcKeyReq->senderData = opPtr->i;
19338 
19339   // Calculate key length and renumber attribute id:s
19340   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
19341   LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
19342 
19343   if (afterValues.getSize() == 0)
19344   {
19345     jam();
19346     ndbrequire(tc_testbit(regApiPtr->m_flags,
19347                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
19348     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
19349     return;
19350   }
19351 
19352   Uint32 keyIVal= RNIL;
19353   bool hasNull= false;
19354   Uint32 err = fk_buildKeyInfo(keyIVal, hasNull, afterValues, fkData, true);
19355   SegmentedSectionGuard guard(this, keyIVal);
19356   if (unlikely(err != 0))
19357   {
19358     abortTransFromTrigger(signal, *transPtr, err);
19359     return;
19360   }
19361 
19362   /* If there's Nulls in the values that become the index table's
19363    * PK then we skip this delete
19364    */
19365   if (hasNull)
19366   {
19367     jam();
19368     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
19369     return;
19370   }
19371 
19372   Uint16 flags = TcConnectRecord::SOF_TRIGGER;
19373   if (((fkData->bits & CreateFKImplReq::FK_ACTION_MASK) == 0) ||
19374       transPtr->p->isExecutingDeferredTriggers())
19375   {
19376     jam();
19377     /**
19378      * We don't need any locks here
19379      */
19380     flags |= TcConnectRecord::SOF_FK_READ_COMMITTED;
19381     TcKeyReq::setSimpleFlag(tcKeyRequestInfo, 1);
19382   }
19383 
19384   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
19385   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
19386   tcKeyReq->attrLen = 0;
19387   tcKeyReq->tableId = parentTabPtr.i;
19388   TcKeyReq::setOperationType(tcKeyRequestInfo, ZREAD);
19389   tcKeyReq->tableSchemaVersion = parentTabPtr.p->currentSchemaVersion;
19390   tcKeyReq->transId1 = regApiPtr->transid[0];
19391   tcKeyReq->transId2 = regApiPtr->transid[1];
19392   tcKeyReq->requestInfo = tcKeyRequestInfo;
19393 
19394   guard.clear(); // now sections will be handled...
19395 
19396   /* Attach KeyInfo section to signal */
19397   ndbrequire(signal->header.m_noOfSections == 0);
19398   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
19399   signal->header.m_noOfSections = 1;
19400 
19401   /**
19402    * Don't fix savepoint id -
19403    *   read latest copy??
19404    */
19405   regApiPtr->m_special_op_flags = flags;
19406   /* Pass trigger Id via ApiConnectRecord (nasty) */
19407   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
19408   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
19409   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
19410   jamEntry();
19411 
19412   /*
19413    * Restore ApiConnectRecord state
19414    */
19415   regApiPtr->immediateTriggerId = RNIL;
19416 }
19417 
releaseFiredTriggerData(DLFifoList<TcFiredTriggerData> * triggers)19418 void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
19419 {
19420   FiredTriggerPtr trigPtr;
19421 
19422   triggers->first(trigPtr);
19423   while (trigPtr.i != RNIL) {
19424     jam();
19425     // Release trigger records
19426 
19427     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
19428     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
19429     tmp1.release();
19430     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
19431     tmp2.release();
19432     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
19433     tmp3.release();
19434 
19435     triggers->next(trigPtr);
19436   }
19437   while (triggers->releaseFirst());
19438 }
19439 
releaseFiredTriggerData(LocalDLFifoList<TcFiredTriggerData> * triggers)19440 void Dbtc::releaseFiredTriggerData(LocalDLFifoList<TcFiredTriggerData>*
19441                                    triggers)
19442 {
19443   FiredTriggerPtr trigPtr;
19444 
19445   triggers->first(trigPtr);
19446   while (trigPtr.i != RNIL)
19447   {
19448     jam();
19449     // Release trigger records
19450 
19451     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
19452     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
19453     tmp1.release();
19454     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
19455     tmp2.release();
19456     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
19457     tmp3.release();
19458     FiredTriggerPtr save = trigPtr;
19459     triggers->next(trigPtr);
19460     triggers->release(save);
19461   }
19462 }
19463 
19464 /**
19465  * abortTransFromTrigger
19466  *
19467  * This method is called when there is a problem with trigger
19468  * handling and the transaction should be aborted with the
19469  * given error code
19470  */
abortTransFromTrigger(Signal * signal,const ApiConnectRecordPtr & transPtr,Uint32 error)19471 void Dbtc::abortTransFromTrigger(Signal* signal,
19472                                  const ApiConnectRecordPtr& transPtr,
19473                                  Uint32 error)
19474 {
19475   jam();
19476   terrorCode = error;
19477 
19478   apiConnectptr = transPtr;
19479 
19480   abortErrorLab(signal);
19481 }
19482 
19483 Uint32
appendDataToSection(Uint32 & sectionIVal,DataBuffer<11> & src,DataBuffer<11>::DataBufferIterator & iter,Uint32 len)19484 Dbtc::appendDataToSection(Uint32& sectionIVal,
19485                           DataBuffer<11> & src,
19486                           DataBuffer<11>::DataBufferIterator & iter,
19487                           Uint32 len)
19488 {
19489   const Uint32 segSize = src.getSegmentSize(); // 11
19490   while (len)
19491   {
19492     /* Copy as many contiguous words as possible */
19493     Uint32 contigLeft = segSize - iter.ind;
19494     ndbassert(contigLeft);
19495     Uint32 contigValid = MIN(len, contigLeft);
19496 
19497     if (unlikely(!appendToSection(sectionIVal,
19498                                   iter.data,
19499                                   contigValid)))
19500     {
19501       goto full;
19502     }
19503     len -= contigValid;
19504     bool hasMore = src.next(iter, contigValid);
19505 
19506     if (len == 0)
19507       break;
19508 
19509     if (unlikely(! hasMore))
19510     {
19511       ndbassert(false); // this is internal error...
19512       goto fail;
19513     }
19514   }
19515   return 0;
19516 
19517 full:
19518   jam();
19519   releaseSection(sectionIVal);
19520   sectionIVal= RNIL;
19521   return ZGET_DATAREC_ERROR;
19522 
19523 fail:
19524   jam();
19525   releaseSection(sectionIVal);
19526   sectionIVal= RNIL;
19527   return ZMISSING_TRIGGER_DATA;
19528 }
19529 
19530 /**
19531  * appendAttrDataToSection
19532  *
19533  * Copy data in AttrInfo form from the given databuffer
19534  * to the given section IVal (can be RNIL).
19535  * If attribute headers are to be copied they will be
19536  * renumbered consecutively, starting with the given
19537  * attrId.
19538  * hasNull is updated to indicate whether any Nulls
19539  * were encountered.
19540  */
appendAttrDataToSection(Uint32 & sectionIVal,DataBuffer<11> & values,bool withHeaders,Uint32 & attrId,bool & hasNull)19541 bool Dbtc::appendAttrDataToSection(Uint32& sectionIVal,
19542                                    DataBuffer<11>& values,
19543                                    bool withHeaders,
19544                                    Uint32& attrId,
19545                                    bool& hasNull)
19546 {
19547   AttributeBuffer::DataBufferIterator iter;
19548   bool moreData= values.first(iter);
19549   hasNull= false;
19550   const Uint32 segSize= values.getSegmentSize(); // 11
19551 
19552   while (moreData)
19553   {
19554     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
19555     Uint32 dataSize= attrHeader->getDataSize();
19556     hasNull |= (dataSize == 0);
19557 
19558     if (withHeaders)
19559     {
19560       AttributeHeader ah(*iter.data);
19561       ah.setAttributeId(attrId); // Renumber AttrIds
19562       if (unlikely(!appendToSection(sectionIVal,
19563                                     &ah.m_value,
19564                                     1)))
19565       {
19566         releaseSection(sectionIVal);
19567         sectionIVal= RNIL;
19568         return false;
19569       }
19570     }
19571 
19572     moreData= values.next(iter, 1);
19573 
19574     while (dataSize)
19575     {
19576       ndbrequire(moreData);
19577       /* Copy as many contiguous words as possible */
19578       Uint32 contigLeft= segSize - iter.ind;
19579       ndbassert(contigLeft);
19580       Uint32 contigValid= MIN(dataSize, contigLeft);
19581 
19582       if (unlikely(!appendToSection(sectionIVal,
19583                                     iter.data,
19584                                     contigValid)))
19585       {
19586         releaseSection(sectionIVal);
19587         sectionIVal= RNIL;
19588         return false;
19589       }
19590       moreData= values.next(iter, contigValid);
19591       dataSize-= contigValid;
19592     }
19593     attrId++;
19594   }
19595 
19596   return true;
19597 }
19598 
insertIntoIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)19599 void Dbtc::insertIntoIndexTable(Signal* signal,
19600                                 TcFiredTriggerData* firedTriggerData,
19601                                 ApiConnectRecordPtr* transPtr,
19602                                 TcConnectRecordPtr* opPtr,
19603                                 TcIndexData* indexData)
19604 {
19605   ApiConnectRecord* regApiPtr = transPtr->p;
19606   TcConnectRecord* opRecord = opPtr->p;
19607   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
19608   Uint32 tcKeyRequestInfo = 0;
19609   TableRecordPtr indexTabPtr;
19610 
19611   jam();
19612 
19613   indexTabPtr.i = indexData->indexId;
19614   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
19615   tcKeyReq->apiConnectPtr = transPtr->i;
19616   tcKeyReq->senderData = opPtr->i;
19617 
19618   /* Key for insert to unique index table is the afterValues from the
19619    * base table operation (from update or insert on base).
19620    * Data for insert to unique index table is the afterValues from the
19621    * base table operation plus the fragment id and packed keyValues from
19622    * the base table operation
19623    */
19624   // Calculate key length and renumber attribute id:s
19625   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
19626   LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
19627   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
19628 
19629   if (afterValues.getSize() == 0)
19630   {
19631     jam();
19632     ndbrequire(tc_testbit(regApiPtr->m_flags,
19633                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
19634     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
19635     return;
19636   }
19637 
19638   Uint32 keyIVal= RNIL;
19639   Uint32 attrIVal= RNIL;
19640   bool appendOk= false;
19641   do
19642   {
19643     Uint32 attrId= 0;
19644     bool hasNull= false;
19645 
19646     /* Build Insert KeyInfo section from aftervalues */
19647     if (unlikely(! appendAttrDataToSection(keyIVal,
19648                                            afterValues,
19649                                            false, // No AttributeHeaders
19650                                            attrId,
19651                                            hasNull)))
19652     {
19653       jam();
19654       break;
19655     }
19656 
19657     if(ERROR_INSERTED(8086))
19658     {
19659       /* Simulate SS exhaustion */
19660       break;
19661     }
19662 
19663     /* If there's Nulls in the values that become the index table's
19664      * PK then we skip this insert
19665      */
19666     if (hasNull)
19667     {
19668       jam();
19669       releaseSection(keyIVal);
19670       trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
19671       return;
19672     }
19673 
19674     /* Build Insert AttrInfo section from aftervalues,
19675      * fragment id + keyvalues
19676      */
19677     AttributeHeader ah(attrId, 0); // Length tbd.
19678     attrId= 0;
19679     if (unlikely((! appendAttrDataToSection(attrIVal,
19680                                             afterValues,
19681                                             true, // Include AttributeHeaders,
19682                                             attrId,
19683                                             hasNull)) ||
19684                  (! appendToSection(attrIVal,
19685                                     &ah.m_value,
19686                                     1))))
19687     {
19688       jam();
19689       break;
19690     }
19691 
19692     AttributeHeader* pkHeader= (AttributeHeader*) getLastWordPtr(attrIVal);
19693     Uint32 startSz= getSectionSz(attrIVal);
19694     if (unlikely((! appendToSection(attrIVal,
19695                                     &firedTriggerData->fragId,
19696                                     1)) ||
19697                  (! appendAttrDataToSection(attrIVal,
19698                                             keyValues,
19699                                             false, // No AttributeHeaders
19700                                             attrId,
19701                                             hasNull))))
19702     {
19703       jam();
19704       break;
19705     }
19706 
19707     appendOk= true;
19708 
19709     /* Now go back and set pk header length */
19710     pkHeader->setDataSize(getSectionSz(attrIVal) - startSz);
19711   } while(0);
19712 
19713   if (unlikely(!appendOk))
19714   {
19715     /* Some failure building up KeyInfo and AttrInfo */
19716     releaseSection(keyIVal);
19717     releaseSection(attrIVal);
19718     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
19719     return;
19720   }
19721 
19722   /* Now build TcKeyReq for insert */
19723   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
19724   tcKeyReq->attrLen = 0;
19725   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
19726   tcKeyReq->tableId = indexData->indexId;
19727   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
19728   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
19729   tcKeyReq->transId1 = regApiPtr->transid[0];
19730   tcKeyReq->transId2 = regApiPtr->transid[1];
19731   tcKeyReq->requestInfo = tcKeyRequestInfo;
19732 
19733   /* Attach Key and AttrInfo sections to signal */
19734   ndbrequire(signal->header.m_noOfSections == 0);
19735   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
19736   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
19737   signal->header.m_noOfSections= 2;
19738 
19739   /*
19740    * Fix savepoint id -
19741    *   fix so that insert has same savepoint id as triggering operation
19742    */
19743   const Uint32 currSavePointId = regApiPtr->currSavePointId;
19744   regApiPtr->currSavePointId = opRecord->savePointId;
19745   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
19746   /* Pass trigger Id via ApiConnectRecord (nasty) */
19747   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
19748   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
19749 
19750   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
19751   jamEntry();
19752 
19753   /*
19754    * Restore ApiConnectRecord state
19755    */
19756   regApiPtr->currSavePointId = currSavePointId;
19757   regApiPtr->immediateTriggerId = RNIL;
19758 }
19759 
deleteFromIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)19760 void Dbtc::deleteFromIndexTable(Signal* signal,
19761                                 TcFiredTriggerData* firedTriggerData,
19762                                 ApiConnectRecordPtr* transPtr,
19763                                 TcConnectRecordPtr* opPtr,
19764                                 TcIndexData* indexData)
19765 {
19766   ApiConnectRecord* regApiPtr = transPtr->p;
19767   TcConnectRecord* opRecord = opPtr->p;
19768   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
19769   Uint32 tcKeyRequestInfo = 0;
19770   TableRecordPtr indexTabPtr;
19771 
19772   indexTabPtr.i = indexData->indexId;
19773   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
19774   tcKeyReq->apiConnectPtr = transPtr->i;
19775   tcKeyReq->senderData = opPtr->i;
19776 
19777   // Calculate key length and renumber attribute id:s
19778   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
19779   LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
19780 
19781   Uint32 keyIVal= RNIL;
19782   Uint32 attrId= 0;
19783   bool hasNull= false;
19784 
19785   if (beforeValues.getSize() == 0)
19786   {
19787     jam();
19788     ndbrequire(tc_testbit(regApiPtr->m_flags,
19789                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
19790     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
19791     return;
19792   }
19793 
19794   /* Build Delete KeyInfo section from beforevalues */
19795   if (unlikely((! appendAttrDataToSection(keyIVal,
19796                                           beforeValues,
19797                                           false, // No AttributeHeaders
19798                                           attrId,
19799                                           hasNull)) ||
19800                ERROR_INSERTED(8086)))
19801   {
19802     jam();
19803     releaseSection(keyIVal);
19804     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
19805     return;
19806   }
19807 
19808   /* If there's Nulls in the values that become the index table's
19809    * PK then we skip this delete
19810    */
19811   if (hasNull)
19812   {
19813     jam();
19814     releaseSection(keyIVal);
19815     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
19816     return;
19817   }
19818 
19819   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
19820   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
19821   tcKeyReq->attrLen = 0;
19822   tcKeyReq->tableId = indexData->indexId;
19823   TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
19824   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
19825   tcKeyReq->transId1 = regApiPtr->transid[0];
19826   tcKeyReq->transId2 = regApiPtr->transid[1];
19827   tcKeyReq->requestInfo = tcKeyRequestInfo;
19828 
19829   /* Attach KeyInfo section to signal */
19830   ndbrequire(signal->header.m_noOfSections == 0);
19831   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
19832   signal->header.m_noOfSections= 1;
19833 
19834   /**
19835    * Fix savepoint id -
19836    *   fix so that delete has same savepoint id as triggering operation
19837    */
19838   const Uint32 currSavePointId = regApiPtr->currSavePointId;
19839   regApiPtr->currSavePointId = opRecord->savePointId;
19840   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
19841   /* Pass trigger Id via ApiConnectRecord (nasty) */
19842   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
19843   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
19844   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
19845   jamEntry();
19846 
19847   /*
19848    * Restore ApiConnectRecord state
19849    */
19850   regApiPtr->currSavePointId = currSavePointId;
19851   regApiPtr->immediateTriggerId = RNIL;
19852 }
19853 
19854 Uint32
getErrorCode(Uint32 schemaVersion) const19855 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
19856   if(!get_enabled())
19857     return ZNO_SUCH_TABLE;
19858   if(get_dropping())
19859     return ZDROP_TABLE_IN_PROGRESS;
19860   if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
19861     return ZWRONG_SCHEMA_VERSION_ERROR;
19862   ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
19863 			      __FILE__, __LINE__);
19864   return 0;
19865 }
19866 
executeReorgTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)19867 void Dbtc::executeReorgTrigger(Signal* signal,
19868                                TcDefinedTriggerData* definedTriggerData,
19869                                TcFiredTriggerData* firedTriggerData,
19870                                ApiConnectRecordPtr* transPtr,
19871                                TcConnectRecordPtr* opPtr)
19872 {
19873 
19874   ApiConnectRecord* regApiPtr = transPtr->p;
19875   TcConnectRecord* opRecord = opPtr->p;
19876   TcKeyReq * tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
19877 
19878   tcKeyReq->apiConnectPtr = transPtr->i;
19879   tcKeyReq->senderData = opPtr->i;
19880 
19881   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
19882   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
19883   LocalDataBuffer<11> attrValues(pool, firedTriggerData->afterValues);
19884 
19885   Uint32 optype;
19886   bool sendAttrInfo= true;
19887 
19888   switch (firedTriggerData->triggerEvent) {
19889   case TriggerEvent::TE_INSERT:
19890     optype = ZINSERT;
19891     break;
19892   case TriggerEvent::TE_UPDATE:
19893     /**
19894      * Only update should be write, as COPY is done as update
19895      *   a (maybe) better solution would be to have a different
19896      *   trigger event for COPY
19897      */
19898     optype = ZWRITE;
19899     break;
19900   case TriggerEvent::TE_DELETE:
19901     optype = ZDELETE;
19902     sendAttrInfo= false;
19903     break;
19904   default:
19905     ndbrequire(false);
19906   }
19907 
19908   Ptr<TableRecord> tablePtr;
19909   tablePtr.i = definedTriggerData->tableId;
19910   ptrCheckGuard(tablePtr, ctabrecFilesize, tableRecord);
19911   Uint32 tableVersion = tablePtr.p->currentSchemaVersion;
19912 
19913   Uint32 tcKeyRequestInfo = 0;
19914   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
19915   TcKeyReq::setOperationType(tcKeyRequestInfo, optype);
19916   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
19917   tcKeyReq->attrLen = 0;
19918   tcKeyReq->tableId = tablePtr.i;
19919   tcKeyReq->requestInfo = tcKeyRequestInfo;
19920   tcKeyReq->tableSchemaVersion = tableVersion;
19921   tcKeyReq->transId1 = regApiPtr->transid[0];
19922   tcKeyReq->transId2 = regApiPtr->transid[1];
19923 
19924   Uint32 keyIVal= RNIL;
19925   Uint32 attrIVal= RNIL;
19926   Uint32 attrId= 0;
19927   bool hasNull= false;
19928 
19929   /* Prepare KeyInfo section */
19930   if (unlikely(!appendAttrDataToSection(keyIVal,
19931                                         keyValues,
19932                                         false, // No AttributeHeaders
19933                                         attrId,
19934                                         hasNull)))
19935   {
19936     releaseSection(keyIVal);
19937     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
19938     return;
19939   }
19940 
19941   ndbrequire(!hasNull);
19942 
19943   if (sendAttrInfo)
19944   {
19945     /* Prepare AttrInfo section from Key values and
19946      * After values
19947      */
19948     LocalDataBuffer<11>::Iterator attrIter;
19949     LocalDataBuffer<11>* buffers[2];
19950     buffers[0]= &keyValues;
19951     buffers[1]= &attrValues;
19952     const Uint32 segSize= keyValues.getSegmentSize(); // 11
19953     for (int buf=0; buf < 2; buf++)
19954     {
19955       Uint32 dataSize= buffers[buf]->getSize();
19956       bool moreData= buffers[buf]->first(attrIter);
19957 
19958       while(dataSize)
19959       {
19960         ndbrequire(moreData);
19961         Uint32 contigLeft= segSize - attrIter.ind;
19962         Uint32 contigValid= MIN(dataSize, contigLeft);
19963 
19964         if (unlikely(!appendToSection(attrIVal,
19965                                       attrIter.data,
19966                                       contigValid)))
19967         {
19968           releaseSection(keyIVal);
19969           releaseSection(attrIVal);
19970           abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
19971           return;
19972         }
19973         moreData= buffers[buf]->next(attrIter, contigValid);
19974         dataSize-= contigValid;
19975       }
19976       ndbassert(!moreData);
19977     }
19978   }
19979 
19980   /* Attach Key and optional AttrInfo sections to signal */
19981   ndbrequire(signal->header.m_noOfSections == 0);
19982   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
19983   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
19984   signal->header.m_noOfSections= sendAttrInfo? 2 : 1;
19985 
19986   /**
19987    * Fix savepoint id -
19988    *   fix so that the op has same savepoint id as triggering operation
19989    */
19990   const Uint32 currSavePointId = regApiPtr->currSavePointId;
19991   regApiPtr->currSavePointId = opRecord->savePointId;
19992   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_TRIGGER;
19993   /* Pass trigger Id via ApiConnectRecord (nasty) */
19994   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
19995 
19996   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
19997   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
19998   jamEntry();
19999 
20000   /*
20001    * Restore ApiConnectRecord state
20002    */
20003   regApiPtr->currSavePointId = currSavePointId;
20004   regApiPtr->immediateTriggerId = RNIL;
20005 }
20006 
20007 void
execROUTE_ORD(Signal * signal)20008 Dbtc::execROUTE_ORD(Signal* signal)
20009 {
20010   jamEntry();
20011   if(!assembleFragments(signal)){
20012     jam();
20013     return;
20014   }
20015 
20016   SectionHandle handle(this, signal);
20017 
20018   RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
20019   Uint32 dstRef = ord->dstRef;
20020   Uint32 srcRef = ord->srcRef;
20021   Uint32 gsn = ord->gsn;
20022 
20023   if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
20024   {
20025     jam();
20026     Uint32 secCount = handle.m_cnt;
20027     ndbrequire(secCount >= 1 && secCount <= 3);
20028 
20029     jamLine(secCount);
20030 
20031     /**
20032      * Put section 0 in signal->theData
20033      */
20034     Uint32 sigLen = handle.m_ptr[0].sz;
20035     ndbrequire(sigLen <= 25);
20036     copy(signal->theData, handle.m_ptr[0]);
20037 
20038     SegmentedSectionPtr save = handle.m_ptr[0];
20039     for (Uint32 i = 0; i < secCount - 1; i++)
20040       handle.m_ptr[i] = handle.m_ptr[i+1];
20041     handle.m_cnt--;
20042 
20043     sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle);
20044 
20045     handle.m_cnt = 1;
20046     handle.m_ptr[0] = save;
20047     releaseSections(handle);
20048     return ;
20049   }
20050 
20051   releaseSections(handle);
20052   warningEvent("Unable to route GSN: %d from %x to %x",
20053 	       gsn, srcRef, dstRef);
20054 
20055 }
20056