1 /*
2    Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 #define DBTC_C
26 
27 #include "Dbtc.hpp"
28 #include "md5_hash.hpp"
29 #include <RefConvert.hpp>
30 #include <ndb_limits.h>
31 #include <ndb_rand.h>
32 
33 #include <signaldata/DiGetNodes.hpp>
34 #include <signaldata/EventReport.hpp>
35 #include <signaldata/TcKeyReq.hpp>
36 #include <signaldata/TcKeyConf.hpp>
37 #include <signaldata/TcKeyRef.hpp>
38 #include <signaldata/KeyInfo.hpp>
39 #include <signaldata/AttrInfo.hpp>
40 #include <signaldata/TransIdAI.hpp>
41 #include <signaldata/TcRollbackRep.hpp>
42 #include <signaldata/NodeFailRep.hpp>
43 #include <signaldata/ReadNodesConf.hpp>
44 #include <signaldata/NFCompleteRep.hpp>
45 #include <signaldata/LqhKey.hpp>
46 #include <signaldata/TcCommit.hpp>
47 #include <signaldata/TcContinueB.hpp>
48 #include <signaldata/TcKeyFailConf.hpp>
49 #include <signaldata/AbortAll.hpp>
50 #include <signaldata/DihScanTab.hpp>
51 #include <signaldata/ScanFrag.hpp>
52 #include <signaldata/ScanTab.hpp>
53 #include <signaldata/PrepDropTab.hpp>
54 #include <signaldata/DropTab.hpp>
55 #include <signaldata/AlterTab.hpp>
56 #include <signaldata/CreateTrig.hpp>
57 #include <signaldata/CreateTrigImpl.hpp>
58 #include <signaldata/DropTrig.hpp>
59 #include <signaldata/DropTrigImpl.hpp>
60 #include <signaldata/FireTrigOrd.hpp>
61 #include <signaldata/TrigAttrInfo.hpp>
62 #include <signaldata/CreateIndx.hpp>
63 #include <signaldata/CreateIndxImpl.hpp>
64 #include <signaldata/DropIndx.hpp>
65 #include <signaldata/DropIndxImpl.hpp>
66 #include <signaldata/AlterIndx.hpp>
67 #include <signaldata/AlterIndxImpl.hpp>
68 #include <signaldata/ScanTab.hpp>
69 #include <signaldata/SystemError.hpp>
70 #include <signaldata/DumpStateOrd.hpp>
71 #include <signaldata/DisconnectRep.hpp>
72 #include <signaldata/TcHbRep.hpp>
73 
74 #include <signaldata/PrepDropTab.hpp>
75 #include <signaldata/DropTab.hpp>
76 #include <signaldata/TcIndx.hpp>
77 #include <signaldata/IndxKeyInfo.hpp>
78 #include <signaldata/IndxAttrInfo.hpp>
79 #include <signaldata/PackedSignal.hpp>
80 #include <signaldata/SignalDroppedRep.hpp>
81 #include <AttributeHeader.hpp>
82 #include <signaldata/DictTabInfo.hpp>
83 #include <AttributeDescriptor.hpp>
84 #include <SectionReader.hpp>
85 #include <KeyDescriptor.hpp>
86 
87 #include <NdbOut.hpp>
88 #include <DebuggerNames.hpp>
89 #include <signaldata/CheckNodeGroups.hpp>
90 
91 #include <signaldata/RouteOrd.hpp>
92 #include <signaldata/GCP.hpp>
93 
94 #include <signaldata/DbinfoScan.hpp>
95 #include <signaldata/TransIdAI.hpp>
96 #include <signaldata/CreateTab.hpp>
97 
98 // Use DEBUG to print messages that should be
99 // seen only when we debug the product
100 #ifdef VM_TRACE
101 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
102 #else
103 #define DEBUG(x)
104 #endif
105 
106 #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
107 
108 #ifdef VM_TRACE
109 NdbOut &
operator <<(NdbOut & out,Dbtc::ConnectionState state)110 operator<<(NdbOut& out, Dbtc::ConnectionState state){
111   switch(state){
112   case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
113   case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
114   case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
115   case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
116   case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
117   case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
118   case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
119   case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
120   case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
121   case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
122   case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
123   case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
124   case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
125   case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
126   case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
127   case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
128   case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
129   case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
130   case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
131   case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
132   case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
133   case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
134   case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
135   case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
136   case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
137   case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
138   default:
139     out << "Unknown: " << (int)state; break;
140   }
141   return out;
142 }
143 NdbOut &
operator <<(NdbOut & out,Dbtc::OperationState state)144 operator<<(NdbOut& out, Dbtc::OperationState state){
145   out << (int)state;
146   return out;
147 }
148 NdbOut &
operator <<(NdbOut & out,Dbtc::AbortState state)149 operator<<(NdbOut& out, Dbtc::AbortState state){
150   out << (int)state;
151   return out;
152 }
153 NdbOut &
operator <<(NdbOut & out,Dbtc::ReturnSignal state)154 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
155   out << (int)state;
156   return out;
157 }
158 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanRecord::ScanState state)159 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
160   out << (int)state;
161   return out;
162 }
163 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanFragRec::ScanFragState state)164 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
165   out << (int)state;
166   return out;
167 }
168 #endif
169 
170 extern int ErrorSignalReceive;
171 extern int ErrorMaxSegmentsToSeize;
172 
173 void
updateBuddyTimer(ApiConnectRecordPtr apiPtr)174 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
175 {
176   if (apiPtr.p->buddyPtr != RNIL) {
177     jam();
178     ApiConnectRecordPtr buddyApiPtr;
179     buddyApiPtr.i = apiPtr.p->buddyPtr;
180     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
181     if (getApiConTimer(buddyApiPtr.i) != 0) {
182       if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
183           (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
184         jam();
185         setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
186       } else {
187         jam();
188         // Not a buddy anymore since not the same transid
189         apiPtr.p->buddyPtr = RNIL;
190       }//if
191     }//if
192   }//if
193 }
194 
195 static
196 inline
197 bool
tc_testbit(Uint32 flags,Uint32 flag)198 tc_testbit(Uint32 flags, Uint32 flag)
199 {
200   return (flags & flag) != 0;
201 }
202 
203 static
204 inline
205 void
tc_clearbit(Uint32 & flags,Uint32 flag)206 tc_clearbit(Uint32 & flags, Uint32 flag)
207 {
208   flags &= ~(Uint32)flag;
209 }
210 
execCONTINUEB(Signal * signal)211 void Dbtc::execCONTINUEB(Signal* signal)
212 {
213   UintR tcase;
214 
215   jamEntry();
216   tcase = signal->theData[0];
217   UintR Tdata0 = signal->theData[1];
218   UintR Tdata1 = signal->theData[2];
219   UintR Tdata2 = signal->theData[3];
220   switch (tcase) {
221   case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
222     jam();
223     ndbrequire(false);
224     return;
225   case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
226     jam();
227     tcNodeFailptr.i = Tdata0;
228     ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
229     completeTransAtTakeOverLab(signal, Tdata1);
230     return;
231   case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
232     jam();
233     timeOutLoopStartLab(signal, Tdata0);
234     return;
235   case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
236     jam();
237     tnodeid = Tdata0;
238     tcNodeFailptr.i = 0;
239     ptrAss(tcNodeFailptr, tcFailRecord);
240     nodeTakeOverCompletedLab(signal);
241     return;
242   case TcContinueB::ZINITIALISE_RECORDS:
243     jam();
244     initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
245     return;
246   case TcContinueB::ZSEND_COMMIT_LOOP:
247     jam();
248     apiConnectptr.i = Tdata0;
249     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
250     tcConnectptr.i = Tdata1;
251     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
252     commit020Lab(signal);
253     return;
254   case TcContinueB::ZSEND_COMPLETE_LOOP:
255     jam();
256     apiConnectptr.i = Tdata0;
257     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
258     tcConnectptr.i = Tdata1;
259     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
260     complete010Lab(signal);
261     return;
262   case TcContinueB::ZHANDLE_FAILED_API_NODE:
263     jam();
264     handleFailedApiNode(signal, Tdata0, Tdata1);
265     return;
266   case TcContinueB::ZTRANS_EVENT_REP:
267     jam();
268     /* Send transaction counters report */
269     {
270       const Uint32 len = c_counters.build_event_rep(signal);
271       sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
272     }
273 
274     {
275       const Uint32 report_interval = 5000;
276       const Uint32 len = c_counters.build_continueB(signal);
277       signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
278       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, report_interval, len);
279     }
280     return;
281   case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
282     jam();
283     timeOutLoopStartFragLab(signal, Tdata0);
284     return;
285   case TcContinueB::ZABORT_BREAK:
286     jam();
287     tcConnectptr.i = Tdata0;
288     apiConnectptr.i = Tdata1;
289     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
290     apiConnectptr.p->counter--;
291     abort015Lab(signal);
292     return;
293   case TcContinueB::ZABORT_TIMEOUT_BREAK:
294     jam();
295     tcConnectptr.i = Tdata0;
296     apiConnectptr.i = Tdata1;
297     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
298     apiConnectptr.p->counter--;
299     sendAbortedAfterTimeout(signal, 1);
300     return;
301   case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
302     jam();
303     removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
304     return;
305   case TcContinueB::ZWAIT_ABORT_ALL:
306     jam();
307     checkAbortAllTimeout(signal, Tdata0);
308     return;
309   case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
310     jam();
311     checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
312     return;
313   case TcContinueB::ZNF_CHECK_TRANSACTIONS:
314     jam();
315     nodeFailCheckTransactions(signal, Tdata0, Tdata1);
316     return;
317   case TcContinueB::TRIGGER_PENDING:
318     jam();
319     ApiConnectRecordPtr transPtr;
320     transPtr.i = Tdata0;
321     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
322 #ifdef ERROR_INSERT
323     if (ERROR_INSERTED(8082))
324     {
325       /* Max of 100000 TRIGGER_PENDING TcContinueBs to
326        * single ApiConnectRecord
327        * See testBlobs -bug 45768
328        */
329       if (++transPtr.p->continueBCount > 100000)
330       {
331         ndbrequire(false);
332       }
333     }
334 #endif
335     /* Check that ConnectRecord is for the same Trans Id */
336     if (likely((transPtr.p->transid[0] == Tdata1) &&
337                (transPtr.p->transid[1] == Tdata2)))
338     {
339       ndbrequire(tc_testbit(transPtr.p->m_flags,
340                             ApiConnectRecord::TF_TRIGGER_PENDING));
341       tc_clearbit(transPtr.p->m_flags, ApiConnectRecord::TF_TRIGGER_PENDING);
342       /* Try executing triggers now */
343       executeTriggers(signal, &transPtr);
344     }
345     return;
346   case TcContinueB::DelayTCKEYCONF:
347     jam();
348     apiConnectptr.i = Tdata0;
349     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
350     sendtckeyconf(signal, Tdata1);
351     return;
352   case TcContinueB::ZSEND_FIRE_TRIG_REQ:
353     jam();
354     apiConnectptr.i = Tdata0;
355     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
356     if (unlikely(! (apiConnectptr.p->transid[0] == Tdata1 &&
357                     apiConnectptr.p->transid[1] == Tdata2 &&
358                     apiConnectptr.p->apiConnectstate == CS_SEND_FIRE_TRIG_REQ)))
359     {
360       warningReport(signal, 29);
361       return;
362     }
363     sendFireTrigReq(signal, apiConnectptr, signal->theData[4]);
364     return;
365   default:
366     ndbrequire(false);
367   }//switch
368 }
369 
execDIGETNODESREF(Signal * signal)370 void Dbtc::execDIGETNODESREF(Signal* signal)
371 {
372   jamEntry();
373   terrorCode = signal->theData[1];
374   releaseAtErrorLab(signal);
375 }
376 
execINCL_NODEREQ(Signal * signal)377 void Dbtc::execINCL_NODEREQ(Signal* signal)
378 {
379   jamEntry();
380   tblockref = signal->theData[0];
381   hostptr.i = signal->theData[1];
382   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
383   hostptr.p->hostStatus = HS_ALIVE;
384   c_alive_nodes.set(hostptr.i);
385 
386   signal->theData[0] = hostptr.i;
387   signal->theData[1] = cownref;
388 
389   if (ERROR_INSERTED(8039))
390   {
391     CLEAR_ERROR_INSERT_VALUE;
392     Uint32 save = signal->theData[0];
393     signal->theData[0] = 9999;
394     sendSignal(numberToRef(CMVMI, hostptr.i),
395 	       GSN_NDB_TAMPER, signal, 1, JBB);
396     signal->theData[0] = save;
397     sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
398     return;
399   }
400 
401   Uint32 Tnode = hostptr.i;
402   Uint32 lqhWorkers = getNodeInfo(Tnode).m_lqh_workers;
403   if (lqhWorkers == 1)
404   {
405     jam();
406     hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, 1, Tnode);
407   }
408   else
409   {
410     jam();
411     hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, Tnode);
412   }
413 
414   sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
415 
416   if (m_deferred_enabled)
417   {
418     jam();
419     if (!ndbd_deferred_unique_constraints(getNodeInfo(Tnode).m_version))
420     {
421       jam();
422       m_deferred_enabled = 0;
423     }
424   }
425 }
426 
execREAD_NODESREF(Signal * signal)427 void Dbtc::execREAD_NODESREF(Signal* signal)
428 {
429   jamEntry();
430   ndbrequire(false);
431 }
432 
433 // create table prepare
execTC_SCHVERREQ(Signal * signal)434 void Dbtc::execTC_SCHVERREQ(Signal* signal)
435 {
436   jamEntry();
437   if (! assembleFragments(signal)) {
438     jam();
439     return;
440   }
441   const TcSchVerReq* req = CAST_CONSTPTR(TcSchVerReq, signal->getDataPtr());
442   tabptr.i = req->tableId;
443   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
444   tabptr.p->currentSchemaVersion = req->tableVersion;
445   tabptr.p->m_flags = 0;
446   tabptr.p->set_storedTable((bool)req->tableLogged);
447   BlockReference retRef = req->senderRef;
448   tabptr.p->tableType = (Uint8)req->tableType;
449   BlockReference retPtr = req->senderData;
450   Uint32 noOfKeyAttr = req->noOfPrimaryKeys;
451   tabptr.p->singleUserMode = (Uint8)req->singleUserMode;
452   Uint32 userDefinedPartitioning = (Uint8)req->userDefinedPartition;
453   ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
454 
455   const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
456   ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
457 
458   ndbrequire(tabptr.p->get_prepared() == false);
459   ndbrequire(tabptr.p->get_enabled() == false);
460   tabptr.p->set_prepared(true);
461   tabptr.p->set_enabled(false);
462   tabptr.p->set_dropping(false);
463   tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
464   tabptr.p->hasCharAttr = desc->hasCharAttr;
465   tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
466   tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
467   tabptr.p->set_user_defined_partitioning(userDefinedPartitioning);
468 
469   TcSchVerConf * conf = (TcSchVerConf*)signal->getDataPtr();
470   conf->senderRef = reference();
471   conf->senderData = retPtr;
472   sendSignal(retRef, GSN_TC_SCHVERCONF, signal,
473              TcSchVerConf::SignalLength, JBB);
474 }//Dbtc::execTC_SCHVERREQ()
475 
476 // create table commit
execTAB_COMMITREQ(Signal * signal)477 void Dbtc::execTAB_COMMITREQ(Signal* signal)
478 {
479   jamEntry();
480   Uint32 senderData = signal->theData[0];
481   Uint32 senderRef = signal->theData[1];
482   tabptr.i = signal->theData[2];
483   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
484 
485   ndbrequire(tabptr.p->get_prepared() == true);
486   ndbrequire(tabptr.p->get_enabled() == false);
487   tabptr.p->set_enabled(true);
488   tabptr.p->set_prepared(false);
489   tabptr.p->set_dropping(false);
490 
491   signal->theData[0] = senderData;
492   signal->theData[1] = reference();
493   signal->theData[2] = tabptr.i;
494   sendSignal(senderRef, GSN_TAB_COMMITCONF, signal, 3, JBB);
495 }
496 
497 void
execPREP_DROP_TAB_REQ(Signal * signal)498 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
499 {
500   jamEntry();
501 
502   PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
503 
504   TableRecordPtr tabPtr;
505   tabPtr.i = req->tableId;
506   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
507 
508   Uint32 senderRef = req->senderRef;
509   Uint32 senderData = req->senderData;
510 
511   if(!tabPtr.p->get_enabled())
512   {
513     jam();
514     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
515     ref->senderRef = reference();
516     ref->senderData = senderData;
517     ref->tableId = tabPtr.i;
518     ref->errorCode = PrepDropTabRef::NoSuchTable;
519     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
520 	       PrepDropTabRef::SignalLength, JBB);
521     return;
522   }
523 
524   if(tabPtr.p->get_dropping())
525   {
526     jam();
527     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
528     ref->senderRef = reference();
529     ref->senderData = senderData;
530     ref->tableId = tabPtr.i;
531     ref->errorCode = PrepDropTabRef::DropInProgress;
532     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
533 	       PrepDropTabRef::SignalLength, JBB);
534     return;
535   }
536 
537   tabPtr.p->set_dropping(true);
538   tabPtr.p->set_prepared(false);
539 
540   PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
541   conf->tableId = tabPtr.i;
542   conf->senderRef = reference();
543   conf->senderData = senderData;
544   sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
545              PrepDropTabConf::SignalLength, JBB);
546 }
547 
548 void
execDROP_TAB_REQ(Signal * signal)549 Dbtc::execDROP_TAB_REQ(Signal* signal)
550 {
551   jamEntry();
552 
553   DropTabReq* req = (DropTabReq*)signal->getDataPtr();
554 
555   TableRecordPtr tabPtr;
556   tabPtr.i = req->tableId;
557   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
558 
559   Uint32 senderRef = req->senderRef;
560   Uint32 senderData = req->senderData;
561   DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
562 
563   if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
564     jam();
565     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
566     ref->senderRef = reference();
567     ref->senderData = senderData;
568     ref->tableId = tabPtr.i;
569     ref->errorCode = DropTabRef::NoSuchTable;
570     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
571 	       DropTabRef::SignalLength, JBB);
572     return;
573   }
574 
575   if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
576     jam();
577     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
578     ref->senderRef = reference();
579     ref->senderData = senderData;
580     ref->tableId = tabPtr.i;
581     ref->errorCode = DropTabRef::DropWoPrep;
582     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
583 	       DropTabRef::SignalLength, JBB);
584     return;
585   }
586 
587   tabPtr.p->set_enabled(false);
588   tabPtr.p->set_prepared(false);
589   tabPtr.p->set_dropping(false);
590 
591   DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
592   conf->tableId = tabPtr.i;
593   conf->senderRef = reference();
594   conf->senderData = senderData;
595   sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
596 	     PrepDropTabConf::SignalLength, JBB);
597 }
598 
execALTER_TAB_REQ(Signal * signal)599 void Dbtc::execALTER_TAB_REQ(Signal * signal)
600 {
601   const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
602   const Uint32 senderRef = req->senderRef;
603   const Uint32 senderData = req->senderData;
604   const Uint32 tableVersion = req->tableVersion;
605   const Uint32 newTableVersion = req->newTableVersion;
606   AlterTabReq::RequestType requestType =
607     (AlterTabReq::RequestType) req->requestType;
608 
609   TableRecordPtr tabPtr;
610   tabPtr.i = req->tableId;
611   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
612 
613   switch (requestType) {
614   case AlterTabReq::AlterTablePrepare:
615     jam();
616     break;
617   case AlterTabReq::AlterTableRevert:
618     jam();
619     tabPtr.p->currentSchemaVersion = tableVersion;
620     break;
621   case AlterTabReq::AlterTableCommit:
622     jam();
623     tabPtr.p->currentSchemaVersion = newTableVersion;
624     break;
625   default:
626     ndbrequire(false);
627     break;
628   }
629 
630   // Request handled successfully
631   AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
632   conf->senderRef = reference();
633   conf->senderData = senderData;
634   conf->connectPtr = RNIL;
635   sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
636 	     AlterTabConf::SignalLength, JBB);
637 }
638 
639 /* ***************************************************************************/
640 /*                                START / RESTART                            */
641 /* ***************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)642 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
643 {
644   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
645   Uint32 ref = req->senderRef;
646   Uint32 senderData = req->senderData;
647   ndbrequire(req->noOfParameters == 0);
648 
649   jamEntry();
650 
651   const ndb_mgm_configuration_iterator * p =
652     m_ctx.m_config.getOwnConfigIterator();
653   ndbrequire(p != 0);
654 
655   initData();
656 
657   UintR apiConnect;
658   UintR tcConnect;
659   UintR tables;
660   UintR localScan;
661   UintR tcScan;
662 
663   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
664   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
665   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
666   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
667   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
668 
669   ccacheFilesize = (apiConnect/3) + 1;
670   capiConnectFilesize = apiConnect;
671   ctcConnectFilesize  = tcConnect;
672   ctabrecFilesize     = tables;
673   cscanrecFileSize = tcScan;
674   cscanFragrecFileSize = localScan;
675 
676   initRecords();
677   initialiseRecordsLab(signal, 0, ref, senderData);
678 
679   Uint32 val = 3000;
680   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
681   set_timeout_value(val);
682 
683   val = 1500;
684   ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
685   cDbHbInterval = (val < 10) ? 10 : val;
686 
687   val = 3000;
688   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
689   set_appl_timeout_value(val);
690 
691   val = 1;
692   //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
693   set_no_parallel_takeover(val);
694 
695   val = ~(Uint32)0;
696   ndb_mgm_get_int_parameter(p, CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION, &val);
697   m_max_writes_per_trans = val;
698 
699   ctimeOutCheckDelay = 50; // 500ms
700 }//Dbtc::execSIZEALT_REP()
701 
execSTTOR(Signal * signal)702 void Dbtc::execSTTOR(Signal* signal)
703 {
704   Uint16 tphase;
705 
706   jamEntry();
707                                                      /* START CASE */
708   tphase = signal->theData[1];
709   csignalKey = signal->theData[6];
710   c_sttor_ref = signal->getSendersBlockRef();
711   switch (tphase) {
712   case ZSPH1:
713     jam();
714     startphase1x010Lab(signal);
715     return;
716   default:
717     jam();
718     sttorryLab(signal); /* START PHASE 255 */
719     return;
720   }//switch
721 }//Dbtc::execSTTOR()
722 
sttorryLab(Signal * signal)723 void Dbtc::sttorryLab(Signal* signal)
724 {
725   signal->theData[0] = csignalKey;
726   signal->theData[1] = 3;    /* BLOCK CATEGORY */
727   signal->theData[2] = 2;    /* SIGNAL VERSION NUMBER */
728   signal->theData[3] = ZSPH1;
729   signal->theData[4] = 255;
730   sendSignal(c_sttor_ref, GSN_STTORRY, signal, 5, JBB);
731 }//Dbtc::sttorryLab()
732 
733 /* ***************************************************************************/
734 /*                          INTERNAL  START / RESTART                        */
735 /*****************************************************************************/
execNDB_STTOR(Signal * signal)736 void Dbtc::execNDB_STTOR(Signal* signal)
737 {
738   Uint16 tndbstartphase;
739   Uint16 tstarttype;
740 
741   jamEntry();
742   tusersblkref = signal->theData[0];
743   tnodeid = signal->theData[1];
744   tndbstartphase = signal->theData[2];   /* START PHASE      */
745   tstarttype = signal->theData[3];       /* START TYPE       */
746   c_sttor_ref = signal->getSendersBlockRef();
747   switch (tndbstartphase) {
748   case ZINTSPH1:
749     jam();
750     intstartphase1x010Lab(signal);
751     return;
752   case ZINTSPH2:
753     jam();
754     ndbsttorry010Lab(signal);
755     return;
756   case ZINTSPH3:
757   {
758     jam();
759     intstartphase3x010Lab(signal);      /* SEIZE CONNECT RECORD IN EACH LQH*/
760 
761     /* Start transaction counters event reporting. */
762     const Uint32 len = c_counters.build_continueB(signal);
763     signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
764     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
765     return;
766   }
767   case ZINTSPH6:
768     jam();
769     csystemStart = SSS_TRUE;
770     break;
771   default:
772     jam();
773     break;
774   }//switch
775   ndbsttorry010Lab(signal);
776   return;
777 }//Dbtc::execNDB_STTOR()
778 
ndbsttorry010Lab(Signal * signal)779 void Dbtc::ndbsttorry010Lab(Signal* signal)
780 {
781   signal->theData[0] = cownref;
782   sendSignal(c_sttor_ref, GSN_NDB_STTORRY, signal, 1, JBB);
783 }//Dbtc::ndbsttorry010Lab()
784 
785 void
set_timeout_value(Uint32 timeOut)786 Dbtc::set_timeout_value(Uint32 timeOut)
787 {
788   timeOut = timeOut / 10;
789   if (timeOut < 2) {
790     jam();
791     timeOut = 100;
792   }//if
793   ctimeOutValue = timeOut;
794 }
795 
796 void
set_appl_timeout_value(Uint32 timeOut)797 Dbtc::set_appl_timeout_value(Uint32 timeOut)
798 {
799   if (timeOut)
800   {
801     timeOut /= 10;
802     if (timeOut < ctimeOutValue) {
803       jam();
804       c_appl_timeout_value = ctimeOutValue;
805     }//if
806   }
807   c_appl_timeout_value = timeOut;
808 }
809 
810 void
set_no_parallel_takeover(Uint32 noParallelTakeOver)811 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
812 {
813   if (noParallelTakeOver == 0) {
814     jam();
815     noParallelTakeOver = 1;
816   } else if (noParallelTakeOver > MAX_NDB_NODES) {
817     jam();
818     noParallelTakeOver = MAX_NDB_NODES;
819   }//if
820   cnoParallelTakeOver = noParallelTakeOver;
821 }
822 
823 /* ***************************************************************************/
824 /*                        S T A R T P H A S E 1 X                            */
825 /*                     INITIALISE BLOCKREF AND BLOCKNUMBERS                  */
826 /* ***************************************************************************/
startphase1x010Lab(Signal * signal)827 void Dbtc::startphase1x010Lab(Signal* signal)
828 {
829   csystemStart = SSS_FALSE;
830   ctimeOutCheckCounter = 0;
831   ctimeOutCheckFragCounter = 0;
832   ctimeOutMissedHeartbeats = 0;
833   ctimeOutCheckHeartbeat = 0;
834   ctimeOutCheckLastHeartbeat = 0;
835   ctimeOutCheckActive = TOCS_FALSE;
836   ctimeOutCheckFragActive = TOCS_FALSE;
837   sttorryLab(signal);
838 }//Dbtc::startphase1x010Lab()
839 
840 /*****************************************************************************/
841 /*                        I N T S T A R T P H A S E 1 X                      */
842 /*                         INITIALISE ALL RECORDS.                           */
843 /*****************************************************************************/
intstartphase1x010Lab(Signal * signal)844 void Dbtc::intstartphase1x010Lab(Signal* signal)
845 {
846   cownNodeid = tnodeid;
847   cownref =          reference();
848   clqhblockref =     calcLqhBlockRef(cownNodeid);
849   cdihblockref =     calcDihBlockRef(cownNodeid);
850   cdictblockref =    calcDictBlockRef(cownNodeid);
851   cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
852   cerrorBlockref   = calcNdbCntrBlockRef(cownNodeid);
853   coperationsize = 0;
854   cfailure_nr = 0;
855   ndbsttorry010Lab(signal);
856 }//Dbtc::intstartphase1x010Lab()
857 
858 /*****************************************************************************/
859 /*                         I N T S T A R T P H A S E 3 X                     */
860 /*                        PREPARE DISTRIBUTED CONNECTIONS                    */
861 /*****************************************************************************/
intstartphase3x010Lab(Signal * signal)862 void Dbtc::intstartphase3x010Lab(Signal* signal)
863 {
864   signal->theData[0] = cownref;
865   sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
866 }//Dbtc::intstartphase3x010Lab()
867 
execREAD_NODESCONF(Signal * signal)868 void Dbtc::execREAD_NODESCONF(Signal* signal)
869 {
870   UintR guard0;
871 
872   jamEntry();
873 
874   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
875 
876   csystemnodes  = readNodes->noOfNodes;
877   cmasterNodeId = readNodes->masterNodeId;
878 
879   con_lineNodes = 0;
880   arrGuard(csystemnodes, MAX_NDB_NODES);
881   guard0 = csystemnodes - 1;
882   arrGuard(guard0, MAX_NDB_NODES);       // Check not zero nodes
883 
884   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
885     jam();
886     if (NdbNodeBitmask::get(readNodes->allNodes, i)) {
887       hostptr.i = i;
888       ptrCheckGuard(hostptr, chostFilesize, hostRecord);
889 
890       if (NdbNodeBitmask::get(readNodes->inactiveNodes, i)) {
891         jam();
892         hostptr.p->hostStatus = HS_DEAD;
893       } else {
894         jam();
895         con_lineNodes++;
896         hostptr.p->hostStatus = HS_ALIVE;
897         c_alive_nodes.set(i);
898         if (getNodeInfo(i).m_lqh_workers == 1)
899         {
900           jam();
901           hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, 1, i);
902         }
903         else
904         {
905           jam();
906           hostptr.p->hostLqhBlockRef = numberToRef(DBLQH, i);
907         }
908         if (!ndbd_deferred_unique_constraints(getNodeInfo(i).m_version))
909         {
910           jam();
911           m_deferred_enabled = 0;
912         }
913       }//if
914     }//if
915   }//for
916   ndbsttorry010Lab(signal);
917 }//Dbtc::execREAD_NODESCONF()
918 
919 /*****************************************************************************/
920 /*                     A P I _ F A I L R E Q                                 */
921 // An API node has failed for some reason. We need to disconnect all API
922 // connections to the API node. This also includes
923 /*****************************************************************************/
execAPI_FAILREQ(Signal * signal)924 void Dbtc::execAPI_FAILREQ(Signal* signal)
925 {
926   /***************************************************************************
927    * Set the block reference to return API_FAILCONF to. Set the number of api
928    * connects currently closing to one to indicate that we are still in the
929    * process of going through the api connect records. Thus checking for zero
930    * can only be true after all api connect records have been checked.
931    **************************************************************************/
932   jamEntry();
933 
934   if (ERROR_INSERTED(8056))
935   {
936     CLEAR_ERROR_INSERT_VALUE;
937     return;
938   }
939 #ifdef ERROR_INSERT
940   if (ERROR_INSERTED(8078))
941   {
942     c_lastFailedApi = signal->theData[0];
943     SET_ERROR_INSERT_VALUE(8079);
944   }
945 #endif
946 
947   capiFailRef = signal->theData[1];
948   arrGuard(signal->theData[0], MAX_NODES);
949   capiConnectClosing[signal->theData[0]] = 1;
950   handleFailedApiNode(signal, signal->theData[0], (UintR)0);
951 }
952 
953 void
handleFailedApiNode(Signal * signal,UintR TapiFailedNode,UintR TapiConnectPtr)954 Dbtc::handleFailedApiNode(Signal* signal,
955                           UintR TapiFailedNode,
956                           UintR TapiConnectPtr)
957 {
958   UintR TloopCount = 0;
959   arrGuard(TapiFailedNode, MAX_NODES);
960   apiConnectptr.i = TapiConnectPtr;
961   do {
962     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
963     const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
964     if (TapiNode == TapiFailedNode) {
965 #ifdef VM_TRACE
966       if (apiConnectptr.p->apiFailState != ZFALSE) {
967         ndbout << "Error in previous API fail handling discovered" << endl
968 	       << "  apiConnectptr.i = " << apiConnectptr.i << endl
969 	       << "  apiConnectstate = " << apiConnectptr.p->apiConnectstate
970 	       << endl
971 	       << "  ndbapiBlockref = " << hex
972 	       << apiConnectptr.p->ndbapiBlockref << endl
973 	       << "  apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
974 	       << endl;
975 	if (apiConnectptr.p->lastTcConnect != RNIL){
976 	  jam();
977 	  tcConnectptr.i = apiConnectptr.p->lastTcConnect;
978 	  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
979 	  ndbout << "  tcConnectptr.i = " << tcConnectptr.i << endl
980 		 << "  tcConnectstate = " << tcConnectptr.p->tcConnectstate
981 		 << endl;
982 	}
983       }//if
984 #endif
985 
986       apiConnectptr.p->returnsignal = RS_NO_RETURN;
987       /***********************************************************************/
988       // The connected node is the failed node.
989       /**********************************************************************/
990       switch(apiConnectptr.p->apiConnectstate) {
991       case CS_DISCONNECTED:
992         /*********************************************************************/
993         // These states do not need any special handling.
994         // Simply continue with the next.
995         /*********************************************************************/
996         jam();
997         break;
998       case CS_ABORTING:
999         /*********************************************************************/
1000         // This could actually mean that the API connection is already
1001         // ready to release if the abortState is IDLE.
1002         /*********************************************************************/
1003         if (apiConnectptr.p->abortState == AS_IDLE) {
1004           jam();
1005           releaseApiCon(signal, apiConnectptr.i);
1006         } else {
1007           jam();
1008           capiConnectClosing[TapiFailedNode]++;
1009           apiConnectptr.p->apiFailState = ZTRUE;
1010         }//if
1011         break;
1012       case CS_WAIT_ABORT_CONF:
1013       case CS_WAIT_COMMIT_CONF:
1014       case CS_START_COMMITTING:
1015       case CS_PREPARE_TO_COMMIT:
1016       case CS_COMMITTING:
1017       case CS_COMMIT_SENT:
1018         /*********************************************************************/
1019         // These states indicate that an abort process or commit process is
1020         // already ongoing. We will set a state in the api record indicating
1021         // that the API node has failed.
1022         // Also we will increase the number of outstanding api records to
1023         // wait for before we can respond with API_FAILCONF.
1024         /*********************************************************************/
1025         jam();
1026         capiConnectClosing[TapiFailedNode]++;
1027         apiConnectptr.p->apiFailState = ZTRUE;
1028         break;
1029       case CS_START_SCAN:
1030         /*********************************************************************/
1031         // The api record was performing a scan operation. We need to check
1032         // on the scan state. Since completing a scan process might involve
1033         // sending several signals we will increase the loop count by 64.
1034         /*********************************************************************/
1035         jam();
1036 
1037 	apiConnectptr.p->apiFailState = ZTRUE;
1038 	capiConnectClosing[TapiFailedNode]++;
1039 
1040 	ScanRecordPtr scanPtr;
1041 	scanPtr.i = apiConnectptr.p->apiScanRec;
1042 	ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
1043 	close_scan_req(signal, scanPtr, true);
1044 
1045         TloopCount += 64;
1046         break;
1047       case CS_CONNECTED:
1048       case CS_REC_COMMITTING:
1049       case CS_RECEIVING:
1050       case CS_STARTED:
1051         /*********************************************************************/
1052         // The api record was in the process of performing a transaction but
1053         // had not yet sent all information.
1054         // We need to initiate an ABORT since the API will not provide any
1055         // more information.
1056         // Since the abort can send many signals we will insert a real-time
1057         // break after checking this record.
1058         /*********************************************************************/
1059         jam();
1060         apiConnectptr.p->apiFailState = ZTRUE;
1061         capiConnectClosing[TapiFailedNode]++;
1062         abort010Lab(signal);
1063         TloopCount = 256;
1064         break;
1065       case CS_PREPARED:
1066         jam();
1067       case CS_REC_PREPARING:
1068         jam();
1069       case CS_START_PREPARING:
1070         jam();
1071         /*********************************************************************/
1072         // Not implemented yet.
1073         /*********************************************************************/
1074         systemErrorLab(signal, __LINE__);
1075         break;
1076       case CS_RESTART:
1077         jam();
1078       case CS_COMPLETING:
1079         jam();
1080       case CS_COMPLETE_SENT:
1081         jam();
1082       case CS_WAIT_COMPLETE_CONF:
1083         jam();
1084       case CS_FAIL_ABORTING:
1085         jam();
1086       case CS_FAIL_ABORTED:
1087         jam();
1088       case CS_FAIL_PREPARED:
1089         jam();
1090       case CS_FAIL_COMMITTING:
1091         jam();
1092       case CS_FAIL_COMMITTED:
1093         /*********************************************************************/
1094         // These states are only valid on copy and fail API connections.
1095         /*********************************************************************/
1096       default:
1097         jam();
1098         systemErrorLab(signal, __LINE__);
1099         break;
1100       }//switch
1101     } else {
1102       jam();
1103     }//if
1104     apiConnectptr.i++;
1105     if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
1106       jam();
1107       /**
1108        * Finished with scanning connection record
1109        *
1110        * Now scan markers
1111        */
1112       removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1113       return;
1114     }//if
1115   } while (TloopCount++ < 256);
1116   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1117   signal->theData[1] = TapiFailedNode;
1118   signal->theData[2] = apiConnectptr.i;
1119   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1120 }//Dbtc::handleFailedApiNode()
1121 
1122 void
removeMarkerForFailedAPI(Signal * signal,Uint32 nodeId,Uint32 startBucket)1123 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1124                                Uint32 nodeId,
1125                                Uint32 startBucket)
1126 {
1127   TcFailRecordPtr node_fail_ptr;
1128   node_fail_ptr.i = 0;
1129   ptrAss(node_fail_ptr, tcFailRecord);
1130   if(node_fail_ptr.p->failStatus != FS_IDLE) {
1131     jam();
1132     DEBUG("Restarting removeMarkerForFailedAPI");
1133     /**
1134      * TC take-over in progress
1135      *   needs to restart as this
1136      *   creates new markers
1137      */
1138     signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1139     signal->theData[1] = nodeId;
1140     signal->theData[2] = 0;
1141     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1142     return;
1143   }
1144 
1145   CommitAckMarkerIterator iter;
1146   m_commitAckMarkerHash.next(startBucket, iter);
1147 
1148   const Uint32 RT_BREAK = 256;
1149   for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1150     jam();
1151 
1152     if(iter.curr.i == RNIL){
1153       jam();
1154       /**
1155        * Done with iteration
1156        */
1157       capiConnectClosing[nodeId]--;
1158       if (capiConnectClosing[nodeId] == 0) {
1159         jam();
1160 
1161         /********************************************************************/
1162         // No outstanding ABORT or COMMIT's of this failed API node.
1163         // Perform SimulatedBlock level cleanup before sending
1164         // API_FAILCONF
1165         /********************************************************************/
1166         Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1167                        nodeId};
1168         simBlockNodeFailure(signal, nodeId, cb);
1169       }
1170       return;
1171     }
1172 
1173     if(iter.curr.p->apiNodeId == nodeId){
1174       jam();
1175 
1176       /**
1177        * Check so that the record is not still in use
1178        *
1179        */
1180       ApiConnectRecordPtr apiConnectPtr;
1181       apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1182       ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
1183       if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
1184 	jam();
1185         /**
1186          * The record is still active
1187          *
1188          * Don't remove it, but continueb instead
1189          */
1190 	break;
1191       }
1192       sendRemoveMarkers(signal, iter.curr.p);
1193       m_commitAckMarkerHash.release(iter.curr);
1194 
1195       break;
1196     }
1197     m_commitAckMarkerHash.next(iter);
1198   }
1199 
1200   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1201   signal->theData[1] = nodeId;
1202   signal->theData[2] = iter.bucket;
1203   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1204 }
1205 
handleApiFailState(Signal * signal,UintR TapiConnectptr)1206 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1207 {
1208   ApiConnectRecordPtr TlocalApiConnectptr;
1209   UintR TfailedApiNode;
1210 
1211   TlocalApiConnectptr.i = TapiConnectptr;
1212   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
1213   TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1214   arrGuard(TfailedApiNode, MAX_NODES);
1215   capiConnectClosing[TfailedApiNode]--;
1216   releaseApiCon(signal, TapiConnectptr);
1217   TlocalApiConnectptr.p->apiFailState = ZFALSE;
1218   if (capiConnectClosing[TfailedApiNode] == 0)
1219   {
1220     jam();
1221 
1222     /**
1223      * Perform block-level cleanups (e.g assembleFragments...)
1224      */
1225     Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1226                    TfailedApiNode};
1227     simBlockNodeFailure(signal, TfailedApiNode, cb);
1228   }//if
1229 }//Dbtc::handleApiFailState()
1230 
1231 /****************************************************************************
1232  *                                T C S E I Z E R E Q
1233  * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1234  * TRANSACTION
1235  * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1236  * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1237  ****************************************************************************/
execTCSEIZEREQ(Signal * signal)1238 void Dbtc::execTCSEIZEREQ(Signal* signal)
1239 {
1240   UintR tapiPointer;
1241   BlockReference tapiBlockref;       /* SENDER BLOCK REFERENCE*/
1242 
1243   jamEntry();
1244   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1245   tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1246 
1247   if (signal->getLength() > 2)
1248   {
1249     ndbassert(instance() == signal->theData[2]);
1250   }
1251 
1252   const NodeState::StartLevel sl =
1253     (NodeState::StartLevel)getNodeState().startLevel;
1254 
1255   const NodeId senderNodeId = refToNode(tapiBlockref);
1256   const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1257 
1258   {
1259     {
1260       if (!(sl == NodeState::SL_STARTED ||
1261 	    (sl == NodeState::SL_STARTING && local == true))) {
1262 	jam();
1263 
1264 	Uint32 errCode = 0;
1265 	if(!local)
1266 	  {
1267 	    switch(sl){
1268 	    case NodeState::SL_STARTING:
1269 	      errCode = ZSYSTEM_NOT_STARTED_ERROR;
1270 	      break;
1271 	    case NodeState::SL_STOPPING_1:
1272 	    case NodeState::SL_STOPPING_2:
1273               if (getNodeState().getSingleUserMode())
1274                 break;
1275 	    case NodeState::SL_STOPPING_3:
1276 	    case NodeState::SL_STOPPING_4:
1277 	      if(getNodeState().stopping.systemShutdown)
1278 		errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1279 	      else
1280 		errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1281 	      break;
1282 	    case NodeState::SL_SINGLEUSER:
1283 	      break;
1284 	    default:
1285 	      errCode = ZWRONG_STATE;
1286 	      break;
1287 	    }
1288             if (errCode)
1289             {
1290               signal->theData[0] = tapiPointer;
1291               signal->theData[1] = errCode;
1292               sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1293               return;
1294             }
1295 	  }//if (!(sl == SL_SINGLEUSER))
1296       } //if
1297     }
1298   }
1299 
1300   if (ERROR_INSERTED(8078) || ERROR_INSERTED(8079))
1301   {
1302     /* Clear testing of API_FAILREQ behaviour */
1303     CLEAR_ERROR_INSERT_VALUE;
1304   };
1305 
1306   seizeApiConnect(signal);
1307   if (terrorCode == ZOK) {
1308     jam();
1309     apiConnectptr.p->ndbapiConnect = tapiPointer;
1310     apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1311     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1312     signal->theData[1] = apiConnectptr.i;
1313     signal->theData[2] = reference();
1314     sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 3, JBB);
1315     return;
1316   }
1317 
1318   signal->theData[0] = tapiPointer;
1319   signal->theData[1] = terrorCode;
1320   sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1321 }//Dbtc::execTCSEIZEREQ()
1322 
1323 /****************************************************************************/
1324 /*                    T C R E L E A S E Q                                   */
1325 /*                  REQUEST TO RELEASE A CONNECT RECORD                     */
1326 /****************************************************************************/
execTCRELEASEREQ(Signal * signal)1327 void Dbtc::execTCRELEASEREQ(Signal* signal)
1328 {
1329   UintR tapiPointer;
1330   BlockReference tapiBlockref;     /* SENDER BLOCK REFERENCE*/
1331 
1332   jamEntry();
1333   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1334   tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1335   tuserpointer = signal->theData[2];
1336   if (tapiPointer >= capiConnectFilesize) {
1337     jam();
1338     signal->theData[0] = tuserpointer;
1339     signal->theData[1] = ZINVALID_CONNECTION;
1340     signal->theData[2] = __LINE__;
1341     sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1342     return;
1343   } else {
1344     jam();
1345     apiConnectptr.i = tapiPointer;
1346   }//if
1347   ptrAss(apiConnectptr, apiConnectRecord);
1348   if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
1349     jam();
1350     signal->theData[0] = tuserpointer;
1351     sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1352   } else {
1353     if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
1354       if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
1355 	  (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
1356 	   apiConnectptr.p->abortState == AS_IDLE) ||
1357 	  (apiConnectptr.p->apiConnectstate == CS_STARTED &&
1358 	   apiConnectptr.p->firstTcConnect == RNIL))
1359       {
1360         jam();                                   /* JUST REPLY OK */
1361 	apiConnectptr.p->m_transaction_nodes.clear();
1362         releaseApiCon(signal, apiConnectptr.i);
1363         signal->theData[0] = tuserpointer;
1364         sendSignal(tapiBlockref,
1365                    GSN_TCRELEASECONF, signal, 1, JBB);
1366       } else {
1367         jam();
1368         signal->theData[0] = tuserpointer;
1369         signal->theData[1] = ZINVALID_CONNECTION;
1370 	signal->theData[2] = __LINE__;
1371 	signal->theData[3] = apiConnectptr.p->apiConnectstate;
1372         sendSignal(tapiBlockref,
1373                    GSN_TCRELEASEREF, signal, 4, JBB);
1374       }
1375     } else {
1376       jam();
1377       signal->theData[0] = tuserpointer;
1378       signal->theData[1] = ZINVALID_CONNECTION;
1379       signal->theData[2] = __LINE__;
1380       signal->theData[3] = tapiBlockref;
1381       signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1382       sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1383     }//if
1384   }//if
1385 }//Dbtc::execTCRELEASEREQ()
1386 
1387 /****************************************************************************/
1388 // Error Handling for TCKEYREQ messages
1389 /****************************************************************************/
signalErrorRefuseLab(Signal * signal)1390 void Dbtc::signalErrorRefuseLab(Signal* signal)
1391 {
1392   ptrGuard(apiConnectptr);
1393   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1394     jam();
1395     apiConnectptr.p->abortState = AS_IDLE;
1396     apiConnectptr.p->apiConnectstate = CS_ABORTING;
1397   }//if
1398   sendSignalErrorRefuseLab(signal);
1399 }//Dbtc::signalErrorRefuseLab()
1400 
sendSignalErrorRefuseLab(Signal * signal)1401 void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
1402 {
1403   ndbassert(false);
1404   ptrGuard(apiConnectptr);
1405   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1406     jam();
1407     ndbrequire(false);
1408     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1409     signal->theData[1] = signal->theData[ttransid_ptr];
1410     signal->theData[2] = signal->theData[ttransid_ptr + 1];
1411     signal->theData[3] = ZSIGNAL_ERROR;
1412     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1413 	       signal, 4, JBB);
1414   }
1415 }//Dbtc::sendSignalErrorRefuseLab()
1416 
abortBeginErrorLab(Signal * signal)1417 void Dbtc::abortBeginErrorLab(Signal* signal)
1418 {
1419   apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1420   apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1421   abortErrorLab(signal);
1422 }//Dbtc::abortBeginErrorLab()
1423 
printState(Signal * signal,int place)1424 void Dbtc::printState(Signal* signal, int place)
1425 {
1426 #ifdef VM_TRACE // Change to if 0 to disable these printouts
1427   ndbout << "-- Dbtc::printState -- " << endl;
1428   ndbout << "Received from place = " << place
1429 	 << " apiConnectptr.i = " << apiConnectptr.i
1430 	 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
1431   ndbout << "ctcTimer = " << ctcTimer
1432 	 << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
1433 	 << " Transid = " << apiConnectptr.p->transid[0]
1434 	 << " " << apiConnectptr.p->transid[1] << endl;
1435   ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
1436 	 << " counter = " << apiConnectptr.p->counter
1437 	 << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
1438 	 << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
1439   ndbout << "abortState = " << apiConnectptr.p->abortState
1440 	 << " apiScanRec = " << apiConnectptr.p->apiScanRec
1441 	 << " returncode = " << apiConnectptr.p->returncode << endl;
1442   ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
1443 	 << " returnsignal = " << apiConnectptr.p->returnsignal
1444 	 << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
1445   if (apiConnectptr.p->cachePtr != RNIL) {
1446     jam();
1447     CacheRecord *localCacheRecord = cacheRecord;
1448     UintR TcacheFilesize = ccacheFilesize;
1449     UintR TcachePtr = apiConnectptr.p->cachePtr;
1450     if (TcachePtr < TcacheFilesize) {
1451       jam();
1452       CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1453       ndbout << "currReclenAi = " << regCachePtr->currReclenAi
1454 	     << " attrlength = " << regCachePtr->attrlength
1455 	     << " tableref = " << regCachePtr->tableref
1456 	     << " keylen = " << regCachePtr->keylen << endl;
1457     } else {
1458       jam();
1459       systemErrorLab(signal, __LINE__);
1460     }//if
1461   }//if
1462 #endif
1463   return;
1464 }//Dbtc::printState()
1465 
1466 void
TCKEY_abort(Signal * signal,int place)1467 Dbtc::TCKEY_abort(Signal* signal, int place)
1468 {
1469   switch (place) {
1470   case 0:
1471     jam();
1472     terrorCode = ZSTATE_ERROR;
1473     apiConnectptr.p->firstTcConnect = RNIL;
1474     printState(signal, 4);
1475     abortBeginErrorLab(signal);
1476     return;
1477   case 1:
1478     jam();
1479     printState(signal, 3);
1480     sendSignalErrorRefuseLab(signal);
1481     return;
1482   case 2:{
1483     printState(signal, 6);
1484     const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
1485     const Uint32 t1 = tcKeyReq->transId1;
1486     const Uint32 t2 = tcKeyReq->transId2;
1487     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1488     signal->theData[1] = t1;
1489     signal->theData[2] = t2;
1490     signal->theData[3] = ZABORT_ERROR;
1491     ndbrequire(false);
1492     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1493 	       signal, 4, JBB);
1494     return;
1495   }
1496   case 3:
1497     jam();
1498     printState(signal, 7);
1499     noFreeConnectionErrorLab(signal);
1500     return;
1501   case 4:
1502     jam();
1503     terrorCode = ZERO_KEYLEN_ERROR;
1504     releaseAtErrorLab(signal);
1505     return;
1506   case 5:
1507     jam();
1508     terrorCode = ZNO_AI_WITH_UPDATE;
1509     releaseAtErrorLab(signal);
1510     return;
1511   case 6:
1512     jam();
1513     warningHandlerLab(signal, __LINE__);
1514     return;
1515 
1516   case 7:
1517     jam();
1518     tabStateErrorLab(signal);
1519     return;
1520 
1521   case 8:
1522     jam();
1523     wrongSchemaVersionErrorLab(signal);
1524     return;
1525 
1526   case 9:
1527     jam();
1528     terrorCode = ZSTATE_ERROR;
1529     releaseAtErrorLab(signal);
1530     return;
1531 
1532   case 10:
1533     jam();
1534     systemErrorLab(signal, __LINE__);
1535     return;
1536 
1537   case 11:
1538     jam();
1539     terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
1540     releaseAtErrorLab(signal);
1541     return;
1542 
1543   case 12:
1544     jam();
1545     terrorCode = ZSIMPLE_READ_WITHOUT_AI;
1546     releaseAtErrorLab(signal);
1547     return;
1548 
1549   case 13:
1550     jam();
1551     switch (tcConnectptr.p->tcConnectstate) {
1552     case OS_WAIT_KEYINFO:
1553       jam();
1554       printState(signal, 8);
1555       terrorCode = ZSTATE_ERROR;
1556       abortErrorLab(signal);
1557       return;
1558     default:
1559       jam();
1560       /********************************************************************/
1561       /*       MISMATCH BETWEEN STATE ON API CONNECTION AND THIS          */
1562       /*       PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB   */
1563       /*       INTERNAL ERROR.                                            */
1564       /********************************************************************/
1565       systemErrorLab(signal, __LINE__);
1566       return;
1567     }//switch
1568     return;
1569 
1570   case 15:
1571     jam();
1572     terrorCode = ZSCAN_NODE_ERROR;
1573     releaseAtErrorLab(signal);
1574     return;
1575 
1576   case 16:
1577     jam();
1578     systemErrorLab(signal, __LINE__);
1579     return;
1580 
1581   case 17:
1582     jam();
1583     systemErrorLab(signal, __LINE__);
1584     return;
1585 
1586   case 18:
1587     jam();
1588     warningHandlerLab(signal, __LINE__);
1589     return;
1590 
1591   case 19:
1592     jam();
1593     return;
1594 
1595   case 20:
1596     jam();
1597     warningHandlerLab(signal, __LINE__);
1598     return;
1599 
1600   case 21:
1601     jam();
1602     systemErrorLab(signal, __LINE__);
1603     return;
1604 
1605   case 22:
1606     jam();
1607     systemErrorLab(signal, __LINE__);
1608     return;
1609 
1610   case 23:
1611     jam();
1612     systemErrorLab(signal, __LINE__);
1613     return;
1614 
1615   case 24:
1616     jam();
1617     appendToSectionErrorLab(signal);
1618     return;
1619 
1620   case 25:
1621     jam();
1622     warningHandlerLab(signal, __LINE__);
1623     return;
1624 
1625   case 26:
1626     jam();
1627     return;
1628 
1629   case 27:
1630     systemErrorLab(signal, __LINE__);
1631     jam();
1632     return;
1633 
1634   case 28:
1635     jam();
1636     // NOT USED
1637     return;
1638 
1639   case 29:
1640     jam();
1641     systemErrorLab(signal, __LINE__);
1642     return;
1643 
1644   case 30:
1645     jam();
1646     systemErrorLab(signal, __LINE__);
1647     return;
1648 
1649   case 31:
1650     jam();
1651     systemErrorLab(signal, __LINE__);
1652     return;
1653 
1654   case 32:
1655     jam();
1656     systemErrorLab(signal, __LINE__);
1657     return;
1658 
1659   case 33:
1660     jam();
1661     systemErrorLab(signal, __LINE__);
1662     return;
1663 
1664   case 34:
1665     jam();
1666     systemErrorLab(signal, __LINE__);
1667     return;
1668 
1669   case 35:
1670     jam();
1671     systemErrorLab(signal, __LINE__);
1672     return;
1673 
1674   case 36:
1675     jam();
1676     systemErrorLab(signal, __LINE__);
1677     return;
1678 
1679   case 37:
1680     jam();
1681     systemErrorLab(signal, __LINE__);
1682     return;
1683 
1684   case 38:
1685     jam();
1686     systemErrorLab(signal, __LINE__);
1687     return;
1688 
1689   case 39:
1690     jam();
1691     systemErrorLab(signal, __LINE__);
1692     return;
1693 
1694   case 40:
1695     jam();
1696     systemErrorLab(signal, __LINE__);
1697     return;
1698 
1699   case 41:
1700     jam();
1701     systemErrorLab(signal, __LINE__);
1702     return;
1703 
1704   case 42:
1705     jam();
1706     systemErrorLab(signal, __LINE__);
1707     return;
1708 
1709   case 43:
1710     jam();
1711     systemErrorLab(signal, __LINE__);
1712     return;
1713 
1714   case 44:
1715     jam();
1716     systemErrorLab(signal, __LINE__);
1717     return;
1718 
1719   case 45:
1720     jam();
1721     systemErrorLab(signal, __LINE__);
1722     return;
1723 
1724   case 46:
1725     jam();
1726     systemErrorLab(signal, __LINE__);
1727     return;
1728 
1729   case 47:
1730     jam();
1731     terrorCode = apiConnectptr.p->returncode;
1732     releaseAtErrorLab(signal);
1733     return;
1734 
1735   case 48:
1736     jam();
1737     terrorCode = ZCOMMIT_TYPE_ERROR;
1738     releaseAtErrorLab(signal);
1739     return;
1740 
1741   case 49:
1742     jam();
1743     abortErrorLab(signal);
1744     return;
1745 
1746   case 50:
1747     jam();
1748     systemErrorLab(signal, __LINE__);
1749     return;
1750 
1751   case 51:
1752     jam();
1753     abortErrorLab(signal);
1754     return;
1755 
1756   case 52:
1757     jam();
1758     abortErrorLab(signal);
1759     return;
1760 
1761   case 53:
1762     jam();
1763     abortErrorLab(signal);
1764     return;
1765 
1766   case 54:
1767     jam();
1768     abortErrorLab(signal);
1769     return;
1770 
1771   case 55:
1772     jam();
1773     printState(signal, 5);
1774     sendSignalErrorRefuseLab(signal);
1775     return;
1776 
1777   case 56:{
1778     jam();
1779     terrorCode = ZNO_FREE_TC_MARKER;
1780     abortErrorLab(signal);
1781     return;
1782   }
1783   case 57:{
1784     jam();
1785     /**
1786      * Initialize object before starting error handling
1787      */
1788     initApiConnectRec(signal, apiConnectptr.p, true);
1789 start_failure:
1790     switch(getNodeState().startLevel){
1791     case NodeState::SL_STOPPING_2:
1792       if (getNodeState().getSingleUserMode())
1793       {
1794         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1795         break;
1796       }
1797     case NodeState::SL_STOPPING_3:
1798     case NodeState::SL_STOPPING_4:
1799       if(getNodeState().stopping.systemShutdown)
1800 	terrorCode  = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1801       else
1802 	terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1803       break;
1804     case NodeState::SL_SINGLEUSER:
1805       terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1806       break;
1807     case NodeState::SL_STOPPING_1:
1808       if (getNodeState().getSingleUserMode())
1809       {
1810         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1811         break;
1812       }
1813     default:
1814       terrorCode = ZWRONG_STATE;
1815       break;
1816     }
1817     abortErrorLab(signal);
1818     return;
1819   }
1820 
1821   case 58:{
1822     jam();
1823     releaseAtErrorLab(signal);
1824     return;
1825   }
1826 
1827   case 59:{
1828     jam();
1829     terrorCode = ZABORTINPROGRESS;
1830     abortErrorLab(signal);
1831     return;
1832   }
1833 
1834   case 60:
1835   {
1836     jam();
1837     initApiConnectRec(signal, apiConnectptr.p, true);
1838     apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
1839     goto start_failure;
1840   }
1841   case 61:
1842   {
1843     jam();
1844     terrorCode = ZUNLOCKED_IVAL_TOO_HIGH;
1845     abortErrorLab(signal);
1846     return;
1847   }
1848   case 62:
1849   {
1850     jam();
1851     terrorCode = ZUNLOCKED_OP_HAS_BAD_STATE;
1852     abortErrorLab(signal);
1853     return;
1854   }
1855   case 63:
1856   {
1857     jam();
1858     /* Function not implemented yet */
1859     terrorCode = 4003;
1860     abortErrorLab(signal);
1861     return;
1862   }
1863   case 64:
1864   {
1865     jam();
1866     /* Invalid distribution key */
1867     terrorCode = ZBAD_DIST_KEY;
1868     abortErrorLab(signal);
1869     return;
1870   }
1871   case 65:
1872   {
1873     jam();
1874     terrorCode = ZTRANS_TOO_BIG;
1875     abortErrorLab(signal);
1876     return;
1877   }
1878   default:
1879     jam();
1880     systemErrorLab(signal, __LINE__);
1881     return;
1882   }//switch
1883 }
1884 
1885 static
1886 inline
1887 bool
compare_transid(Uint32 * val0,Uint32 * val1)1888 compare_transid(Uint32* val0, Uint32* val1)
1889 {
1890   Uint32 tmp0 = val0[0] ^ val1[0];
1891   Uint32 tmp1 = val0[1] ^ val1[1];
1892   return (tmp0 | tmp1) == 0;
1893 }
1894 
execKEYINFO(Signal * signal)1895 void Dbtc::execKEYINFO(Signal* signal)
1896 {
1897   jamEntry();
1898   apiConnectptr.i = signal->theData[0];
1899   tmaxData = 20;
1900   if (apiConnectptr.i >= capiConnectFilesize) {
1901     TCKEY_abort(signal, 18);
1902     return;
1903   }//if
1904   ptrAss(apiConnectptr, apiConnectRecord);
1905   ttransid_ptr = 1;
1906   if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
1907   {
1908     TCKEY_abort(signal, 19);
1909     return;
1910   }//if
1911   switch (apiConnectptr.p->apiConnectstate) {
1912   case CS_RECEIVING:
1913   case CS_REC_COMMITTING:
1914   case CS_START_SCAN:
1915     jam();
1916     /*empty*/;
1917     break;
1918                 /* OK */
1919   case CS_ABORTING:
1920     jam();
1921     return;     /* IGNORE */
1922   case CS_CONNECTED:
1923     jam();
1924     /****************************************************************>*/
1925     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
1926     /*       SET STATE TO ABORTING.                                   */
1927     /****************************************************************>*/
1928     printState(signal, 11);
1929     signalErrorRefuseLab(signal);
1930     return;
1931   case CS_STARTED:
1932     jam();
1933     /****************************************************************>*/
1934     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
1935     /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
1936     /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
1937     /****************************************************************>*/
1938     terrorCode = ZSIGNAL_ERROR;
1939     printState(signal, 2);
1940     abortErrorLab(signal);
1941     return;
1942   default:
1943     jam();
1944     warningHandlerLab(signal, __LINE__);
1945     return;
1946   }//switch
1947 
1948   CacheRecord *localCacheRecord = cacheRecord;
1949   UintR TcacheFilesize = ccacheFilesize;
1950   UintR TcachePtr = apiConnectptr.p->cachePtr;
1951   UintR TtcTimer = ctcTimer;
1952   CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1953   if (TcachePtr >= TcacheFilesize) {
1954     TCKEY_abort(signal, 42);
1955     return;
1956   }//if
1957   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
1958   cachePtr.i = TcachePtr;
1959   cachePtr.p = regCachePtr;
1960 
1961   tcConnectptr.i = apiConnectptr.p->lastTcConnect;
1962   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
1963   switch (tcConnectptr.p->tcConnectstate) {
1964   case OS_WAIT_KEYINFO:
1965     jam();
1966     tckeyreq020Lab(signal);
1967     return;
1968   case OS_WAIT_SCAN:
1969     jam();
1970     scanKeyinfoLab(signal);
1971     return;
1972   default:
1973     jam();
1974     terrorCode = ZSTATE_ERROR;
1975     abortErrorLab(signal);
1976     return;
1977   }//switch
1978 }//Dbtc::execKEYINFO()
1979 
1980 /**
1981  * sendKeyInfoTrain
1982  * Method to send a KeyInfo signal train from KeyInfo in the supplied
1983  * Section
1984  * KeyInfo will be taken from the section, starting at the supplied
1985  * offset
1986  */
sendKeyInfoTrain(Signal * signal,BlockReference TBRef,Uint32 connectPtr,Uint32 offset,Uint32 sectionIVal)1987 void Dbtc::sendKeyInfoTrain(Signal* signal,
1988                             BlockReference TBRef,
1989                             Uint32 connectPtr,
1990                             Uint32 offset,
1991                             Uint32 sectionIVal)
1992 {
1993   jam();
1994 
1995   signal->theData[0] = connectPtr;
1996   signal->theData[1] = apiConnectptr.p->transid[0];
1997   signal->theData[2] = apiConnectptr.p->transid[1];
1998   Uint32 * dst = signal->theData + KeyInfo::HeaderLength;
1999 
2000   ndbassert( sectionIVal != RNIL );
2001   SectionReader keyInfoReader(sectionIVal, getSectionSegmentPool());
2002 
2003   Uint32 totalLen= keyInfoReader.getSize();
2004 
2005   ndbassert( offset < totalLen );
2006 
2007   keyInfoReader.step(offset);
2008   totalLen-= offset;
2009 
2010   while(totalLen != 0)
2011   {
2012     Uint32 dataInSignal= MIN(KeyInfo::DataLength, totalLen);
2013     keyInfoReader.getWords(dst, dataInSignal);
2014     totalLen-= dataInSignal;
2015 
2016     sendSignal(TBRef, GSN_KEYINFO, signal,
2017                KeyInfo::HeaderLength + dataInSignal, JBB);
2018   }
2019 }//Dbtc::sendKeyInfoTrain()
2020 
2021 /**
2022  * tckeyreq020Lab
2023  * Handle received KEYINFO signal
2024  */
tckeyreq020Lab(Signal * signal)2025 void Dbtc::tckeyreq020Lab(Signal* signal)
2026 {
2027   CacheRecord * const regCachePtr = cachePtr.p;
2028   UintR TkeyLen = regCachePtr->keylen;
2029   UintR Tlen = regCachePtr->save1;
2030   UintR wordsInSignal= MIN(KeyInfo::DataLength,
2031                            (TkeyLen - Tlen));
2032 
2033   ndbassert(! regCachePtr->isLongTcKeyReq );
2034   ndbassert( regCachePtr->keyInfoSectionI != RNIL );
2035 
2036   /* Add received KeyInfo data to the existing KeyInfo section */
2037   if (! appendToSection(regCachePtr->keyInfoSectionI,
2038                         &signal->theData[KeyInfo::HeaderLength],
2039                         wordsInSignal))
2040   {
2041     jam();
2042     appendToSectionErrorLab(signal);
2043     return;
2044   }
2045   Tlen+= wordsInSignal;
2046 
2047   if (Tlen < TkeyLen)
2048   {
2049     /* More KeyInfo still to be read
2050      * Set timer and state and wait
2051      */
2052     jam();
2053     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2054     regCachePtr->save1 = Tlen;
2055     tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2056     return;
2057   }
2058   else
2059   {
2060     /* Have all the KeyInfo ... continue processing
2061      * TCKEYREQ
2062      */
2063     jam();
2064     tckeyreq050Lab(signal);
2065     return;
2066   }
2067 }//Dbtc::tckeyreq020Lab()
2068 
execATTRINFO(Signal * signal)2069 void Dbtc::execATTRINFO(Signal* signal)
2070 {
2071   UintR Tdata1 = signal->theData[0];
2072   UintR Tlength = signal->length();
2073   UintR TapiConnectFilesize = capiConnectFilesize;
2074   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2075 
2076   jamEntry();
2077   apiConnectptr.i = Tdata1;
2078   ttransid_ptr = 1;
2079   if (Tdata1 >= TapiConnectFilesize) {
2080     DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2081     TCKEY_abort(signal, 18);
2082     return;
2083   }//if
2084 
2085   ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
2086   apiConnectptr.p = regApiPtr;
2087 
2088   if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
2089   {
2090     DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2091 	  << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2092     TCKEY_abort(signal, 19);
2093     return;
2094   }//if
2095   if (Tlength < 4) {
2096     DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2097     TCKEY_abort(signal, 20);
2098     return;
2099   }
2100   Tlength -= AttrInfo::HeaderLength;
2101   UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2102   UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2103   UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2104 
2105   if (TcompBOTH) {
2106     jam();
2107     if (ERROR_INSERTED(8015)) {
2108       CLEAR_ERROR_INSERT_VALUE;
2109       return;
2110     }//if
2111     if (ERROR_INSERTED(8016)) {
2112       CLEAR_ERROR_INSERT_VALUE;
2113       return;
2114     }//if
2115     CacheRecord *localCacheRecord = cacheRecord;
2116     UintR TcacheFilesize = ccacheFilesize;
2117     UintR TcachePtr = regApiPtr->cachePtr;
2118     UintR TtcTimer = ctcTimer;
2119     CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2120     if (TcachePtr >= TcacheFilesize) {
2121       TCKEY_abort(signal, 43);
2122       return;
2123     }//if
2124 
2125     /* Update TC global cache ptr */
2126     cachePtr.i= TcachePtr;
2127     cachePtr.p= regCachePtr;
2128 
2129     regCachePtr->currReclenAi+= Tlength;
2130     int TattrlengthRemain = regCachePtr->attrlength -
2131       regCachePtr->currReclenAi;
2132 
2133     /* Setup tcConnectptr to ensure that error handling etc.
2134      * can access required state
2135      */
2136     tcConnectptr.i = regApiPtr->lastTcConnect;
2137     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2138 
2139     /* Add AttrInfo to any existing AttrInfo we have
2140      * Some short TCKEYREQ signals have no ATTRINFO in
2141      * the TCKEYREQ itself
2142      */
2143     if (! appendToSection(regCachePtr->attrInfoSectionI,
2144                           &signal->theData[AttrInfo::HeaderLength],
2145                           Tlength))
2146     {
2147       DEBUG("No more section segments available");
2148       appendToSectionErrorLab(signal);
2149       return;
2150     }//if
2151 
2152     setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2153 
2154     if (TattrlengthRemain == 0) {
2155       /****************************************************************>*/
2156       /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS       */
2157       /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2158       /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2159       /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER          */
2160       /* OPERATIONS.                                                     */
2161       /****************************************************************>*/
2162       if (TcompRECEIVING) {
2163         jam();
2164         regApiPtr->apiConnectstate = CS_STARTED;
2165       } else {
2166         jam();
2167         regApiPtr->apiConnectstate = CS_START_COMMITTING;
2168       }//if
2169       attrinfoDihReceivedLab(signal);
2170     } else if (TattrlengthRemain < 0) {
2171       jam();
2172       DEBUG("ATTRINFO wrong total length="<<Tlength
2173 	    <<", TattrlengthRemain="<<TattrlengthRemain
2174 	    <<", TattrLen="<< regCachePtr->attrlength
2175 	    <<", TcurrReclenAi="<< regCachePtr->currReclenAi);
2176       tcConnectptr.i = regApiPtr->lastTcConnect;
2177       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2178       aiErrorLab(signal);
2179     }//if
2180     return;
2181   } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
2182     jam();
2183     scanAttrinfoLab(signal, Tlength);
2184     return;
2185   } else {
2186     switch (regApiPtr->apiConnectstate) {
2187     case CS_ABORTING:
2188       jam();
2189       /* JUST IGNORE THE SIGNAL*/
2190       // DEBUG("Drop ATTRINFO, CS_ABORTING");
2191       return;
2192     case CS_CONNECTED:
2193       jam();
2194       /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2195       // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2196       return;
2197     case CS_STARTED:
2198       jam();
2199       /****************************************************************>*/
2200       /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2201       /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
2202       /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
2203       /****************************************************************>*/
2204       terrorCode = ZSIGNAL_ERROR;
2205       printState(signal, 1);
2206       abortErrorLab(signal);
2207       return;
2208     default:
2209       jam();
2210       /****************************************************************>*/
2211       /*       SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2212       /*       SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED.    */
2213       /****************************************************************>*/
2214       DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2215       printState(signal, 9);
2216       return;
2217     }//switch
2218   }//if
2219 }//Dbtc::execATTRINFO()
2220 
2221 /* *********************************************************************>> */
2222 /*                                                                        */
2223 /*       MODULE: HASH MODULE                                              */
2224 /*       DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION                 */
2225 /* *********************************************************************> */
hash(Signal * signal)2226 void Dbtc::hash(Signal* signal)
2227 {
2228   UintR*  Tdata32;
2229 
2230   CacheRecord * const regCachePtr = cachePtr.p;
2231   SegmentedSectionPtr keyInfoSection;
2232   UintR keylen = (UintR)regCachePtr->keylen;
2233   Uint32 distKey = regCachePtr->distributionKeyIndicator;
2234 
2235   getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
2236 
2237   ndbassert( keyInfoSection.sz <= MAX_KEY_SIZE_IN_WORDS );
2238   ndbassert( keyInfoSection.sz == keylen );
2239   /* Copy KeyInfo section from segmented storage into linear storage
2240    * in signal->theData
2241    */
2242   if (keylen <= SectionSegment::DataLength)
2243   {
2244     /* No need to copy keyinfo into a linear space
2245      * Note that we require that the data in the section is
2246      * 64-bit aligned for md5_hash below
2247      */
2248     ndbassert( keyInfoSection.p != NULL );
2249 
2250     Tdata32= &keyInfoSection.p->theData[0];
2251   }
2252   else
2253   {
2254     /* Copy segmented keyinfo into linear space in the signal */
2255     Tdata32= signal->theData;
2256     copy(Tdata32, keyInfoSection);
2257   }
2258 
2259   Uint32 tmp[4];
2260   if(!regCachePtr->m_special_hash)
2261   {
2262     md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2263   }
2264   else
2265   {
2266     if (regCachePtr->m_no_hash)
2267     {
2268       /* No need for tuple key hash at LQH */
2269       ndbassert(distKey); /* User must supply distkey */
2270       Uint32 zero[4] = {0, 0, 0, 0};
2271       *tmp = *zero;
2272     }
2273     else
2274     {
2275       handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2276     }
2277   }
2278 
2279   /* Primary key hash value is first word of hash on PK columns
2280    * Distribution key hash value is second word of hash on distribution
2281    * key columns, or a user defined value
2282    */
2283   thashValue = tmp[0];
2284   if (distKey){
2285     jam();
2286     tdistrHashValue = regCachePtr->distributionKey;
2287   } else {
2288     jam();
2289     tdistrHashValue = tmp[1];
2290   }//if
2291 }//Dbtc::hash()
2292 
2293 bool
handle_special_hash(Uint32 dstHash[4],const Uint32 * src,Uint32 srcLen,Uint32 tabPtrI,bool distr)2294 Dbtc::handle_special_hash(Uint32 dstHash[4],
2295                           const Uint32* src, Uint32 srcLen,
2296 			  Uint32 tabPtrI,
2297 			  bool distr)
2298 {
2299   const Uint32 MAX_KEY_SIZE_IN_LONG_WORDS=
2300     (MAX_KEY_SIZE_IN_WORDS + 1) / 2;
2301   Uint64 alignedWorkspace[MAX_KEY_SIZE_IN_LONG_WORDS * MAX_XFRM_MULTIPLY];
2302   Uint32* workspace= (Uint32*)alignedWorkspace;
2303   const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2304   const bool hasVarKeys = tabPtrP->hasVarKeys;
2305   const bool hasCharAttr = tabPtrP->hasCharAttr;
2306   const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2307 
2308   const Uint32 *hashInput = workspace;
2309   Uint32 inputLen = 0;
2310   Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2311   Uint32 * keyPartLenPtr;
2312 
2313   /* Normalise KeyInfo into workspace if necessary */
2314   if(hasCharAttr || (compute_distkey && hasVarKeys))
2315   {
2316     keyPartLenPtr = keyPartLen;
2317     inputLen = xfrm_key(tabPtrI,
2318                         src,
2319                         workspace,
2320                         sizeof(alignedWorkspace) >> 2,
2321                         keyPartLenPtr);
2322     if (unlikely(inputLen == 0))
2323     {
2324       goto error;
2325     }
2326   }
2327   else
2328   {
2329     /* Keyinfo already suitable for hash */
2330     hashInput = src;
2331     inputLen = srcLen;
2332     keyPartLenPtr = 0;
2333   }
2334 
2335   /* Calculate primary key hash */
2336   md5_hash(dstHash, (Uint64*)hashInput, inputLen);
2337 
2338   /* If the distribution key != primary key then we have to
2339    * form a distribution key from the primary key and calculate
2340    * a separate distribution hash based on this
2341    */
2342   if(compute_distkey)
2343   {
2344     jam();
2345 
2346     Uint32 distrKeyHash[4];
2347     /* Reshuffle primary key columns to get just distribution key */
2348     Uint32 len = create_distr_key(tabPtrI, hashInput, workspace, keyPartLenPtr);
2349     /* Calculate distribution key hash */
2350     md5_hash(distrKeyHash, (Uint64*) workspace, len);
2351 
2352     /* Just one word used for distribution */
2353     dstHash[1] = distrKeyHash[1];
2354   }
2355   return true;  // success
2356 
2357 error:
2358   terrorCode = ZINVALID_KEY;
2359   return false;
2360 }
2361 
2362 /*
2363 INIT_API_CONNECT_REC
2364 ---------------------------
2365 */
2366 /* ========================================================================= */
2367 /* =======                       INIT_API_CONNECT_REC                ======= */
2368 /*                                                                           */
2369 /* ========================================================================= */
initApiConnectRec(Signal * signal,ApiConnectRecord * const regApiPtr,bool releaseIndexOperations)2370 void Dbtc::initApiConnectRec(Signal* signal,
2371                              ApiConnectRecord * const regApiPtr,
2372 			     bool releaseIndexOperations)
2373 {
2374   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2375   UintR TfailureNr = cfailure_nr;
2376   UintR Ttransid0 = tcKeyReq->transId1;
2377   UintR Ttransid1 = tcKeyReq->transId2;
2378 
2379   tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
2380   regApiPtr->returncode = 0;
2381   regApiPtr->returnsignal = RS_TCKEYCONF;
2382   ndbassert(regApiPtr->firstTcConnect == RNIL);
2383   regApiPtr->firstTcConnect = RNIL;
2384   regApiPtr->lastTcConnect = RNIL;
2385   regApiPtr->globalcheckpointid = 0;
2386   regApiPtr->lqhkeyconfrec = 0;
2387   regApiPtr->lqhkeyreqrec = 0;
2388   regApiPtr->tckeyrec = 0;
2389   regApiPtr->tcindxrec = 0;
2390   tc_clearbit(regApiPtr->m_flags,
2391               ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
2392   regApiPtr->no_commit_ack_markers = 0;
2393   regApiPtr->failureNr = TfailureNr;
2394   regApiPtr->transid[0] = Ttransid0;
2395   regApiPtr->transid[1] = Ttransid1;
2396   regApiPtr->commitAckMarker = RNIL;
2397   regApiPtr->buddyPtr = RNIL;
2398   regApiPtr->currSavePointId = 0;
2399   regApiPtr->m_transaction_nodes.clear();
2400   regApiPtr->singleUserMode = 0;
2401   regApiPtr->m_pre_commit_pass = 0;
2402   // Trigger data
2403   releaseFiredTriggerData(&regApiPtr->theFiredTriggers);
2404   // Index data
2405   tc_clearbit(regApiPtr->m_flags,
2406               ApiConnectRecord::TF_INDEX_OP_RETURN);
2407   regApiPtr->noIndexOp = 0;
2408   if(releaseIndexOperations)
2409     releaseAllSeizedIndexOperations(regApiPtr);
2410   regApiPtr->immediateTriggerId = RNIL;
2411 
2412   tc_clearbit(regApiPtr->m_flags,
2413               ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
2414   c_counters.ctransCount++;
2415 
2416 #ifdef ERROR_INSERT
2417   regApiPtr->continueBCount = 0;
2418 #endif
2419 
2420   regApiPtr->m_write_count = 0;
2421 }//Dbtc::initApiConnectRec()
2422 
2423 int
seizeTcRecord(Signal * signal)2424 Dbtc::seizeTcRecord(Signal* signal)
2425 {
2426   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2427   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
2428   UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
2429   UintR TtcConnectFilesize = ctcConnectFilesize;
2430   tcConnectptr.i = TfirstfreeTcConnect;
2431   if (TfirstfreeTcConnect >= TtcConnectFilesize) {
2432     int place = 3;
2433     if (TfirstfreeTcConnect != RNIL) {
2434       place = 10;
2435     }//if
2436     TCKEY_abort(signal, place);
2437     return 1;
2438   }//if
2439   //--------------------------------------------------------------------------
2440   // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
2441   //--------------------------------------------------------------------------
2442   TcConnectRecord * const regTcPtr =
2443                            &localTcConnectRecord[TfirstfreeTcConnect];
2444 
2445   UintR TlastTcConnect = regApiPtr->lastTcConnect;
2446   UintR TtcConnectptrIndex = tcConnectptr.i;
2447   TcConnectRecordPtr tmpTcConnectptr;
2448 
2449   cfirstfreeTcConnect = regTcPtr->nextTcConnect;
2450   tcConnectptr.p = regTcPtr;
2451 
2452   c_counters.cconcurrentOp++;
2453 
2454   regTcPtr->prevTcConnect = TlastTcConnect;
2455   regTcPtr->nextTcConnect = RNIL;
2456   regTcPtr->noFiredTriggers = 0;
2457   regTcPtr->noReceivedTriggers = 0;
2458   regTcPtr->triggerExecutionCount = 0;
2459   regTcPtr->triggeringOperation = RNIL;
2460   regTcPtr->m_special_op_flags = 0;
2461   regTcPtr->indexOp = RNIL;
2462   regTcPtr->currentTriggerId = RNIL;
2463   regTcPtr->tcConnectstate = OS_ABORTING;
2464   regTcPtr->noOfNodes = 0;
2465 
2466   regApiPtr->lastTcConnect = TtcConnectptrIndex;
2467 
2468   if (TlastTcConnect == RNIL) {
2469     jam();
2470     regApiPtr->firstTcConnect = TtcConnectptrIndex;
2471   } else {
2472     tmpTcConnectptr.i = TlastTcConnect;
2473     jam();
2474     ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
2475     tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
2476   }//if
2477   return 0;
2478 }//Dbtc::seizeTcRecord()
2479 
2480 int
seizeCacheRecord(Signal * signal)2481 Dbtc::seizeCacheRecord(Signal* signal)
2482 {
2483   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2484   UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2485   UintR TcacheFilesize = ccacheFilesize;
2486   CacheRecord *localCacheRecord = cacheRecord;
2487   if (TfirstfreeCacheRec >= TcacheFilesize) {
2488     TCKEY_abort(signal, 41);
2489     return 1;
2490   }//if
2491   CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
2492 
2493   regApiPtr->cachePtr = TfirstfreeCacheRec;
2494   cfirstfreeCacheRec = regCachePtr->nextCacheRec;
2495   cachePtr.i = TfirstfreeCacheRec;
2496   cachePtr.p = regCachePtr;
2497 
2498   regCachePtr->currReclenAi = 0;
2499   regCachePtr->keyInfoSectionI = RNIL;
2500   regCachePtr->attrInfoSectionI = RNIL;
2501   return 0;
2502 }//Dbtc::seizeCacheRecord()
2503 
2504 /*****************************************************************************/
2505 /*                               T C K E Y R E Q                             */
2506 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN      */
2507 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST   */
2508 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES       */
2509 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA                */
2510 /*****************************************************************************/
execTCKEYREQ(Signal * signal)2511 void Dbtc::execTCKEYREQ(Signal* signal)
2512 {
2513   Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
2514   UintR compare_transid1, compare_transid2;
2515   const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
2516   UintR Treqinfo;
2517   SectionHandle handle(this, signal);
2518 
2519   jamEntry();
2520   /*-------------------------------------------------------------------------
2521    * Common error routines are used for several signals, they need to know
2522    * where to find the transaction identifier in the signal.
2523    *-------------------------------------------------------------------------*/
2524   const UintR TapiIndex = tcKeyReq->apiConnectPtr;
2525   const UintR TapiMaxIndex = capiConnectFilesize;
2526   const UintR TtabIndex = tcKeyReq->tableId;
2527   const UintR TtabMaxIndex = ctabrecFilesize;
2528   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2529 
2530   ttransid_ptr = 6;
2531   apiConnectptr.i = TapiIndex;
2532   if (TapiIndex >= TapiMaxIndex) {
2533     releaseSections(handle);
2534     TCKEY_abort(signal, 6);
2535     return;
2536   }//if
2537   if (TtabIndex >= TtabMaxIndex) {
2538     releaseSections(handle);
2539     TCKEY_abort(signal, 7);
2540     return;
2541   }//if
2542 
2543 #ifdef ERROR_INSERT
2544   if (ERROR_INSERTED(8079))
2545   {
2546     /* Test that no signals received after API_FAILREQ */
2547     if (sendersNodeId == c_lastFailedApi)
2548     {
2549       /* Signal from API node received *after* API_FAILREQ */
2550       ndbrequire(false);
2551     }
2552   }
2553 #endif
2554 
2555   Treqinfo = tcKeyReq->requestInfo;
2556   //--------------------------------------------------------------------------
2557   // Optimised version of ptrAss(tabptr, tableRecord)
2558   // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
2559   //--------------------------------------------------------------------------
2560   ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
2561   apiConnectptr.p = regApiPtr;
2562 
2563   Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
2564   Uint32 TexecFlag =
2565     TcKeyReq::getExecuteFlag(Treqinfo) ? ApiConnectRecord::TF_EXEC_FLAG : 0;
2566 
2567   Uint8 Tspecial_op_flags = regApiPtr->m_special_op_flags;
2568   bool isIndexOpReturn = tc_testbit(regApiPtr->m_flags,
2569                                     ApiConnectRecord::TF_INDEX_OP_RETURN);
2570   bool isExecutingTrigger = Tspecial_op_flags & TcConnectRecord::SOF_TRIGGER;
2571   regApiPtr->m_special_op_flags = 0; // Reset marker
2572   regApiPtr->m_flags |= TexecFlag;
2573   TableRecordPtr localTabptr;
2574   localTabptr.i = TtabIndex;
2575   localTabptr.p = &tableRecord[TtabIndex];
2576   switch (regApiPtr->apiConnectstate) {
2577   case CS_CONNECTED:{
2578     if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2579       //---------------------------------------------------------------------
2580       // Initialise API connect record if transaction is started.
2581       //---------------------------------------------------------------------
2582       jam();
2583       initApiConnectRec(signal, regApiPtr);
2584       regApiPtr->m_flags |= TexecFlag;
2585     } else {
2586       releaseSections(handle);
2587       if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2588 	/*------------------------------------------------------------------
2589 	 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
2590 	 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
2591 	 * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
2592 	 *-----------------------------------------------------------------*/
2593 	TCKEY_abort(signal, 0);
2594 	return;
2595       } else {
2596 	/**
2597 	 * getAllowStartTransaction(sendersNodeId) == false
2598 	 */
2599 	TCKEY_abort(signal, TexecFlag ? 60 : 57);
2600 	return;
2601       }//if
2602     }
2603   }
2604   break;
2605   case CS_STARTED:
2606     if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
2607     {
2608       /**
2609        * If last operation in last transaction was a simple/dirty read
2610        *  it does not have to be committed or rollbacked hence,
2611        *  the state will be CS_STARTED
2612        */
2613       jam();
2614       if (unlikely(getNodeState().getSingleUserMode()) &&
2615           getNodeState().getSingleUserApi() != sendersNodeId &&
2616           !localTabptr.p->singleUserMode)
2617       {
2618         releaseSections(handle);
2619 	TCKEY_abort(signal, TexecFlag ? 60 : 57);
2620         return;
2621       }
2622       initApiConnectRec(signal, regApiPtr);
2623       regApiPtr->m_flags |= TexecFlag;
2624     } else {
2625       //----------------------------------------------------------------------
2626       // Transaction is started already.
2627       // Check that the operation is on the same transaction.
2628       //-----------------------------------------------------------------------
2629       compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
2630       compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
2631       jam();
2632       compare_transid1 = compare_transid1 | compare_transid2;
2633       if (compare_transid1 != 0) {
2634         releaseSections(handle);
2635 	TCKEY_abort(signal, 1);
2636 	return;
2637       }//if
2638     }
2639     break;
2640   case CS_ABORTING:
2641     if (regApiPtr->abortState == AS_IDLE) {
2642       if (TstartFlag == 1) {
2643         if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
2644           releaseSections(handle);
2645           TCKEY_abort(signal, TexecFlag ? 60 : 57);
2646           return;
2647         }
2648 	//--------------------------------------------------------------------
2649 	// Previous transaction had been aborted and the abort was completed.
2650 	// It is then OK to start a new transaction again.
2651 	//--------------------------------------------------------------------
2652         jam();
2653         initApiConnectRec(signal, regApiPtr);
2654 	regApiPtr->m_flags |= TexecFlag;
2655       } else if(TexecFlag) {
2656         releaseSections(handle);
2657 	TCKEY_abort(signal, 59);
2658 	return;
2659       } else {
2660 	//--------------------------------------------------------------------
2661 	// The current transaction was aborted successfully.
2662 	// We will not do anything before we receive an operation
2663 	// with a start indicator. We will ignore this signal.
2664 	//--------------------------------------------------------------------
2665 	jam();
2666 	DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
2667         releaseSections(handle);
2668         return;
2669       }//if
2670     } else {
2671       //----------------------------------------------------------------------
2672       // Previous transaction is still aborting
2673       //----------------------------------------------------------------------
2674       jam();
2675       releaseSections(handle);
2676       if (TstartFlag == 1) {
2677 	//--------------------------------------------------------------------
2678 	// If a new transaction tries to start while the old is
2679 	// still aborting, we will report this to the starting API.
2680 	//--------------------------------------------------------------------
2681         TCKEY_abort(signal, 2);
2682         return;
2683       } else if(TexecFlag) {
2684         TCKEY_abort(signal, 59);
2685         return;
2686       }
2687       //----------------------------------------------------------------------
2688       // Ignore signals without start indicator set when aborting transaction.
2689       //----------------------------------------------------------------------
2690       DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
2691       return;
2692     }//if
2693     break;
2694   case CS_START_COMMITTING:
2695   case CS_SEND_FIRE_TRIG_REQ:
2696   case CS_WAIT_FIRE_TRIG_REQ:
2697     jam();
2698     if(isIndexOpReturn || isExecutingTrigger){
2699       break;
2700     }
2701   default:
2702     jam();
2703     /*----------------------------------------------------------------------
2704      * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
2705      * WHEN IT WAS NOT EXPECTED TO.
2706      * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
2707      * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
2708      * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
2709      * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
2710      * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
2711      *---------------------------------------------------------------------*/
2712     releaseSections(handle);
2713     TCKEY_abort(signal, 55);
2714     return;
2715   }//switch
2716 
2717   if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
2718     ;
2719   } else {
2720     /*-----------------------------------------------------------------------*/
2721     /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT.  */
2722     /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED.                          */
2723     /*-----------------------------------------------------------------------*/
2724     releaseSections(handle);
2725     TCKEY_abort(signal, 8);
2726     return;
2727   }//if
2728 
2729   //-------------------------------------------------------------------------
2730   // Error Insertion for testing purposes. Test to see what happens when no
2731   // more TC records available.
2732   //-------------------------------------------------------------------------
2733   if (ERROR_INSERTED(8032)) {
2734     releaseSections(handle);
2735     TCKEY_abort(signal, 3);
2736     return;
2737   }//if
2738 
2739   if (seizeTcRecord(signal) != 0) {
2740     releaseSections(handle);
2741     return;
2742   }//if
2743 
2744   if (seizeCacheRecord(signal) != 0) {
2745     releaseSections(handle);
2746     return;
2747   }//if
2748 
2749   CRASH_INSERTION(8063);
2750 
2751   TcConnectRecord * const regTcPtr = tcConnectptr.p;
2752   CacheRecord * const regCachePtr = cachePtr.p;
2753 
2754   /*
2755     INIT_TC_CONNECT_REC
2756     -------------------------
2757   */
2758   /* ---------------------------------------------------------------------- */
2759   /* -------     INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS   ------- */
2760   /*                                                                        */
2761   /* ---------------------------------------------------------------------- */
2762 
2763   UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen);
2764   UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
2765   regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
2766   regCachePtr->apiVersionNo = TapiVersionNo;
2767 
2768   /* If we have any sections at all then this is a long TCKEYREQ */
2769   regCachePtr->isLongTcKeyReq= ( handle.m_cnt != 0 );
2770 
2771   UintR TapiConnectptrIndex = apiConnectptr.i;
2772   UintR TsenderData = tcKeyReq->senderData;
2773 
2774   if (ERROR_INSERTED(8065))
2775   {
2776     ErrorSignalReceive= 1;
2777     ErrorMaxSegmentsToSeize= 10;
2778   }
2779   if (ERROR_INSERTED(8066))
2780   {
2781     ErrorSignalReceive= 1;
2782     ErrorMaxSegmentsToSeize= 1;
2783   }
2784   if (ERROR_INSERTED(8067))
2785   {
2786     ErrorSignalReceive= 1;
2787     ErrorMaxSegmentsToSeize= 0;
2788   }
2789   if (ERROR_INSERTED(8068))
2790   {
2791     ErrorSignalReceive= 0;
2792     ErrorMaxSegmentsToSeize= 0;
2793     CLEAR_ERROR_INSERT_VALUE;
2794     DEBUG("Max segments to seize cleared");
2795   }
2796 #ifdef ERROR_INSERT
2797   if (ErrorSignalReceive)
2798     DEBUG("Max segments to seize : "
2799           << ErrorMaxSegmentsToSeize);
2800 #endif
2801 
2802   /* Key and attribute lengths are passed in the header for
2803    * short TCKEYREQ and  passed as section lengths for long
2804    * TCKEYREQ
2805    */
2806   UintR TkeyLength = 0;
2807   UintR TattrLen = 0;
2808   UintR titcLenAiInTckeyreq = 0;
2809 
2810   if (regCachePtr->isLongTcKeyReq)
2811   {
2812     SegmentedSectionPtr keyInfoSec;
2813     if (handle.getSection(keyInfoSec, TcKeyReq::KeyInfoSectionNum))
2814       TkeyLength= keyInfoSec.sz;
2815 
2816     SegmentedSectionPtr attrInfoSec;
2817     if (handle.getSection(attrInfoSec, TcKeyReq::AttrInfoSectionNum))
2818       TattrLen= attrInfoSec.sz;
2819 
2820     if (TcKeyReq::getDeferredConstraints(Treqinfo))
2821     {
2822       regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
2823     }
2824   }
2825   else
2826   {
2827     TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
2828     TattrLen= TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
2829     titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
2830   }
2831 
2832   regCachePtr->keylen = TkeyLength;
2833   regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
2834   regCachePtr->currReclenAi = titcLenAiInTckeyreq;
2835 
2836   regTcPtr->apiConnect = TapiConnectptrIndex;
2837   regTcPtr->clientData = TsenderData;
2838   regTcPtr->commitAckMarker = RNIL;
2839   regTcPtr->m_special_op_flags = Tspecial_op_flags;
2840   regTcPtr->indexOp = regApiPtr->executingIndexOp;
2841   regTcPtr->savePointId = regApiPtr->currSavePointId;
2842   regApiPtr->executingIndexOp = RNIL;
2843 
2844   regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
2845 
2846   if (isExecutingTrigger)
2847   {
2848     // Save the TcOperationPtr for fireing operation
2849     regTcPtr->triggeringOperation = TsenderData;
2850     // Grab trigger Id from ApiConnectRecord
2851     ndbrequire(regApiPtr->immediateTriggerId != RNIL);
2852     regTcPtr->currentTriggerId= regApiPtr->immediateTriggerId;
2853   }
2854   ndbassert(isExecutingTrigger ||
2855             (regApiPtr->immediateTriggerId == RNIL));
2856 
2857   if (TexecFlag){
2858     Uint32 currSPId = regApiPtr->currSavePointId;
2859     regApiPtr->currSavePointId = ++currSPId;
2860   }
2861 
2862   regCachePtr->attrlength = TattrLen;
2863   c_counters.cattrinfoCount += TattrLen;
2864 
2865   UintR TtabptrIndex = localTabptr.i;
2866   UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
2867   Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
2868   regCachePtr->tableref = TtabptrIndex;
2869   regCachePtr->schemaVersion = TtableSchemaVersion;
2870   regTcPtr->operation = TOperationType;
2871 
2872   Uint8 TSimpleFlag         = TcKeyReq::getSimpleFlag(Treqinfo);
2873   Uint8 TDirtyFlag          = TcKeyReq::getDirtyFlag(Treqinfo);
2874   Uint8 TInterpretedFlag    = TcKeyReq::getInterpretedFlag(Treqinfo);
2875   Uint8 TDistrKeyFlag       = TcKeyReq::getDistributionKeyFlag(Treqinfo);
2876   Uint8 TNoDiskFlag         = TcKeyReq::getNoDiskFlag(Treqinfo);
2877   Uint8 TexecuteFlag        = TexecFlag;
2878   Uint8 Treorg              = TcKeyReq::getReorgFlag(Treqinfo);
2879   const Uint8 TViaSPJFlag   = TcKeyReq::getViaSPJFlag(Treqinfo);
2880   const Uint8 Tqueue        = TcKeyReq::getQueueOnRedoProblemFlag(Treqinfo);
2881 
2882   if (Treorg)
2883   {
2884     if (TOperationType == ZWRITE)
2885       regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_COPY;
2886     else if (TOperationType == ZDELETE)
2887       regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_DELETE;
2888     else
2889     {
2890       ndbassert(false);
2891     }
2892   }
2893 
2894   regTcPtr->dirtyOp  = TDirtyFlag;
2895   regTcPtr->opSimple = TSimpleFlag;
2896   regCachePtr->opExec   = TInterpretedFlag;
2897   regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
2898   regCachePtr->m_no_disk_flag = TNoDiskFlag;
2899   regCachePtr->viaSPJFlag = TViaSPJFlag;
2900   regCachePtr->m_op_queue = Tqueue;
2901 
2902   //-------------------------------------------------------------
2903   // The next step is to read the upto three conditional words.
2904   //-------------------------------------------------------------
2905   Uint32 TkeyIndex;
2906   Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
2907   {
2908     Uint32  TDistrGHIndex    = TcKeyReq::getScanIndFlag(Treqinfo);
2909     Uint32  TDistrKeyIndex   = TDistrGHIndex;
2910 
2911     Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
2912 
2913     regCachePtr->scanTakeOverInd = TDistrGHIndex;
2914     regCachePtr->scanInfo = TscanInfo;
2915 
2916     regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
2917 
2918     TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
2919   }
2920 
2921   regCachePtr->m_no_hash = false;
2922 
2923   if (TOperationType == ZUNLOCK)
2924   {
2925     /* Unlock op has distribution key containing
2926      * LQH nodeid and fragid
2927      */
2928     ndbassert( regCachePtr->distributionKeyIndicator );
2929     regCachePtr->m_no_hash = 1;
2930     regCachePtr->unlockNodeId = (regCachePtr->distributionKey >> 16);
2931     regCachePtr->distributionKey &= 0xffff;
2932   }
2933 
2934   regCachePtr->m_special_hash =
2935     localTabptr.p->hasCharAttr |
2936     (localTabptr.p->noOfDistrKeys > 0) |
2937     regCachePtr->m_no_hash;
2938 
2939   if (TkeyLength == 0)
2940   {
2941     releaseSections(handle);
2942     TCKEY_abort(signal, 4);
2943     return;
2944   }
2945 
2946   /* KeyInfo and AttrInfo are buffered in segmented sections
2947    * If they arrived in segmented sections then there's nothing to do
2948    * If they arrived in short signals then they are appended into
2949    * segmented sections
2950    */
2951   if (regCachePtr->isLongTcKeyReq)
2952   {
2953     ndbassert( titcLenAiInTckeyreq == 0);
2954     /* Long TcKeyReq - KI and AI already in sections */
2955     SegmentedSectionPtr keyInfoSection, attrInfoSection;
2956 
2957     /* Store i value for first long section of KeyInfo
2958      * and AttrInfo in Cache Record
2959      */
2960     handle.getSection(keyInfoSection,
2961                       TcKeyReq::KeyInfoSectionNum);
2962 
2963     regCachePtr->keyInfoSectionI= keyInfoSection.i;
2964 
2965     if (regCachePtr->attrlength != 0)
2966     {
2967       ndbassert( handle.m_cnt == 2 );
2968       handle.getSection(attrInfoSection,
2969                         TcKeyReq::AttrInfoSectionNum);
2970       regCachePtr->attrInfoSectionI= attrInfoSection.i;
2971     }
2972     else
2973     {
2974       ndbassert( handle.m_cnt == 1 );
2975     }
2976 
2977     /* Detach sections from the handle, we are now responsible
2978      * for always freeing them before returning
2979      * For a long TcKeyReq, they will be freed at the end
2980      * of the processing this signal.
2981      */
2982     handle.clear();
2983   }
2984   else
2985   {
2986     /* Short TcKeyReq - need to receive KI and AI into
2987      * segmented sections
2988      * We store any KI and AI from the TCKeyReq now and
2989      * will then wait for further signals if necessary
2990      */
2991     ndbassert( handle.m_cnt == 0 );
2992     Uint32 keyInfoInTCKeyReq= MIN(TkeyLength, TcKeyReq::MaxKeyInfo);
2993 
2994     bool ok= appendToSection(regCachePtr->keyInfoSectionI,
2995                              &TOptionalDataPtr[TkeyIndex],
2996                              keyInfoInTCKeyReq);
2997     if (!ok)
2998     {
2999       jam();
3000       appendToSectionErrorLab(signal);
3001       return;
3002     }
3003 
3004     if (titcLenAiInTckeyreq != 0)
3005     {
3006       Uint32 TAIDataIndex= TkeyIndex + keyInfoInTCKeyReq;
3007 
3008       ok= appendToSection(regCachePtr->attrInfoSectionI,
3009                           &TOptionalDataPtr[TAIDataIndex],
3010                           titcLenAiInTckeyreq);
3011       if (!ok)
3012       {
3013         jam();
3014         appendToSectionErrorLab(signal);
3015         return;
3016       }
3017     }
3018   }
3019 
3020   if (TOperationType == ZUNLOCK)
3021   {
3022     jam();
3023     // TODO : Consider adding counter for unlock operations
3024   }
3025   else if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
3026     jam();
3027     c_counters.creadCount++;
3028   }
3029   else
3030   {
3031     /* Insert, Update, Write, Delete */
3032     if (!tc_testbit(regApiPtr->m_flags,
3033                     ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED))
3034     {
3035       if(regApiPtr->commitAckMarker != RNIL)
3036         regTcPtr->commitAckMarker = regApiPtr->commitAckMarker;
3037       else
3038       {
3039         jam();
3040         CommitAckMarkerPtr tmp;
3041         if (ERROR_INSERTED(8087))
3042         {
3043           CLEAR_ERROR_INSERT_VALUE;
3044           TCKEY_abort(signal, 56);
3045           return;
3046         }
3047 
3048         if (!m_commitAckMarkerHash.seize(tmp))
3049         {
3050           TCKEY_abort(signal, 56);
3051           return;
3052         }
3053         else
3054         {
3055           regTcPtr->commitAckMarker = tmp.i;
3056           regApiPtr->commitAckMarker = tmp.i;
3057           tmp.p->transid1      = tcKeyReq->transId1;
3058           tmp.p->transid2      = tcKeyReq->transId2;
3059           tmp.p->apiNodeId     = refToNode(regApiPtr->ndbapiBlockref);
3060           tmp.p->apiConnectPtr = TapiIndex;
3061           tmp.p->m_commit_ack_marker_nodes.clear();
3062 #if defined VM_TRACE || defined ERROR_INSERT
3063 	  {
3064 	    CommitAckMarkerPtr check;
3065 	    ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
3066           }
3067 #endif
3068           m_commitAckMarkerHash.add(tmp);
3069         }
3070       }
3071       regApiPtr->no_commit_ack_markers++;
3072     }
3073 
3074     UintR Toperationsize = coperationsize;
3075     /* --------------------------------------------------------------------
3076      *   THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
3077      *   THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
3078      *   TEMP TABLES DON'T PARTICIPATE.
3079      * -------------------------------------------------------------------- */
3080     if (localTabptr.p->get_storedTable()) {
3081       coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
3082     }
3083     c_counters.cwriteCount++;
3084     switch (TOperationType) {
3085     case ZUPDATE:
3086     case ZINSERT:
3087     case ZDELETE:
3088     case ZWRITE:
3089     case ZREFRESH:
3090       jam();
3091       if (unlikely((++ regApiPtr->m_write_count) > m_max_writes_per_trans))
3092       {
3093         TCKEY_abort(signal, 65);
3094         return;
3095       }
3096       break;
3097     default:
3098       TCKEY_abort(signal, 9);
3099       return;
3100     }//switch
3101   }//if
3102 
3103   Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
3104   regTcPtr->m_execAbortOption = TabortOption;
3105 
3106   /*-------------------------------------------------------------------------
3107    * Check error handling per operation
3108    * If CommitFlag is set state accordingly and check for early abort
3109    *------------------------------------------------------------------------*/
3110   if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
3111     ndbrequire(TexecuteFlag);
3112     regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3113   } else {
3114     /* ---------------------------------------------------------------------
3115      *       PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
3116      * ---------------------------------------------------------------------
3117      *       ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
3118      * IF PREPARE TRANSACTION THEN
3119      *   API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
3120      * SET STATE TO PREPARING
3121      * --------------------------------------------------------------------- */
3122     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3123       jam();
3124       // Trigger execution at commit
3125       regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3126     } else if (!regApiPtr->isExecutingDeferredTriggers()) {
3127       jam();
3128       regApiPtr->apiConnectstate = CS_RECEIVING;
3129     }//if
3130   }//if
3131 
3132   if (regCachePtr->isLongTcKeyReq)
3133   {
3134     jam();
3135     /* Have all the KeyInfo (and AttrInfo), process now */
3136     tckeyreq050Lab(signal);
3137   }
3138   else if (TkeyLength <= TcKeyReq::MaxKeyInfo)
3139   {
3140     jam();
3141     /* Have all the KeyInfo, get any extra AttrInfo */
3142     tckeyreq050Lab(signal);
3143   }
3144   else
3145   {
3146     jam();
3147     /* --------------------------------------------------------------------
3148      * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
3149      * SAVE STATE AND WAIT FOR KEYINFO
3150      * --------------------------------------------------------------------*/
3151     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
3152     regCachePtr->save1 = 8;
3153     regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
3154     return;
3155   }//if
3156 
3157   return;
3158 }//Dbtc::execTCKEYREQ()
3159 
3160 static
3161 void
handle_reorg_trigger(DiGetNodesConf * conf)3162 handle_reorg_trigger(DiGetNodesConf * conf)
3163 {
3164   if (conf->reqinfo & DiGetNodesConf::REORG_MOVING)
3165   {
3166     conf->fragId = conf->nodes[MAX_REPLICAS];
3167     conf->reqinfo = conf->nodes[MAX_REPLICAS+1];
3168     memcpy(conf->nodes, conf->nodes+MAX_REPLICAS+2, sizeof(conf->nodes));
3169   }
3170   else
3171   {
3172     conf->nodes[0] = 0; // Should not execute...
3173   }
3174 }
3175 
3176 bool
isRefreshSupported() const3177 Dbtc::isRefreshSupported() const
3178 {
3179   const NodeVersionInfo& nvi = getNodeVersionInfo();
3180   const Uint32 minVer = nvi.m_type[NodeInfo::DB].m_min_version;
3181   const Uint32 maxVer = nvi.m_type[NodeInfo::DB].m_max_version;
3182 
3183   if (likely (minVer == maxVer))
3184   {
3185     /* Normal case, use function */
3186     return ndb_refresh_tuple(minVer);
3187   }
3188 
3189   /* As refresh feature was introduced across three minor versions
3190    * we check that all data nodes support it.  This slow path
3191    * should only be hit during upgrades between versions
3192    */
3193   for (Uint32 i=1; i < MAX_NODES; i++)
3194   {
3195     const NodeInfo& nodeInfo = getNodeInfo(i);
3196     if ((nodeInfo.m_type == NODE_TYPE_DB) &&
3197         (nodeInfo.m_connected) &&
3198         (! ndb_refresh_tuple(nodeInfo.m_version)))
3199       return false;
3200   }
3201   return true;
3202 }
3203 
3204 /**
3205  * tckeyreq050Lab
3206  * This method is executed once all KeyInfo has been obtained for
3207  * the TcKeyReq signal
3208  */
tckeyreq050Lab(Signal * signal)3209 void Dbtc::tckeyreq050Lab(Signal* signal)
3210 {
3211   UintR tnoOfBackup;
3212   UintR tnoOfStandby;
3213   UintR tnodeinfo;
3214 
3215   terrorCode = 0;
3216 
3217   hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
3218 
3219   CacheRecord * const regCachePtr = cachePtr.p;
3220   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3221   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3222 
3223   UintR TtcTimer = ctcTimer;
3224   UintR ThashValue = thashValue;
3225   UintR TdistrHashValue = tdistrHashValue;
3226   UintR Ttableref = regCachePtr->tableref;
3227   Uint8 Tspecial_op_flags = regTcPtr->m_special_op_flags;
3228 
3229   TableRecordPtr localTabptr;
3230   localTabptr.i = Ttableref;
3231   localTabptr.p = &tableRecord[localTabptr.i];
3232   Uint32 schemaVersion = regCachePtr->schemaVersion;
3233   if(localTabptr.p->checkTable(schemaVersion)){
3234     ;
3235   } else {
3236     terrorCode = localTabptr.p->getErrorCode(schemaVersion);
3237     TCKEY_abort(signal, 58);
3238     return;
3239   }
3240 
3241   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3242   regCachePtr->hashValue = ThashValue;
3243 
3244   ndbassert( signal->getNoOfSections() == 0 );
3245 
3246   DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
3247   req->tableId = Ttableref;
3248   req->hashValue = TdistrHashValue;
3249   req->distr_key_indicator = regCachePtr->distributionKeyIndicator;
3250   * (EmulatedJamBuffer**)req->jamBuffer = jamBuffer();
3251 
3252   /*-------------------------------------------------------------*/
3253   /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
3254   /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE   */
3255   /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION.   */
3256   /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
3257   /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
3258   /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB.            */
3259   /*-------------------------------------------------------------*/
3260   EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
3261                  DiGetNodesReq::SignalLength, 0);
3262   DiGetNodesConf * conf = (DiGetNodesConf *)&signal->theData[0];
3263   UintR Tdata2 = conf->reqinfo;
3264   UintR TerrorIndicator = signal->theData[0];
3265   jamEntry();
3266   if (TerrorIndicator != 0) {
3267     execDIGETNODESREF(signal);
3268     return;
3269   }
3270 
3271   if((ERROR_INSERTED(8071) || ERROR_INSERTED(8072)) &&
3272      (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) &&
3273      signal->theData[3] != getOwnNodeId())
3274   {
3275     ndbassert(false);
3276     signal->theData[1] = 626;
3277     execDIGETNODESREF(signal);
3278     return;
3279   }
3280 
3281   if((ERROR_INSERTED(8050) || ERROR_INSERTED(8072)) &&
3282      refToBlock(regApiPtr->ndbapiBlockref) != DBUTIL &&
3283      regTcPtr->m_special_op_flags == 0 &&
3284      signal->theData[3] != getOwnNodeId())
3285   {
3286     ndbassert(false);
3287     signal->theData[1] = 626;
3288     execDIGETNODESREF(signal);
3289     return;
3290   }
3291 
3292   /****************>>*/
3293   /* DIGETNODESCONF >*/
3294   /* ***************>*/
3295   if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_TRIGGER_BASE)
3296   {
3297     jam();
3298     handle_reorg_trigger(conf);
3299     Tdata2 = conf->reqinfo;
3300   }
3301   else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_DELETE)
3302   {
3303     jam();
3304     handle_reorg_trigger(conf);
3305     Tdata2 = conf->reqinfo;
3306   }
3307   else if (Tdata2 & DiGetNodesConf::REORG_MOVING)
3308   {
3309     jam();
3310     regTcPtr->m_special_op_flags |= TcConnectRecord::SOF_REORG_MOVING;
3311   }
3312   else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_COPY)
3313   {
3314     jam();
3315     conf->nodes[0] = 0;
3316   }
3317 
3318   UintR Tdata1 = conf->fragId;
3319   UintR Tdata3 = conf->nodes[0];
3320   UintR Tdata4 = conf->nodes[1];
3321   UintR Tdata5 = conf->nodes[2];
3322   UintR Tdata6 = conf->nodes[3];
3323 
3324   regCachePtr->fragmentid = Tdata1;
3325   tnodeinfo = Tdata2;
3326 
3327   regTcPtr->tcNodedata[0] = Tdata3;
3328   regTcPtr->tcNodedata[1] = Tdata4;
3329   regTcPtr->tcNodedata[2] = Tdata5;
3330   regTcPtr->tcNodedata[3] = Tdata6;
3331 
3332   regTcPtr->lqhInstanceKey = (Tdata2 >> 24) & 127;// 1 bit used for reorg moving
3333 
3334   Uint8 Toperation = regTcPtr->operation;
3335   Uint8 TopSimple = regTcPtr->opSimple;
3336   Uint8 TopDirty = regTcPtr->dirtyOp;
3337   tnoOfBackup = tnodeinfo & 3;
3338   tnoOfStandby = (tnodeinfo >> 8) & 3;
3339 
3340   regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
3341   if (Toperation == ZREAD || Toperation == ZREAD_EX)
3342   {
3343     regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3344     if (TopSimple == 1 && TopDirty == 0){
3345       jam();
3346       /*-------------------------------------------------------------*/
3347       /*       A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND       */
3348       /*       BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS      */
3349       /*       NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION   */
3350       /*       WITH SIMPLE READS.                                    */
3351       /*-------------------------------------------------------------*/
3352       arrGuard(tnoOfBackup, MAX_REPLICAS);
3353       UintR Tindex;
3354       UintR TownNode = cownNodeid;
3355       for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
3356         UintR Tnode = regTcPtr->tcNodedata[Tindex];
3357         jam();
3358         if (Tnode == TownNode) {
3359           jam();
3360           regTcPtr->tcNodedata[0] = Tnode;
3361         }//if
3362       }//for
3363       if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
3364       {
3365 	for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
3366 	{
3367 	  UintR Tnode = regTcPtr->tcNodedata[Tindex];
3368 	  jam();
3369 	  if (Tnode != TownNode) {
3370 	    jam();
3371 	    regTcPtr->tcNodedata[0] = Tnode;
3372 	    ndbout_c("Choosing %d", Tnode);
3373 	  }//if
3374 	}//for
3375       }
3376     }//if
3377     jam();
3378     regTcPtr->lastReplicaNo = 0;
3379     regTcPtr->noOfNodes = 1;
3380   }
3381   else if (Toperation == ZUNLOCK)
3382   {
3383     regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
3384 
3385     const Uint32 numNodes = tnoOfBackup + 1;
3386     /* Check that node from dist key is one of the nodes returned */
3387     bool found = false;
3388     for (Uint32 idx = 0; idx < numNodes; idx ++)
3389     {
3390       Uint32 nodeId = regTcPtr->tcNodedata[ idx ];
3391       jam();
3392       if (nodeId == regCachePtr->unlockNodeId)
3393       {
3394         jam();
3395         found = true;
3396         break;
3397       }
3398     }
3399 
3400     if (unlikely(!found))
3401     {
3402       /* DIH says the specified node does not store the fragment
3403        * requested
3404        */
3405       jam();
3406       TCKEY_abort(signal, 64);
3407       return;
3408     }
3409 
3410     /* Check that the relevant LQH node can handle an unlock request */
3411     Uint32 lqhVersion = getNodeInfo(regCachePtr->unlockNodeId).m_version;
3412 
3413     if (unlikely( lqhVersion < NDBD_UNLOCK_OP_SUPPORTED ))
3414     {
3415       TCKEY_abort(signal, 63);
3416       return;
3417     }
3418 
3419     /* Select the specified node for the unlock op */
3420     regTcPtr->tcNodedata[0] = regCachePtr->unlockNodeId;
3421     regTcPtr->lastReplicaNo = 0;
3422     regTcPtr->noOfNodes = 1;
3423   }
3424   else {
3425     UintR TlastReplicaNo;
3426     jam();
3427     TlastReplicaNo = tnoOfBackup + tnoOfStandby;
3428     regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
3429     regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
3430 
3431     if (unlikely((Toperation == ZREFRESH) &&
3432                  (! isRefreshSupported())))
3433     {
3434       /* Function not implemented yet */
3435       TCKEY_abort(signal,63);
3436       return;
3437     }
3438   }//if
3439 
3440   if (regCachePtr->isLongTcKeyReq ||
3441       (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength)) {
3442     /****************************************************************>*/
3443     /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS      */
3444     /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
3445     /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
3446     /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER         */
3447     /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
3448     /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET.                */
3449     /****************************************************************>*/
3450     switch (regApiPtr->apiConnectstate) {
3451     case CS_RECEIVING:
3452       jam();
3453       regApiPtr->apiConnectstate = CS_STARTED;
3454       break;
3455     case CS_REC_COMMITTING:
3456       jam();
3457       regApiPtr->apiConnectstate = CS_START_COMMITTING;
3458       break;
3459     case CS_SEND_FIRE_TRIG_REQ:
3460     case CS_WAIT_FIRE_TRIG_REQ:
3461       jam();
3462       break;
3463     default:
3464       jam();
3465       systemErrorLab(signal, __LINE__);
3466       return;
3467     }//switch
3468     attrinfoDihReceivedLab(signal);
3469     return;
3470   } else {
3471     if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
3472       TtcTimer = ctcTimer;
3473       jam();
3474       setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3475       regTcPtr->tcConnectstate = OS_WAIT_ATTR;
3476       return;
3477     } else {
3478       TCKEY_abort(signal, 11);
3479       return;
3480     }//if
3481   }//if
3482   return;
3483 }//Dbtc::tckeyreq050Lab()
3484 
attrinfoDihReceivedLab(Signal * signal)3485 void Dbtc::attrinfoDihReceivedLab(Signal* signal)
3486 {
3487   CacheRecord * const regCachePtr = cachePtr.p;
3488   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3489   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3490   Uint16 Tnode = regTcPtr->tcNodedata[0];
3491 
3492   TableRecordPtr localTabptr;
3493   localTabptr.i = regCachePtr->tableref;
3494   localTabptr.p = &tableRecord[localTabptr.i];
3495 
3496   if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
3497     ;
3498   } else {
3499     terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
3500     TCKEY_abort(signal, 58);
3501     return;
3502   }
3503   if (Tnode != 0)
3504   {
3505     jam();
3506     arrGuard(Tnode, MAX_NDB_NODES);
3507     Uint32 instanceKey = regTcPtr->lqhInstanceKey;
3508     BlockReference lqhRef;
3509     if(regCachePtr->viaSPJFlag){
3510       //ndbout << "TC:Choosing SPJ." << endl;
3511       lqhRef = numberToRef(DBSPJ, Tnode); // Only 1 instance
3512     }else{
3513       //ndbout << "TC:Choosing LQH." << endl;
3514       lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
3515     }
3516     packLqhkeyreq(signal, lqhRef);
3517   }
3518   else
3519   {
3520     /**
3521      * 1) This is when a reorg trigger fired...
3522      *   but the tuple should *not* move
3523      *   This should be prevent using the LqhKeyReq::setReorgFlag
3524      *
3525      * 2) This also happens during reorg copy, when a row should *not* be moved
3526      */
3527     jam();
3528     Uint32 trigOp = regTcPtr->triggeringOperation;
3529     Uint32 TclientData = regTcPtr->clientData;
3530     releaseKeys();
3531     releaseAttrinfo();
3532     regApiPtr->lqhkeyreqrec--;
3533     unlinkReadyTcCon(signal);
3534     clearCommitAckMarker(regApiPtr, regTcPtr);
3535     releaseTcCon();
3536 
3537     if (trigOp != RNIL)
3538     {
3539       jam();
3540       //ndbassert(false); // see above
3541       TcConnectRecordPtr opPtr;
3542       opPtr.i = trigOp;
3543       ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
3544       trigger_op_finished(signal, apiConnectptr, opPtr.p);
3545       return;
3546     }
3547     else
3548     {
3549       jam();
3550       Uint32 Ttckeyrec = regApiPtr->tckeyrec;
3551       regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
3552       regApiPtr->tcSendArray[Ttckeyrec + 1] = 0;
3553       regApiPtr->tckeyrec = Ttckeyrec + 2;
3554       lqhKeyConf_checkTransactionState(signal, apiConnectptr);
3555     }
3556   }
3557 }//Dbtc::attrinfoDihReceivedLab()
3558 
packLqhkeyreq(Signal * signal,BlockReference TBRef)3559 void Dbtc::packLqhkeyreq(Signal* signal,
3560                          BlockReference TBRef)
3561 {
3562   CacheRecord * const regCachePtr = cachePtr.p;
3563   UintR Tkeylen = regCachePtr->keylen;
3564 
3565   ndbassert( signal->getNoOfSections() == 0 );
3566 
3567   sendlqhkeyreq(signal, TBRef);
3568 
3569   /* Do we need to send a KeyInfo signal train? */
3570   if ((! regCachePtr->useLongLqhKeyReq) &&
3571       (Tkeylen > LqhKeyReq::MaxKeyInfo))
3572   {
3573     /* Build KeyInfo train from KeyInfo long signal section */
3574     sendKeyInfoTrain(signal,
3575                      TBRef,
3576                      tcConnectptr.i,
3577                      LqhKeyReq::MaxKeyInfo,
3578                      regCachePtr->keyInfoSectionI);
3579   }//if
3580 
3581   /* Release key storage */
3582   releaseKeys();
3583   packLqhkeyreq040Lab(signal,
3584                       TBRef);
3585 }//Dbtc::packLqhkeyreq()
3586 
3587 
sendlqhkeyreq(Signal * signal,BlockReference TBRef)3588 void Dbtc::sendlqhkeyreq(Signal* signal,
3589                          BlockReference TBRef)
3590 {
3591   UintR tslrAttrLen;
3592   UintR Tdata10;
3593   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3594   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3595   CacheRecord * const regCachePtr = cachePtr.p;
3596   Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
3597   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
3598 #ifdef ERROR_INSERT
3599   if (ERROR_INSERTED(8002)) {
3600     systemErrorLab(signal, __LINE__);
3601   }//if
3602   if (ERROR_INSERTED(8007)) {
3603     if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3604       CLEAR_ERROR_INSERT_VALUE;
3605       return;
3606     }//if
3607   }//if
3608   if (ERROR_INSERTED(8008)) {
3609     if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3610       CLEAR_ERROR_INSERT_VALUE;
3611       return;
3612     }//if
3613   }//if
3614   if (ERROR_INSERTED(8009)) {
3615     if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3616       return;
3617     }//if
3618   }//if
3619   if (ERROR_INSERTED(8010)) {
3620     if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3621       return;
3622     }//if
3623   }//if
3624 #endif
3625   Uint32 Tdeferred = tc_testbit(regApiPtr->m_flags,
3626                                 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
3627   Uint32 reorg = 0;
3628   Uint32 Tspecial_op = regTcPtr->m_special_op_flags;
3629   if (Tspecial_op == 0)
3630   {
3631   }
3632   else if (Tspecial_op & (TcConnectRecord::SOF_REORG_TRIGGER_BASE |
3633                           TcConnectRecord::SOF_REORG_DELETE))
3634   {
3635     reorg = 1;
3636   }
3637   else if (Tspecial_op & TcConnectRecord::SOF_REORG_MOVING)
3638   {
3639     reorg = 2;
3640   }
3641 
3642   Uint32 inlineKeyLen= 0;
3643   Uint32 inlineAttrLen= 0;
3644 
3645   /* We normally send long LQHKEYREQ unless the
3646    * destination cannot handle it or we are
3647    * testing
3648    */
3649   if (unlikely((version < NDBD_LONG_LQHKEYREQ) ||
3650                ERROR_INSERTED(8069)))
3651   {
3652     /* Short LQHKEYREQ, with some key/attr data inline */
3653     regCachePtr->useLongLqhKeyReq= 0;
3654     inlineKeyLen= regCachePtr->keylen;
3655     inlineAttrLen= regCachePtr->attrlength;
3656   }
3657   else
3658     /* Long LQHKEYREQ, with key/attr data in long sections */
3659     regCachePtr->useLongLqhKeyReq= 1;
3660 
3661   tslrAttrLen = 0;
3662   LqhKeyReq::setAttrLen(tslrAttrLen, inlineAttrLen);
3663   /* ---------------------------------------------------------------------- */
3664   // Bit16 == 0 since StoredProcedures are not yet supported.
3665   /* ---------------------------------------------------------------------- */
3666   LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
3667   LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
3668   LqhKeyReq::setReorgFlag(tslrAttrLen, reorg);
3669 
3670   Tdata10 = 0;
3671   sig0 = regTcPtr->opSimple;
3672   sig1 = regTcPtr->operation;
3673   sig2 = regTcPtr->dirtyOp;
3674   bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
3675   LqhKeyReq::setKeyLen(Tdata10, inlineKeyLen);
3676   LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
3677   if (unlikely(version < NDBD_ROWID_VERSION))
3678   {
3679     Uint32 op = regTcPtr->operation;
3680     Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
3681     LqhKeyReq::setLockType(Tdata10, lock);
3682   }
3683   /* ---------------------------------------------------------------------- */
3684   // Indicate Application Reference is present in bit 15
3685   /* ---------------------------------------------------------------------- */
3686   LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
3687   LqhKeyReq::setDirtyFlag(Tdata10, sig2);
3688   LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
3689   LqhKeyReq::setSimpleFlag(Tdata10, sig0);
3690   LqhKeyReq::setOperation(Tdata10, sig1);
3691   LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
3692   LqhKeyReq::setQueueOnRedoProblemFlag(Tdata10, regCachePtr->m_op_queue);
3693   LqhKeyReq::setDeferredConstraints(Tdata10, (Tdeferred & m_deferred_enabled));
3694 
3695   /* -----------------------------------------------------------------------
3696    * If we are sending a short LQHKEYREQ, then there will be some AttrInfo
3697    * in the LQHKEYREQ.
3698    * Work out how much we'll send
3699    * ----------------------------------------------------------------------- */
3700   UintR aiInLqhKeyReq= 0;
3701 
3702   if (! regCachePtr->useLongLqhKeyReq)
3703   {
3704     /* Short LQHKEYREQ :
3705      * Send max 5 words of AttrInfo in LQHKEYREQ
3706      */
3707     aiInLqhKeyReq= MIN(LqhKeyReq::MaxAttrInfo, regCachePtr->attrlength);
3708   }
3709 
3710   LqhKeyReq::setAIInLqhKeyReq(Tdata10, aiInLqhKeyReq);
3711   /* -----------------------------------------------------------------------
3712    * Bit 27 == 0 since TC record is the same as the client record.
3713    * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
3714    * ----------------------------------------------------------------------- */
3715   //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
3716   LqhKeyReq::setMarkerFlag(Tdata10, regTcPtr->commitAckMarker != RNIL ? 1 : 0);
3717 
3718   /* ************************************************************> */
3719   /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT    */
3720   /* IS SENT TO A PRIMARY NODE.                                    */
3721   /* ************************************************************> */
3722 
3723   LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
3724 
3725   sig0 = tcConnectptr.i;
3726   sig2 = regCachePtr->hashValue;
3727   sig4 = cownref;
3728   sig5 = regTcPtr->savePointId;
3729 
3730   lqhKeyReq->clientConnectPtr = sig0;
3731   lqhKeyReq->attrLen = tslrAttrLen;
3732   lqhKeyReq->hashValue = sig2;
3733   lqhKeyReq->requestInfo = Tdata10;
3734   lqhKeyReq->tcBlockref = sig4;
3735   lqhKeyReq->savePointId = sig5;
3736 
3737   sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
3738   sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
3739   sig2 = regApiPtr->transid[0];
3740   sig3 = regApiPtr->transid[1];
3741   sig4 =
3742     (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) ?
3743     reference() : regApiPtr->ndbapiBlockref;
3744   sig5 = regTcPtr->clientData;
3745   sig6 = regCachePtr->scanInfo;
3746 
3747   if (! dirtyRead)
3748   {
3749     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
3750     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
3751     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
3752     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
3753   }
3754 
3755   lqhKeyReq->tableSchemaVersion = sig0;
3756   lqhKeyReq->fragmentData = sig1;
3757   lqhKeyReq->transId1 = sig2;
3758   lqhKeyReq->transId2 = sig3;
3759   lqhKeyReq->scanInfo = sig6;
3760 
3761   lqhKeyReq->variableData[0] = sig4;
3762   lqhKeyReq->variableData[1] = sig5;
3763 
3764   UintR nextPos = 2;
3765 
3766   if (regTcPtr->lastReplicaNo > 1) {
3767     sig0 = (UintR)regTcPtr->tcNodedata[2] +
3768            (UintR)(regTcPtr->tcNodedata[3] << 16);
3769     lqhKeyReq->variableData[nextPos] = sig0;
3770     nextPos++;
3771   }//if
3772 
3773   // Reset trigger count
3774   regTcPtr->noFiredTriggers = 0;
3775   regTcPtr->triggerExecutionCount = 0;
3776 
3777   if (regCachePtr->useLongLqhKeyReq)
3778   {
3779     /* Build long LQHKeyReq using Key + AttrInfo sections */
3780     SectionHandle handle(this);
3781     SegmentedSectionPtr keyInfoSection;
3782 
3783     getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
3784 
3785     handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
3786     handle.m_cnt= 1;
3787 
3788     if (regCachePtr->attrlength != 0)
3789     {
3790       SegmentedSectionPtr attrInfoSection;
3791 
3792       ndbassert(regCachePtr->attrInfoSectionI != RNIL);
3793       getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
3794 
3795       handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
3796       handle.m_cnt= 2;
3797     }
3798 
3799     sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3800                nextPos + LqhKeyReq::FixedSignalLength, JBB,
3801                &handle);
3802 
3803     /* Long sections were freed as part of sendSignal */
3804     ndbassert( handle.m_cnt == 0 );
3805     regCachePtr->keyInfoSectionI= RNIL;
3806     regCachePtr->attrInfoSectionI= RNIL;
3807   }
3808   else
3809   {
3810     /* Build short LQHKeyReq from Key + AttrInfo sections
3811      *
3812      * Read upto 4 words of KeyInfo from TCKEYREQ KeyInfo section into
3813      * LqhKeyReq signal
3814      */
3815     SegmentedSectionPtr keyInfoSection;
3816 
3817     getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
3818     SectionReader keyInfoReader(keyInfoSection, getSectionSegmentPool());
3819 
3820     UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo, regCachePtr->keylen);
3821 
3822     keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos], keyLenInLqhKeyReq);
3823 
3824     nextPos+= keyLenInLqhKeyReq;
3825 
3826     if (aiInLqhKeyReq != 0)
3827     {
3828       /* Read upto 5 words of AttrInfo from TCKEYREQ KeyInfo section into
3829        * LqhKeyReq signal
3830        */
3831       SegmentedSectionPtr attrInfoSection;
3832 
3833       ndbassert(regCachePtr->attrInfoSectionI != RNIL);
3834 
3835       getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
3836       SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
3837 
3838       attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos], aiInLqhKeyReq);
3839 
3840       nextPos+= aiInLqhKeyReq;
3841     }
3842 
3843     sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3844                nextPos + LqhKeyReq::FixedSignalLength, JBB);
3845   }
3846 }//Dbtc::sendlqhkeyreq()
3847 
packLqhkeyreq040Lab(Signal * signal,BlockReference TBRef)3848 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
3849                                BlockReference TBRef)
3850 {
3851   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3852   CacheRecord * const regCachePtr = cachePtr.p;
3853 #ifdef ERROR_INSERT
3854   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3855 
3856   if (ERROR_INSERTED(8009)) {
3857     if (regApiPtr->apiConnectstate == CS_STARTED) {
3858       CLEAR_ERROR_INSERT_VALUE;
3859       return;
3860     }//if
3861   }//if
3862   if (ERROR_INSERTED(8010)) {
3863     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3864       CLEAR_ERROR_INSERT_VALUE;
3865       return;
3866     }//if
3867   }//if
3868 #endif
3869 
3870   /* Do we have an ATTRINFO train to send? */
3871   if (!regCachePtr->useLongLqhKeyReq)
3872   {
3873     /* Short LqhKeyReq */
3874     if (regCachePtr->attrlength > LqhKeyReq::MaxAttrInfo)
3875     {
3876       if (unlikely( !sendAttrInfoTrain(signal,
3877                                        TBRef,
3878                                        tcConnectptr.i,
3879                                        LqhKeyReq::MaxAttrInfo,
3880                                        regCachePtr->attrInfoSectionI)))
3881       {
3882         jam();
3883         TCKEY_abort(signal, 17);
3884         return;
3885       }
3886     }
3887   } // useLongLqhKeyReq
3888 
3889   /* Release AttrInfo related storage, and the Cache Record */
3890   releaseAttrinfo();
3891 
3892   UintR TtcTimer = ctcTimer;
3893   UintR Tread = (regTcPtr->operation == ZREAD);
3894   UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
3895   UintR Tboth = Tread & Tdirty;
3896   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3897   jam();
3898   /*--------------------------------------------------------------------
3899    *   WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
3900    *---------------------------------------------------------------------*/
3901   if (Tboth) {
3902     jam();
3903     releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
3904     return;
3905   }//if
3906   regTcPtr->tcConnectstate = OS_OPERATING;
3907   return;
3908 }//Dbtc::packLqhkeyreq040Lab()
3909 
3910 /* ========================================================================= */
3911 /* -------      RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD  ------- */
3912 /* ========================================================================= */
releaseAttrinfo()3913 void Dbtc::releaseAttrinfo()
3914 {
3915   CacheRecord * const regCachePtr = cachePtr.p;
3916   Uint32 attrInfoSectionI= cachePtr.p->attrInfoSectionI;
3917 
3918   /* Release AttrInfo section if there is one */
3919   releaseSection( attrInfoSectionI );
3920   cachePtr.p->attrInfoSectionI= RNIL;
3921 
3922   //---------------------------------------------------
3923   // Now we will release the cache record at the same
3924   // time as releasing the attrinfo records.
3925   //---------------------------------------------------
3926   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3927   UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
3928   UintR TCacheIndex = cachePtr.i;
3929   regCachePtr->nextCacheRec = TfirstfreeCacheRec;
3930   cfirstfreeCacheRec = TCacheIndex;
3931   regApiPtr->cachePtr = RNIL;
3932   return;
3933 }//Dbtc::releaseAttrinfo()
3934 
3935 /* ========================================================================= */
3936 /* -------   RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION     ------- */
3937 /* ========================================================================= */
releaseDirtyRead(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * regTcPtr)3938 void Dbtc::releaseDirtyRead(Signal* signal,
3939                             ApiConnectRecordPtr regApiPtr,
3940                             TcConnectRecord* regTcPtr)
3941 {
3942   Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
3943   Uint32 TclientData = regTcPtr->clientData;
3944   Uint32 Tnode = regTcPtr->tcNodedata[0];
3945   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3946   ConnectionState state = regApiPtr.p->apiConnectstate;
3947 
3948   regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3949   regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
3950   regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3951 
3952   unlinkReadyTcCon(signal);
3953   releaseTcCon();
3954 
3955   /**
3956    * No LQHKEYCONF in Simple/Dirty read
3957    * Therefore decrese no LQHKEYCONF(REF) we are waiting for
3958    */
3959   c_counters.csimpleReadCount++;
3960   regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
3961 
3962   if(Tlqhkeyreqrec == 0)
3963   {
3964     /**
3965      * Special case of lqhKeyConf_checkTransactionState:
3966      * - commit with zero operations: handle only for simple read
3967      */
3968     sendtckeyconf(signal, state == CS_START_COMMITTING);
3969     regApiPtr.p->apiConnectstate =
3970       (state == CS_START_COMMITTING ? CS_CONNECTED : state);
3971     setApiConTimer(regApiPtr.i, 0, __LINE__);
3972 
3973     return;
3974   }
3975 
3976   /**
3977    * Emulate LQHKEYCONF
3978    */
3979   lqhKeyConf_checkTransactionState(signal, regApiPtr);
3980 }//Dbtc::releaseDirtyRead()
3981 
3982 /* ------------------------------------------------------------------------- */
3983 /* -------        CHECK IF ALL TC CONNECTIONS ARE COMPLETED          ------- */
3984 /* ------------------------------------------------------------------------- */
unlinkReadyTcCon(Signal * signal)3985 void Dbtc::unlinkReadyTcCon(Signal* signal)
3986 {
3987   TcConnectRecordPtr urtTcConnectptr;
3988 
3989   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3990   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3991   UintR TtcConnectFilesize = ctcConnectFilesize;
3992   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3993   if (regTcPtr->prevTcConnect != RNIL) {
3994     jam();
3995     urtTcConnectptr.i = regTcPtr->prevTcConnect;
3996     ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3997     urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
3998   } else {
3999     jam();
4000     regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
4001   }//if
4002   if (regTcPtr->nextTcConnect != RNIL) {
4003     jam();
4004     urtTcConnectptr.i = regTcPtr->nextTcConnect;
4005     ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4006     urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
4007   } else {
4008     jam();
4009     regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
4010   }//if
4011 }//Dbtc::unlinkReadyTcCon()
4012 
releaseTcCon()4013 void Dbtc::releaseTcCon()
4014 {
4015   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4016   UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
4017   UintR TtcConnectptrIndex = tcConnectptr.i;
4018 
4019   ndbrequire(regTcPtr->commitAckMarker == RNIL);
4020   regTcPtr->tcConnectstate = OS_CONNECTED;
4021   regTcPtr->nextTcConnect = TfirstfreeTcConnect;
4022   regTcPtr->apiConnect = RNIL;
4023   regTcPtr->m_special_op_flags = 0;
4024   regTcPtr->indexOp = RNIL;
4025   cfirstfreeTcConnect = TtcConnectptrIndex;
4026   c_counters.cconcurrentOp--;
4027 }//Dbtc::releaseTcCon()
4028 
execPACKED_SIGNAL(Signal * signal)4029 void Dbtc::execPACKED_SIGNAL(Signal* signal)
4030 {
4031   LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
4032 
4033   UintR Ti;
4034   UintR Tstep = 0;
4035   UintR Tlength;
4036   UintR TpackedData[28];
4037   UintR Tdata1, Tdata2, Tdata3, Tdata4;
4038 
4039   jamEntry();
4040   Tlength = signal->length();
4041   if (Tlength > 25) {
4042     jam();
4043     systemErrorLab(signal, __LINE__);
4044     return;
4045   }//if
4046   Uint32* TpackDataPtr;
4047   for (Ti = 0; Ti < Tlength; Ti += 4) {
4048     Uint32* TsigDataPtr = &signal->theData[Ti];
4049     Tdata1 = TsigDataPtr[0];
4050     Tdata2 = TsigDataPtr[1];
4051     Tdata3 = TsigDataPtr[2];
4052     Tdata4 = TsigDataPtr[3];
4053 
4054     TpackDataPtr = &TpackedData[Ti];
4055     TpackDataPtr[0] = Tdata1;
4056     TpackDataPtr[1] = Tdata2;
4057     TpackDataPtr[2] = Tdata3;
4058     TpackDataPtr[3] = Tdata4;
4059   }//for
4060   while (Tlength > Tstep) {
4061 
4062     TpackDataPtr = &TpackedData[Tstep];
4063     Tdata1 = TpackDataPtr[0];
4064     Tdata2 = TpackDataPtr[1];
4065     Tdata3 = TpackDataPtr[2];
4066 
4067     lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
4068     lqhKeyConf->opPtr = Tdata2;
4069     lqhKeyConf->userRef = Tdata3;
4070 
4071     switch (Tdata1 >> 28) {
4072     case ZCOMMITTED:
4073       signal->header.theLength = 3;
4074       execCOMMITTED(signal);
4075       Tstep += 3;
4076       break;
4077     case ZCOMPLETED:
4078       signal->header.theLength = 3;
4079       execCOMPLETED(signal);
4080       Tstep += 3;
4081       break;
4082     case ZLQHKEYCONF:
4083       jam();
4084       Tdata1 = TpackDataPtr[3];
4085       Tdata2 = TpackDataPtr[4];
4086       Tdata3 = TpackDataPtr[5];
4087       Tdata4 = TpackDataPtr[6];
4088 
4089       lqhKeyConf->readLen = Tdata1;
4090       lqhKeyConf->transId1 = Tdata2;
4091       lqhKeyConf->transId2 = Tdata3;
4092       lqhKeyConf->noFiredTriggers = Tdata4;
4093       signal->header.theLength = LqhKeyConf::SignalLength;
4094       execLQHKEYCONF(signal);
4095       Tstep += LqhKeyConf::SignalLength;
4096       break;
4097     case ZFIRE_TRIG_CONF:
4098       jam();
4099       signal->header.theLength = 4;
4100       signal->theData[3] = TpackDataPtr[3];
4101       execFIRE_TRIG_CONF(signal);
4102       Tstep += 4;
4103       break;
4104     default:
4105       systemErrorLab(signal, __LINE__);
4106       return;
4107     }//switch
4108   }//while
4109   return;
4110 }//Dbtc::execPACKED_SIGNAL()
4111 
4112 
execSIGNAL_DROPPED_REP(Signal * signal)4113 void Dbtc::execSIGNAL_DROPPED_REP(Signal* signal)
4114 {
4115   /* An incoming signal was dropped, handle it
4116    * Dropped signal really means that we ran out of
4117    * long signal buffering to store its sections
4118    */
4119   jamEntry();
4120 
4121   if (!assembleDroppedFragments(signal))
4122   {
4123     jam();
4124     return;
4125   }
4126 
4127   const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
4128   Uint32 originalGSN= rep->originalGsn;
4129 
4130   DEBUG("SignalDroppedRep received for GSN " << originalGSN);
4131 
4132   switch(originalGSN) {
4133   case GSN_TCKEYREQ:
4134     jam();
4135     /* Fall through */
4136   case GSN_TCINDXREQ:
4137   {
4138     jam();
4139 
4140     /* Get original signal data - unfortunately it may
4141      * have been truncated.  We must not read beyond
4142      * word # 22
4143      * We will send an Abort to the Api using info from
4144      * the received signal and clean up our transaction
4145      * state
4146      */
4147     const TcKeyReq * const truncatedTcKeyReq =
4148       (TcKeyReq *) &rep->originalData[0];
4149 
4150     const UintR apiIndex = truncatedTcKeyReq->apiConnectPtr;
4151 
4152     if (apiIndex >= capiConnectFilesize)
4153     {
4154       jam();
4155       warningHandlerLab(signal, __LINE__);
4156       return;
4157     }
4158 
4159     /* We have a valid Api ConnectPtr...
4160      * Ensure that we have the  necessary information
4161      * to send a rollback to the client
4162      */
4163     apiConnectptr.i = apiIndex;
4164     ApiConnectRecord * const regApiPtr = &apiConnectRecord[apiIndex];
4165     apiConnectptr.p = regApiPtr;
4166     UintR transId1= truncatedTcKeyReq->transId1;
4167     UintR transId2= truncatedTcKeyReq->transId2;
4168 
4169     /* Ensure that the apiConnectptr global is initialised
4170      * may not be in cases where we drop the first signal of
4171      * a transaction
4172      */
4173     apiConnectptr.p->transid[0] = transId1;
4174     apiConnectptr.p->transid[1] = transId2;
4175     apiConnectptr.p->returncode = ZGET_DATAREC_ERROR;
4176 
4177     /* Set m_exec_flag according to the dropped request */
4178     apiConnectptr.p->m_flags |=
4179       TcKeyReq::getExecuteFlag(truncatedTcKeyReq->requestInfo) ?
4180       ApiConnectRecord::TF_EXEC_FLAG : 0;
4181 
4182     DEBUG(" Execute flag set to " << tc_testbit(apiConnectptr.p->m_flags,
4183                                                 ApiConnectRecord::TF_EXEC_FLAG)
4184           );
4185 
4186     abortErrorLab(signal);
4187 
4188     break;
4189   }
4190   case GSN_SCAN_TABREQ:
4191   {
4192     jam();
4193     /* Get information necessary to send SCAN_TABREF back to client */
4194     // TODO : Handle dropped signal fragments
4195     const ScanTabReq * const truncatedScanTabReq =
4196       (ScanTabReq *) &rep->originalData[0];
4197 
4198     Uint32 apiConnectPtr= truncatedScanTabReq->apiConnectPtr;
4199     Uint32 transId1= truncatedScanTabReq->transId1;
4200     Uint32 transId2= truncatedScanTabReq->transId2;
4201 
4202     if (apiConnectPtr >= capiConnectFilesize)
4203     {
4204       jam();
4205       warningHandlerLab(signal, __LINE__);
4206       return;
4207     }//if
4208 
4209     apiConnectptr.i = apiConnectPtr;
4210     ptrAss(apiConnectptr, apiConnectRecord);
4211     ApiConnectRecord * transP = apiConnectptr.p;
4212 
4213     /* Now send the SCAN_TABREF */
4214     ScanTabRef* ref= (ScanTabRef*)&signal->theData[0];
4215     ref->apiConnectPtr = transP->ndbapiConnect;
4216     ref->transId1= transId1;
4217     ref->transId2= transId2;
4218     ref->errorCode= ZGET_ATTRBUF_ERROR;
4219     ref->closeNeeded= 0;
4220 
4221     sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
4222                signal, ScanTabRef::SignalLength, JBB);
4223     break;
4224   }
4225   default:
4226     jam();
4227     /* Don't expect dropped signals for other GSNs,
4228      * default handling
4229      * TODO : Can TC get long TRANSID_AI as part of
4230      * Unique index operations?
4231      */
4232     SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
4233   };
4234 
4235   return;
4236 }
4237 
4238 
execLQHKEYCONF(Signal * signal)4239 void Dbtc::execLQHKEYCONF(Signal* signal)
4240 {
4241   const LqhKeyConf * lqhKeyConf = CAST_CONSTPTR(LqhKeyConf,
4242                                                 signal->getDataPtr());
4243 #ifdef UNUSED
4244   ndbout << "TC: Received LQHKEYCONF"
4245          << " transId1=" << lqhKeyConf-> transId1
4246          << " transId2=" << lqhKeyConf-> transId2
4247 	 << endl;
4248 #endif /*UNUSED*/
4249   UintR compare_transid1, compare_transid2;
4250   BlockReference tlastLqhBlockref;
4251   UintR tlastLqhConnect;
4252   UintR treadlenAi;
4253   UintR TtcConnectptrIndex;
4254   UintR TtcConnectFilesize = ctcConnectFilesize;
4255 
4256   tlastLqhConnect = lqhKeyConf->connectPtr;
4257   TtcConnectptrIndex = lqhKeyConf->opPtr;
4258   tlastLqhBlockref = lqhKeyConf->userRef;
4259   treadlenAi = lqhKeyConf->readLen;
4260   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4261 
4262   /*------------------------------------------------------------------------
4263    * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
4264    * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
4265    * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
4266    * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
4267    * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
4268    * OPERATIONS ON THE LQH CONNECT RECORD.
4269    *------------------------------------------------------------------------
4270    * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
4271    * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
4272    * PROBLEM  WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
4273    * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
4274    * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
4275    * BEFORE ACCEPTING THIS SIGNAL.
4276    * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
4277    * this.
4278    * This is more reason to ignore the signal if not all states are correct.
4279    *------------------------------------------------------------------------*/
4280   if (TtcConnectptrIndex >= TtcConnectFilesize) {
4281     TCKEY_abort(signal, 25);
4282     return;
4283   }//if
4284   TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
4285   OperationState TtcConnectstate = regTcPtr->tcConnectstate;
4286   tcConnectptr.i = TtcConnectptrIndex;
4287   tcConnectptr.p = regTcPtr;
4288   if (TtcConnectstate != OS_OPERATING) {
4289     warningReport(signal, 23);
4290     return;
4291   }//if
4292   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4293   UintR TapiConnectptrIndex = regTcPtr->apiConnect;
4294   UintR TapiConnectFilesize = capiConnectFilesize;
4295   UintR Ttrans1 = lqhKeyConf->transId1;
4296   UintR Ttrans2 = lqhKeyConf->transId2;
4297   Uint32 noFired = LqhKeyConf::getFiredCount(lqhKeyConf->noFiredTriggers);
4298   Uint32 deferred = LqhKeyConf::getDeferredBit(lqhKeyConf->noFiredTriggers);
4299 
4300   if (TapiConnectptrIndex >= TapiConnectFilesize) {
4301     TCKEY_abort(signal, 29);
4302     return;
4303   }//if
4304   Ptr<ApiConnectRecord> regApiPtr;
4305   regApiPtr.i = TapiConnectptrIndex;
4306   regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
4307   apiConnectptr.i = TapiConnectptrIndex;
4308   apiConnectptr.p = regApiPtr.p;
4309   compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
4310   compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
4311   compare_transid1 = compare_transid1 | compare_transid2;
4312   if (compare_transid1 != 0) {
4313     warningReport(signal, 24);
4314     return;
4315   }//if
4316 
4317 #ifdef ERROR_INSERT
4318   if (ERROR_INSERTED(8029)) {
4319     systemErrorLab(signal, __LINE__);
4320   }//if
4321   if (ERROR_INSERTED(8003)) {
4322     if (regApiPtr.p->apiConnectstate == CS_STARTED) {
4323       CLEAR_ERROR_INSERT_VALUE;
4324       return;
4325     }//if
4326   }//if
4327   if (ERROR_INSERTED(8004)) {
4328     if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
4329       CLEAR_ERROR_INSERT_VALUE;
4330       return;
4331     }//if
4332   }//if
4333   if (ERROR_INSERTED(8005)) {
4334     if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
4335       CLEAR_ERROR_INSERT_VALUE;
4336       return;
4337     }//if
4338   }//if
4339   if (ERROR_INSERTED(8006)) {
4340     if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
4341       CLEAR_ERROR_INSERT_VALUE;
4342       return;
4343     }//if
4344   }//if
4345   if (ERROR_INSERTED(8023)) {
4346     SET_ERROR_INSERT_VALUE(8024);
4347     return;
4348   }//if
4349 #endif
4350   UintR TtcTimer = ctcTimer;
4351   regTcPtr->lastLqhCon = tlastLqhConnect;
4352   regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
4353   regTcPtr->noFiredTriggers = noFired;
4354   regTcPtr->m_special_op_flags |= (deferred) ?
4355     TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
4356   regApiPtr.p->m_flags |= (deferred) ?
4357     ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
4358 
4359   UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
4360   UintR TclientData = regTcPtr->clientData;
4361   UintR TdirtyOp = regTcPtr->dirtyOp;
4362   Uint32 TopSimple = regTcPtr->opSimple;
4363   Uint32 Toperation = regTcPtr->operation;
4364   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4365 
4366   if (TapiConnectstate == CS_ABORTING) {
4367     warningReport(signal, 27);
4368     return;
4369   }//if
4370 
4371   Uint32 lockingOpI = RNIL;
4372   if (Toperation == ZUNLOCK)
4373   {
4374     /* For unlock operations readlen in TCKEYCONF carries
4375      * the locking operation TC reference
4376      */
4377     lockingOpI = treadlenAi;
4378     treadlenAi = 0;
4379   }
4380 
4381   Uint32 commitAckMarker = regTcPtr->commitAckMarker;
4382   regTcPtr->commitAckMarker = RNIL;
4383   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
4384 
4385   if (commitAckMarker != RNIL)
4386   {
4387     const Uint32 noOfLqhs = regTcPtr->noOfNodes;
4388     CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
4389     jam();
4390     regApiPtr.p->m_flags |= ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED;
4391     /**
4392      * Populate LQH array
4393      */
4394     for(Uint32 i = 0; i < noOfLqhs; i++)
4395       tmp->m_commit_ack_marker_nodes.set(regTcPtr->tcNodedata[i]);
4396   }
4397   if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4398     jam();
4399     // This was an internal TCKEYREQ
4400     // will be returned unpacked
4401     regTcPtr->attrInfoLen = treadlenAi;
4402   } else {
4403     if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
4404       jam();
4405 
4406       if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
4407         TCKEY_abort(signal, 30);
4408         return;
4409       }
4410 
4411       /*
4412        * Skip counting triggering operations the first round
4413        * since they will enter execLQHKEYCONF a second time
4414        * Skip counting internally generated TcKeyReq
4415        */
4416       regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
4417       regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
4418       regApiPtr.p->tckeyrec = Ttckeyrec + 2;
4419     }//if
4420   }//if
4421   if (TdirtyOp == ZTRUE)
4422   {
4423     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4424     jam();
4425     releaseDirtyWrite(signal);
4426     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4427   }
4428   else if (Toperation == ZREAD && TopSimple)
4429   {
4430     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4431     jam();
4432     unlinkReadyTcCon(signal);
4433     releaseTcCon();
4434     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
4435   }
4436   else if (Toperation == ZUNLOCK)
4437   {
4438     jam();
4439     /* We've unlocked and released a read operation in LQH
4440      * The readLenAi member contains the TC OP reference
4441      * for the unlocked operation.
4442      * So here we :
4443      * 1) Validate the TC OP reference
4444      * 2) Release the referenced TC op
4445      * 3) Send TCKEYCONF back to the user
4446      * 4) Release our own TC op
4447      */
4448     Uint32 unlockOpI = tcConnectptr.i;
4449 
4450     ndbrequire( noFired == 0 );
4451     ndbrequire( regTcPtr->triggeringOperation == RNIL );
4452 
4453     /* Switch to the original locking operation */
4454     if (unlikely( lockingOpI >= ctcConnectFilesize ))
4455     {
4456       jam();
4457       TCKEY_abort(signal, 61);
4458       return;
4459     }
4460     tcConnectptr.i = lockingOpI;
4461     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4462 
4463     const TcConnectRecord * regLockTcPtr = tcConnectptr.p;
4464 
4465     /* Validate the locking operation's state */
4466     bool locking_op_ok =
4467       ( ( regLockTcPtr->apiConnect == regTcPtr->apiConnect ) &&
4468         ( ( regLockTcPtr->operation == ZREAD ) ||
4469           ( regLockTcPtr->operation == ZREAD_EX ) ) &&
4470         ( regLockTcPtr->tcConnectstate == OS_PREPARED ) &&
4471         ( ! regLockTcPtr->dirtyOp ) &&
4472         ( ! regLockTcPtr->opSimple ) &&
4473         ( ! TcConnectRecord::isIndexOp(regLockTcPtr->m_special_op_flags) ) &&
4474         ( regLockTcPtr->commitAckMarker == RNIL ) );
4475 
4476     if (unlikely (! locking_op_ok ))
4477     {
4478       jam();
4479       TCKEY_abort(signal, 63);
4480       return;
4481     }
4482 
4483     /* Ok, all checks passed, release the original locking op */
4484     unlinkReadyTcCon(signal);
4485     releaseTcCon();
4486 
4487     /* Remove record of original locking op's LQHKEYREQ/CONF
4488      * etc.
4489      */
4490     ndbrequire( regApiPtr.p->lqhkeyreqrec );
4491     ndbrequire( regApiPtr.p->lqhkeyconfrec );
4492     regApiPtr.p->lqhkeyreqrec -= 1;
4493     regApiPtr.p->lqhkeyconfrec -= 1;
4494 
4495     /* Switch back to the unlock operation */
4496     tcConnectptr.i = unlockOpI;
4497     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
4498 
4499     /* Release the unlock operation */
4500     unlinkReadyTcCon(signal);
4501     releaseTcCon();
4502 
4503     /* Remove record of unlock op's LQHKEYREQ */
4504     ndbrequire( regApiPtr.p->lqhkeyreqrec );
4505     regApiPtr.p->lqhkeyreqrec -= 1;
4506 
4507     /* TCKEYCONF sent below */
4508   }
4509   else
4510   {
4511     jam();
4512     if (noFired == 0) {
4513       jam();
4514       // No triggers to execute
4515       UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4516       regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
4517       regTcPtr->tcConnectstate = OS_PREPARED;
4518     }
4519   }//if
4520 
4521   /**
4522    * And now decide what to do next
4523    */
4524   if (regTcPtr->triggeringOperation != RNIL &&
4525       !regApiPtr.p->isExecutingDeferredTriggers()) {
4526     jam();
4527     // This operation was created by a trigger execting operation
4528     // Restart it if we have executed all it's triggers
4529     TcConnectRecordPtr opPtr;
4530 
4531     opPtr.i = regTcPtr->triggeringOperation;
4532     ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
4533     trigger_op_finished(signal, regApiPtr, opPtr.p);
4534   } else if (noFired == 0) {
4535     // This operation did not fire any triggers, finish operation
4536     jam();
4537     if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)) {
4538       jam();
4539       setupIndexOpReturn(regApiPtr.p, regTcPtr);
4540     }
4541     lqhKeyConf_checkTransactionState(signal, regApiPtr);
4542   } else {
4543     // We have fired triggers
4544     jam();
4545     saveTriggeringOpState(signal, regTcPtr);
4546     if (regTcPtr->noReceivedTriggers == noFired)
4547     {
4548       // We have received all data
4549       jam();
4550       executeTriggers(signal, &regApiPtr);
4551     }
4552     // else wait for more trigger data
4553   }
4554 }//Dbtc::execLQHKEYCONF()
4555 
setupIndexOpReturn(ApiConnectRecord * regApiPtr,TcConnectRecord * regTcPtr)4556 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
4557 			      TcConnectRecord* regTcPtr)
4558 {
4559   regApiPtr->m_flags |= ApiConnectRecord::TF_INDEX_OP_RETURN;
4560   regApiPtr->indexOp = regTcPtr->indexOp;
4561   regApiPtr->clientData = regTcPtr->clientData;
4562   regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
4563 }
4564 
4565 /**
4566  * lqhKeyConf_checkTransactionState
4567  *
4568  * This functions checks state variables, and
4569  *   decides if it should wait for more LQHKEYCONF signals
4570  *   or if it should start commiting
4571  */
4572 void
lqhKeyConf_checkTransactionState(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)4573 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
4574 				       Ptr<ApiConnectRecord> regApiPtr)
4575 {
4576 /*---------------------------------------------------------------*/
4577 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
4578 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN   */
4579 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE   */
4580 /* WHOLE TRANSACTION                                             */
4581 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF  */
4582 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
4583 /* TRANSACTION                                                   */
4584 /*---------------------------------------------------------------*/
4585   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
4586   UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
4587   UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
4588   int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
4589 
4590   apiConnectptr = regApiPtr;
4591   switch (TapiConnectstate) {
4592   case CS_START_COMMITTING:
4593     if (TnoOfOutStanding == 0) {
4594       jam();
4595       diverify010Lab(signal);
4596       return;
4597     } else if (TnoOfOutStanding > 0) {
4598       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4599         jam();
4600         sendtckeyconf(signal, 0);
4601         return;
4602       }
4603       else if (tc_testbit(regApiPtr.p->m_flags,
4604                           ApiConnectRecord::TF_INDEX_OP_RETURN))
4605       {
4606 	jam();
4607         sendtckeyconf(signal, 0);
4608         return;
4609       }//if
4610       jam();
4611       return;
4612     } else {
4613       TCKEY_abort(signal, 44);
4614       return;
4615     }//if
4616     return;
4617   case CS_STARTED:
4618   case CS_RECEIVING:
4619     if (TnoOfOutStanding == 0) {
4620       jam();
4621       sendtckeyconf(signal, 2);
4622       return;
4623     } else {
4624       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4625         jam();
4626         sendtckeyconf(signal, 0);
4627         return;
4628       }
4629       else if (tc_testbit(regApiPtr.p->m_flags,
4630                           ApiConnectRecord::TF_INDEX_OP_RETURN))
4631       {
4632 	jam();
4633         sendtckeyconf(signal, 0);
4634         return;
4635       }//if
4636       jam();
4637     }//if
4638     return;
4639   case CS_REC_COMMITTING:
4640     if (TnoOfOutStanding > 0) {
4641       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
4642         jam();
4643         sendtckeyconf(signal, 0);
4644         return;
4645       }
4646       else if (tc_testbit(regApiPtr.p->m_flags,
4647                           ApiConnectRecord::TF_INDEX_OP_RETURN))
4648       {
4649         jam();
4650         sendtckeyconf(signal, 0);
4651         return;
4652       }//if
4653       jam();
4654       return;
4655     }//if
4656     TCKEY_abort(signal, 45);
4657     return;
4658   case CS_CONNECTED:
4659     jam();
4660 /*---------------------------------------------------------------*/
4661 /*       WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY     */
4662 /*       CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE        */
4663 /*       COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS.   */
4664 /*---------------------------------------------------------------*/
4665     regApiPtr.p->tckeyrec = 0;
4666     return;
4667   case CS_SEND_FIRE_TRIG_REQ:
4668     return;
4669   case CS_WAIT_FIRE_TRIG_REQ:
4670     if (TnoOfOutStanding == 0 && regApiPtr.p->pendingTriggers == 0)
4671     {
4672       jam();
4673       regApiPtr.p->apiConnectstate = CS_START_COMMITTING;
4674       diverify010Lab(signal);
4675       return;
4676     }
4677     return;
4678   default:
4679     TCKEY_abort(signal, 46);
4680     return;
4681   }//switch
4682 }//Dbtc::lqhKeyConf_checkTransactionState()
4683 
sendtckeyconf(Signal * signal,UintR TcommitFlag)4684 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
4685 {
4686   if(ERROR_INSERTED(8049)){
4687     CLEAR_ERROR_INSERT_VALUE;
4688     signal->theData[0] = TcContinueB::DelayTCKEYCONF;
4689     signal->theData[1] = apiConnectptr.i;
4690     signal->theData[2] = TcommitFlag;
4691     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
4692     return;
4693   }
4694 
4695   HostRecordPtr localHostptr;
4696   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4697   const UintR TopWords = (UintR)regApiPtr->tckeyrec;
4698   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
4699   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
4700   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
4701   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
4702   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
4703   ptrAss(localHostptr, hostRecord);
4704   UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
4705   UintR confInfo = 0;
4706   TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
4707   TcKeyConf::setMarkerFlag(confInfo, Tmarker);
4708   const UintR TpacketLen = 6 + TopWords;
4709   regApiPtr->tckeyrec = 0;
4710 
4711   if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN))
4712   {
4713     jam();
4714     // Return internally generated TCKEY
4715     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4716     TcKeyConf::setNoOfOperations(confInfo, 1);
4717     tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
4718     tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
4719     Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[1];
4720     * gci_lo = Uint32(regApiPtr->globalcheckpointid);
4721     tcKeyConf->confInfo = confInfo;
4722     tcKeyConf->transId1 = regApiPtr->transid[0];
4723     tcKeyConf->transId2 = regApiPtr->transid[1];
4724     tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
4725     tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
4726     Uint32 sigLen = 1 /** gci_lo */ +
4727       TcKeyConf::StaticLength + TcKeyConf::OperationLength;
4728     EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
4729     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN);
4730     if (TopWords == 0) {
4731       jam();
4732       return; // No queued TcKeyConf
4733     }//if
4734   }//if
4735   if(TcommitFlag){
4736     jam();
4737     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
4738   }
4739   TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
4740   if ((TpacketLen + 1 /** gci_lo */ > 25) || !is_api){
4741     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4742 
4743     jam();
4744     tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4745     tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
4746     Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[TopWords >> 1];
4747     tcKeyConf->confInfo = confInfo;
4748     tcKeyConf->transId1 = regApiPtr->transid[0];
4749     tcKeyConf->transId2 = regApiPtr->transid[1];
4750     copyFromToLen(&regApiPtr->tcSendArray[0],
4751 		  (UintR*)&tcKeyConf->operations,
4752 		  (UintR)ZTCOPCONF_SIZE);
4753     * gci_lo = Uint32(regApiPtr->globalcheckpointid);
4754     sendSignal(regApiPtr->ndbapiBlockref,
4755 	       GSN_TCKEYCONF, signal, (TpacketLen - 1) + 1 /** gci_lo */, JBB);
4756     return;
4757   } else if (((TcurrLen + TpacketLen + 1 /** gci_lo */) > 25) &&
4758              (TcurrLen > 0)) {
4759     jam();
4760     sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
4761     TcurrLen = 0;
4762   } else {
4763     jam();
4764     updatePackedList(signal, localHostptr.p, localHostptr.i);
4765   }//if
4766   // -------------------------------------------------------------------------
4767   // The header contains the block reference of receiver plus the real signal
4768   // length - 3, since we have the real signal length plus one additional word
4769   // for the header we have to do - 4.
4770   // -------------------------------------------------------------------------
4771   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4 + 1 /** gci_lo */);
4772   UintR Tpack1 = regApiPtr->ndbapiConnect;
4773   UintR Tpack2 = Uint32(regApiPtr->globalcheckpointid >> 32);
4774   UintR Tpack3 = confInfo;
4775   UintR Tpack4 = regApiPtr->transid[0];
4776   UintR Tpack5 = regApiPtr->transid[1];
4777   UintR Tpack6 = Uint32(regApiPtr->globalcheckpointid);
4778 
4779   localHostptr.p->noOfWordsTCKEYCONF = TcurrLen + TpacketLen + 1 /** gci_lo */;
4780 
4781   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 0] = Tpack0;
4782   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 1] = Tpack1;
4783   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 2] = Tpack2;
4784   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 3] = Tpack3;
4785   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 4] = Tpack4;
4786   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 5] = Tpack5;
4787 
4788   UintR Ti;
4789   for (Ti = 6; Ti < TpacketLen; Ti++) {
4790     localHostptr.p->packedWordsTCKEYCONF[TcurrLen + Ti] =
4791       regApiPtr->tcSendArray[Ti - 6];
4792   }//for
4793   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + TpacketLen] = Tpack6;
4794 
4795   if (unlikely(!ndb_check_micro_gcp(getNodeInfo(localHostptr.i).m_version)))
4796   {
4797     jam();
4798     ndbassert(Tpack6 == 0 ||
4799               getNodeInfo(localHostptr.i).m_version == 0); // Disconnected
4800   }
4801 }//Dbtc::sendtckeyconf()
4802 
copyFromToLen(UintR * sourceBuffer,UintR * destBuffer,UintR Tlen)4803 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
4804 {
4805   UintR Tindex = 0;
4806   UintR Ti;
4807   while (Tlen >= 4) {
4808     UintR Tdata0 = sourceBuffer[Tindex + 0];
4809     UintR Tdata1 = sourceBuffer[Tindex + 1];
4810     UintR Tdata2 = sourceBuffer[Tindex + 2];
4811     UintR Tdata3 = sourceBuffer[Tindex + 3];
4812     Tlen -= 4;
4813     destBuffer[Tindex + 0] = Tdata0;
4814     destBuffer[Tindex + 1] = Tdata1;
4815     destBuffer[Tindex + 2] = Tdata2;
4816     destBuffer[Tindex + 3] = Tdata3;
4817     Tindex += 4;
4818   }//while
4819   for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
4820     destBuffer[Tindex] = sourceBuffer[Tindex];
4821   }//for
4822 }//Dbtc::copyFromToLen()
4823 
execSEND_PACKED(Signal * signal)4824 void Dbtc::execSEND_PACKED(Signal* signal)
4825 {
4826   HostRecordPtr Thostptr;
4827   HostRecord *localHostRecord = hostRecord;
4828   UintR i;
4829   UintR TpackedListIndex = cpackedListIndex;
4830   jamEntry();
4831   for (i = 0; i < TpackedListIndex; i++) {
4832     Thostptr.i = cpackedList[i];
4833     ptrAss(Thostptr, localHostRecord);
4834     arrGuard(Thostptr.i - 1, MAX_NODES - 1);
4835     UintR TnoOfPackedWordsLqh = Thostptr.p->noOfPackedWordsLqh;
4836     UintR TnoOfWordsTCKEYCONF = Thostptr.p->noOfWordsTCKEYCONF;
4837     jam();
4838     if (TnoOfPackedWordsLqh > 0) {
4839       jam();
4840       sendPackedSignalLqh(signal, Thostptr.p);
4841     }//if
4842     if (TnoOfWordsTCKEYCONF > 0) {
4843       jam();
4844       sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4845     }//if
4846     Thostptr.p->inPackedList = false;
4847   }//for
4848   cpackedListIndex = 0;
4849   return;
4850 }//Dbtc::execSEND_PACKED()
4851 
4852 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 ahostIndex)4853 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
4854 {
4855   if (ahostptr->inPackedList == false) {
4856     UintR TpackedListIndex = cpackedListIndex;
4857     jam();
4858     ahostptr->inPackedList = true;
4859     cpackedList[TpackedListIndex] = ahostIndex;
4860     cpackedListIndex = TpackedListIndex + 1;
4861   }//if
4862 }//Dbtc::updatePackedList()
4863 
sendPackedSignalLqh(Signal * signal,HostRecord * ahostptr)4864 void Dbtc::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
4865 {
4866   UintR Tj;
4867   UintR TnoOfWords = ahostptr->noOfPackedWordsLqh;
4868   for (Tj = 0; Tj < TnoOfWords; Tj += 4) {
4869     UintR sig0 = ahostptr->packedWordsLqh[Tj + 0];
4870     UintR sig1 = ahostptr->packedWordsLqh[Tj + 1];
4871     UintR sig2 = ahostptr->packedWordsLqh[Tj + 2];
4872     UintR sig3 = ahostptr->packedWordsLqh[Tj + 3];
4873     signal->theData[Tj + 0] = sig0;
4874     signal->theData[Tj + 1] = sig1;
4875     signal->theData[Tj + 2] = sig2;
4876     signal->theData[Tj + 3] = sig3;
4877   }//for
4878   ahostptr->noOfPackedWordsLqh = 0;
4879   sendSignal(ahostptr->hostLqhBlockRef,
4880              GSN_PACKED_SIGNAL,
4881              signal,
4882              TnoOfWords,
4883              JBB);
4884 }//Dbtc::sendPackedSignalLqh()
4885 
sendPackedTCKEYCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)4886 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
4887                                HostRecord * ahostptr,
4888                                UintR hostId)
4889 {
4890   UintR Tj;
4891   UintR TnoOfWords = ahostptr->noOfWordsTCKEYCONF;
4892   BlockReference TBref = numberToRef(API_PACKED, hostId);
4893   for (Tj = 0; Tj < ahostptr->noOfWordsTCKEYCONF; Tj += 4) {
4894     UintR sig0 = ahostptr->packedWordsTCKEYCONF[Tj + 0];
4895     UintR sig1 = ahostptr->packedWordsTCKEYCONF[Tj + 1];
4896     UintR sig2 = ahostptr->packedWordsTCKEYCONF[Tj + 2];
4897     UintR sig3 = ahostptr->packedWordsTCKEYCONF[Tj + 3];
4898     signal->theData[Tj + 0] = sig0;
4899     signal->theData[Tj + 1] = sig1;
4900     signal->theData[Tj + 2] = sig2;
4901     signal->theData[Tj + 3] = sig3;
4902   }//for
4903   ahostptr->noOfWordsTCKEYCONF = 0;
4904   sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
4905 }//Dbtc::sendPackedTCKEYCONF()
4906 
4907 /*
4908 4.3.11 DIVERIFY
4909 ---------------
4910 */
4911 /*****************************************************************************/
4912 /*                               D I V E R I F Y                             */
4913 /*                                                                           */
4914 /*****************************************************************************/
diverify010Lab(Signal * signal)4915 void Dbtc::diverify010Lab(Signal* signal)
4916 {
4917   UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
4918   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4919   signal->theData[0] = apiConnectptr.i;
4920   signal->theData[1] = instance() ? instance() - 1 : 0;
4921   if (ERROR_INSERTED(8022)) {
4922     jam();
4923     systemErrorLab(signal, __LINE__);
4924   }//if
4925 
4926   if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS))
4927   {
4928     jam();
4929     /**
4930      * If trans has deferred triggers, let them fire just before
4931      *   transaction starts to commit
4932      */
4933     regApiPtr->pendingTriggers = 0;
4934     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_DEFERRED_TRIGGERS);
4935     sendFireTrigReq(signal, apiConnectptr, regApiPtr->firstTcConnect);
4936     return;
4937   }
4938 
4939   if (regApiPtr->lqhkeyreqrec)
4940   {
4941     if (TfirstfreeApiConnectCopy != RNIL) {
4942       seizeApiConnectCopy(signal);
4943       regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
4944       /*-----------------------------------------------------------------------
4945        * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
4946        * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
4947        * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
4948        * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
4949        *---------------------------------------------------------------------*/
4950       * (EmulatedJamBuffer**)(signal->theData+2) = jamBuffer();
4951       EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal,
4952                      2 + sizeof(void*)/sizeof(Uint32), 0);
4953       if (signal->theData[3] == 0) {
4954         execDIVERIFYCONF(signal);
4955       }
4956       return;
4957     } else {
4958       /*-----------------------------------------------------------------------
4959        * There were no free copy connections available. We must abort the
4960        * transaction since otherwise we will have a problem with the report
4961        * to the application.
4962        * This should more or less not happen but if it happens we do
4963        * not want to crash and we do not want to create code to handle it
4964        * properly since it is difficult to test it and will be complex to
4965        * handle a problem more or less not occurring.
4966        *---------------------------------------------------------------------*/
4967       terrorCode = ZSEIZE_API_COPY_ERROR;
4968       abortErrorLab(signal);
4969       return;
4970     }
4971   }
4972   else
4973   {
4974     jam();
4975     sendtckeyconf(signal, 1);
4976     regApiPtr->apiConnectstate = CS_CONNECTED;
4977     regApiPtr->m_transaction_nodes.clear();
4978     setApiConTimer(apiConnectptr.i, 0,__LINE__);
4979   }
4980 }//Dbtc::diverify010Lab()
4981 
4982 /* ------------------------------------------------------------------------- */
4983 /* -------                  SEIZE_API_CONNECT                        ------- */
4984 /*                  SEIZE CONNECT RECORD FOR A REQUEST                       */
4985 /* ------------------------------------------------------------------------- */
seizeApiConnectCopy(Signal * signal)4986 void Dbtc::seizeApiConnectCopy(Signal* signal)
4987 {
4988   ApiConnectRecordPtr locApiConnectptr;
4989 
4990   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4991   UintR TapiConnectFilesize = capiConnectFilesize;
4992   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4993 
4994   locApiConnectptr.i = cfirstfreeApiConnectCopy;
4995   ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4996   cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
4997   locApiConnectptr.p->nextApiConnect = RNIL;
4998   regApiPtr->apiCopyRecord = locApiConnectptr.i;
4999   tc_clearbit(regApiPtr->m_flags,
5000               ApiConnectRecord::TF_TRIGGER_PENDING);
5001   regApiPtr->m_special_op_flags = 0;
5002 }//Dbtc::seizeApiConnectCopy()
5003 
execDIVERIFYCONF(Signal * signal)5004 void Dbtc::execDIVERIFYCONF(Signal* signal)
5005 {
5006   UintR TapiConnectptrIndex = signal->theData[0];
5007   UintR TapiConnectFilesize = capiConnectFilesize;
5008   UintR Tgci_hi = signal->theData[1];
5009   UintR Tgci_lo = signal->theData[2];
5010   Uint64 Tgci = Tgci_lo | (Uint64(Tgci_hi) << 32);
5011   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5012 
5013   jamEntry();
5014   if (ERROR_INSERTED(8017)) {
5015     CLEAR_ERROR_INSERT_VALUE;
5016     return;
5017   }//if
5018   if (TapiConnectptrIndex >= TapiConnectFilesize) {
5019     TCKEY_abort(signal, 31);
5020     return;
5021   }//if
5022   ApiConnectRecord * const regApiPtr =
5023                             &localApiConnectRecord[TapiConnectptrIndex];
5024   ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
5025   UintR TApifailureNr = regApiPtr->failureNr;
5026   UintR Tfailure_nr = cfailure_nr;
5027   apiConnectptr.i = TapiConnectptrIndex;
5028   apiConnectptr.p = regApiPtr;
5029   if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
5030     TCKEY_abort(signal, 32);
5031     return;
5032   }//if
5033   /*--------------------------------------------------------------------------
5034    * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
5035    * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
5036    * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
5037    * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
5038    * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
5039    *-------------------------------------------------------------------------*/
5040   if (TApifailureNr != Tfailure_nr) {
5041     DIVER_node_fail_handling(signal, Tgci);
5042     return;
5043   }//if
5044   commitGciHandling(signal, Tgci);
5045 
5046   /**************************************************************************
5047    *                                 C O M M I T
5048    * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
5049    **************************************************************************/
5050 
5051   UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
5052   UintR TtcConnectFilesize = ctcConnectFilesize;
5053   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5054 
5055   regApiPtr->counter = regApiPtr->lqhkeyconfrec;
5056   regApiPtr->apiConnectstate = CS_COMMITTING;
5057   if (TtcConnectptrIndex >= TtcConnectFilesize) {
5058     TCKEY_abort(signal, 33);
5059     return;
5060   }//if
5061   TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
5062   tcConnectptr.i = TtcConnectptrIndex;
5063   tcConnectptr.p = regTcPtr;
5064   commit020Lab(signal);
5065 }//Dbtc::execDIVERIFYCONF()
5066 
5067 /*--------------------------------------------------------------------------*/
5068 /*                             COMMIT_GCI_HANDLING                          */
5069 /*       SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT.       */
5070 /*--------------------------------------------------------------------------*/
commitGciHandling(Signal * signal,Uint64 Tgci)5071 void Dbtc::commitGciHandling(Signal* signal, Uint64 Tgci)
5072 {
5073   GcpRecordPtr localGcpPointer;
5074 
5075   UintR TgcpFilesize = cgcpFilesize;
5076   UintR Tfirstgcp = cfirstgcp;
5077   Ptr<ApiConnectRecord> regApiPtr = apiConnectptr;
5078   GcpRecord *localGcpRecord = gcpRecord;
5079 
5080   regApiPtr.p->globalcheckpointid = Tgci;
5081   if (Tfirstgcp != RNIL) {
5082     /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
5083     localGcpPointer.i = Tfirstgcp;
5084     ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5085     do {
5086       if (regApiPtr.p->globalcheckpointid == localGcpPointer.p->gcpId) {
5087         jam();
5088         linkApiToGcp(localGcpPointer, regApiPtr);
5089         return;
5090       } else {
5091         if (unlikely(! (regApiPtr.p->globalcheckpointid > localGcpPointer.p->gcpId)))
5092         {
5093           ndbout_c("%u/%u %u/%u",
5094                    Uint32(regApiPtr.p->globalcheckpointid >> 32),
5095                    Uint32(regApiPtr.p->globalcheckpointid),
5096                    Uint32(localGcpPointer.p->gcpId >> 32),
5097                    Uint32(localGcpPointer.p->gcpId));
5098           crash_gcp(__LINE__);
5099         }
5100         localGcpPointer.i = localGcpPointer.p->nextGcp;
5101         jam();
5102         if (localGcpPointer.i != RNIL) {
5103           jam();
5104           ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5105           continue;
5106         }//if
5107       }//if
5108       seizeGcp(localGcpPointer, Tgci);
5109       linkApiToGcp(localGcpPointer, regApiPtr);
5110       return;
5111     } while (1);
5112   } else {
5113     jam();
5114     seizeGcp(localGcpPointer, Tgci);
5115     linkApiToGcp(localGcpPointer, regApiPtr);
5116   }//if
5117 }//Dbtc::commitGciHandling()
5118 
5119 /* --------------------------------------------------------------------------*/
5120 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
5121 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS   */
5122 /* LINKED OUT OF THE LIST.                                                   */
5123 /*---------------------------------------------------------------------------*/
linkApiToGcp(Ptr<GcpRecord> regGcpPtr,Ptr<ApiConnectRecord> regApiPtr)5124 void Dbtc::linkApiToGcp(Ptr<GcpRecord> regGcpPtr,
5125                         Ptr<ApiConnectRecord> regApiPtr)
5126 {
5127   ApiConnectRecordPtr localApiConnectptr;
5128   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5129 
5130   regApiPtr.p->nextGcpConnect = RNIL;
5131   if (regGcpPtr.p->firstApiConnect == RNIL) {
5132     regGcpPtr.p->firstApiConnect = regApiPtr.i;
5133     jam();
5134   } else {
5135     UintR TapiConnectFilesize = capiConnectFilesize;
5136     localApiConnectptr.i = regGcpPtr.p->lastApiConnect;
5137     jam();
5138     ptrCheckGuard(localApiConnectptr,
5139                   TapiConnectFilesize, localApiConnectRecord);
5140     localApiConnectptr.p->nextGcpConnect = regApiPtr.i;
5141   }//if
5142   UintR TlastApiConnect = regGcpPtr.p->lastApiConnect;
5143   regApiPtr.p->gcpPointer = regGcpPtr.i;
5144   regApiPtr.p->prevGcpConnect = TlastApiConnect;
5145   regGcpPtr.p->lastApiConnect = regApiPtr.i;
5146 }//Dbtc::linkApiToGcp()
5147 
5148 void
crash_gcp(Uint32 line)5149 Dbtc::crash_gcp(Uint32 line)
5150 {
5151   GcpRecordPtr localGcpPointer;
5152 
5153   localGcpPointer.i = cfirstgcp;
5154 
5155   while (localGcpPointer.i != RNIL)
5156   {
5157     ptrCheckGuard(localGcpPointer, cgcpFilesize, gcpRecord);
5158     ndbout_c("%u : %u/%u nomoretrans: %u api %u %u next: %u",
5159              localGcpPointer.i,
5160              Uint32(localGcpPointer.p->gcpId >> 32),
5161              Uint32(localGcpPointer.p->gcpId),
5162              localGcpPointer.p->gcpNomoretransRec,
5163              localGcpPointer.p->firstApiConnect,
5164              localGcpPointer.p->lastApiConnect,
5165              localGcpPointer.p->nextGcp);
5166     localGcpPointer.i = localGcpPointer.p->nextGcp;
5167   }
5168   progError(line, NDBD_EXIT_NDBREQUIRE);
5169   ndbrequire(false);
5170 }
5171 
seizeGcp(Ptr<GcpRecord> & dst,Uint64 Tgci)5172 void Dbtc::seizeGcp(Ptr<GcpRecord> & dst, Uint64 Tgci)
5173 {
5174   GcpRecordPtr tmpGcpPointer;
5175   GcpRecordPtr localGcpPointer;
5176 
5177   UintR Tfirstgcp = cfirstgcp;
5178   UintR TgcpFilesize = cgcpFilesize;
5179   GcpRecord *localGcpRecord = gcpRecord;
5180 
5181   localGcpPointer.i = cfirstfreeGcp;
5182   if (unlikely(localGcpPointer.i > TgcpFilesize))
5183   {
5184     ndbout_c("%u/%u", Uint32(Tgci >> 32), Uint32(Tgci));
5185     crash_gcp(__LINE__);
5186   }
5187   ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
5188   UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
5189   localGcpPointer.p->gcpId = Tgci;
5190   localGcpPointer.p->nextGcp = RNIL;
5191   localGcpPointer.p->firstApiConnect = RNIL;
5192   localGcpPointer.p->lastApiConnect = RNIL;
5193   localGcpPointer.p->gcpNomoretransRec = ZFALSE;
5194   cfirstfreeGcp = TfirstfreeGcp;
5195 
5196   if (Tfirstgcp == RNIL) {
5197     jam();
5198     cfirstgcp = localGcpPointer.i;
5199   } else {
5200     tmpGcpPointer.i = clastgcp;
5201     jam();
5202     ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
5203     tmpGcpPointer.p->nextGcp = localGcpPointer.i;
5204   }//if
5205   clastgcp = localGcpPointer.i;
5206   dst = localGcpPointer;
5207 }//Dbtc::seizeGcp()
5208 
5209 /*---------------------------------------------------------------------------*/
5210 // Send COMMIT messages to all LQH operations involved in the transaction.
5211 /*---------------------------------------------------------------------------*/
commit020Lab(Signal * signal)5212 void Dbtc::commit020Lab(Signal* signal)
5213 {
5214   TcConnectRecordPtr localTcConnectptr;
5215   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5216   UintR TtcConnectFilesize = ctcConnectFilesize;
5217   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5218 
5219   localTcConnectptr.p = tcConnectptr.p;
5220   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5221   UintR Tcount = 0;
5222   do {
5223     /*-----------------------------------------------------------------------
5224      * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
5225      *-----------------------------------------------------------------------*/
5226     /* *********< */
5227     /*  COMMIT  < */
5228     /* *********< */
5229     localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
5230     localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
5231     Tcount += sendCommitLqh(signal, localTcConnectptr.p);
5232 
5233     if (localTcConnectptr.i != RNIL) {
5234       if (Tcount < 16 &&
5235           ! (ERROR_INSERTED(8057) ||
5236              ERROR_INSERTED(8073) ||
5237              ERROR_INSERTED(8089)))
5238       {
5239         ptrCheckGuard(localTcConnectptr,
5240                       TtcConnectFilesize, localTcConnectRecord);
5241         jam();
5242         continue;
5243       } else {
5244         jam();
5245         if (ERROR_INSERTED(8014)) {
5246           CLEAR_ERROR_INSERT_VALUE;
5247           return;
5248         }//if
5249 
5250         if (ERROR_INSERTED(8073))
5251         {
5252           execSEND_PACKED(signal);
5253           signal->theData[0] = 9999;
5254           sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
5255           return;
5256         }
5257         signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
5258         signal->theData[1] = apiConnectptr.i;
5259         signal->theData[2] = localTcConnectptr.i;
5260         if (ERROR_INSERTED(8089))
5261         {
5262           sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
5263           return;
5264         }
5265         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5266         return;
5267       }//if
5268     } else {
5269       jam();
5270       if (ERROR_INSERTED(8057))
5271         CLEAR_ERROR_INSERT_VALUE;
5272 
5273       if (ERROR_INSERTED(8089))
5274         CLEAR_ERROR_INSERT_VALUE;
5275 
5276       regApiPtr->apiConnectstate = CS_COMMIT_SENT;
5277       return;
5278     }//if
5279   } while (1);
5280 }//Dbtc::commit020Lab()
5281 
5282 Uint32
sendCommitLqh(Signal * signal,TcConnectRecord * const regTcPtr)5283 Dbtc::sendCommitLqh(Signal* signal,
5284                     TcConnectRecord * const regTcPtr)
5285 {
5286   HostRecordPtr Thostptr;
5287   UintR ThostFilesize = chostFilesize;
5288   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5289   Thostptr.i = regTcPtr->lastLqhNodeId;
5290   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5291 
5292   Uint32 Tnode = Thostptr.i;
5293   Uint32 self = getOwnNodeId();
5294   Uint32 ret = (Tnode == self) ? 4 : 1;
5295 
5296   Uint32 Tdata[5];
5297   Tdata[0] = regTcPtr->lastLqhCon;
5298   Tdata[1] = Uint32(regApiPtr->globalcheckpointid >> 32);
5299   Tdata[2] = regApiPtr->transid[0];
5300   Tdata[3] = regApiPtr->transid[1];
5301   Tdata[4] = Uint32(regApiPtr->globalcheckpointid);
5302   Uint32 len = 5;
5303 
5304   if (unlikely(!ndb_check_micro_gcp(getNodeInfo(Thostptr.i).m_version)))
5305   {
5306     jam();
5307     ndbassert(Tdata[4] == 0 || getNodeInfo(Thostptr.i).m_version == 0);
5308     len = 4;
5309   }
5310 
5311   // currently packed signal cannot address specific instance
5312   const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5313   if (send_unpacked) {
5314     memcpy(&signal->theData[0], &Tdata[0], len << 2);
5315     Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5316     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5317     sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
5318     return ret;
5319   }
5320 
5321   if (Thostptr.p->noOfPackedWordsLqh > 25 - 5) {
5322     jam();
5323     sendPackedSignalLqh(signal, Thostptr.p);
5324   } else {
5325     jam();
5326     ret = 1;
5327     updatePackedList(signal, Thostptr.p, Thostptr.i);
5328   }
5329 
5330   Tdata[0] |= (ZCOMMIT << 28);
5331   UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5332   UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5333   memcpy(TDataPtr, &Tdata[0], len << 2);
5334   Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5335   return ret;
5336 }
5337 
5338 void
DIVER_node_fail_handling(Signal * signal,Uint64 Tgci)5339 Dbtc::DIVER_node_fail_handling(Signal* signal, Uint64 Tgci)
5340 {
5341   /*------------------------------------------------------------------------
5342    * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
5343    * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
5344    * ABORT AND THE COMMIT CASES WE NEED  TO SET-UP THE DATA FOR THE
5345    * ABORT/COMMIT/COMPLETE  HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
5346    *------------------------------------------------------------------------*/
5347   tabortInd = ZFALSE;
5348   setupFailData(signal);
5349   if (false && tabortInd == ZFALSE) {
5350     jam();
5351     commitGciHandling(signal, Tgci);
5352     toCommitHandlingLab(signal);
5353   } else {
5354     jam();
5355     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
5356     apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
5357     toAbortHandlingLab(signal);
5358   }//if
5359   return;
5360 }//Dbtc::DIVER_node_fail_handling()
5361 
5362 
5363 /* ------------------------------------------------------------------------- */
5364 /* -------                       ENTER COMMITTED                     ------- */
5365 /*                                                                           */
5366 /* ------------------------------------------------------------------------- */
execCOMMITTED(Signal * signal)5367 void Dbtc::execCOMMITTED(Signal* signal)
5368 {
5369   TcConnectRecordPtr localTcConnectptr;
5370   ApiConnectRecordPtr localApiConnectptr;
5371   ApiConnectRecordPtr localCopyPtr;
5372 
5373   UintR TtcConnectFilesize = ctcConnectFilesize;
5374   UintR TapiConnectFilesize = capiConnectFilesize;
5375   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5376   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5377 
5378 #ifdef ERROR_INSERT
5379   if (ERROR_INSERTED(8018)) {
5380     CLEAR_ERROR_INSERT_VALUE;
5381     return;
5382   }//if
5383   CRASH_INSERTION(8030);
5384   if (ERROR_INSERTED(8025)) {
5385     SET_ERROR_INSERT_VALUE(8026);
5386     return;
5387   }//if
5388   if (ERROR_INSERTED(8041)) {
5389     CLEAR_ERROR_INSERT_VALUE;
5390     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
5391     return;
5392   }//if
5393   if (ERROR_INSERTED(8042)) {
5394     SET_ERROR_INSERT_VALUE(8046);
5395     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
5396     return;
5397   }//if
5398 #endif
5399   localTcConnectptr.i = signal->theData[0];
5400   jamEntry();
5401   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5402   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
5403   if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
5404     warningReport(signal, 4);
5405     return;
5406   }//if
5407   ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
5408 		localApiConnectRecord);
5409   UintR Tcounter = localApiConnectptr.p->counter - 1;
5410   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
5411   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
5412   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
5413   Tdata1 = Tdata1 | Tdata2;
5414   bool TcheckCondition =
5415     (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
5416 
5417   setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
5418   localApiConnectptr.p->counter = Tcounter;
5419   localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
5420   if (Tdata1 != 0) {
5421     warningReport(signal, 5);
5422     return;
5423   }//if
5424   if (TcheckCondition) {
5425     jam();
5426     /*-------------------------------------------------------*/
5427     // We have not sent all COMMIT requests yet. We could be
5428     // in the state that all sent are COMMITTED but we are
5429     // still waiting for a CONTINUEB to send the rest of the
5430     // COMMIT requests.
5431     /*-------------------------------------------------------*/
5432     return;
5433   }//if
5434   if (ERROR_INSERTED(8020)) {
5435     jam();
5436     systemErrorLab(signal, __LINE__);
5437   }//if
5438   /*-------------------------------------------------------*/
5439   /* THE ENTIRE TRANSACTION IS NOW COMMITED                */
5440   /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION.  */
5441   /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
5442   /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A     */
5443   /* NEW API CONNECT RECORD.                               */
5444   /*-------------------------------------------------------*/
5445 
5446   apiConnectptr = localApiConnectptr;
5447   localCopyPtr = sendApiCommit(signal);
5448 
5449   localTcConnectptr.i = localCopyPtr.p->firstTcConnect;
5450   UintR Tlqhkeyconfrec = localCopyPtr.p->lqhkeyconfrec;
5451   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5452   localCopyPtr.p->counter = Tlqhkeyconfrec;
5453 
5454   apiConnectptr = localCopyPtr;
5455   tcConnectptr = localTcConnectptr;
5456   complete010Lab(signal);
5457   return;
5458 
5459 }//Dbtc::execCOMMITTED()
5460 
5461 /*-------------------------------------------------------*/
5462 /*                       SEND_API_COMMIT                 */
5463 /*       SEND COMMIT DECISION TO THE API.                */
5464 /*-------------------------------------------------------*/
5465 Ptr<Dbtc::ApiConnectRecord>
sendApiCommit(Signal * signal)5466 Dbtc::sendApiCommit(Signal* signal)
5467 {
5468   ApiConnectRecordPtr regApiPtr = apiConnectptr;
5469 
5470   if (ERROR_INSERTED(8055))
5471   {
5472     /**
5473      * 1) Kill self
5474      * 2) Disconnect API
5475      * 3) Prevent execAPI_FAILREQ from handling trans...
5476      */
5477     signal->theData[0] = 9999;
5478     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
5479     Uint32 node = refToNode(regApiPtr.p->ndbapiBlockref);
5480     signal->theData[0] = node;
5481     sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
5482 
5483     SET_ERROR_INSERT_VALUE(8056);
5484 
5485     goto err8055;
5486   }
5487 
5488   if (regApiPtr.p->returnsignal == RS_TCKEYCONF)
5489   {
5490     if (ERROR_INSERTED(8054))
5491     {
5492       CLEAR_ERROR_INSERT_VALUE;
5493       signal->theData[0] = 9999;
5494       sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 5000, 1);
5495     }
5496     else
5497     {
5498       sendtckeyconf(signal, 1);
5499     }
5500   }
5501   else if (regApiPtr.p->returnsignal == RS_TC_COMMITCONF)
5502   {
5503     jam();
5504     TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
5505     if(regApiPtr.p->commitAckMarker == RNIL)
5506     {
5507       jam();
5508       commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect;
5509     }
5510     else
5511     {
5512       jam();
5513       commitConf->apiConnectPtr = regApiPtr.p->ndbapiConnect | 1;
5514     }
5515     commitConf->transId1 = regApiPtr.p->transid[0];
5516     commitConf->transId2 = regApiPtr.p->transid[1];
5517     commitConf->gci_hi = Uint32(regApiPtr.p->globalcheckpointid >> 32);
5518     commitConf->gci_lo = Uint32(regApiPtr.p->globalcheckpointid);
5519 
5520     sendSignal(regApiPtr.p->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
5521 	       TcCommitConf::SignalLength, JBB);
5522   }
5523   else if (regApiPtr.p->returnsignal == RS_NO_RETURN)
5524   {
5525     jam();
5526   }
5527   else
5528   {
5529     TCKEY_abort(signal, 37);
5530     return regApiPtr;
5531   }//if
5532 
5533 err8055:
5534   Ptr<ApiConnectRecord> copyPtr;
5535   UintR TapiConnectFilesize = capiConnectFilesize;
5536   copyPtr.i = regApiPtr.p->apiCopyRecord;
5537   UintR TapiFailState = regApiPtr.p->apiFailState;
5538   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5539 
5540   c_counters.ccommitCount++;
5541   ptrCheckGuard(copyPtr, TapiConnectFilesize, localApiConnectRecord);
5542   copyApi(copyPtr, regApiPtr);
5543   if (TapiFailState != ZTRUE) {
5544     return copyPtr;
5545   } else {
5546     jam();
5547     handleApiFailState(signal, regApiPtr.i);
5548     return copyPtr;
5549   }//if
5550 }//Dbtc::sendApiCommit()
5551 
5552 /* ========================================================================= */
5553 /* =======                  COPY_API                                 ======= */
5554 /*   COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT                */
5555 /*   IS PREPARED TO RECEIVE A NEW TRANSACTION.                               */
5556 /*===========================================================================*/
copyApi(ApiConnectRecordPtr copyPtr,ApiConnectRecordPtr regApiPtr)5557 void Dbtc::copyApi(ApiConnectRecordPtr copyPtr, ApiConnectRecordPtr regApiPtr)
5558 {
5559   UintR TndbapiConnect = regApiPtr.p->ndbapiConnect;
5560   UintR TfirstTcConnect = regApiPtr.p->firstTcConnect;
5561   UintR Ttransid1 = regApiPtr.p->transid[0];
5562   UintR Ttransid2 = regApiPtr.p->transid[1];
5563   UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
5564   UintR TgcpPointer = regApiPtr.p->gcpPointer;
5565   UintR TgcpFilesize = cgcpFilesize;
5566   NdbNodeBitmask Tnodes = regApiPtr.p->m_transaction_nodes;
5567   GcpRecord *localGcpRecord = gcpRecord;
5568 
5569   copyPtr.p->ndbapiBlockref = regApiPtr.p->ndbapiBlockref;
5570   copyPtr.p->ndbapiConnect = TndbapiConnect;
5571   copyPtr.p->firstTcConnect = TfirstTcConnect;
5572   copyPtr.p->apiConnectstate = CS_COMPLETING;
5573   copyPtr.p->transid[0] = Ttransid1;
5574   copyPtr.p->transid[1] = Ttransid2;
5575   copyPtr.p->lqhkeyconfrec = Tlqhkeyconfrec;
5576   copyPtr.p->commitAckMarker = RNIL;
5577   copyPtr.p->m_transaction_nodes = Tnodes;
5578   copyPtr.p->singleUserMode = 0;
5579 
5580   Ptr<GcpRecord> gcpPtr;
5581   gcpPtr.i = TgcpPointer;
5582   ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
5583   unlinkApiConnect(gcpPtr, regApiPtr);
5584   linkApiToGcp(gcpPtr, copyPtr);
5585   setApiConTimer(regApiPtr.i, 0, __LINE__);
5586   regApiPtr.p->apiConnectstate = CS_CONNECTED;
5587   regApiPtr.p->commitAckMarker = RNIL;
5588   regApiPtr.p->firstTcConnect = RNIL;
5589   regApiPtr.p->lastTcConnect = RNIL;
5590   regApiPtr.p->m_transaction_nodes.clear();
5591   regApiPtr.p->singleUserMode = 0;
5592   releaseAllSeizedIndexOperations(regApiPtr.p);
5593 }//Dbtc::copyApi()
5594 
unlinkApiConnect(Ptr<GcpRecord> gcpPtr,Ptr<ApiConnectRecord> regApiPtr)5595 void Dbtc::unlinkApiConnect(Ptr<GcpRecord> gcpPtr,
5596                             Ptr<ApiConnectRecord> regApiPtr)
5597 {
5598   ApiConnectRecordPtr localApiConnectptr;
5599   UintR TapiConnectFilesize = capiConnectFilesize;
5600   UintR TprevGcpConnect = regApiPtr.p->prevGcpConnect;
5601   UintR TnextGcpConnect = regApiPtr.p->nextGcpConnect;
5602   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5603 
5604   if (TprevGcpConnect == RNIL) {
5605     gcpPtr.p->firstApiConnect = TnextGcpConnect;
5606     jam();
5607   } else {
5608     localApiConnectptr.i = TprevGcpConnect;
5609     jam();
5610     ptrCheckGuard(localApiConnectptr,
5611                   TapiConnectFilesize, localApiConnectRecord);
5612     localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
5613   }//if
5614   if (TnextGcpConnect == RNIL) {
5615     gcpPtr.p->lastApiConnect = TprevGcpConnect;
5616     jam();
5617   } else {
5618     localApiConnectptr.i = TnextGcpConnect;
5619     jam();
5620     ptrCheckGuard(localApiConnectptr,
5621                   TapiConnectFilesize, localApiConnectRecord);
5622     localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
5623   }//if
5624 }//Dbtc::unlinkApiConnect()
5625 
complete010Lab(Signal * signal)5626 void Dbtc::complete010Lab(Signal* signal)
5627 {
5628   TcConnectRecordPtr localTcConnectptr;
5629   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5630   UintR TtcConnectFilesize = ctcConnectFilesize;
5631   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5632 
5633   localTcConnectptr.p = tcConnectptr.p;
5634   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5635   UintR TapiConnectptrIndex = apiConnectptr.i;
5636   UintR Tcount = 0;
5637   do {
5638     localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
5639     localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
5640 
5641     /* ************ */
5642     /*  COMPLETE  < */
5643     /* ************ */
5644     const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
5645     Tcount += sendCompleteLqh(signal, localTcConnectptr.p);
5646     localTcConnectptr.i = nextTcConnect;
5647     if (localTcConnectptr.i != RNIL) {
5648       if (Tcount < 16) {
5649         ptrCheckGuard(localTcConnectptr,
5650                       TtcConnectFilesize, localTcConnectRecord);
5651         jam();
5652         continue;
5653       } else {
5654         jam();
5655         if (ERROR_INSERTED(8013)) {
5656           CLEAR_ERROR_INSERT_VALUE;
5657           return;
5658         }//if
5659         signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
5660         signal->theData[1] = apiConnectptr.i;
5661         signal->theData[2] = localTcConnectptr.i;
5662         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
5663         return;
5664       }//if
5665     } else {
5666       jam();
5667       regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
5668       return;
5669     }//if
5670   } while (1);
5671 }//Dbtc::complete010Lab()
5672 
5673 Uint32
sendCompleteLqh(Signal * signal,TcConnectRecord * const regTcPtr)5674 Dbtc::sendCompleteLqh(Signal* signal,
5675                       TcConnectRecord * const regTcPtr)
5676 {
5677   HostRecordPtr Thostptr;
5678   UintR ThostFilesize = chostFilesize;
5679   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5680   Thostptr.i = regTcPtr->lastLqhNodeId; //last???
5681   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5682 
5683   Uint32 Tnode = Thostptr.i;
5684   Uint32 self = getOwnNodeId();
5685   Uint32 ret = (Tnode == self) ? 4 : 1;
5686 
5687   Uint32 Tdata[3];
5688   Tdata[0] = regTcPtr->lastLqhCon;
5689   Tdata[1] = regApiPtr->transid[0];
5690   Tdata[2] = regApiPtr->transid[1];
5691   Uint32 len = 3;
5692 
5693   // currently packed signal cannot address specific instance
5694   const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5695   if (send_unpacked) {
5696     memcpy(&signal->theData[0], &Tdata[0], len << 2);
5697     Uint32 instanceKey = regTcPtr->lqhInstanceKey;
5698     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5699     sendSignal(lqhRef, GSN_COMPLETE, signal, 3, JBB);
5700     return ret;
5701   }
5702 
5703   if (Thostptr.p->noOfPackedWordsLqh > 22) {
5704     jam();
5705     sendPackedSignalLqh(signal, Thostptr.p);
5706   } else {
5707     jam();
5708     ret = 1;
5709     updatePackedList(signal, Thostptr.p, Thostptr.i);
5710   }
5711 
5712   Tdata[0] |= (ZCOMPLETE << 28);
5713   UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5714   UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5715   memcpy(TDataPtr, &Tdata[0], len << 2);
5716   Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5717 
5718   return ret;
5719 }
5720 
5721 void
sendFireTrigReq(Signal * signal,Ptr<ApiConnectRecord> regApiPtr,Uint32 TopPtrI)5722 Dbtc::sendFireTrigReq(Signal* signal,
5723                       Ptr<ApiConnectRecord> regApiPtr,
5724                       Uint32 TopPtrI)
5725 {
5726   UintR TtcConnectFilesize = ctcConnectFilesize;
5727   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5728   TcConnectRecordPtr localTcConnectptr;
5729 
5730   setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
5731   regApiPtr.p->apiConnectstate = CS_SEND_FIRE_TRIG_REQ;
5732 
5733   localTcConnectptr.i = TopPtrI;
5734   ndbassert(TopPtrI != RNIL);
5735   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5736   Uint32 pass = regApiPtr.p->m_pre_commit_pass;
5737   for (Uint32 i = 0; localTcConnectptr.i != RNIL && i < 16; i++)
5738   {
5739     ptrCheckGuard(localTcConnectptr,
5740                   TtcConnectFilesize, localTcConnectRecord);
5741 
5742     const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
5743     Uint32 flags = localTcConnectptr.p->m_special_op_flags;
5744     if (flags & TcConnectRecord::SOF_DEFERRED_TRIGGER)
5745     {
5746       jam();
5747       tc_clearbit(flags, TcConnectRecord::SOF_DEFERRED_TRIGGER);
5748       ndbrequire(localTcConnectptr.p->tcConnectstate == OS_PREPARED);
5749       localTcConnectptr.p->tcConnectstate = OS_FIRE_TRIG_REQ;
5750       localTcConnectptr.p->m_special_op_flags = flags;
5751       i += sendFireTrigReqLqh(signal, localTcConnectptr, pass);
5752       Tlqhkeyreqrec++;
5753     }
5754     localTcConnectptr.i = nextTcConnect;
5755   }
5756 
5757   regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec;
5758   if (localTcConnectptr.i == RNIL)
5759   {
5760     /**
5761      * Now wait for FIRE_TRIG_CONF
5762      */
5763     jam();
5764     regApiPtr.p->apiConnectstate = CS_WAIT_FIRE_TRIG_REQ;
5765     ndbrequire(pass < 255);
5766     regApiPtr.p->m_pre_commit_pass = (Uint8)(pass + 1);
5767     return;
5768   }
5769   else
5770   {
5771     jam();
5772     signal->theData[0] = TcContinueB::ZSEND_FIRE_TRIG_REQ;
5773     signal->theData[1] = regApiPtr.i;
5774     signal->theData[2] = regApiPtr.p->transid[0];
5775     signal->theData[3] = regApiPtr.p->transid[1];
5776     signal->theData[4] = localTcConnectptr.i;
5777     if (ERROR_INSERTED_CLEAR(8090))
5778     {
5779       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 5);
5780     }
5781     else
5782     {
5783       sendSignal(cownref, GSN_CONTINUEB, signal, 5, JBB);
5784     }
5785   }
5786 }
5787 
5788 Uint32
sendFireTrigReqLqh(Signal * signal,Ptr<TcConnectRecord> regTcPtr,Uint32 pass)5789 Dbtc::sendFireTrigReqLqh(Signal* signal,
5790                          Ptr<TcConnectRecord> regTcPtr,
5791                          Uint32 pass)
5792 {
5793   HostRecordPtr Thostptr;
5794   UintR ThostFilesize = chostFilesize;
5795   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5796   Thostptr.i = regTcPtr.p->tcNodedata[0];
5797   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
5798 
5799   Uint32 Tnode = Thostptr.i;
5800   Uint32 self = getOwnNodeId();
5801   Uint32 ret = (Tnode == self) ? 4 : 1;
5802 
5803   Uint32 Tdata[FireTrigReq::SignalLength];
5804   FireTrigReq * req = CAST_PTR(FireTrigReq, Tdata);
5805   req->tcOpRec = regTcPtr.i;
5806   req->transId[0] = regApiPtr->transid[0];
5807   req->transId[1] = regApiPtr->transid[1];
5808   req->pass = pass;
5809   Uint32 len = FireTrigReq::SignalLength;
5810 
5811   // currently packed signal cannot address specific instance
5812   const bool send_unpacked = getNodeInfo(Thostptr.i).m_lqh_workers > 1;
5813   if (send_unpacked) {
5814     memcpy(signal->theData, Tdata, len << 2);
5815     Uint32 instanceKey = regTcPtr.p->lqhInstanceKey;
5816     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
5817     sendSignal(lqhRef, GSN_FIRE_TRIG_REQ, signal, len, JBB);
5818     return ret;
5819   }
5820 
5821   if (Thostptr.p->noOfPackedWordsLqh > 25 - len) {
5822     jam();
5823     sendPackedSignalLqh(signal, Thostptr.p);
5824   } else {
5825     jam();
5826     ret = 1;
5827     updatePackedList(signal, Thostptr.p, Thostptr.i);
5828   }
5829 
5830   Tdata[0] |= (ZFIRE_TRIG_REQ << 28);
5831   UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
5832   UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
5833   memcpy(TDataPtr, Tdata, len << 2);
5834   Thostptr.p->noOfPackedWordsLqh = Tindex + len;
5835   return ret;
5836 }
5837 
5838 void
execFIRE_TRIG_CONF(Signal * signal)5839 Dbtc::execFIRE_TRIG_CONF(Signal* signal)
5840 {
5841   TcConnectRecordPtr localTcConnectptr;
5842   ApiConnectRecordPtr regApiPtr;
5843 
5844   UintR TtcConnectFilesize = ctcConnectFilesize;
5845   UintR TapiConnectFilesize = capiConnectFilesize;
5846   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5847   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5848 
5849   const FireTrigConf * conf = CAST_CONSTPTR(FireTrigConf, signal->theData);
5850   localTcConnectptr.i = conf->tcOpRec;
5851   jamEntry();
5852   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5853   regApiPtr.i = localTcConnectptr.p->apiConnect;
5854   if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
5855   {
5856     warningReport(signal, 28);
5857     return;
5858   }//if
5859   ptrCheckGuard(regApiPtr, TapiConnectFilesize,
5860                 localApiConnectRecord);
5861 
5862   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5863   Uint32 TapiConnectstate = regApiPtr.p->apiConnectstate;
5864   UintR Tdata1 = regApiPtr.p->transid[0] - conf->transId[0];
5865   UintR Tdata2 = regApiPtr.p->transid[1] - conf->transId[1];
5866   Uint32 TcheckCondition =
5867     (TapiConnectstate != CS_SEND_FIRE_TRIG_REQ) &&
5868     (TapiConnectstate != CS_WAIT_FIRE_TRIG_REQ);
5869 
5870   Tdata1 = Tdata1 | Tdata2 | TcheckCondition;
5871 
5872   if (Tdata1 != 0) {
5873     warningReport(signal, 28);
5874     return;
5875   }//if
5876 
5877   if (ERROR_INSERTED_CLEAR(8091))
5878   {
5879     jam();
5880     return;
5881   }
5882 
5883   CRASH_INSERTION(8092);
5884 
5885   setApiConTimer(regApiPtr.i, ctcTimer, __LINE__);
5886   ndbassert(Tlqhkeyreqrec > 0);
5887   regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
5888   localTcConnectptr.p->tcConnectstate = OS_PREPARED;
5889 
5890   Uint32 noFired  = FireTrigConf::getFiredCount(conf->noFiredTriggers);
5891   Uint32 deferred = FireTrigConf::getDeferredBit(conf->noFiredTriggers);
5892 
5893   regApiPtr.p->pendingTriggers += noFired;
5894   regApiPtr.p->m_flags |= (deferred) ?
5895     ApiConnectRecord::TF_DEFERRED_TRIGGERS : 0;
5896   localTcConnectptr.p->m_special_op_flags |= (deferred) ?
5897     TcConnectRecord::SOF_DEFERRED_TRIGGER : 0;
5898 
5899   if (regApiPtr.p->pendingTriggers == 0)
5900   {
5901     jam();
5902     lqhKeyConf_checkTransactionState(signal, regApiPtr);
5903   }
5904 }
5905 
5906 void
execFIRE_TRIG_REF(Signal * signal)5907 Dbtc::execFIRE_TRIG_REF(Signal* signal)
5908 {
5909   TcConnectRecordPtr localTcConnectptr;
5910   ApiConnectRecordPtr regApiPtr;
5911 
5912   UintR TtcConnectFilesize = ctcConnectFilesize;
5913   UintR TapiConnectFilesize = capiConnectFilesize;
5914   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5915   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
5916 
5917   const FireTrigRef * ref = CAST_CONSTPTR(FireTrigRef, signal->theData);
5918   localTcConnectptr.i = ref->tcOpRec;
5919   jamEntry();
5920   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5921   regApiPtr.i = localTcConnectptr.p->apiConnect;
5922   if (localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ)
5923   {
5924     warningReport(signal, 28);
5925     return;
5926   }//if
5927   ptrCheckGuard(regApiPtr, TapiConnectFilesize,
5928                 localApiConnectRecord);
5929 
5930   apiConnectptr = regApiPtr;
5931 
5932   UintR Tdata1 = regApiPtr.p->transid[0] - ref->transId[0];
5933   UintR Tdata2 = regApiPtr.p->transid[1] - ref->transId[1];
5934   Tdata1 = Tdata1 | Tdata2;
5935   if (Tdata1 != 0) {
5936     warningReport(signal, 28);
5937     return;
5938   }//if
5939 
5940   if (regApiPtr.p->apiConnectstate != CS_SEND_FIRE_TRIG_REQ &&
5941       regApiPtr.p->apiConnectstate != CS_WAIT_FIRE_TRIG_REQ)
5942   {
5943     jam();
5944     warningReport(signal, 28);
5945     return;
5946   }
5947 
5948   terrorCode = ref->errCode;
5949   abortErrorLab(signal);
5950 }
5951 
5952 void
execTC_COMMIT_ACK(Signal * signal)5953 Dbtc::execTC_COMMIT_ACK(Signal* signal){
5954   jamEntry();
5955 
5956   CommitAckMarker key;
5957   key.transid1 = signal->theData[0];
5958   key.transid2 = signal->theData[1];
5959 
5960   CommitAckMarkerPtr removedMarker;
5961   m_commitAckMarkerHash.remove(removedMarker, key);
5962   if (removedMarker.i == RNIL) {
5963     jam();
5964     warningHandlerLab(signal, __LINE__);
5965     return;
5966   }//if
5967   sendRemoveMarkers(signal, removedMarker.p);
5968   m_commitAckMarkerPool.release(removedMarker);
5969 }
5970 
5971 void
sendRemoveMarkers(Signal * signal,const CommitAckMarker * marker)5972 Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker)
5973 {
5974   jam();
5975   const Uint32 transId1 = marker->transid1;
5976   const Uint32 transId2 = marker->transid2;
5977 
5978   for(Uint32 node_id = 1; node_id < MAX_NDB_NODES; node_id++)
5979   {
5980     jam();
5981     if (marker->m_commit_ack_marker_nodes.get(node_id))
5982       sendRemoveMarker(signal, node_id, transId1, transId2);
5983   }
5984 }
5985 
5986 void
sendRemoveMarker(Signal * signal,NodeId nodeId,Uint32 transid1,Uint32 transid2)5987 Dbtc::sendRemoveMarker(Signal* signal,
5988                        NodeId nodeId,
5989                        Uint32 transid1,
5990                        Uint32 transid2){
5991   /**
5992    * Seize host ptr
5993    */
5994   HostRecordPtr hostPtr;
5995   const UintR ThostFilesize = chostFilesize;
5996   hostPtr.i = nodeId;
5997   ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
5998 
5999   Uint32 Tdata[3];
6000   Tdata[0] = 0;
6001   Tdata[1] = transid1;
6002   Tdata[2] = transid2;
6003   Uint32 len = 3;
6004 
6005   // currently packed signals can not address specific instance
6006   bool send_unpacked = getNodeInfo(hostPtr.i).m_lqh_workers > 1;
6007   if (send_unpacked) {
6008     jam();
6009     // first word omitted
6010     memcpy(&signal->theData[0], &Tdata[1], (len - 1) << 2);
6011     Uint32 Tnode = hostPtr.i;
6012     Uint32 i;
6013     for (i = 0; i < MAX_NDBMT_LQH_WORKERS; i++) {
6014       // wl4391_todo skip workers not part of tx
6015       Uint32 instanceKey = 1 + i;
6016       BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
6017       sendSignal(ref, GSN_REMOVE_MARKER_ORD, signal, len - 1, JBB);
6018     }
6019     return;
6020   }
6021 
6022   if (hostPtr.p->noOfPackedWordsLqh > (25 - 3)){
6023     jam();
6024     sendPackedSignalLqh(signal, hostPtr.p);
6025   } else {
6026     jam();
6027     updatePackedList(signal, hostPtr.p, hostPtr.i);
6028   }
6029 
6030   UintR  numWord = hostPtr.p->noOfPackedWordsLqh;
6031   UintR* dataPtr = &hostPtr.p->packedWordsLqh[numWord];
6032 
6033   Tdata[0] |= (ZREMOVE_MARKER << 28);
6034   memcpy(dataPtr, &Tdata[0], len << 2);
6035   hostPtr.p->noOfPackedWordsLqh = numWord + 3;
6036 }
6037 
execCOMPLETED(Signal * signal)6038 void Dbtc::execCOMPLETED(Signal* signal)
6039 {
6040   TcConnectRecordPtr localTcConnectptr;
6041   ApiConnectRecordPtr localApiConnectptr;
6042 
6043   UintR TtcConnectFilesize = ctcConnectFilesize;
6044   UintR TapiConnectFilesize = capiConnectFilesize;
6045   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6046   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
6047 
6048 #ifdef ERROR_INSERT
6049   if (ERROR_INSERTED(8031)) {
6050     systemErrorLab(signal, __LINE__);
6051   }//if
6052   if (ERROR_INSERTED(8019)) {
6053     CLEAR_ERROR_INSERT_VALUE;
6054     return;
6055   }//if
6056   if (ERROR_INSERTED(8027)) {
6057     SET_ERROR_INSERT_VALUE(8028);
6058     return;
6059   }//if
6060   if (ERROR_INSERTED(8043)) {
6061     CLEAR_ERROR_INSERT_VALUE;
6062     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6063     return;
6064   }//if
6065   if (ERROR_INSERTED(8044)) {
6066     SET_ERROR_INSERT_VALUE(8047);
6067     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
6068     return;
6069   }//if
6070 #endif
6071   localTcConnectptr.i = signal->theData[0];
6072   jamEntry();
6073   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6074   bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
6075   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
6076   if (Tcond1) {
6077     warningReport(signal, 6);
6078     return;
6079   }//if
6080   ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
6081 		localApiConnectRecord);
6082   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
6083   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
6084   UintR Tcounter = localApiConnectptr.p->counter - 1;
6085   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
6086   Tdata1 = Tdata1 | Tdata2;
6087   bool TcheckCondition =
6088     (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
6089   if (Tdata1 != 0) {
6090     warningReport(signal, 7);
6091     return;
6092   }//if
6093   setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
6094   localApiConnectptr.p->counter = Tcounter;
6095   localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
6096   localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
6097   if (TcheckCondition) {
6098     jam();
6099     /*-------------------------------------------------------*/
6100     // We have not sent all COMPLETE requests yet. We could be
6101     // in the state that all sent are COMPLETED but we are
6102     // still waiting for a CONTINUEB to send the rest of the
6103     // COMPLETE requests.
6104     /*-------------------------------------------------------*/
6105     return;
6106   }//if
6107   if (ERROR_INSERTED(8021)) {
6108     jam();
6109     systemErrorLab(signal, __LINE__);
6110   }//if
6111   apiConnectptr = localApiConnectptr;
6112   releaseTransResources(signal);
6113 }//Dbtc::execCOMPLETED()
6114 
6115 /*---------------------------------------------------------------------------*/
6116 /*                               RELEASE_TRANS_RESOURCES                     */
6117 /*       RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION.       */
6118 /*---------------------------------------------------------------------------*/
releaseTransResources(Signal * signal)6119 void Dbtc::releaseTransResources(Signal* signal)
6120 {
6121   TcConnectRecordPtr localTcConnectptr;
6122   UintR TtcConnectFilesize = ctcConnectFilesize;
6123   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6124   apiConnectptr.p->m_transaction_nodes.clear();
6125   localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
6126   do {
6127     jam();
6128     ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
6129     UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
6130     tcConnectptr.i = localTcConnectptr.i;
6131     tcConnectptr.p = localTcConnectptr.p;
6132     localTcConnectptr.i = rtrTcConnectptrIndex;
6133     releaseTcCon();
6134   } while (localTcConnectptr.i != RNIL);
6135   handleGcp(signal, apiConnectptr);
6136   releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
6137   releaseAllSeizedIndexOperations(apiConnectptr.p);
6138   releaseApiConCopy(signal);
6139 }//Dbtc::releaseTransResources()
6140 
6141 /* *********************************************************************>> */
6142 /*       MODULE: HANDLE_GCP                                                */
6143 /*       DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
6144 /*       OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC   */
6145 /*       SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
6146 /*       GLOBAL CHECKPOINT HAVE COMPLETED.                                 */
6147 /* *********************************************************************>> */
handleGcp(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)6148 void Dbtc::handleGcp(Signal* signal, Ptr<ApiConnectRecord> regApiPtr)
6149 {
6150   GcpRecord *localGcpRecord = gcpRecord;
6151   GcpRecordPtr localGcpPtr;
6152   UintR TgcpFilesize = cgcpFilesize;
6153   localGcpPtr.i = apiConnectptr.p->gcpPointer;
6154   ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
6155   unlinkApiConnect(localGcpPtr, regApiPtr);
6156   if (localGcpPtr.p->firstApiConnect == RNIL) {
6157     if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
6158       if (c_ongoing_take_over_cnt == 0)
6159       {
6160         jam();
6161         gcpTcfinished(signal, localGcpPtr.p->gcpId);
6162         unlinkGcp(localGcpPtr);
6163       }
6164     }//if
6165   }
6166 }//Dbtc::handleGcp()
6167 
releaseApiConCopy(Signal * signal)6168 void Dbtc::releaseApiConCopy(Signal* signal)
6169 {
6170   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6171   UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
6172   cfirstfreeApiConnectCopy = apiConnectptr.i;
6173   regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
6174   setApiConTimer(apiConnectptr.i, 0, __LINE__);
6175   regApiPtr->apiConnectstate = CS_RESTART;
6176   ndbrequire(regApiPtr->commitAckMarker == RNIL);
6177 }//Dbtc::releaseApiConCopy()
6178 
6179 /* ========================================================================= */
6180 /* -------  RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
6181 /* ========================================================================= */
releaseDirtyWrite(Signal * signal)6182 void Dbtc::releaseDirtyWrite(Signal* signal)
6183 {
6184   unlinkReadyTcCon(signal);
6185   releaseTcCon();
6186   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6187   if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6188     if (regApiPtr->firstTcConnect == RNIL) {
6189       jam();
6190       regApiPtr->apiConnectstate = CS_CONNECTED;
6191       setApiConTimer(apiConnectptr.i, 0, __LINE__);
6192       sendtckeyconf(signal, 1);
6193     }//if
6194   }//if
6195 }//Dbtc::releaseDirtyWrite()
6196 
6197 /*****************************************************************************
6198  *                               L Q H K E Y R E F
6199  * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
6200  * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
6201  * TCROLLBACKREP WILL BE SENT TO THE API.
6202  *
6203  * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
6204  * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
6205  * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
6206  * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
6207  * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
6208  * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
6209  * "REC_LQHREFUSE",
6210  * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
6211  * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
6212  *****************************************************************************/
execLQHKEYREF(Signal * signal)6213 void Dbtc::execLQHKEYREF(Signal* signal)
6214 {
6215   const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
6216   Uint32 indexId = 0;
6217   jamEntry();
6218 
6219   UintR compare_transid1, compare_transid2;
6220   UintR TtcConnectFilesize = ctcConnectFilesize;
6221   /*-------------------------------------------------------------------------
6222    *
6223    * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
6224    * TRANSACTION PARTS ACTIVE ANYMORE.
6225    * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
6226    *-------------------------------------------------------------------------*/
6227   if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
6228     /*-----------------------------------------------------------------------
6229      * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
6230      * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
6231      * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
6232      * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
6233      * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
6234      * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
6235      * ALREADY COMPLETED (ABORTED).
6236      *-----------------------------------------------------------------------*/
6237     tcConnectptr.i = lqhKeyRef->connectPtr;
6238     Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
6239     ptrAss(tcConnectptr, tcConnectRecord);
6240     TcConnectRecord * const regTcPtr = tcConnectptr.p;
6241     if (regTcPtr->tcConnectstate == OS_OPERATING) {
6242       Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
6243       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6244       ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6245       compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
6246       compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
6247       compare_transid1 = compare_transid1 | compare_transid2;
6248       if (compare_transid1 != 0) {
6249 	warningReport(signal, 25);
6250 	return;
6251       }//if
6252 
6253       const Uint32 triggeringOp = regTcPtr->triggeringOperation;
6254       if (triggeringOp != RNIL) {
6255         jam();
6256 	// This operation was created by a trigger execting operation
6257 	TcConnectRecordPtr opPtr;
6258 	TcConnectRecord *localTcConnectRecord = tcConnectRecord;
6259 
6260         opPtr.i = triggeringOp;
6261         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
6262 
6263         const Uint32 opType = regTcPtr->operation;
6264         Ptr<TcDefinedTriggerData> trigPtr;
6265         c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
6266         switch(trigPtr.p->triggerType){
6267         case TriggerType::SECONDARY_INDEX:{
6268           jam();
6269 
6270           // The operation executed an index trigger
6271           TcIndexData* indexData = c_theIndexes.getPtr(trigPtr.p->indexId);
6272           indexId = indexData->indexId;
6273           regApiPtr->errorData = indexId;
6274           if (errCode == ZALREADYEXIST)
6275           {
6276             jam();
6277             errCode = terrorCode = ZNOTUNIQUE;
6278             goto do_abort;
6279           }
6280           else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
6281             jam();
6282             /**
6283              * "Normal path"
6284              */
6285             goto do_abort;
6286           }
6287           else
6288           {
6289             jam();
6290             /** ZDELETE && NOT_FOUND */
6291             if (indexData->indexState != IS_BUILDING)
6292             {
6293               jam();
6294               goto do_abort;
6295             }
6296           }
6297           goto do_ignore;
6298         }
6299         case TriggerType::REORG_TRIGGER:
6300           jam();
6301           if (opType == ZINSERT && errCode == ZALREADYEXIST)
6302           {
6303             jam();
6304             ndbout_c("reorg, ignore ZALREADYEXIST");
6305             goto do_ignore;
6306           }
6307           else if (errCode == ZNOT_FOUND)
6308           {
6309             jam();
6310             ndbout_c("reorg, ignore ZNOT_FOUND");
6311             goto do_ignore;
6312           }
6313           else if (errCode == 839)
6314           {
6315             jam();
6316             ndbout_c("reorg, ignore 839");
6317             goto do_ignore;
6318           }
6319           else
6320           {
6321             ndbout_c("reorg: opType: %u errCode: %u", opType, errCode);
6322           }
6323           // fall-through
6324         default:
6325           jam();
6326           goto do_abort;
6327         }
6328 
6329     do_ignore:
6330         jam();
6331         /**
6332          * Ignore error
6333          */
6334         regApiPtr->lqhkeyreqrec--;
6335 
6336         /**
6337          * An failing op in LQH, never leaves the commit ack marker around
6338          * TODO: This can be bug in ordinary code too!!!
6339          */
6340         clearCommitAckMarker(regApiPtr, regTcPtr);
6341 
6342         unlinkReadyTcCon(signal);
6343         releaseTcCon();
6344 
6345         trigger_op_finished(signal, apiConnectptr, opPtr.p);
6346         return;
6347       }
6348 
6349   do_abort:
6350       markOperationAborted(regApiPtr, regTcPtr);
6351 
6352       if(regApiPtr->apiConnectstate == CS_ABORTING){
6353 	/**
6354 	 * We're already aborting' so don't send an "extra" TCKEYREF
6355 	 */
6356 	jam();
6357 	return;
6358       }
6359 
6360       const Uint32 abort = regTcPtr->m_execAbortOption;
6361       if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
6362 	/**
6363 	 * No error is allowed on this operation
6364 	 */
6365 	TCKEY_abort(signal, 49);
6366 	return;
6367       }//if
6368 
6369       /* *************** */
6370       /*    TCKEYREF   < */
6371       /* *************** */
6372       TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
6373       tcKeyRef->transId[0] = regApiPtr->transid[0];
6374       tcKeyRef->transId[1] = regApiPtr->transid[1];
6375       tcKeyRef->errorCode = terrorCode;
6376       bool isIndexOp = regTcPtr->isIndexOp(regTcPtr->m_special_op_flags);
6377       Uint32 indexOp = tcConnectptr.p->indexOp;
6378       Uint32 clientData = regTcPtr->clientData;
6379       unlinkReadyTcCon(signal);   /* LINK TC CONNECT RECORD OUT OF  */
6380       releaseTcCon();       /* RELEASE THE TC CONNECT RECORD  */
6381       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6382       if (isIndexOp) {
6383         jam();
6384 	regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
6385 	tcKeyRef->connectPtr = indexOp;
6386         tcKeyRef->errorData = indexId;
6387 	EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
6388 	apiConnectptr.i = save;
6389 	apiConnectptr.p = regApiPtr;
6390       } else {
6391         jam();
6392 	tcKeyRef->connectPtr = clientData;
6393         tcKeyRef->errorData = indexId;
6394 	sendSignal(regApiPtr->ndbapiBlockref,
6395 		   GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
6396       }//if
6397 
6398       /*---------------------------------------------------------------------
6399        * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
6400        * LQHKEYREQ THAT HAVE RETURNED.
6401        * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
6402        * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
6403        *---------------------------------------------------------------------*/
6404       regApiPtr->lqhkeyreqrec--;
6405       if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
6406 	if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
6407           jam();
6408           diverify010Lab(signal);
6409 	  return;
6410 	}
6411         else if (regApiPtr->tckeyrec > 0 ||
6412                  tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG))
6413         {
6414 	  jam();
6415 	  sendtckeyconf(signal, 2);
6416 	  return;
6417 	}
6418       }//if
6419       return;
6420 
6421     } else {
6422       warningReport(signal, 26);
6423     }//if
6424   } else {
6425     errorReport(signal, 6);
6426   }//if
6427   return;
6428 }//Dbtc::execLQHKEYREF()
6429 
clearCommitAckMarker(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)6430 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
6431 				TcConnectRecord * const regTcPtr)
6432 {
6433   const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
6434   if (regApiPtr->commitAckMarker == RNIL)
6435   {
6436     ndbassert(commitAckMarker == RNIL);
6437   }
6438 
6439   if(commitAckMarker != RNIL)
6440   {
6441     jam();
6442     ndbassert(regApiPtr->commitAckMarker == commitAckMarker);
6443     ndbrequire(regApiPtr->no_commit_ack_markers > 0);
6444     regApiPtr->no_commit_ack_markers--;
6445     regTcPtr->commitAckMarker = RNIL;
6446     if (regApiPtr->no_commit_ack_markers == 0)
6447     {
6448       regApiPtr->commitAckMarker = RNIL;
6449       tc_clearbit(regApiPtr->m_flags,
6450                   ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
6451       m_commitAckMarkerHash.release(commitAckMarker);
6452     }
6453   }
6454 }
6455 
markOperationAborted(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)6456 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
6457 				TcConnectRecord * const regTcPtr)
6458 {
6459   /*------------------------------------------------------------------------
6460    * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
6461    * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
6462    * ALREADY COMPLETED.
6463    *------------------------------------------------------------------------*/
6464   regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
6465   regTcPtr->tcConnectstate = OS_ABORTING;
6466   clearCommitAckMarker(regApiPtr, regTcPtr);
6467 }
6468 
6469 /*--------------------------------------*/
6470 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ  */
6471 /* OR TCROLLBACKREQ FROM THE USER TO    */
6472 /* CONTINUE THE TRANSACTION             */
6473 /*--------------------------------------*/
execTC_COMMITREQ(Signal * signal)6474 void Dbtc::execTC_COMMITREQ(Signal* signal)
6475 {
6476   UintR compare_transid1, compare_transid2;
6477 
6478   jamEntry();
6479   apiConnectptr.i = signal->theData[0];
6480   if (apiConnectptr.i < capiConnectFilesize) {
6481     ptrAss(apiConnectptr, apiConnectRecord);
6482     compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
6483     compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
6484     compare_transid1 = compare_transid1 | compare_transid2;
6485     if (compare_transid1 != 0) {
6486       jam();
6487       return;
6488     }//if
6489 
6490     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6491 
6492     const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
6493     const Uint32 apiBlockRef   = regApiPtr->ndbapiBlockref;
6494     const Uint32 transId1      = regApiPtr->transid[0];
6495     const Uint32 transId2      = regApiPtr->transid[1];
6496     Uint32 errorCode           = 0;
6497 
6498     regApiPtr->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
6499     switch (regApiPtr->apiConnectstate) {
6500     case CS_STARTED:
6501       tcConnectptr.i = regApiPtr->firstTcConnect;
6502       if (tcConnectptr.i != RNIL) {
6503         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6504         if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
6505           jam();
6506           /*******************************************************************/
6507           // The proper case where the application is waiting for commit or
6508           // abort order.
6509           // Start the commit order.
6510           /*******************************************************************/
6511           regApiPtr->returnsignal = RS_TC_COMMITCONF;
6512           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6513           diverify010Lab(signal);
6514           return;
6515         } else {
6516           jam();
6517           /*******************************************************************/
6518           // The transaction is started but not all operations are completed.
6519           // It is not possible to commit the transaction in this state.
6520           // We will abort it instead.
6521           /*******************************************************************/
6522           regApiPtr->returnsignal = RS_NO_RETURN;
6523           errorCode = ZTRANS_STATUS_ERROR;
6524           abort010Lab(signal);
6525         }//if
6526       } else {
6527         jam();
6528         /**
6529          * No operations, accept commit
6530          */
6531         TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
6532         commitConf->apiConnectPtr = apiConnectPtr;
6533         commitConf->transId1 = transId1;
6534         commitConf->transId2 = transId2;
6535         commitConf->gci_hi = 0;
6536         commitConf->gci_lo = 0;
6537         sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
6538 		   TcCommitConf::SignalLength, JBB);
6539 
6540         regApiPtr->returnsignal = RS_NO_RETURN;
6541         releaseAbortResources(signal);
6542         return;
6543       }//if
6544       break;
6545     case CS_RECEIVING:
6546       jam();
6547       /***********************************************************************/
6548       // A transaction is still receiving data. We cannot commit an unfinished
6549       // transaction. We will abort it instead.
6550       /***********************************************************************/
6551       regApiPtr->returnsignal = RS_NO_RETURN;
6552       errorCode = ZPREPAREINPROGRESS;
6553       abort010Lab(signal);
6554       break;
6555 
6556     case CS_START_COMMITTING:
6557     case CS_COMMITTING:
6558     case CS_COMMIT_SENT:
6559     case CS_COMPLETING:
6560     case CS_COMPLETE_SENT:
6561     case CS_REC_COMMITTING:
6562     case CS_PREPARE_TO_COMMIT:
6563       jam();
6564       /***********************************************************************/
6565       // The transaction is already performing a commit but it is not concluded
6566       // yet.
6567       /***********************************************************************/
6568       errorCode = ZCOMMITINPROGRESS;
6569       break;
6570     case CS_ABORTING:
6571       jam();
6572       errorCode = regApiPtr->returncode ?
6573 	regApiPtr->returncode : ZABORTINPROGRESS;
6574       break;
6575     case CS_START_SCAN:
6576       jam();
6577       /***********************************************************************/
6578       // The transaction is a scan. Scans cannot commit
6579       /***********************************************************************/
6580       errorCode = ZSCANINPROGRESS;
6581       break;
6582     case CS_PREPARED:
6583       jam();
6584       return;
6585     case CS_START_PREPARING:
6586       jam();
6587       return;
6588     case CS_REC_PREPARING:
6589       jam();
6590       return;
6591       break;
6592     default:
6593       warningHandlerLab(signal, __LINE__);
6594       return;
6595     }//switch
6596     TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
6597     commitRef->apiConnectPtr = apiConnectPtr;
6598     commitRef->transId1 = transId1;
6599     commitRef->transId2 = transId2;
6600     commitRef->errorCode = errorCode;
6601     sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
6602 	       TcCommitRef::SignalLength, JBB);
6603     return;
6604   } else /** apiConnectptr.i < capiConnectFilesize */ {
6605     jam();
6606     warningHandlerLab(signal, __LINE__);
6607     return;
6608   }
6609 }//Dbtc::execTC_COMMITREQ()
6610 
6611 /**
6612  * TCROLLBACKREQ
6613  *
6614  * Format is:
6615  *
6616  * thedata[0] = apiconnectptr
6617  * thedata[1] = transid[0]
6618  * thedata[2] = transid[1]
6619  * OPTIONAL thedata[3] = flags
6620  *
6621  * Flags:
6622  *    0x1  =  potentiallyBad data from API (try not to assert)
6623  */
execTCROLLBACKREQ(Signal * signal)6624 void Dbtc::execTCROLLBACKREQ(Signal* signal)
6625 {
6626   bool potentiallyBad= false;
6627   UintR compare_transid1, compare_transid2;
6628 
6629   jamEntry();
6630 
6631   if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
6632   {
6633     ndbout_c("Trying to roll back potentially bad txn\n");
6634     potentiallyBad= true;
6635   }
6636 
6637   apiConnectptr.i = signal->theData[0];
6638   if (apiConnectptr.i >= capiConnectFilesize) {
6639     goto TC_ROLL_warning;
6640   }//if
6641   ptrAss(apiConnectptr, apiConnectRecord);
6642   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
6643   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
6644   compare_transid1 = compare_transid1 | compare_transid2;
6645   if (compare_transid1 != 0) {
6646     jam();
6647     return;
6648   }//if
6649 
6650   apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
6651   switch (apiConnectptr.p->apiConnectstate) {
6652   case CS_STARTED:
6653   case CS_RECEIVING:
6654     jam();
6655     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6656     abort010Lab(signal);
6657     return;
6658   case CS_CONNECTED:
6659     jam();
6660     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6661     signal->theData[1] = apiConnectptr.p->transid[0];
6662     signal->theData[2] = apiConnectptr.p->transid[1];
6663     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
6664 	       signal, 3, JBB);
6665     break;
6666   case CS_START_SCAN:
6667   case CS_PREPARE_TO_COMMIT:
6668   case CS_COMMITTING:
6669   case CS_COMMIT_SENT:
6670   case CS_COMPLETING:
6671   case CS_COMPLETE_SENT:
6672   case CS_WAIT_COMMIT_CONF:
6673   case CS_WAIT_COMPLETE_CONF:
6674   case CS_RESTART:
6675   case CS_DISCONNECTED:
6676   case CS_START_COMMITTING:
6677   case CS_REC_COMMITTING:
6678     jam();
6679     /* ***************< */
6680     /* TC_ROLLBACKREF < */
6681     /* ***************< */
6682     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6683     signal->theData[1] = apiConnectptr.p->transid[0];
6684     signal->theData[2] = apiConnectptr.p->transid[1];
6685     signal->theData[3] = ZROLLBACKNOTALLOWED;
6686     signal->theData[4] = apiConnectptr.p->apiConnectstate;
6687     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
6688 	       signal, 5, JBB);
6689     break;
6690                                                  /* SEND A REFUSAL SIGNAL*/
6691   case CS_ABORTING:
6692     jam();
6693     if (apiConnectptr.p->abortState == AS_IDLE) {
6694       jam();
6695       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
6696       signal->theData[1] = apiConnectptr.p->transid[0];
6697       signal->theData[2] = apiConnectptr.p->transid[1];
6698       sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
6699 		 signal, 3, JBB);
6700     } else {
6701       jam();
6702       apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6703     }//if
6704     break;
6705   case CS_WAIT_ABORT_CONF:
6706     jam();
6707     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
6708     break;
6709   case CS_START_PREPARING:
6710     jam();
6711   case CS_PREPARED:
6712     jam();
6713   case CS_REC_PREPARING:
6714     jam();
6715   default:
6716     goto TC_ROLL_system_error;
6717     break;
6718   }//switch
6719   return;
6720 
6721 TC_ROLL_warning:
6722   jam();
6723   if(likely(potentiallyBad==false))
6724     warningHandlerLab(signal, __LINE__);
6725   return;
6726 
6727 TC_ROLL_system_error:
6728   jam();
6729   if(likely(potentiallyBad==false))
6730     systemErrorLab(signal, __LINE__);
6731   return;
6732 }//Dbtc::execTCROLLBACKREQ()
6733 
execTC_HBREP(Signal * signal)6734 void Dbtc::execTC_HBREP(Signal* signal)
6735 {
6736   const TcHbRep * const tcHbRep =
6737     (TcHbRep *)signal->getDataPtr();
6738 
6739   jamEntry();
6740   apiConnectptr.i = tcHbRep->apiConnectPtr;
6741   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6742 
6743   if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
6744       apiConnectptr.p->transid[1] == tcHbRep->transId2){
6745 
6746     if (getApiConTimer(apiConnectptr.i) != 0){
6747       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6748     } else {
6749       DEBUG("TCHBREP received when timer was off apiConnectptr.i="
6750 	    << apiConnectptr.i);
6751     }
6752   }
6753 }//Dbtc::execTCHBREP()
6754 
6755 /*
6756 4.3.15 ABORT
6757 -----------
6758 */
6759 /*****************************************************************************/
6760 /*                                  A B O R T                                */
6761 /*                                                                           */
6762 /*****************************************************************************/
warningReport(Signal * signal,int place)6763 void Dbtc::warningReport(Signal* signal, int place)
6764 {
6765   switch (place) {
6766   case 0:
6767     jam();
6768 #ifdef ABORT_TRACE
6769     ndbout << "ABORTED to not active TC record" << endl;
6770 #endif
6771     break;
6772   case 1:
6773     jam();
6774 #ifdef ABORT_TRACE
6775     ndbout << "ABORTED to TC record active with new transaction" << endl;
6776 #endif
6777     break;
6778   case 2:
6779     jam();
6780 #ifdef ABORT_TRACE
6781     ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
6782 #endif
6783     break;
6784   case 3:
6785     jam();
6786 #ifdef ABORT_TRACE
6787     ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
6788     ndbout << "This is ok when aborting in node failure situations" << endl;
6789 #endif
6790     break;
6791   case 4:
6792     jam();
6793 #ifdef ABORT_TRACE
6794     ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
6795 #endif
6796     break;
6797   case 5:
6798     jam();
6799 #ifdef ABORT_TRACE
6800     ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
6801 #endif
6802     break;
6803   case 6:
6804     jam();
6805 #ifdef ABORT_TRACE
6806     ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
6807 #endif
6808     break;
6809   case 7:
6810     jam();
6811 #ifdef ABORT_TRACE
6812     ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
6813 #endif
6814     break;
6815   case 8:
6816     jam();
6817 #ifdef ABORT_TRACE
6818     ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
6819 #endif
6820     break;
6821   case 9:
6822     jam();
6823 #ifdef ABORT_TRACE
6824     ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
6825 #endif
6826     break;
6827   case 10:
6828     jam();
6829 #ifdef ABORT_TRACE
6830     ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
6831 #endif
6832     break;
6833   case 11:
6834     jam();
6835 #ifdef ABORT_TRACE
6836     ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
6837 #endif
6838     break;
6839   case 12:
6840     jam();
6841 #ifdef ABORT_TRACE
6842     ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
6843 #endif
6844     break;
6845   case 13:
6846     jam();
6847 #ifdef ABORT_TRACE
6848     ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
6849 #endif
6850     break;
6851   case 14:
6852     jam();
6853 #ifdef ABORT_TRACE
6854     ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
6855 #endif
6856     break;
6857   case 15:
6858     jam();
6859 #ifdef ABORT_TRACE
6860     ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
6861 #endif
6862     break;
6863   case 16:
6864     jam();
6865 #ifdef ABORT_TRACE
6866     ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
6867 #endif
6868     break;
6869   case 17:
6870     jam();
6871 #ifdef ABORT_TRACE
6872     ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
6873 #endif
6874     break;
6875   case 18:
6876     jam();
6877 #ifdef ABORT_TRACE
6878     ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
6879 #endif
6880     break;
6881   case 19:
6882     jam();
6883 #ifdef ABORT_TRACE
6884     ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
6885 #endif
6886     break;
6887   case 20:
6888     jam();
6889 #ifdef ABORT_TRACE
6890     ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
6891 #endif
6892     break;
6893   case 21:
6894     jam();
6895 #ifdef ABORT_TRACE
6896     ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
6897 #endif
6898     break;
6899   case 22:
6900     jam();
6901 #ifdef ABORT_TRACE
6902     ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
6903 #endif
6904     break;
6905   case 23:
6906     jam();
6907 #ifdef ABORT_TRACE
6908     ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
6909 #endif
6910     break;
6911   case 24:
6912     jam();
6913 #ifdef ABORT_TRACE
6914     ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
6915 #endif
6916     break;
6917   case 25:
6918     jam();
6919 #ifdef ABORT_TRACE
6920     ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
6921 #endif
6922     break;
6923   case 26:
6924     jam();
6925 #ifdef ABORT_TRACE
6926     ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
6927 #endif
6928     break;
6929   case 27:
6930     jam();
6931     // printState(signal, 27);
6932 #ifdef ABORT_TRACE
6933     ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
6934 #endif
6935     break;
6936   case 28:
6937     jam();
6938 #ifdef ABORT_TRACE
6939     ndbout << "Discarding FIRE_TRIG_REF/CONF in Dbtc" << endl;
6940 #endif
6941     break;
6942   case 29:
6943     jam();
6944 #ifdef ABORT_TRACE
6945     ndbout << "Discarding TcContinueB::ZSEND_FIRE_TRIG_REQ in Dbtc" << endl;
6946 #endif
6947     break;
6948   default:
6949     jam();
6950     break;
6951   }//switch
6952   return;
6953 }//Dbtc::warningReport()
6954 
errorReport(Signal * signal,int place)6955 void Dbtc::errorReport(Signal* signal, int place)
6956 {
6957   switch (place) {
6958   case 0:
6959     jam();
6960     break;
6961   case 1:
6962     jam();
6963     break;
6964   case 2:
6965     jam();
6966     break;
6967   case 3:
6968     jam();
6969     break;
6970   case 4:
6971     jam();
6972     break;
6973   case 5:
6974     jam();
6975     break;
6976   case 6:
6977     jam();
6978     break;
6979   default:
6980     jam();
6981     break;
6982   }//switch
6983   systemErrorLab(signal, __LINE__);
6984   return;
6985 }//Dbtc::errorReport()
6986 
6987 /* ------------------------------------------------------------------------- */
6988 /* -------                       ENTER ABORTED                       ------- */
6989 /*                                                                           */
6990 /*-------------------------------------------------------------------------- */
execABORTED(Signal * signal)6991 void Dbtc::execABORTED(Signal* signal)
6992 {
6993   UintR compare_transid1, compare_transid2;
6994 
6995   jamEntry();
6996   tcConnectptr.i = signal->theData[0];
6997   UintR Tnodeid = signal->theData[3];
6998   UintR TlastLqhInd = signal->theData[4];
6999 
7000   if (ERROR_INSERTED(8040)) {
7001     CLEAR_ERROR_INSERT_VALUE;
7002     sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
7003     return;
7004   }//if
7005   /*------------------------------------------------------------------------
7006    *    ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
7007    *------------------------------------------------------------------------*/
7008   if (tcConnectptr.i >= ctcConnectFilesize) {
7009     errorReport(signal, 0);
7010     return;
7011   }//if
7012   /*-------------------------------------------------------------------------
7013    *     WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
7014    *     TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
7015    *     IN TC WAITING FOR ABORTED.
7016    *-------------------------------------------------------------------------*/
7017   ptrAss(tcConnectptr, tcConnectRecord);
7018   if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
7019     warningReport(signal, 2);
7020     return;
7021     /*-----------------------------------------------------------------------*/
7022     // ABORTED reported on an operation not expecting ABORT.
7023     /*-----------------------------------------------------------------------*/
7024   }//if
7025   apiConnectptr.i = tcConnectptr.p->apiConnect;
7026   if (apiConnectptr.i >= capiConnectFilesize) {
7027     warningReport(signal, 0);
7028     return;
7029   }//if
7030   ptrAss(apiConnectptr, apiConnectRecord);
7031   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
7032   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
7033   compare_transid1 = compare_transid1 | compare_transid2;
7034   if (compare_transid1 != 0) {
7035     warningReport(signal, 1);
7036     return;
7037   }//if
7038   if (ERROR_INSERTED(8024)) {
7039     jam();
7040     systemErrorLab(signal, __LINE__);
7041   }//if
7042 
7043   /**
7044    * Release marker
7045    */
7046   clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
7047 
7048   Uint32 i;
7049   Uint32 Tfound = 0;
7050   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7051     jam();
7052     if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
7053       /*---------------------------------------------------------------------
7054        * We have received ABORTED from one of the participants in this
7055        * operation in this aborted transaction.
7056        * Record all nodes that have completed abort.
7057        * If last indicator is set it means that no more replica has
7058        * heard of the operation and are thus also aborted.
7059        *---------------------------------------------------------------------*/
7060       jam();
7061       Tfound = 1;
7062       clearTcNodeData(signal, TlastLqhInd, i);
7063     }//if
7064   }//for
7065   if (Tfound == 0) {
7066     warningReport(signal, 3);
7067     return;
7068   }
7069   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
7070     if (tcConnectptr.p->tcNodedata[i] != 0) {
7071       /*--------------------------------------------------------------------
7072        * There are still outstanding ABORTED's to wait for.
7073        *--------------------------------------------------------------------*/
7074       jam();
7075       return;
7076     }//if
7077   }//for
7078   tcConnectptr.p->noOfNodes = 0;
7079   tcConnectptr.p->tcConnectstate = OS_ABORTING;
7080   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7081   apiConnectptr.p->counter--;
7082   if (apiConnectptr.p->counter > 0) {
7083     jam();
7084     /*----------------------------------------------------------------------
7085      *       WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
7086      *----------------------------------------------------------------------*/
7087     return;
7088   }//if
7089   /*------------------------------------------------------------------------*/
7090   /*                                                                        */
7091   /*     WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED  */
7092   /*     FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL   */
7093   /*     RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
7094   /*------------------------------------------------------------------------*/
7095   releaseAbortResources(signal);
7096 }//Dbtc::execABORTED()
7097 
clearTcNodeData(Signal * signal,UintR TLastLqhIndicator,UintR Tstart)7098 void Dbtc::clearTcNodeData(Signal* signal,
7099                            UintR TLastLqhIndicator,
7100                            UintR Tstart)
7101 {
7102   UintR Ti;
7103   if (TLastLqhIndicator == ZTRUE) {
7104     for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7105       jam();
7106       tcConnectptr.p->tcNodedata[Ti] = 0;
7107     }//for
7108   } else {
7109     jam();
7110     tcConnectptr.p->tcNodedata[Tstart] = 0;
7111   }//for
7112 }//clearTcNodeData()
7113 
abortErrorLab(Signal * signal)7114 void Dbtc::abortErrorLab(Signal* signal)
7115 {
7116   ptrGuard(apiConnectptr);
7117   ApiConnectRecord * transP = apiConnectptr.p;
7118   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7119     jam();
7120     return;
7121   }
7122   transP->returnsignal = RS_TCROLLBACKREP;
7123   if(transP->returncode == 0){
7124     jam();
7125     transP->returncode = terrorCode;
7126   }
7127   abort010Lab(signal);
7128 }//Dbtc::abortErrorLab()
7129 
abort010Lab(Signal * signal)7130 void Dbtc::abort010Lab(Signal* signal)
7131 {
7132   ApiConnectRecord * transP = apiConnectptr.p;
7133   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
7134     jam();
7135     return;
7136   }
7137   transP->apiConnectstate = CS_ABORTING;
7138   /*------------------------------------------------------------------------*/
7139   /*     AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
7140   /*     ALL PARTICIPANTS IN THE TRANSACTION.                               */
7141   /*------------------------------------------------------------------------*/
7142   transP->abortState = AS_ACTIVE;
7143   transP->counter = 0;
7144 
7145   if (transP->firstTcConnect == RNIL) {
7146     jam();
7147     /*--------------------------------------------------------------------*/
7148     /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION.                        */
7149     /*--------------------------------------------------------------------*/
7150     releaseAbortResources(signal);
7151     return;
7152   }//if
7153   tcConnectptr.i = transP->firstTcConnect;
7154   abort015Lab(signal);
7155 }//Dbtc::abort010Lab()
7156 
7157 /*--------------------------------------------------------------------------*/
7158 /*                                                                          */
7159 /*       WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP    */
7160 /*       ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE.        */
7161 /*       EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE   */
7162 /*       MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES    */
7163 /*       NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
7164 /*       WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
7165 /*--------------------------------------------------------------------------*/
abort015Lab(Signal * signal)7166 void Dbtc::abort015Lab(Signal* signal)
7167 {
7168   Uint32 TloopCount = 0;
7169 ABORT020:
7170   jam();
7171   TloopCount++;
7172   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7173   switch (tcConnectptr.p->tcConnectstate) {
7174   case OS_WAIT_DIH:
7175   case OS_WAIT_KEYINFO:
7176   case OS_WAIT_ATTR:
7177     jam();
7178     /*----------------------------------------------------------------------*/
7179     /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
7180     /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING.              */
7181     /*----------------------------------------------------------------------*/
7182     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7183     tcConnectptr.p->tcConnectstate = OS_ABORTING;
7184     break;
7185   case OS_CONNECTED:
7186     jam();
7187     /*-----------------------------------------------------------------------
7188      *   WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
7189      *   NEED NOT BOTHER ABOUT ANY LQH ABORTS.
7190      *-----------------------------------------------------------------------*/
7191     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
7192     tcConnectptr.p->tcConnectstate = OS_ABORTING;
7193     break;
7194   case OS_PREPARED:
7195     jam();
7196   case OS_OPERATING:
7197     jam();
7198   case OS_FIRE_TRIG_REQ:
7199     jam();
7200     /*----------------------------------------------------------------------
7201      * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
7202      * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
7203      * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
7204      *----------------------------------------------------------------------*/
7205     releaseAndAbort(signal);
7206     tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
7207     TloopCount += 127;
7208     break;
7209   case OS_ABORTING:
7210     jam();
7211     break;
7212   case OS_ABORT_SENT:
7213     jam();
7214     DEBUG("ABORT_SENT state in abort015Lab(), not expected");
7215     systemErrorLab(signal, __LINE__);
7216     return;
7217   default:
7218     jam();
7219     DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
7220     systemErrorLab(signal, __LINE__);
7221     return;
7222   }//switch
7223 
7224   if (tcConnectptr.p->nextTcConnect != RNIL) {
7225     jam();
7226     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7227     if (TloopCount < 1024 && !
7228         (ERROR_INSERTED(8089)))
7229     {
7230       goto ABORT020;
7231     }
7232     else
7233     {
7234       jam();
7235       /*---------------------------------------------------------------------
7236        * Reset timer to avoid time-out in real-time break.
7237        * Increase counter to ensure that we don't think that all ABORTED have
7238        * been received before all have been sent.
7239        *---------------------------------------------------------------------*/
7240       apiConnectptr.p->counter++;
7241       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7242       signal->theData[0] = TcContinueB::ZABORT_BREAK;
7243       signal->theData[1] = tcConnectptr.i;
7244       signal->theData[2] = apiConnectptr.i;
7245       if (ERROR_INSERTED(8089))
7246       {
7247         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
7248         return;
7249       }
7250       sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7251       return;
7252     }//if
7253   }//if
7254 
7255   if (ERROR_INSERTED(8089))
7256   {
7257     CLEAR_ERROR_INSERT_VALUE;
7258   }
7259 
7260   if (apiConnectptr.p->counter > 0) {
7261     jam();
7262     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7263     return;
7264   }//if
7265   /*-----------------------------------------------------------------------
7266    *    WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
7267    *    FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
7268    *    RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
7269    *------------------------------------------------------------------------*/
7270   releaseAbortResources(signal);
7271 }//Dbtc::abort015Lab()
7272 
7273 /*--------------------------------------------------------------------------*/
7274 /*       RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK.  */
7275 /*--------------------------------------------------------------------------*/
releaseAndAbort(Signal * signal)7276 int Dbtc::releaseAndAbort(Signal* signal)
7277 {
7278   HostRecordPtr localHostptr;
7279   UintR TnoLoops = tcConnectptr.p->noOfNodes;
7280 
7281   apiConnectptr.p->counter++;
7282   bool prevAlive = false;
7283   for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
7284     localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
7285     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
7286     if (localHostptr.p->hostStatus == HS_ALIVE) {
7287       jam();
7288       if (prevAlive) {
7289         // if previous is alive, its LQH forwards abort to this node
7290         jam();
7291         continue;
7292       }
7293       /* ************< */
7294       /*    ABORT    < */
7295       /* ************< */
7296       Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7297       tblockref = numberToRef(DBLQH, instanceKey, localHostptr.i);
7298       signal->theData[0] = tcConnectptr.i;
7299       signal->theData[1] = cownref;
7300       signal->theData[2] = apiConnectptr.p->transid[0];
7301       signal->theData[3] = apiConnectptr.p->transid[1];
7302       sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
7303       prevAlive = true;
7304     } else {
7305       jam();
7306       signal->theData[0] = tcConnectptr.i;
7307       signal->theData[1] = apiConnectptr.p->transid[0];
7308       signal->theData[2] = apiConnectptr.p->transid[1];
7309       signal->theData[3] = localHostptr.i;
7310       signal->theData[4] = ZFALSE;
7311       sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7312       prevAlive = false;
7313     }//if
7314   }//for
7315   return 1;
7316 }//Dbtc::releaseAndAbort()
7317 
7318 /* ------------------------------------------------------------------------- */
7319 /* -------                       ENTER TIME_SIGNAL                   ------- */
7320 /*                                                                           */
7321 /* ------------------------------------------------------------------------- */
execTIME_SIGNAL(Signal * signal)7322 void Dbtc::execTIME_SIGNAL(Signal* signal)
7323 {
7324 
7325   jamEntry();
7326   ctcTimer++;
7327   if (csystemStart != SSS_TRUE) {
7328     jam();
7329     return;
7330   }//if
7331   checkStartTimeout(signal);
7332   checkStartFragTimeout(signal);
7333 }//Dbtc::execTIME_SIGNAL()
7334 
7335 /*------------------------------------------------*/
7336 /* Start timeout handling if not already going on */
7337 /*------------------------------------------------*/
checkStartTimeout(Signal * signal)7338 void Dbtc::checkStartTimeout(Signal* signal)
7339 {
7340   ctimeOutCheckCounter++;
7341   if (ctimeOutCheckActive == TOCS_TRUE) {
7342     jam();
7343     // Check heartbeat of timeout loop
7344     if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
7345       jam();
7346       ctimeOutMissedHeartbeats = 0;
7347     }else{
7348       jam();
7349       ctimeOutMissedHeartbeats++;
7350       if (ctimeOutMissedHeartbeats > 100){
7351 	jam();
7352 	systemErrorLab(signal, __LINE__);
7353       }
7354     }
7355     ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
7356     return;
7357   }//if
7358   if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
7359     jam();
7360     /*------------------------------------------------------------------*/
7361     /*                                                                  */
7362     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
7363     /*------------------------------------------------------------------*/
7364     return;
7365   }//if
7366   ctimeOutCheckActive = TOCS_TRUE;
7367   ctimeOutCheckCounter = 0;
7368   timeOutLoopStartLab(signal, 0); // 0 is first api connect record
7369   return;
7370 }//Dbtc::execTIME_SIGNAL()
7371 
7372 /*----------------------------------------------------------------*/
7373 /* Start fragment (scan) timeout handling if not already going on */
7374 /*----------------------------------------------------------------*/
checkStartFragTimeout(Signal * signal)7375 void Dbtc::checkStartFragTimeout(Signal* signal)
7376 {
7377   ctimeOutCheckFragCounter++;
7378   if (ctimeOutCheckFragActive == TOCS_TRUE) {
7379     jam();
7380     return;
7381   }//if
7382   if (ctimeOutCheckFragCounter < ctimeOutCheckDelay) {
7383     jam();
7384     /*------------------------------------------------------------------*/
7385     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
7386     /*------------------------------------------------------------------*/
7387     return;
7388   }//if
7389 
7390   // Go through the fragment records and look for timeout in a scan.
7391   ctimeOutCheckFragActive = TOCS_TRUE;
7392   ctimeOutCheckFragCounter = 0;
7393   timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
7394 }//checkStartFragTimeout()
7395 
7396 /*------------------------------------------------------------------*/
7397 /*       IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE      */
7398 /*       BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM     */
7399 /*       SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM  */
7400 /*       THE WAITING PART OF A PROTOCOL.                            */
7401 /*
7402 The algorithm used here is to check 1024 transactions at a time before
7403 doing a real-time break.
7404 To avoid aborting both transactions in a deadlock detected by time-out
7405 we insert a random extra time-out of upto 630 ms by using the lowest
7406 six bits of the api connect reference.
7407 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
7408 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
7409 and otherwise we spread it out 310 ms.
7410 */
7411 /*------------------------------------------------------------------*/
timeOutLoopStartLab(Signal * signal,Uint32 api_con_ptr)7412 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
7413 {
7414   Uint32 end_ptr, time_passed, time_out_value, mask_value;
7415   Uint32 old_mask_value= 0;
7416   const Uint32 api_con_sz= capiConnectFilesize;
7417   const Uint32 tc_timer= ctcTimer;
7418   const Uint32 time_out_param= ctimeOutValue;
7419   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
7420 
7421   ctimeOutCheckHeartbeat = tc_timer;
7422 
7423   if (api_con_ptr + 1024 < api_con_sz) {
7424     jam();
7425     end_ptr= api_con_ptr + 1024;
7426   } else {
7427     jam();
7428     end_ptr= api_con_sz;
7429   }
7430   if (time_out_param > 300) {
7431     jam();
7432     mask_value= 63;
7433   } else if (time_out_param < 30) {
7434     jam();
7435     mask_value= 7;
7436   } else {
7437     jam();
7438     mask_value= 31;
7439   }
7440   if (time_out_param != old_time_out_param &&
7441       getNodeState().getSingleUserMode())
7442   {
7443     // abort during single user mode, use old_mask_value as flag
7444     // and calculate value to be used for connections with allowed api
7445     if (old_time_out_param > 300) {
7446       jam();
7447       old_mask_value= 63;
7448     } else if (old_time_out_param < 30) {
7449       jam();
7450       old_mask_value= 7;
7451     } else {
7452       jam();
7453       old_mask_value= 31;
7454     }
7455   }
7456   for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
7457     Uint32 api_timer= getApiConTimer(api_con_ptr);
7458     jam();
7459     if (api_timer != 0) {
7460       Uint32 error= ZTIME_OUT_ERROR;
7461       time_out_value= time_out_param + (ndb_rand() & mask_value);
7462       if (unlikely(old_mask_value)) // abort during single user mode
7463       {
7464         apiConnectptr.i = api_con_ptr;
7465         ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7466         if ((getNodeState().getSingleUserApi() ==
7467              refToNode(apiConnectptr.p->ndbapiBlockref)) ||
7468             !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
7469         {
7470           // api allowed during single user, use original timeout
7471           time_out_value=
7472             old_time_out_param + (api_con_ptr & old_mask_value);
7473         }
7474         else
7475         {
7476           error= ZCLUSTER_IN_SINGLEUSER_MODE;
7477         }
7478       }
7479       time_passed= tc_timer - api_timer;
7480       if (time_passed > time_out_value)
7481       {
7482         jam();
7483         timeOutFoundLab(signal, api_con_ptr, error);
7484 	api_con_ptr++;
7485 	break;
7486       }
7487     }
7488   }
7489   if (api_con_ptr == api_con_sz) {
7490     jam();
7491     /*------------------------------------------------------------------*/
7492     /*                                                                  */
7493     /*       WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
7494     /*       STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW    */
7495     /*       READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK.            */
7496     /*------------------------------------------------------------------*/
7497     ctimeOutCheckActive = TOCS_FALSE;
7498   } else {
7499     jam();
7500     sendContinueTimeOutControl(signal, api_con_ptr);
7501   }
7502   return;
7503 }//Dbtc::timeOutLoopStartLab()
7504 
timeOutFoundLab(Signal * signal,Uint32 TapiConPtr,Uint32 errCode)7505 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
7506 {
7507   apiConnectptr.i = TapiConPtr;
7508   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7509   /*------------------------------------------------------------------*/
7510   /*                                                                  */
7511   /*       THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
7512   /*       FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
7513   /*------------------------------------------------------------------*/
7514   DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
7515 	<< " H'" << apiConnectptr.p->transid[1] << "] " << dec
7516 	<< "Time-out in state = " << apiConnectptr.p->apiConnectstate
7517 	<< " apiConnectptr.i = " << apiConnectptr.i
7518 	<< " - exec: "
7519         << tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG)
7520 	<< " - place: " << c_apiConTimer_line[apiConnectptr.i]
7521 	<< " code: " << errCode);
7522   switch (apiConnectptr.p->apiConnectstate) {
7523   case CS_STARTED:
7524     if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
7525        errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
7526       jam();
7527       /*
7528       We are waiting for application to continue the transaction. In this
7529       particular state we will use the application timeout parameter rather
7530       than the shorter Deadlock detection timeout.
7531       */
7532       if (c_appl_timeout_value == 0 ||
7533           (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
7534         jam();
7535         return;
7536       }//if
7537     }
7538     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
7539     apiConnectptr.p->returncode = errCode;
7540     abort010Lab(signal);
7541     return;
7542   case CS_RECEIVING:
7543   case CS_REC_COMMITTING:
7544   case CS_START_COMMITTING:
7545   case CS_WAIT_FIRE_TRIG_REQ:
7546   case CS_SEND_FIRE_TRIG_REQ:
7547     jam();
7548     /*------------------------------------------------------------------*/
7549     /*       WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS  */
7550     /*       NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO     */
7551     /*       START ABORTING THE TRANSACTION. ALSO START CHECKING THE    */
7552     /*       REMAINING TRANSACTIONS.                                    */
7553     /*------------------------------------------------------------------*/
7554     terrorCode = errCode;
7555     abortErrorLab(signal);
7556     return;
7557   case CS_COMMITTING:
7558     jam();
7559     /*------------------------------------------------------------------*/
7560     // We are simply waiting for a signal in the job buffer. Only extreme
7561     // conditions should get us here. We ignore it.
7562     /*------------------------------------------------------------------*/
7563   case CS_COMPLETING:
7564     jam();
7565     /*------------------------------------------------------------------*/
7566     // We are simply waiting for a signal in the job buffer. Only extreme
7567     // conditions should get us here. We ignore it.
7568     /*------------------------------------------------------------------*/
7569   case CS_PREPARE_TO_COMMIT:
7570   {
7571     jam();
7572     /*------------------------------------------------------------------*/
7573     /*       WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
7574     /*       KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO.  */
7575     /*       IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE.  */
7576     // To ensure against strange bugs we crash the system if we have passed
7577     // time-out period by a factor of 10 and it is also at least 5 seconds.
7578     /*------------------------------------------------------------------*/
7579     Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
7580     if (time_passed > 500 &&
7581         time_passed > (5 * cDbHbInterval) &&
7582         time_passed > (10 * ctimeOutValue))
7583     {
7584       jam();
7585       ndbout_c("timeOutFoundLab trans: 0x%x 0x%x state: %u",
7586                apiConnectptr.p->transid[0],
7587                apiConnectptr.p->transid[1],
7588                (Uint32)apiConnectptr.p->apiConnectstate);
7589 
7590       // Reset timeout to not flood log...
7591       setApiConTimer(apiConnectptr.i, 0, __LINE__);
7592     }//if
7593     break;
7594   }
7595   case CS_COMMIT_SENT:
7596     jam();
7597     /*------------------------------------------------------------------*/
7598     /*       WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
7599     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE   */
7600     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL  */
7601     /*       TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO   */
7602     /*       A NODE FAILURE.                                            */
7603     /*------------------------------------------------------------------*/
7604     tabortInd = ZCOMMIT_SETUP;
7605     setupFailData(signal);
7606     toCommitHandlingLab(signal);
7607     return;
7608   case CS_COMPLETE_SENT:
7609     jam();
7610     /*--------------------------------------------------------------------*/
7611     /*       WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
7612     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE     */
7613     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL  */
7614     /*       TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO   */
7615     /*       A NODE FAILURE.                                              */
7616     /*--------------------------------------------------------------------*/
7617     tabortInd = ZCOMMIT_SETUP;
7618     setupFailData(signal);
7619     toCompleteHandlingLab(signal);
7620     return;
7621   case CS_ABORTING:
7622     jam();
7623     /*------------------------------------------------------------------*/
7624     /*       TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL     */
7625     /*       NODES THAT HAVE FAILED BEFORE SENDING ABORTED.             */
7626     /*------------------------------------------------------------------*/
7627     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7628     sendAbortedAfterTimeout(signal, 0);
7629     break;
7630   case CS_START_SCAN:{
7631     jam();
7632 
7633     /*
7634       We are waiting for application to continue the transaction. In this
7635       particular state we will use the application timeout parameter rather
7636       than the shorter Deadlock detection timeout.
7637     */
7638     if (c_appl_timeout_value == 0 ||
7639 	(ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
7640       jam();
7641       return;
7642     }//if
7643 
7644     ScanRecordPtr scanPtr;
7645     scanPtr.i = apiConnectptr.p->apiScanRec;
7646     ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
7647     scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
7648     break;
7649   }
7650   case CS_WAIT_ABORT_CONF:
7651     jam();
7652     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7653     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7654     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7655     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7656     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7657     if (hostptr.p->hostStatus == HS_ALIVE) {
7658       /*------------------------------------------------------------------*/
7659       // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
7660       // case.
7661       /*------------------------------------------------------------------*/
7662       warningReport(signal, 20);
7663       apiConnectptr.p->timeOutCounter++;
7664       if (apiConnectptr.p->timeOutCounter > 3) {
7665 	/*------------------------------------------------------------------*/
7666 	// 100 time-outs are not acceptable. We will shoot down the node
7667 	// not responding.
7668 	/*------------------------------------------------------------------*/
7669         reportNodeFailed(signal, hostptr.i);
7670       }//if
7671       apiConnectptr.p->currentReplicaNo++;
7672     }//if
7673     tcurrentReplicaNo = (Uint8)Z8NIL;
7674     toAbortHandlingLab(signal);
7675     return;
7676   case CS_WAIT_COMMIT_CONF:
7677     jam();
7678     CRASH_INSERTION(8053);
7679     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7680     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7681     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7682     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7683     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7684     if (hostptr.p->hostStatus == HS_ALIVE) {
7685       /*------------------------------------------------------------------*/
7686       // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
7687       // case.
7688       /*------------------------------------------------------------------*/
7689       warningReport(signal, 21);
7690       apiConnectptr.p->timeOutCounter++;
7691       if (apiConnectptr.p->timeOutCounter > 3) {
7692 	/*------------------------------------------------------------------*/
7693 	// 100 time-outs are not acceptable. We will shoot down the node
7694 	// not responding.
7695 	/*------------------------------------------------------------------*/
7696         reportNodeFailed(signal, hostptr.i);
7697       }//if
7698       apiConnectptr.p->currentReplicaNo++;
7699     }//if
7700     tcurrentReplicaNo = (Uint8)Z8NIL;
7701     toCommitHandlingLab(signal);
7702     return;
7703   case CS_WAIT_COMPLETE_CONF:
7704     jam();
7705     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
7706     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7707     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7708     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
7709     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7710     if (hostptr.p->hostStatus == HS_ALIVE) {
7711       /*------------------------------------------------------------------*/
7712       // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
7713       // just in case.
7714       /*------------------------------------------------------------------*/
7715       warningReport(signal, 22);
7716       apiConnectptr.p->timeOutCounter++;
7717       if (apiConnectptr.p->timeOutCounter > 100) {
7718 	/*------------------------------------------------------------------*/
7719 	// 100 time-outs are not acceptable. We will shoot down the node
7720 	// not responding.
7721 	/*------------------------------------------------------------------*/
7722         reportNodeFailed(signal, hostptr.i);
7723       }//if
7724       apiConnectptr.p->currentReplicaNo++;
7725     }//if
7726     tcurrentReplicaNo = (Uint8)Z8NIL;
7727     toCompleteHandlingLab(signal);
7728     return;
7729   case CS_FAIL_PREPARED:
7730     jam();
7731   case CS_FAIL_COMMITTING:
7732     jam();
7733   case CS_FAIL_COMMITTED:
7734     jam();
7735   case CS_REC_PREPARING:
7736     jam();
7737   case CS_START_PREPARING:
7738     jam();
7739   case CS_PREPARED:
7740     jam();
7741   case CS_RESTART:
7742     jam();
7743   case CS_FAIL_ABORTED:
7744     jam();
7745   case CS_DISCONNECTED:
7746     jam();
7747   default:
7748     jam();
7749     /*------------------------------------------------------------------*/
7750     /*       AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM.              */
7751     /*------------------------------------------------------------------*/
7752     DEBUG("State = " << apiConnectptr.p->apiConnectstate);
7753     systemErrorLab(signal, __LINE__);
7754     return;
7755   }//switch
7756   return;
7757 }//Dbtc::timeOutFoundLab()
7758 
sendAbortedAfterTimeout(Signal * signal,int Tcheck)7759 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
7760 {
7761   ApiConnectRecord * transP = apiConnectptr.p;
7762   if(transP->abortState == AS_IDLE){
7763     jam();
7764     warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
7765 		 __LINE__,
7766 		 apiConnectptr.i,
7767 		 transP->apiConnectstate,
7768 		 c_apiConTimer_line[apiConnectptr.i],
7769 		 transP->firstTcConnect,
7770 		 c_apiConTimer[apiConnectptr.i]
7771 		 );
7772     ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
7773 	     __LINE__,
7774 	     apiConnectptr.i,
7775 	     transP->apiConnectstate,
7776 	     c_apiConTimer_line[apiConnectptr.i],
7777 	     transP->firstTcConnect,
7778 	     c_apiConTimer[apiConnectptr.i]
7779 	     );
7780     ndbrequire(false);
7781     setApiConTimer(apiConnectptr.i, 0, __LINE__);
7782     return;
7783   }
7784 
7785   bool found = false;
7786   OperationState tmp[16];
7787 
7788   Uint32 TloopCount = 0;
7789   do {
7790     jam();
7791     if (tcConnectptr.i == RNIL) {
7792       jam();
7793 
7794 #ifdef VM_TRACE
7795       ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
7796 	       found, Tcheck, apiConnectptr.p->counter);
7797 #endif
7798       if (found || apiConnectptr.p->counter)
7799       {
7800 	jam();
7801 	/**
7802 	 * We sent atleast one ABORT/ABORTED
7803 	 *   or ZABORT_TIMEOUT_BREAK is in job buffer
7804 	 *   wait for reception...
7805 	 */
7806 	return;
7807       }
7808 
7809       if (Tcheck == 1)
7810       {
7811 	jam();
7812 	releaseAbortResources(signal);
7813 	return;
7814       }
7815 
7816       if (Tcheck == 0)
7817       {
7818         jam();
7819 	/*------------------------------------------------------------------
7820 	 * All nodes had already reported ABORTED for all tcConnect records.
7821 	 * Crash since it is an error situation that we then received a
7822 	 * time-out.
7823 	 *------------------------------------------------------------------*/
7824 	char buf[96]; buf[0] = 0;
7825 	char buf2[96];
7826 	BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
7827 			     __LINE__, apiConnectptr.i,
7828 			     apiConnectptr.p->counter);
7829 	for(Uint32 i = 0; i<TloopCount; i++)
7830 	{
7831 	  BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
7832 	  BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
7833 	}
7834 	warningEvent("%s", buf);
7835 	ndbout_c("%s", buf);
7836 	ndbrequire(false);
7837 	releaseAbortResources(signal);
7838 	return;
7839       }
7840 
7841       return;
7842     }//if
7843     TloopCount++;
7844     if (TloopCount >= 1024) {
7845       jam();
7846       /*------------------------------------------------------------------*/
7847       // Insert a real-time break for large transactions to avoid blowing
7848       // away the job buffer.
7849       /*------------------------------------------------------------------*/
7850       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7851       apiConnectptr.p->counter++;
7852       signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
7853       signal->theData[1] = tcConnectptr.i;
7854       signal->theData[2] = apiConnectptr.i;
7855       if (ERROR_INSERTED(8080))
7856       {
7857 	ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
7858 		 Tcheck, apiConnectptr.p->counter);
7859 	sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
7860       }
7861       else
7862       {
7863 	sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7864       }
7865       return;
7866     }//if
7867     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7868     if(TloopCount < 16){
7869       jam();
7870       tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
7871     }
7872 
7873     if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
7874       jam();
7875       /*------------------------------------------------------------------*/
7876       // We have sent an ABORT signal to this node but not yet received any
7877       // reply. We have to send an ABORTED signal on our own in some cases.
7878       // If the node is declared as up and running and still do not respond
7879       // in time to the ABORT signal we will declare it as dead.
7880       /*------------------------------------------------------------------*/
7881       UintR Ti = 0;
7882       arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
7883       for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
7884         jam();
7885         if (tcConnectptr.p->tcNodedata[Ti] != 0) {
7886           TloopCount += 31;
7887 	  found = true;
7888           hostptr.i = tcConnectptr.p->tcNodedata[Ti];
7889           ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7890           if (hostptr.p->hostStatus == HS_ALIVE) {
7891             jam();
7892 	    /*---------------------------------------------------------------
7893 	     * A backup replica has not sent ABORTED.
7894 	     * Could be that a node before him has crashed.
7895 	     * Send an ABORT signal specifically to this node.
7896 	     * We will not send to any more nodes after this
7897 	     * to avoid race problems.
7898 	     * To also ensure that we use this message also as a heartbeat
7899 	     * we will move this node to the primary replica seat.
7900 	     * The primary replica and any failed node after it will
7901 	     * be removed from the node list. Update also number of nodes.
7902 	     * Finally break the loop to ensure we don't mess
7903 	     * things up by executing another loop.
7904 	     * We also update the timer to ensure we don't get time-out
7905 	     * too early.
7906 	     *--------------------------------------------------------------*/
7907             Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
7908             BlockReference TBRef = numberToRef(DBLQH, instanceKey, hostptr.i);
7909             signal->theData[0] = tcConnectptr.i;
7910             signal->theData[1] = cownref;
7911             signal->theData[2] = apiConnectptr.p->transid[0];
7912             signal->theData[3] = apiConnectptr.p->transid[1];
7913             sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
7914             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7915             break;
7916           } else {
7917             jam();
7918 	    /*--------------------------------------------------------------
7919 	     * The node we are waiting for is dead. We will send ABORTED to
7920 	     * ourselves vicarious for the failed node.
7921 	     *--------------------------------------------------------------*/
7922             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7923             signal->theData[0] = tcConnectptr.i;
7924             signal->theData[1] = apiConnectptr.p->transid[0];
7925             signal->theData[2] = apiConnectptr.p->transid[1];
7926             signal->theData[3] = hostptr.i;
7927             signal->theData[4] = ZFALSE;
7928             sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
7929           }//if
7930         }//if
7931       }//for
7932     }//if
7933     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7934   } while (1);
7935 }//Dbtc::sendAbortedAfterTimeout()
7936 
reportNodeFailed(Signal * signal,Uint32 nodeId)7937 void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
7938 {
7939   DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
7940   rep->nodeId = nodeId;
7941   rep->err = DisconnectRep::TcReportNodeFailed;
7942   sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
7943 	     DisconnectRep::SignalLength, JBB);
7944 }//Dbtc::reportNodeFailed()
7945 
7946 /*-------------------------------------------------*/
7947 /*      Timeout-loop for scanned fragments.        */
7948 /*-------------------------------------------------*/
timeOutLoopStartFragLab(Signal * signal,Uint32 TscanConPtr)7949 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
7950 {
7951   ScanFragRecPtr timeOutPtr[8];
7952   UintR tfragTimer[8];
7953   UintR texpiredTime[8];
7954   UintR TloopCount = 0;
7955   Uint32 TtcTimer = ctcTimer;
7956 
7957   while ((TscanConPtr + 8) < cscanFragrecFileSize) {
7958     jam();
7959     timeOutPtr[0].i  = TscanConPtr + 0;
7960     timeOutPtr[1].i  = TscanConPtr + 1;
7961     timeOutPtr[2].i  = TscanConPtr + 2;
7962     timeOutPtr[3].i  = TscanConPtr + 3;
7963     timeOutPtr[4].i  = TscanConPtr + 4;
7964     timeOutPtr[5].i  = TscanConPtr + 5;
7965     timeOutPtr[6].i  = TscanConPtr + 6;
7966     timeOutPtr[7].i  = TscanConPtr + 7;
7967 
7968     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
7969     c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
7970     c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
7971     c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
7972     c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
7973     c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
7974     c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
7975     c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
7976 
7977     tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
7978     tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
7979     tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
7980     tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
7981     tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
7982     tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
7983     tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
7984     tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
7985 
7986     texpiredTime[0] = TtcTimer - tfragTimer[0];
7987     texpiredTime[1] = TtcTimer - tfragTimer[1];
7988     texpiredTime[2] = TtcTimer - tfragTimer[2];
7989     texpiredTime[3] = TtcTimer - tfragTimer[3];
7990     texpiredTime[4] = TtcTimer - tfragTimer[4];
7991     texpiredTime[5] = TtcTimer - tfragTimer[5];
7992     texpiredTime[6] = TtcTimer - tfragTimer[6];
7993     texpiredTime[7] = TtcTimer - tfragTimer[7];
7994 
7995     for (Uint32 Ti = 0; Ti < 8; Ti++) {
7996       jam();
7997       if (tfragTimer[Ti] != 0) {
7998 
7999         if (texpiredTime[Ti] > ctimeOutValue) {
8000 	  jam();
8001 	  DEBUG("Fragment timeout found:"<<
8002 		" ctimeOutValue=" <<ctimeOutValue
8003 		<<", texpiredTime="<<texpiredTime[Ti]<<endl
8004 		<<"      tfragTimer="<<tfragTimer[Ti]
8005 		<<", ctcTimer="<<ctcTimer);
8006           timeOutFoundFragLab(signal, TscanConPtr + Ti);
8007           return;
8008         }//if
8009       }//if
8010     }//for
8011     TscanConPtr += 8;
8012     /*----------------------------------------------------------------*/
8013     /* We split the process up checking 1024 fragmentrecords at a time*/
8014     /* to maintain real time behaviour.                               */
8015     /*----------------------------------------------------------------*/
8016     if (TloopCount++ > 128 ) {
8017       jam();
8018       signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8019       signal->theData[1] = TscanConPtr;
8020       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8021       return;
8022     }//if
8023   }//while
8024   for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
8025     jam();
8026     timeOutPtr[0].i = TscanConPtr;
8027     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
8028     if (timeOutPtr[0].p->scanFragTimer != 0) {
8029       texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
8030       if (texpiredTime[0] > ctimeOutValue) {
8031         jam();
8032 	DEBUG("Fragment timeout found:"<<
8033 	      " ctimeOutValue=" <<ctimeOutValue
8034 	      <<", texpiredTime="<<texpiredTime[0]<<endl
8035 		<<"      tfragTimer="<<tfragTimer[0]
8036 		<<", ctcTimer="<<ctcTimer);
8037         timeOutFoundFragLab(signal, TscanConPtr);
8038         return;
8039       }//if
8040     }//if
8041   }//for
8042   ctimeOutCheckFragActive = TOCS_FALSE;
8043 
8044   return;
8045 }//timeOutLoopStartFragLab()
8046 
8047 /*--------------------------------------------------------------------------*/
8048 /*Handle the heartbeat signal from LQH in a scan process                    */
8049 // (Set timer on fragrec.)
8050 /*--------------------------------------------------------------------------*/
execSCAN_HBREP(Signal * signal)8051 void Dbtc::execSCAN_HBREP(Signal* signal)
8052 {
8053   jamEntry();
8054 
8055   scanFragptr.i = signal->theData[0];
8056   c_scan_frag_pool.getPtr(scanFragptr);
8057   switch (scanFragptr.p->scanFragState){
8058   case ScanFragRec::LQH_ACTIVE:
8059     break;
8060   default:
8061     DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
8062     systemErrorLab(signal, __LINE__);
8063     break;
8064   }
8065 
8066   ScanRecordPtr scanptr;
8067   scanptr.i = scanFragptr.p->scanRec;
8068   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8069 
8070   apiConnectptr.i = scanptr.p->scanApiRec;
8071   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8072 
8073   if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
8074 	apiConnectptr.p->transid[1] == signal->theData[2])){
8075     jam();
8076     /**
8077      * Send signal back to sender so that the crash occurs there
8078      */
8079     // Save original transid
8080     signal->theData[3] = signal->theData[0];
8081     signal->theData[4] = signal->theData[1];
8082     // Set transid to illegal values
8083     signal->theData[1] = RNIL;
8084     signal->theData[2] = RNIL;
8085 
8086     sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
8087     DEBUG("SCAN_HBREP with wrong transid("
8088 	  <<signal->theData[3]<<", "<<signal->theData[4]<<")");
8089     return;
8090   }//if
8091 
8092   // Update timer on ScanFragRec
8093   if (scanFragptr.p->scanFragTimer != 0){
8094     updateBuddyTimer(apiConnectptr);
8095     scanFragptr.p->startFragTimer(ctcTimer);
8096   } else {
8097     ndbassert(false);
8098     DEBUG("SCAN_HBREP when scanFragTimer was turned off");
8099   }
8100 }//execSCAN_HBREP()
8101 
8102 /*--------------------------------------------------------------------------*/
8103 /*      Timeout has occured on a fragment which means a scan has timed out. */
8104 /*      If this is true we have an error in LQH/ACC.                        */
8105 /*--------------------------------------------------------------------------*/
timeOutFoundFragLab(Signal * signal,UintR TscanConPtr)8106 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
8107 {
8108   ScanFragRecPtr ptr;
8109   c_scan_frag_pool.getPtr(ptr, TscanConPtr);
8110 #ifdef VM_TRACE
8111   {
8112     ScanRecordPtr scanptr;
8113     scanptr.i = ptr.p->scanRec;
8114     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8115     ApiConnectRecordPtr TlocalApiConnectptr;
8116     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8117     ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8118 
8119     DEBUG("[ H'" << hex << TlocalApiConnectptr.p->transid[0]
8120 	<< " H'" << TlocalApiConnectptr.p->transid[1] << "] "
8121         << TscanConPtr << " timeOutFoundFragLab: scanFragState = "
8122         << ptr.p->scanFragState);
8123   }
8124 #endif
8125 
8126   const Uint32 time_out_param= ctimeOutValue;
8127   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
8128 
8129   if (unlikely(time_out_param != old_time_out_param &&
8130 	       getNodeState().getSingleUserMode()))
8131   {
8132     jam();
8133     ScanRecordPtr scanptr;
8134     scanptr.i = ptr.p->scanRec;
8135     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8136     ApiConnectRecordPtr TlocalApiConnectptr;
8137     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
8138     ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
8139 
8140     if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
8141 	getNodeState().getSingleUserApi())
8142     {
8143       jam();
8144       Uint32 val = ctcTimer - ptr.p->scanFragTimer;
8145       if (val <= old_time_out_param)
8146       {
8147 	jam();
8148 	goto next;
8149       }
8150     }
8151   }
8152 
8153   /*-------------------------------------------------------------------------*/
8154   // The scan fragment has expired its timeout. Check its state to decide
8155   // what to do.
8156   /*-------------------------------------------------------------------------*/
8157   switch (ptr.p->scanFragState) {
8158   case ScanFragRec::WAIT_GET_PRIMCONF:
8159     jam();
8160     ndbrequire(false);
8161     break;
8162   case ScanFragRec::LQH_ACTIVE:{
8163     jam();
8164 
8165     /**
8166      * The LQH expired it's timeout, try to close it
8167      */
8168     Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
8169     Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
8170     ScanRecordPtr scanptr;
8171     scanptr.i = ptr.p->scanRec;
8172     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
8173 
8174     if(connectCount != ptr.p->m_connectCount){
8175       jam();
8176       /**
8177        * The node has died
8178        */
8179       ptr.p->scanFragState = ScanFragRec::COMPLETED;
8180       ptr.p->stopFragTimer();
8181       {
8182         ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8183         run.release(ptr);
8184       }
8185     }
8186 
8187     scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
8188     break;
8189   }
8190   case ScanFragRec::DELIVERED:
8191     jam();
8192   case ScanFragRec::IDLE:
8193     jam();
8194   case ScanFragRec::QUEUED_FOR_DELIVERY:
8195     jam();
8196     /*-----------------------------------------------------------------------
8197      * Should never occur. We will simply report set the timer to zero and
8198      * continue. In a debug version we should crash here but not in a release
8199      * version. In a release version we will simply set the time-out to zero.
8200      *-----------------------------------------------------------------------*/
8201 #ifdef VM_TRACE
8202     systemErrorLab(signal, __LINE__);
8203 #endif
8204     scanFragptr.p->stopFragTimer();
8205     break;
8206   default:
8207     jam();
8208     /*-----------------------------------------------------------------------
8209      * Non-existent state. Crash.
8210      *-----------------------------------------------------------------------*/
8211     systemErrorLab(signal, __LINE__);
8212     break;
8213   }//switch
8214 
8215 next:
8216   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
8217   signal->theData[1] = TscanConPtr + 1;
8218   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8219   return;
8220 }//timeOutFoundFragLab()
8221 
8222 
8223 /*
8224   4.3.16 GCP_NOMORETRANS
8225   ----------------------
8226 */
8227 /*****************************************************************************
8228  *                         G C P _ N O M O R E T R A N S
8229  *
8230  *  WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
8231  *  THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
8232  *  SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
8233  *  CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
8234  *  FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
8235  *  COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
8236  *  THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
8237  *  THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
8238  *  TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
8239  *****************************************************************************/
execGCP_NOMORETRANS(Signal * signal)8240 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
8241 {
8242   jamEntry();
8243   GCPNoMoreTrans* req = (GCPNoMoreTrans*)signal->getDataPtr();
8244   c_gcp_ref = req->senderRef;
8245   c_gcp_data = req->senderData;
8246   Uint32 gci_lo = req->gci_lo;
8247   Uint32 gci_hi = req->gci_hi;
8248   tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32);
8249 
8250   Ptr<GcpRecord> gcpPtr;
8251   if (cfirstgcp != RNIL) {
8252     jam();
8253                                       /* A GLOBAL CHECKPOINT IS GOING ON */
8254     gcpPtr.i = cfirstgcp;             /* SET POINTER TO FIRST GCP IN QUEUE*/
8255     ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8256     if (gcpPtr.p->gcpId == tcheckGcpId)
8257     {
8258       jam();
8259       bool empty = gcpPtr.p->firstApiConnect == RNIL;
8260       bool nfhandling = c_ongoing_take_over_cnt;
8261 
8262       if (empty && nfhandling)
8263       {
8264         jam();
8265         ndbout_c("NOT returning gcpTcfinished due to nfhandling %u/%u",
8266                  gci_hi, gci_lo);
8267       }
8268 
8269       if (!empty || c_ongoing_take_over_cnt)
8270       {
8271         jam();
8272         gcpPtr.p->gcpNomoretransRec = ZTRUE;
8273       } else {
8274         jam();
8275         gcpTcfinished(signal, tcheckGcpId);
8276         unlinkGcp(gcpPtr);
8277       }//if
8278     }
8279     else if (c_ongoing_take_over_cnt == 0)
8280     {
8281       jam();
8282       /*------------------------------------------------------------*/
8283       /*       IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO       */
8284       /*       RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE  */
8285       /*       THE GLOBAL CHECKPOINTS IN ORDER.                     */
8286       /*------------------------------------------------------------*/
8287       gcpTcfinished(signal, tcheckGcpId);
8288     }
8289     else
8290     {
8291       jam();
8292       goto outoforder;
8293     }
8294   }
8295   else if (c_ongoing_take_over_cnt == 0)
8296   {
8297     jam();
8298     gcpTcfinished(signal, tcheckGcpId);
8299   }
8300   else
8301   {
8302 seize:
8303     jam();
8304     ndbout_c("execGCP_NOMORETRANS(%u/%u) c_ongoing_take_over_cnt -> seize",
8305              gci_hi, gci_lo);
8306     seizeGcp(gcpPtr, tcheckGcpId);
8307     gcpPtr.p->gcpNomoretransRec = ZTRUE;
8308   }
8309   return;
8310 
8311 outoforder:
8312   printf("ooo: execGCP_NOMORETRANS tcheckGcpId: %u/%u cfirstgcp: %u/%u",
8313          gci_hi, gci_lo,
8314          Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8315 
8316   if (tcheckGcpId < gcpPtr.p->gcpId)
8317   {
8318     jam();
8319 
8320     Ptr<GcpRecord> tmp;
8321     tmp.i = cfirstfreeGcp;
8322     ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8323     cfirstfreeGcp = tmp.p->nextGcp;
8324 
8325     tmp.p->gcpId = tcheckGcpId;
8326     tmp.p->nextGcp = cfirstgcp;
8327     tmp.p->firstApiConnect = RNIL;
8328     tmp.p->lastApiConnect = RNIL;
8329     tmp.p->gcpNomoretransRec = ZTRUE;
8330     cfirstgcp = tmp.i;
8331     ndbout_c("LINK FIRST");
8332     return;
8333   }
8334   else
8335   {
8336     Ptr<GcpRecord> prev = gcpPtr;
8337     while (tcheckGcpId > gcpPtr.p->gcpId)
8338     {
8339       jam();
8340       if (gcpPtr.p->nextGcp == RNIL)
8341       {
8342         printf("nextGcp == RNIL -> ");
8343         goto seize;
8344       }
8345 
8346       prev = gcpPtr;
8347       gcpPtr.i = gcpPtr.p->nextGcp;
8348       ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
8349     }
8350 
8351     if (tcheckGcpId == gcpPtr.p->gcpId)
8352     {
8353       jam();
8354       gcpPtr.p->gcpNomoretransRec = ZTRUE;
8355       ndbout_c("found");
8356       return;
8357     }
8358     ndbrequire(prev.i != gcpPtr.i); // checked earlier with initial "<"
8359     ndbrequire(prev.p->gcpId < tcheckGcpId);
8360     ndbrequire(gcpPtr.p->gcpId > tcheckGcpId);
8361 
8362     Ptr<GcpRecord> tmp;
8363     tmp.i = cfirstfreeGcp;
8364     ptrCheckGuard(tmp, cgcpFilesize, gcpRecord);
8365     cfirstfreeGcp = tmp.p->nextGcp;
8366 
8367     tmp.p->gcpId = tcheckGcpId;
8368     tmp.p->nextGcp = gcpPtr.i;
8369     tmp.p->firstApiConnect = RNIL;
8370     tmp.p->lastApiConnect = RNIL;
8371     tmp.p->gcpNomoretransRec = ZTRUE;
8372     prev.p->nextGcp = tmp.i;
8373     ndbout_c("link middle %u/%u < %u/%u < %u/%u",
8374              Uint32(prev.p->gcpId >> 32), Uint32(prev.p->gcpId),
8375              gci_hi, gci_lo,
8376              Uint32(gcpPtr.p->gcpId >> 32), Uint32(gcpPtr.p->gcpId));
8377     return;
8378   }
8379 }//Dbtc::execGCP_NOMORETRANS()
8380 
8381 /*****************************************************************************/
8382 /*                                                                           */
8383 /*                            TAKE OVER MODULE                               */
8384 /*                                                                           */
8385 /*****************************************************************************/
8386 /*                                                                           */
8387 /*    THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE  */
8388 /*    NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT   */
8389 /*    ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE   */
8390 /*    FAILED.                                                                */
8391 /*                                                                           */
8392 /*    AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
8393 /*    CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
8394 /*    COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED.    */
8395 /*    IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO  */
8396 /*    WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT.            */
8397 /*****************************************************************************/
execNODE_FAILREP(Signal * signal)8398 void Dbtc::execNODE_FAILREP(Signal* signal)
8399 {
8400   jamEntry();
8401 
8402   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
8403 
8404   cfailure_nr = nodeFail->failNo;
8405   const Uint32 tnoOfNodes  = nodeFail->noOfNodes;
8406   const Uint32 tnewMasterId = nodeFail->masterNodeId;
8407 
8408   arrGuard(tnoOfNodes, MAX_NDB_NODES);
8409   Uint32 i;
8410   int index = 0;
8411   for (i = 1; i< MAX_NDB_NODES; i++)
8412   {
8413     if(NdbNodeBitmask::get(nodeFail->theNodes, i))
8414     {
8415       cdata[index] = i;
8416       index++;
8417     }//if
8418   }//for
8419 
8420   cmasterNodeId = tnewMasterId;
8421 
8422   HostRecordPtr myHostPtr;
8423 
8424   tcNodeFailptr.i = 0;
8425   ptrAss(tcNodeFailptr, tcFailRecord);
8426   for (i = 0; i < tnoOfNodes; i++)
8427   {
8428     jam();
8429     myHostPtr.i = cdata[i];
8430     ptrCheckGuard(myHostPtr, chostFilesize, hostRecord);
8431 
8432     /*------------------------------------------------------------*/
8433     /*       SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS   */
8434     /*       FAILED.                                              */
8435     /*------------------------------------------------------------*/
8436     myHostPtr.p->hostStatus = HS_DEAD;
8437     myHostPtr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
8438     c_ongoing_take_over_cnt++;
8439     c_alive_nodes.clear(myHostPtr.i);
8440 
8441     if (tcNodeFailptr.p->failStatus == FS_LISTENING)
8442     {
8443       jam();
8444       /*------------------------------------------------------------*/
8445       /*       THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE   */
8446       /*       FAILURE.                                             */
8447       /*------------------------------------------------------------*/
8448       if (myHostPtr.p->lqhTransStatus == LTS_ACTIVE)
8449       {
8450 	jam();
8451 	/*------------------------------------------------------------*/
8452 	/*       WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
8453 	/*       PROTOCOL FOR TC.                                     */
8454 	/*------------------------------------------------------------*/
8455 	signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
8456 	signal->theData[1] = myHostPtr.i;
8457 	sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
8458       }//if
8459     }//if
8460 
8461     jam();
8462     signal->theData[0] = myHostPtr.i;
8463     sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
8464 
8465     checkScanActiveInFailedLqh(signal, 0, myHostPtr.i);
8466     nodeFailCheckTransactions(signal, 0, myHostPtr.i);
8467     Callback cb = {safe_cast(&Dbtc::ndbdFailBlockCleanupCallback),
8468                   myHostPtr.i};
8469     simBlockNodeFailure(signal, myHostPtr.i, cb);
8470   }
8471 
8472   if (m_deferred_enabled == 0)
8473   {
8474     jam();
8475     Uint32 ok = 1;
8476     for(Uint32 n = c_alive_nodes.find_first();
8477         n != c_alive_nodes.NotFound;
8478         n = c_alive_nodes.find_next(n+1))
8479     {
8480       if (!ndbd_deferred_unique_constraints(getNodeInfo(n).m_version))
8481       {
8482         jam();
8483         ok = 0;
8484         break;
8485       }
8486     }
8487     if (ok)
8488     {
8489       jam();
8490       m_deferred_enabled = ~Uint32(0);
8491     }
8492   }
8493 }//Dbtc::execNODE_FAILREP()
8494 
8495 void
checkNodeFailComplete(Signal * signal,Uint32 failedNodeId,Uint32 bit)8496 Dbtc::checkNodeFailComplete(Signal* signal,
8497 			    Uint32 failedNodeId,
8498 			    Uint32 bit)
8499 {
8500   hostptr.i = failedNodeId;
8501   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8502   hostptr.p->m_nf_bits &= ~bit;
8503   if (hostptr.p->m_nf_bits == 0)
8504   {
8505     NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
8506     nfRep->blockNo      = DBTC;
8507     nfRep->nodeId       = cownNodeid;
8508     nfRep->failedNodeId = hostptr.i;
8509 
8510     if (instance() == 0)
8511     {
8512       jam();
8513       sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
8514                  NFCompleteRep::SignalLength, JBB);
8515       sendSignal(QMGR_REF, GSN_NF_COMPLETEREP, signal,
8516                  NFCompleteRep::SignalLength, JBB);
8517     }
8518     else
8519     {
8520       /**
8521        * Send to proxy
8522        */
8523       sendSignal(DBTC_REF, GSN_NF_COMPLETEREP, signal,
8524                  NFCompleteRep::SignalLength, JBB);
8525     }
8526   }
8527 
8528   CRASH_INSERTION(8058);
8529   if (ERROR_INSERTED(8059))
8530   {
8531     signal->theData[0] = 9999;
8532     sendSignalWithDelay(numberToRef(CMVMI, hostptr.i),
8533                         GSN_NDB_TAMPER, signal, 100, 1);
8534   }
8535 }
8536 
checkScanActiveInFailedLqh(Signal * signal,Uint32 scanPtrI,Uint32 failedNodeId)8537 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
8538 				      Uint32 scanPtrI,
8539 				      Uint32 failedNodeId){
8540 
8541   ScanRecordPtr scanptr;
8542   for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
8543     jam();
8544     ptrAss(scanptr, scanRecord);
8545     bool found = false;
8546     if (scanptr.p->scanState != ScanRecord::IDLE){
8547       jam();
8548       ScanFragRecPtr ptr;
8549       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
8550 
8551       for(run.first(ptr); !ptr.isNull(); ){
8552 	jam();
8553 	ScanFragRecPtr curr = ptr;
8554 	run.next(ptr);
8555 	if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
8556 	    refToNode(curr.p->lqhBlockref) == failedNodeId){
8557 	  jam();
8558 
8559 	  run.release(curr);
8560 	  curr.p->scanFragState = ScanFragRec::COMPLETED;
8561 	  curr.p->stopFragTimer();
8562 	  found = true;
8563 	}
8564       }
8565 
8566       ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
8567       for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
8568       {
8569 	jam();
8570 	if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
8571 	{
8572 	  jam();
8573 	  found = true;
8574 	  break;
8575 	}
8576       }
8577     }
8578     if(found){
8579       jam();
8580       scanError(signal, scanptr, ZSCAN_LQH_ERROR);
8581     }
8582 
8583     // Send CONTINUEB to continue later
8584     signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
8585     signal->theData[1] = scanptr.i + 1; // Check next scanptr
8586     signal->theData[2] = failedNodeId;
8587     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8588     return;
8589   }//for
8590 
8591   checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
8592 }
8593 
8594 void
nodeFailCheckTransactions(Signal * signal,Uint32 transPtrI,Uint32 failedNodeId)8595 Dbtc::nodeFailCheckTransactions(Signal* signal,
8596 				Uint32 transPtrI,
8597 				Uint32 failedNodeId)
8598 {
8599   jam();
8600   Ptr<ApiConnectRecord> transPtr;
8601   Uint32 TtcTimer = ctcTimer;
8602   Uint32 TapplTimeout = c_appl_timeout_value;
8603   Uint32 RT_BREAK = 64;
8604   Uint32 endPtrI = transPtrI + RT_BREAK;
8605   if (endPtrI > capiConnectFilesize)
8606   {
8607     endPtrI = capiConnectFilesize;
8608   }
8609 
8610   for (transPtr.i = transPtrI; transPtr.i < endPtrI; transPtr.i++)
8611   {
8612     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
8613     if (transPtr.p->m_transaction_nodes.get(failedNodeId))
8614     {
8615       jam();
8616 
8617       // Force timeout regardless of state
8618       c_appl_timeout_value = 1;
8619       setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
8620       timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
8621       c_appl_timeout_value = TapplTimeout;
8622 
8623       transPtr.i++;
8624       break;
8625     }
8626   }
8627 
8628   if (transPtr.i == capiConnectFilesize)
8629   {
8630     jam();
8631     checkNodeFailComplete(signal, failedNodeId,
8632                           HostRecord::NF_CHECK_TRANSACTION);
8633   }
8634   else
8635   {
8636     signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
8637     signal->theData[1] = transPtr.i;
8638     signal->theData[2] = failedNodeId;
8639     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8640   }
8641 }
8642 
8643 void
ndbdFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)8644 Dbtc::ndbdFailBlockCleanupCallback(Signal* signal,
8645                                    Uint32 failedNodeId,
8646                                    Uint32 ignoredRc)
8647 {
8648   jamEntry();
8649 
8650   checkNodeFailComplete(signal, failedNodeId,
8651                         HostRecord::NF_BLOCK_HANDLE);
8652 }
8653 
8654 void
apiFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)8655 Dbtc::apiFailBlockCleanupCallback(Signal* signal,
8656                                   Uint32 failedNodeId,
8657                                   Uint32 ignoredRc)
8658 {
8659   jamEntry();
8660 
8661   signal->theData[0] = failedNodeId;
8662   signal->theData[1] = reference();
8663   sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
8664 }
8665 
8666 void
checkScanFragList(Signal * signal,Uint32 failedNodeId,ScanRecord * scanP,ScanFragList::Head & head)8667 Dbtc::checkScanFragList(Signal* signal,
8668 			Uint32 failedNodeId,
8669 			ScanRecord * scanP,
8670 			ScanFragList::Head & head){
8671 
8672   DEBUG("checkScanActiveInFailedLqh: scanFragError");
8673 }
8674 
execTAKE_OVERTCCONF(Signal * signal)8675 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
8676 {
8677   jamEntry();
8678 
8679   if (!checkNodeFailSequence(signal))
8680   {
8681     jam();
8682     return;
8683   }
8684 
8685   tfailedNodeId = signal->theData[0];
8686   hostptr.i = tfailedNodeId;
8687   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8688 
8689   Uint32 senderRef = signal->theData[1];
8690   if (signal->getLength() < 2)
8691   {
8692     jam();
8693     senderRef = 0; // currently only used to see if it's from self
8694   }
8695 
8696   if (senderRef != reference())
8697   {
8698     jam();
8699 
8700     tcNodeFailptr.i = 0;
8701     ptrAss(tcNodeFailptr, tcFailRecord);
8702 
8703     /**
8704      * Node should be in queue
8705      */
8706     Uint32 i = 0;
8707     Uint32 end = tcNodeFailptr.p->queueIndex;
8708     for (; i<end; i++)
8709     {
8710       jam();
8711       if (tcNodeFailptr.p->queueList[i] == hostptr.i)
8712       {
8713         jam();
8714         break;
8715       }
8716     }
8717     ndbrequire(i != end);
8718     tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[end-1];
8719     tcNodeFailptr.p->queueIndex = end - 1;
8720   }
8721 
8722   Uint32 cnt = c_ongoing_take_over_cnt;
8723   ndbrequire(cnt);
8724   c_ongoing_take_over_cnt = cnt - 1;
8725   checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
8726 
8727   if (cnt == 1 && cfirstgcp != RNIL)
8728   {
8729     /**
8730      * Check if there are any hanging GCP_NOMORETRANS
8731      */
8732     GcpRecordPtr tmpGcpPointer;
8733     tmpGcpPointer.i = cfirstgcp;
8734     ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
8735     if (tmpGcpPointer.p->gcpNomoretransRec &&
8736         tmpGcpPointer.p->firstApiConnect == RNIL)
8737     {
8738       jam();
8739       ndbout_c("completing gcp %u/%u in execTAKE_OVERTCCONF",
8740                Uint32(tmpGcpPointer.p->gcpId >> 32),
8741                Uint32(tmpGcpPointer.p->gcpId));
8742       gcpTcfinished(signal, tmpGcpPointer.p->gcpId);
8743       unlinkGcp(tmpGcpPointer);
8744     }
8745   }
8746 }//Dbtc::execTAKE_OVERTCCONF()
8747 
execTAKE_OVERTCREQ(Signal * signal)8748 void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
8749 {
8750   jamEntry();
8751   tfailedNodeId = signal->theData[0];
8752   tcNodeFailptr.i = 0;
8753   ptrAss(tcNodeFailptr, tcFailRecord);
8754   if (tcNodeFailptr.p->failStatus != FS_IDLE ||
8755       cmasterNodeId != getOwnNodeId() ||
8756       (! (instance() == 0 /* single TC */ ||
8757           instance() == TAKE_OVER_INSTANCE))) /* in mt-TC case let 1 instance
8758                                                  do take-over */
8759   {
8760     jam();
8761     /*------------------------------------------------------------*/
8762     /*       WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
8763     /*------------------------------------------------------------*/
8764     /*       IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL      */
8765     /*       QUEUE THE TAKE OVER AND START IT AS SOON AS THE      */
8766     /*       PREVIOUS ARE COMPLETED.                              */
8767     /*------------------------------------------------------------*/
8768     arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
8769     tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
8770     tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
8771     return;
8772   }//if
8773   ndbrequire(instance() == 0 || instance() == TAKE_OVER_INSTANCE);
8774   startTakeOverLab(signal);
8775 }//Dbtc::execTAKE_OVERTCREQ()
8776 
8777 /*------------------------------------------------------------*/
8778 /*       INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS  */
8779 /*       AND OPERATIONS DURING TC TAKE OVER.                  */
8780 /*------------------------------------------------------------*/
startTakeOverLab(Signal * signal)8781 void Dbtc::startTakeOverLab(Signal* signal)
8782 {
8783   for (tindex = 0; tindex <= 511; tindex++) {
8784     ctransidFailHash[tindex] = RNIL;
8785   }//for
8786   for (tindex = 0; tindex <= 1023; tindex++) {
8787     ctcConnectFailHash[tindex] = RNIL;
8788   }//for
8789   tcNodeFailptr.p->failStatus = FS_LISTENING;
8790   tcNodeFailptr.p->takeOverNode = tfailedNodeId;
8791   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
8792     jam();
8793     ptrAss(hostptr, hostRecord);
8794     if (hostptr.p->hostStatus == HS_ALIVE) {
8795       jam();
8796       tblockref = calcLqhBlockRef(hostptr.i);
8797       hostptr.p->lqhTransStatus = LTS_ACTIVE;
8798       signal->theData[0] = tcNodeFailptr.i;
8799       signal->theData[1] = cownref;
8800       signal->theData[2] = tfailedNodeId;
8801       if (ERROR_INSERTED(8064) && hostptr.i == getOwnNodeId())
8802       {
8803         ndbout_c("sending delayed GSN_LQH_TRANSREQ to self");
8804         sendSignalWithDelay(tblockref, GSN_LQH_TRANSREQ, signal, 100, 3);
8805         CLEAR_ERROR_INSERT_VALUE;
8806       }
8807       else
8808       {
8809         sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
8810       }
8811     }//if
8812   }//for
8813 }//Dbtc::startTakeOverLab()
8814 
8815 /*------------------------------------------------------------*/
8816 /*       A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
8817 /*------------------------------------------------------------*/
execLQH_TRANSCONF(Signal * signal)8818 void Dbtc::execLQH_TRANSCONF(Signal* signal)
8819 {
8820   jamEntry();
8821   LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
8822 
8823   CRASH_INSERTION(8060);
8824 
8825   tcNodeFailptr.i = lqhTransConf->tcRef;
8826   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
8827   tnodeid = lqhTransConf->lqhNodeId;
8828   ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
8829   ttransid1    = lqhTransConf->transId1;
8830   ttransid2    = lqhTransConf->transId2;
8831   ttcOprec     = lqhTransConf->oldTcOpRec;
8832   treqinfo     = lqhTransConf->requestInfo;
8833   tgci         = Uint64(lqhTransConf->gci_hi) << 32;
8834   cnodes[0]    = lqhTransConf->nextNodeId1;
8835   cnodes[1]    = lqhTransConf->nextNodeId2;
8836   cnodes[2]    = lqhTransConf->nextNodeId3;
8837   const Uint32 ref = tapplRef = lqhTransConf->apiRef;
8838   tapplOprec   = lqhTransConf->apiOpRec;
8839   const Uint32 tableId = lqhTransConf->tableId;
8840   Uint32 gci_lo = lqhTransConf->gci_lo;
8841   Uint32 fragId = lqhTransConf->fragId;
8842   if (ttransStatus == LqhTransConf::Committed &&
8843       unlikely(signal->getLength() < LqhTransConf::SignalLength_GCI_LO))
8844   {
8845     jam();
8846     gci_lo = 0;
8847     ndbassert(!ndb_check_micro_gcp(getNodeInfo(tnodeid).m_version));
8848   }
8849   tgci |= gci_lo;
8850 
8851   if (ttransStatus == LqhTransConf::LastTransConf){
8852     jam();
8853     /*------------------------------------------------------------*/
8854     /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
8855     /*------------------------------------------------------------*/
8856     nodeTakeOverCompletedLab(signal);
8857     return;
8858   }//if
8859   if (ttransStatus == LqhTransConf::Marker){
8860     jam();
8861     treqinfo = 0;
8862     LqhTransConf::setMarkerFlag(treqinfo, 1);
8863   } else {
8864     TableRecordPtr tabPtr;
8865     tabPtr.i = tableId;
8866     ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
8867     switch((DictTabInfo::TableType)tabPtr.p->tableType){
8868     case DictTabInfo::SystemTable:
8869     case DictTabInfo::UserTable:
8870       break;
8871     default:
8872       tapplRef = 0;
8873       tapplOprec = 0;
8874     }
8875   }
8876 
8877   findApiConnectFail(signal);
8878 
8879   if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
8880     apiConnectptr.p->ndbapiBlockref = ref;
8881     apiConnectptr.p->ndbapiConnect = tapplOprec;
8882   }
8883 
8884   if (ttransStatus != LqhTransConf::Marker)
8885   {
8886     jam();
8887 
8888     Uint32 instanceKey;
8889 
8890     if (unlikely(signal->getLength() < LqhTransConf::SignalLength_FRAG_ID))
8891     {
8892       jam();
8893       instanceKey = 0;
8894     }
8895     else
8896     {
8897       jam();
8898       instanceKey = getInstanceKey(tableId, fragId);
8899     }
8900     findTcConnectFail(signal, instanceKey);
8901   }
8902 }//Dbtc::execLQH_TRANSCONF()
8903 
8904 /*------------------------------------------------------------*/
8905 /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
8906 /*------------------------------------------------------------*/
nodeTakeOverCompletedLab(Signal * signal)8907 void Dbtc::nodeTakeOverCompletedLab(Signal* signal)
8908 {
8909   Uint32 guard0;
8910 
8911   CRASH_INSERTION(8061);
8912 
8913   hostptr.i = tnodeid;
8914   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8915   hostptr.p->lqhTransStatus = LTS_IDLE;
8916   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
8917     jam();
8918     ptrAss(hostptr, hostRecord);
8919     if (hostptr.p->hostStatus == HS_ALIVE) {
8920       if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
8921         jam();
8922 	/*------------------------------------------------------------*/
8923 	/*       NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE    */
8924 	/*       TAKE OVER.                                           */
8925 	/*------------------------------------------------------------*/
8926         return;
8927       }//if
8928     }//if
8929   }//for
8930   /*------------------------------------------------------------*/
8931   /*       ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
8932   /*       OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE  */
8933   /*       ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE       */
8934   /*       TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN     */
8935   /*       UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
8936   /*       TO THE APPLICATION IF THAT IS STILL ALIVE.           */
8937   /*------------------------------------------------------------*/
8938   tcNodeFailptr.p->currentHashIndexTakeOver = 0;
8939   tcNodeFailptr.p->completedTakeOver = 0;
8940   tcNodeFailptr.p->failStatus = FS_COMPLETING;
8941   guard0 = cnoParallelTakeOver - 1;
8942   /*------------------------------------------------------------*/
8943   /*       WE WILL COMPLETE THE TRANSACTIONS BY STARTING A      */
8944   /*       NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL    */
8945   /*       COMPLETE ONE TRANSACTION AT A TIME AND IN THAT       */
8946   /*       TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
8947   /*       WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
8948   /*       IS COMPLETED.                                        */
8949   /*------------------------------------------------------------*/
8950   arrGuard(guard0, MAX_NDB_NODES);
8951   for (tindex = 0; tindex <= guard0; tindex++) {
8952     jam();
8953     tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
8954     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
8955     signal->theData[1] = tcNodeFailptr.i;
8956     signal->theData[2] = tindex;
8957     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8958   }//for
8959 }//Dbtc::nodeTakeOverCompletedLab()
8960 
8961 /*------------------------------------------------------------*/
8962 /*       COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF    */
8963 /*       TRANSACTIONS TO COMPLETE.                            */
8964 /*------------------------------------------------------------*/
completeTransAtTakeOverLab(Signal * signal,UintR TtakeOverInd)8965 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
8966 {
8967   jam();
8968   while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
8969     jam();
8970     apiConnectptr.i =
8971         ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
8972     if (apiConnectptr.i != RNIL) {
8973       jam();
8974       /*------------------------------------------------------------*/
8975       /*       WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE         */
8976       /*       COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT   */
8977       /*       NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS     */
8978       /*       TRANSACTION.                                         */
8979       /*------------------------------------------------------------*/
8980       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8981       ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
8982         apiConnectptr.p->nextApiConnect;
8983 
8984       completeTransAtTakeOverDoOne(signal, TtakeOverInd);
8985       // One transaction taken care of, return from this function
8986       // and wait for the next CONTINUEB to continue processing
8987       break;
8988 
8989     } else {
8990       if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
8991         jam();
8992         tcNodeFailptr.p->currentHashIndexTakeOver++;
8993       } else {
8994         jam();
8995         completeTransAtTakeOverDoLast(signal, TtakeOverInd);
8996         tcNodeFailptr.p->currentHashIndexTakeOver++;
8997       }//if
8998     }//if
8999   }//while
9000 }//Dbtc::completeTransAtTakeOverLab()
9001 
9002 
9003 
9004 
completeTransAtTakeOverDoLast(Signal * signal,UintR TtakeOverInd)9005 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
9006 {
9007   Uint32 guard0;
9008   /*------------------------------------------------------------*/
9009   /*       THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS     */
9010   /*       ACTIVITY IS COMPLETED.                               */
9011   /*------------------------------------------------------------*/
9012   arrGuard(TtakeOverInd, MAX_NDB_NODES);
9013   if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
9014     jam();
9015     systemErrorLab(signal, __LINE__);
9016     return;
9017   }//if
9018   tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
9019   tcNodeFailptr.p->completedTakeOver++;
9020 
9021   CRASH_INSERTION(8062);
9022 
9023   if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
9024     jam();
9025     /*------------------------------------------------------------*/
9026     /*       WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
9027     /*       TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL     */
9028     /*       NODES THAT ARE ALIVE.                                */
9029     /*------------------------------------------------------------*/
9030     NodeReceiverGroup rg(DBTC, c_alive_nodes);
9031     signal->theData[0] = tcNodeFailptr.p->takeOverNode;
9032     signal->theData[1] = reference();
9033     sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 2, JBB);
9034 
9035     if (tcNodeFailptr.p->queueIndex > 0) {
9036       jam();
9037       /*------------------------------------------------------------*/
9038       /*       THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START  */
9039       /*       THE TAKE OVER.                                       */
9040       /*------------------------------------------------------------*/
9041       tfailedNodeId = tcNodeFailptr.p->queueList[0];
9042       guard0 = tcNodeFailptr.p->queueIndex - 1;
9043       arrGuard(guard0 + 1, MAX_NDB_NODES);
9044       for (tindex = 0; tindex <= guard0; tindex++) {
9045         jam();
9046         tcNodeFailptr.p->queueList[tindex] =
9047           tcNodeFailptr.p->queueList[tindex + 1];
9048       }//for
9049       tcNodeFailptr.p->queueIndex--;
9050       startTakeOverLab(signal);
9051       return;
9052     } else {
9053       jam();
9054       tcNodeFailptr.p->failStatus = FS_IDLE;
9055     }//if
9056   }//if
9057   return;
9058 }//Dbtc::completeTransAtTakeOverDoLast()
9059 
completeTransAtTakeOverDoOne(Signal * signal,UintR TtakeOverInd)9060 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
9061 {
9062   apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
9063   apiConnectptr.p->takeOverInd = TtakeOverInd;
9064 
9065   switch (apiConnectptr.p->apiConnectstate) {
9066   case CS_FAIL_COMMITTED:
9067     jam();
9068     /*------------------------------------------------------------*/
9069     /*       ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
9070     /*       HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT  */
9071     /*       COMMITTED TO THE APPLICATION AND CONTINUE WITH THE   */
9072     /*       COMPLETE PHASE.                                      */
9073     /*------------------------------------------------------------*/
9074     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9075     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9076     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9077     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9078     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9079     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9080     commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
9081     toCompleteHandlingLab(signal);
9082     return;
9083   case CS_FAIL_COMMITTING:
9084     jam();
9085     /*------------------------------------------------------------*/
9086     /*       AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
9087     /*       PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
9088     /*       THEN CONTINUE AS AFTER COMMITTED.                    */
9089     /*------------------------------------------------------------*/
9090     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9091     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9092     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9093     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9094     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9095     commitGciHandling(signal, apiConnectptr.p->globalcheckpointid);
9096     toCommitHandlingLab(signal);
9097     return;
9098   case CS_FAIL_ABORTING:
9099   case CS_FAIL_PREPARED:
9100     jam();
9101     /*------------------------------------------------------------*/
9102     /*       WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
9103     /*       STATE IN THIS VERSION. IN LATER VERSIONS WE WILL     */
9104     /*       HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT  */
9105     /*       TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
9106     /*       HAVE HEARD FROM THE TRANSACTION COORDINATOR.         */
9107     /*                                                            */
9108     /*       IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE       */
9109     /*       PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL  */
9110     /*       LATER VERSIONS.                                      */
9111     /*------------------------------------------------------------*/
9112     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9113     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9114     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9115     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9116     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9117     toAbortHandlingLab(signal);
9118     return;
9119   case CS_FAIL_ABORTED:
9120     jam();
9121     sendTCKEY_FAILREF(signal, apiConnectptr.p);
9122 
9123     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9124     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9125     signal->theData[2] = apiConnectptr.p->takeOverInd;
9126     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9127     releaseTakeOver(signal);
9128     break;
9129   case CS_FAIL_COMPLETED:
9130     jam();
9131     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9132 
9133     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9134     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9135     signal->theData[2] = apiConnectptr.p->takeOverInd;
9136     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9137     releaseApiConnectFail(signal);
9138     break;
9139   default:
9140     jam();
9141     systemErrorLab(signal, __LINE__);
9142     return;
9143   }//switch
9144 }//Dbtc::completeTransAtTakeOverDoOne()
9145 
9146 void
sendTCKEY_FAILREF(Signal * signal,ApiConnectRecord * regApiPtr)9147 Dbtc::sendTCKEY_FAILREF(Signal* signal, ApiConnectRecord * regApiPtr){
9148   jam();
9149 
9150   const Uint32 ref = regApiPtr->ndbapiBlockref;
9151   const Uint32 nodeId = refToNode(ref);
9152   if(ref != 0)
9153   {
9154     jam();
9155     bool connectedToNode = getNodeInfo(nodeId).m_connected;
9156     signal->theData[0] = regApiPtr->ndbapiConnect;
9157     signal->theData[1] = regApiPtr->transid[0];
9158     signal->theData[2] = regApiPtr->transid[1];
9159 
9160     if (likely(connectedToNode))
9161     {
9162       jam();
9163       sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
9164     }
9165     else
9166     {
9167       routeTCKEY_FAILREFCONF(signal, regApiPtr, GSN_TCKEY_FAILREF, 3);
9168     }
9169   }
9170 
9171   const Uint32 marker = regApiPtr->commitAckMarker;
9172   if(marker != RNIL)
9173   {
9174     jam();
9175     m_commitAckMarkerHash.release(marker);
9176     regApiPtr->commitAckMarker = RNIL;
9177   }
9178 }
9179 
9180 void
sendTCKEY_FAILCONF(Signal * signal,ApiConnectRecord * regApiPtr)9181 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
9182   jam();
9183   TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
9184 
9185   const Uint32 ref = regApiPtr->ndbapiBlockref;
9186   const Uint32 marker = regApiPtr->commitAckMarker;
9187   const Uint32 nodeId = refToNode(ref);
9188   if(ref != 0)
9189   {
9190     jam();
9191     failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
9192     failConf->transId1 = regApiPtr->transid[0];
9193     failConf->transId2 = regApiPtr->transid[1];
9194 
9195     bool connectedToNode = getNodeInfo(nodeId).m_connected;
9196     if (likely(connectedToNode))
9197     {
9198       jam();
9199       sendSignal(ref, GSN_TCKEY_FAILCONF, signal,
9200 		 TcKeyFailConf::SignalLength, JBB);
9201     }
9202     else
9203     {
9204       routeTCKEY_FAILREFCONF(signal, regApiPtr,
9205 			     GSN_TCKEY_FAILCONF, TcKeyFailConf::SignalLength);
9206     }
9207   }
9208   regApiPtr->commitAckMarker = RNIL;
9209 }
9210 
9211 void
routeTCKEY_FAILREFCONF(Signal * signal,const ApiConnectRecord * regApiPtr,Uint32 gsn,Uint32 len)9212 Dbtc::routeTCKEY_FAILREFCONF(Signal* signal, const ApiConnectRecord* regApiPtr,
9213 			     Uint32 gsn, Uint32 len)
9214 {
9215   jam();
9216 
9217   Uint32 ref = regApiPtr->ndbapiBlockref;
9218 
9219   /**
9220    * We're not connected
9221    *   so we find another node in same node group as died node
9222    *   and send to it, so that it can forward
9223    */
9224   tcNodeFailptr.i = regApiPtr->takeOverRec;
9225   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
9226 
9227   /**
9228    * Save signal
9229    */
9230   Uint32 save[25];
9231   ndbrequire(len <= 25);
9232   memcpy(save, signal->theData, 4*len);
9233 
9234   Uint32 node = tcNodeFailptr.p->takeOverNode;
9235 
9236   CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
9237   sd->blockRef = reference();
9238   sd->requestType =
9239     CheckNodeGroups::Direct |
9240     CheckNodeGroups::GetNodeGroupMembers;
9241   sd->nodeId = node;
9242   EXECUTE_DIRECT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
9243 		 CheckNodeGroups::SignalLength);
9244   jamEntry();
9245 
9246   NdbNodeBitmask mask;
9247   mask.assign(sd->mask);
9248   mask.clear(getOwnNodeId());
9249   memcpy(signal->theData, save, 4*len);
9250 
9251   Uint32 i = 0;
9252   while((i = mask.find(i + 1)) != NdbNodeBitmask::NotFound)
9253   {
9254     jam();
9255     HostRecordPtr localHostptr;
9256     localHostptr.i = i;
9257     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
9258     if (localHostptr.p->hostStatus == HS_ALIVE)
9259     {
9260       jam();
9261       signal->theData[len] = gsn;
9262       signal->theData[len+1] = ref;
9263       sendSignal(calcTcBlockRef(i), GSN_TCKEY_FAILREFCONF_R,
9264 		 signal, len+2, JBB);
9265       return;
9266     }
9267   }
9268 
9269 
9270    /**
9271     * This code was 'unfinished' code for partially connected API's
9272     *   it does however not really work...
9273     *   and we seriously need to think about semantics for API connect
9274     */
9275 #if 0
9276   ndbrequire(getNodeInfo(refToNode(ref)).m_type == NodeInfo::DB);
9277 #endif
9278 }
9279 
9280 void
execTCKEY_FAILREFCONF_R(Signal * signal)9281 Dbtc::execTCKEY_FAILREFCONF_R(Signal* signal)
9282 {
9283   jamEntry();
9284   Uint32 len = signal->getLength();
9285   Uint32 gsn = signal->theData[len-2];
9286   Uint32 ref = signal->theData[len-1];
9287   sendSignal(ref, gsn, signal, len-2, JBB);
9288 }
9289 
9290 /*------------------------------------------------------------*/
9291 /*       THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A   */
9292 /*       NODE FAILURE BEFORE THE COMMIT DECISION.             */
9293 /*------------------------------------------------------------*/
9294 /*       ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID      */
9295 /*------------------------------------------------------------*/
execABORTCONF(Signal * signal)9296 void Dbtc::execABORTCONF(Signal* signal)
9297 {
9298   UintR compare_transid1, compare_transid2;
9299 
9300   jamEntry();
9301   tcConnectptr.i = signal->theData[0];
9302   tnodeid = signal->theData[2];
9303   if (ERROR_INSERTED(8045)) {
9304     CLEAR_ERROR_INSERT_VALUE;
9305     sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
9306     return;
9307   }//if
9308   if (tcConnectptr.i >= ctcConnectFilesize) {
9309     errorReport(signal, 5);
9310     return;
9311   }//if
9312   ptrAss(tcConnectptr, tcConnectRecord);
9313   if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
9314     warningReport(signal, 16);
9315     return;
9316   }//if
9317   apiConnectptr.i = tcConnectptr.p->apiConnect;
9318   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9319   if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
9320     warningReport(signal, 17);
9321     return;
9322   }//if
9323   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
9324   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
9325   compare_transid1 = compare_transid1 | compare_transid2;
9326   if (compare_transid1 != 0) {
9327     warningReport(signal, 18);
9328     return;
9329   }//if
9330   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9331   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9332       tnodeid) {
9333     warningReport(signal, 19);
9334     return;
9335   }//if
9336   tcurrentReplicaNo = (Uint8)Z8NIL;
9337   tcConnectptr.p->tcConnectstate = OS_ABORTING;
9338   toAbortHandlingLab(signal);
9339 }//Dbtc::execABORTCONF()
9340 
toAbortHandlingLab(Signal * signal)9341 void Dbtc::toAbortHandlingLab(Signal* signal)
9342 {
9343   do {
9344     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9345       jam();
9346       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9347       const LqhTransConf::OperationStatus stat =
9348 	(LqhTransConf::OperationStatus)
9349 	tcConnectptr.p->failData[tcurrentReplicaNo];
9350       switch(stat){
9351       case LqhTransConf::InvalidStatus:
9352       case LqhTransConf::Aborted:
9353         jam();
9354         /*empty*/;
9355         break;
9356       case LqhTransConf::Prepared:
9357         jam();
9358         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9359         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9360         if (hostptr.p->hostStatus == HS_ALIVE) {
9361           jam();
9362           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9363           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9364           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9365           tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
9366           apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
9367           apiConnectptr.p->timeOutCounter = 0;
9368           signal->theData[0] = tcConnectptr.i;
9369           signal->theData[1] = cownref;
9370           signal->theData[2] = apiConnectptr.p->transid[0];
9371           signal->theData[3] = apiConnectptr.p->transid[1];
9372           signal->theData[4] = apiConnectptr.p->tcBlockref;
9373           signal->theData[5] = tcConnectptr.p->tcOprec;
9374           sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
9375           return;
9376         }//if
9377         break;
9378       default:
9379         jam();
9380         systemErrorLab(signal, __LINE__);
9381         return;
9382       }//switch
9383     }//if
9384     if (apiConnectptr.p->currentReplicaNo > 0) {
9385       jam();
9386       /*------------------------------------------------------------*/
9387       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
9388       /*       ABORTED.                                             */
9389       /*------------------------------------------------------------*/
9390       apiConnectptr.p->currentReplicaNo--;
9391       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9392     } else {
9393       /*------------------------------------------------------------*/
9394       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
9395       /*------------------------------------------------------------*/
9396       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9397       if (tcConnectptr.i == RNIL) {
9398 	/*------------------------------------------------------------*/
9399 	/*       WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
9400 	/*       THE ABORT STATUS TO THE APPLICATION AND CONTINUE     */
9401 	/*       WITH THE NEXT TRANSACTION.                           */
9402 	/*------------------------------------------------------------*/
9403         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9404           jam();
9405 	  sendTCKEY_FAILREF(signal, apiConnectptr.p);
9406 
9407 	  /*------------------------------------------------------------*/
9408 	  /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
9409 	  /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
9410 	  /*------------------------------------------------------------*/
9411           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9412           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9413           signal->theData[2] = apiConnectptr.p->takeOverInd;
9414           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9415           releaseTakeOver(signal);
9416         } else {
9417           jam();
9418           releaseAbortResources(signal);
9419         }//if
9420         return;
9421       }//if
9422       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9423       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9424       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9425       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9426     }//if
9427   } while (1);
9428 }//Dbtc::toAbortHandlingLab()
9429 
9430 /*------------------------------------------------------------*/
9431 /*       THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A  */
9432 /*       NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE.      */
9433 /*------------------------------------------------------------*/
9434 /*       COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID     */
9435 /*------------------------------------------------------------*/
execCOMMITCONF(Signal * signal)9436 void Dbtc::execCOMMITCONF(Signal* signal)
9437 {
9438   UintR compare_transid1, compare_transid2;
9439 
9440   jamEntry();
9441   tcConnectptr.i = signal->theData[0];
9442   tnodeid = signal->theData[1];
9443   if (ERROR_INSERTED(8046)) {
9444     CLEAR_ERROR_INSERT_VALUE;
9445     sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
9446     return;
9447   }//if
9448   if (tcConnectptr.i >= ctcConnectFilesize) {
9449     errorReport(signal, 4);
9450     return;
9451   }//if
9452   ptrAss(tcConnectptr, tcConnectRecord);
9453   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
9454     warningReport(signal, 8);
9455     return;
9456   }//if
9457   apiConnectptr.i = tcConnectptr.p->apiConnect;
9458   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9459   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
9460     warningReport(signal, 9);
9461     return;
9462   }//if
9463   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
9464   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
9465   compare_transid1 = compare_transid1 | compare_transid2;
9466   if (compare_transid1 != 0) {
9467     warningReport(signal, 10);
9468     return;
9469   }//if
9470   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9471   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9472       tnodeid) {
9473     warningReport(signal, 11);
9474     return;
9475   }//if
9476   if (ERROR_INSERTED(8026)) {
9477     jam();
9478     systemErrorLab(signal, __LINE__);
9479   }//if
9480   tcurrentReplicaNo = (Uint8)Z8NIL;
9481   tcConnectptr.p->tcConnectstate = OS_COMMITTED;
9482   toCommitHandlingLab(signal);
9483 }//Dbtc::execCOMMITCONF()
9484 
toCommitHandlingLab(Signal * signal)9485 void Dbtc::toCommitHandlingLab(Signal* signal)
9486 {
9487   do {
9488     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9489       jam();
9490       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9491       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
9492       case LqhTransConf::InvalidStatus:
9493         jam();
9494         /*empty*/;
9495         break;
9496       case LqhTransConf::Committed:
9497         jam();
9498         /*empty*/;
9499         break;
9500       case LqhTransConf::Prepared:
9501         jam();
9502         /*------------------------------------------------------------*/
9503         /*       THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR    */
9504         /*       COMMIT REQUEST FROM TC.                              */
9505         /*------------------------------------------------------------*/
9506         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9507         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9508         if (hostptr.p->hostStatus == HS_ALIVE) {
9509           jam();
9510           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9511           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9512           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9513           apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
9514           apiConnectptr.p->timeOutCounter = 0;
9515           tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
9516           Uint64 gci = apiConnectptr.p->globalcheckpointid;
9517           signal->theData[0] = tcConnectptr.i;
9518           signal->theData[1] = cownref;
9519           signal->theData[2] = Uint32(gci >> 32); // XXX JON
9520           signal->theData[3] = apiConnectptr.p->transid[0];
9521           signal->theData[4] = apiConnectptr.p->transid[1];
9522           signal->theData[5] = apiConnectptr.p->tcBlockref;
9523           signal->theData[6] = tcConnectptr.p->tcOprec;
9524           signal->theData[7] = Uint32(gci);
9525           sendSignal(tblockref, GSN_COMMITREQ, signal, 8, JBB);
9526           return;
9527         }//if
9528         break;
9529       default:
9530         jam();
9531         systemErrorLab(signal, __LINE__);
9532         return;
9533         break;
9534       }//switch
9535     }//if
9536     if (apiConnectptr.p->currentReplicaNo > 0) {
9537       jam();
9538       /*------------------------------------------------------------*/
9539       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
9540       /*       COMMITTED.                                           */
9541       /*------------------------------------------------------------*/
9542       apiConnectptr.p->currentReplicaNo--;
9543       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9544     } else {
9545       /*------------------------------------------------------------*/
9546       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
9547       /*------------------------------------------------------------*/
9548       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9549       if (tcConnectptr.i == RNIL) {
9550 	/*------------------------------------------------------------*/
9551 	/*       WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
9552 	/*       THE COMMIT STATUS TO THE APPLICATION AND CONTINUE    */
9553 	/*       WITH THE COMPLETE PHASE.                             */
9554 	/*------------------------------------------------------------*/
9555         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9556           jam();
9557 	  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
9558 	} else {
9559           jam();
9560           apiConnectptr = sendApiCommit(signal);
9561         }//if
9562         apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
9563         tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9564         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9565         tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9566         apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
9567         toCompleteHandlingLab(signal);
9568         return;
9569       }//if
9570       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9571       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9572       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
9573       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9574     }//if
9575   } while (1);
9576 }//Dbtc::toCommitHandlingLab()
9577 
9578 /*------------------------------------------------------------*/
9579 /*       COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE   */
9580 /*       HAVE FAILED.                                         */
9581 /*------------------------------------------------------------*/
9582 /*       THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION   */
9583 /*------------------------------------------------------------*/
execCOMPLETECONF(Signal * signal)9584 void Dbtc::execCOMPLETECONF(Signal* signal)
9585 {
9586   UintR compare_transid1, compare_transid2;
9587 
9588   jamEntry();
9589   tcConnectptr.i = signal->theData[0];
9590   tnodeid = signal->theData[1];
9591   if (ERROR_INSERTED(8047)) {
9592     CLEAR_ERROR_INSERT_VALUE;
9593     sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
9594     return;
9595   }//if
9596   if (tcConnectptr.i >= ctcConnectFilesize) {
9597     errorReport(signal, 3);
9598     return;
9599   }//if
9600   ptrAss(tcConnectptr, tcConnectRecord);
9601   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
9602     warningReport(signal, 12);
9603     return;
9604   }//if
9605   apiConnectptr.i = tcConnectptr.p->apiConnect;
9606   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9607   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
9608     warningReport(signal, 13);
9609     return;
9610   }//if
9611   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
9612   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
9613   compare_transid1 = compare_transid1 | compare_transid2;
9614   if (compare_transid1 != 0) {
9615     warningReport(signal, 14);
9616     return;
9617   }//if
9618   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9619   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
9620       tnodeid) {
9621     warningReport(signal, 15);
9622     return;
9623   }//if
9624   if (ERROR_INSERTED(8028)) {
9625     jam();
9626     systemErrorLab(signal, __LINE__);
9627   }//if
9628   tcConnectptr.p->tcConnectstate = OS_COMPLETED;
9629   tcurrentReplicaNo = (Uint8)Z8NIL;
9630   toCompleteHandlingLab(signal);
9631 }//Dbtc::execCOMPLETECONF()
9632 
toCompleteHandlingLab(Signal * signal)9633 void Dbtc::toCompleteHandlingLab(Signal* signal)
9634 {
9635   do {
9636     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
9637       jam();
9638       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
9639       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
9640       case LqhTransConf::InvalidStatus:
9641         jam();
9642         /*empty*/;
9643         break;
9644       default:
9645         jam();
9646         /*------------------------------------------------------------*/
9647         /*       THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
9648         /*       IT MUST HAVE FAILED.                                 */
9649         /*------------------------------------------------------------*/
9650         /*------------------------------------------------------------*/
9651         /*       SEND COMPLETEREQ TO THE NEXT REPLICA.                */
9652         /*------------------------------------------------------------*/
9653         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
9654         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9655         if (hostptr.p->hostStatus == HS_ALIVE) {
9656           jam();
9657           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9658           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
9659           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
9660           tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
9661           apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
9662           apiConnectptr.p->timeOutCounter = 0;
9663           tcConnectptr.p->apiConnect = apiConnectptr.i;
9664           signal->theData[0] = tcConnectptr.i;
9665           signal->theData[1] = cownref;
9666           signal->theData[2] = apiConnectptr.p->transid[0];
9667           signal->theData[3] = apiConnectptr.p->transid[1];
9668           signal->theData[4] = apiConnectptr.p->tcBlockref;
9669           signal->theData[5] = tcConnectptr.p->tcOprec;
9670           sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
9671           return;
9672         }//if
9673         break;
9674       }//switch
9675     }//if
9676     if (apiConnectptr.p->currentReplicaNo != 0) {
9677       jam();
9678       /*------------------------------------------------------------*/
9679       /*       THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE  */
9680       /*       NEED TO CONTINUE WITH THOSE REPLICAS.                */
9681       /*------------------------------------------------------------*/
9682       apiConnectptr.p->currentReplicaNo--;
9683       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
9684     } else {
9685       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9686       if (tcConnectptr.i == RNIL) {
9687         /*------------------------------------------------------------*/
9688         /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
9689         /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
9690         /*------------------------------------------------------------*/
9691         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
9692           jam();
9693           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
9694           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
9695           signal->theData[2] = apiConnectptr.p->takeOverInd;
9696           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9697           handleGcp(signal, apiConnectptr);
9698           releaseTakeOver(signal);
9699         } else {
9700           jam();
9701           releaseTransResources(signal);
9702         }//if
9703         return;
9704       }//if
9705       /*------------------------------------------------------------*/
9706       /*       WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
9707       /*       COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
9708       /*       FIRST REPLICA SINCE IT IS THE COMPLETE PHASE.        */
9709       /*------------------------------------------------------------*/
9710       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
9711       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9712       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
9713       apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
9714     }//if
9715   } while (1);
9716 }//Dbtc::toCompleteHandlingLab()
9717 
9718 /*------------------------------------------------------------*/
9719 /*                                                            */
9720 /*       FIND THE API CONNECT RECORD FOR THIS TRANSACTION     */
9721 /*       DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS    */
9722 /*       YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT  */
9723 /*       INTO THE HASH TABLE.                                 */
9724 /*------------------------------------------------------------*/
findApiConnectFail(Signal * signal)9725 void Dbtc::findApiConnectFail(Signal* signal)
9726 {
9727   ApiConnectRecordPtr fafPrevApiConnectptr;
9728   ApiConnectRecordPtr fafNextApiConnectptr;
9729   UintR tfafHashNumber;
9730 
9731   tfafHashNumber = ttransid1 & 511;
9732   fafPrevApiConnectptr.i = RNIL;
9733   ptrNull(fafPrevApiConnectptr);
9734   arrGuard(tfafHashNumber, 512);
9735   fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
9736   ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
9737 FAF_LOOP:
9738   jam();
9739   if (fafNextApiConnectptr.i == RNIL) {
9740     jam();
9741     if (cfirstfreeApiConnectFail == RNIL) {
9742       jam();
9743       systemErrorLab(signal, __LINE__);
9744       return;
9745     }//if
9746     seizeApiConnectFail(signal);
9747     if (fafPrevApiConnectptr.i == RNIL) {
9748       jam();
9749       ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
9750     } else {
9751       jam();
9752       ptrGuard(fafPrevApiConnectptr);
9753       fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
9754     }//if
9755     apiConnectptr.p->nextApiConnect = RNIL;
9756     initApiConnectFail(signal);
9757   } else {
9758     jam();
9759     fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
9760     fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
9761     apiConnectptr.i = fafNextApiConnectptr.i;
9762     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9763     fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
9764     ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
9765     if ((apiConnectptr.p->transid[1] != ttransid2) ||
9766         (apiConnectptr.p->transid[0] != ttransid1)) {
9767       goto FAF_LOOP;
9768     }//if
9769     updateApiStateFail(signal);
9770   }//if
9771 }//Dbtc::findApiConnectFail()
9772 
9773 /*----------------------------------------------------------*/
9774 /*       FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW  */
9775 /*----------------------------------------------------------*/
findTcConnectFail(Signal * signal,Uint32 instanceKey)9776 void Dbtc::findTcConnectFail(Signal* signal, Uint32 instanceKey)
9777 {
9778   UintR tftfHashNumber;
9779 
9780   tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
9781   tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
9782   do {
9783     if (tcConnectptr.i == RNIL) {
9784       jam();
9785       if (cfirstfreeTcConnectFail == RNIL) {
9786         jam();
9787         systemErrorLab(signal, __LINE__);
9788         return;
9789       }//if
9790       seizeTcConnectFail(signal);
9791       linkTcInConnectionlist(signal);
9792       tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
9793       ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
9794       initTcConnectFail(signal, instanceKey);
9795       return;
9796     } else {
9797       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9798       if (tcConnectptr.p->tcOprec != ttcOprec) {
9799         jam();  /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
9800         tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
9801       } else {
9802         updateTcStateFail(signal, instanceKey);
9803         return;
9804       }//if
9805     }//if
9806   } while (1);
9807 }//Dbtc::findTcConnectFail()
9808 
9809 /*----------------------------------------------------------*/
9810 /*       INITIALISE AN API CONNECT FAIL RECORD              */
9811 /*----------------------------------------------------------*/
initApiConnectFail(Signal * signal)9812 void Dbtc::initApiConnectFail(Signal* signal)
9813 {
9814   apiConnectptr.p->transid[0] = ttransid1;
9815   apiConnectptr.p->transid[1] = ttransid2;
9816   apiConnectptr.p->firstTcConnect = RNIL;
9817   apiConnectptr.p->currSavePointId = 0;
9818   apiConnectptr.p->lastTcConnect = RNIL;
9819   tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
9820 
9821   apiConnectptr.p->tcBlockref = tblockref;
9822   apiConnectptr.p->ndbapiBlockref = 0;
9823   apiConnectptr.p->ndbapiConnect = 0;
9824   apiConnectptr.p->buddyPtr = RNIL;
9825   apiConnectptr.p->m_transaction_nodes.clear();
9826   apiConnectptr.p->singleUserMode = 0;
9827   setApiConTimer(apiConnectptr.i, 0, __LINE__);
9828   switch(ttransStatus){
9829   case LqhTransConf::Committed:
9830     jam();
9831     apiConnectptr.p->globalcheckpointid = tgci;
9832     apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
9833     break;
9834   case LqhTransConf::Prepared:
9835     jam();
9836     apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
9837     break;
9838   case LqhTransConf::Aborted:
9839     jam();
9840     apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
9841     break;
9842   case LqhTransConf::Marker:
9843     jam();
9844     apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
9845     break;
9846   default:
9847     jam();
9848     systemErrorLab(signal, __LINE__);
9849   }//if
9850   apiConnectptr.p->commitAckMarker = RNIL;
9851   if(LqhTransConf::getMarkerFlag(treqinfo)){
9852     jam();
9853     CommitAckMarkerPtr tmp;
9854     m_commitAckMarkerHash.seize(tmp);
9855 
9856     ndbrequire(tmp.i != RNIL);
9857 
9858     apiConnectptr.p->commitAckMarker = tmp.i;
9859     tmp.p->transid1      = ttransid1;
9860     tmp.p->transid2      = ttransid2;
9861     tmp.p->apiNodeId     = refToNode(tapplRef);
9862     tmp.p->m_commit_ack_marker_nodes.clear();
9863     tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
9864     tmp.p->apiConnectPtr = apiConnectptr.i;
9865 
9866 #if defined VM_TRACE || defined ERROR_INSERT
9867     {
9868       CommitAckMarkerPtr check;
9869       ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
9870     }
9871 #endif
9872     m_commitAckMarkerHash.add(tmp);
9873   }
9874 }//Dbtc::initApiConnectFail()
9875 
9876 /*------------------------------------------------------------*/
9877 /*       INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
9878 /*       THE TC CONNECT RECORD.                               */
9879 /*------------------------------------------------------------*/
initTcConnectFail(Signal * signal,Uint32 instanceKey)9880 void Dbtc::initTcConnectFail(Signal* signal, Uint32 instanceKey)
9881 {
9882   tcConnectptr.p->apiConnect = apiConnectptr.i;
9883   tcConnectptr.p->tcOprec = ttcOprec;
9884   Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
9885   for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
9886     tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
9887   }//for
9888   tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
9889   tcConnectptr.p->failData[treplicaNo] = ttransStatus;
9890   tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
9891   tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
9892   tcConnectptr.p->lqhInstanceKey = instanceKey;
9893 
9894 }//Dbtc::initTcConnectFail()
9895 
9896 /*----------------------------------------------------------*/
9897 /*       INITIALISE TC NODE FAIL RECORD.                    */
9898 /*----------------------------------------------------------*/
initTcFail(Signal * signal)9899 void Dbtc::initTcFail(Signal* signal)
9900 {
9901   tcNodeFailptr.i = 0;
9902   ptrAss(tcNodeFailptr, tcFailRecord);
9903   tcNodeFailptr.p->queueIndex = 0;
9904   tcNodeFailptr.p->failStatus = FS_IDLE;
9905 }//Dbtc::initTcFail()
9906 
9907 /*----------------------------------------------------------*/
9908 /*               RELEASE_TAKE_OVER                          */
9909 /*----------------------------------------------------------*/
releaseTakeOver(Signal * signal)9910 void Dbtc::releaseTakeOver(Signal* signal)
9911 {
9912   TcConnectRecordPtr rtoNextTcConnectptr;
9913 
9914   rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
9915   do {
9916     jam();
9917     tcConnectptr.i = rtoNextTcConnectptr.i;
9918     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9919     rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
9920     releaseTcConnectFail(signal);
9921   } while (rtoNextTcConnectptr.i != RNIL);
9922   releaseApiConnectFail(signal);
9923 }//Dbtc::releaseTakeOver()
9924 
9925 /*---------------------------------------------------------------------------*/
9926 /*                               SETUP_FAIL_DATA                             */
9927 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE      */
9928 /* FAILURE SITUATIONS.                                                       */
9929 /*---------------------------------------------------------------------------*/
setupFailData(Signal * signal)9930 void Dbtc::setupFailData(Signal* signal)
9931 {
9932   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
9933   do {
9934     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9935     switch (tcConnectptr.p->tcConnectstate) {
9936     case OS_PREPARED:
9937     case OS_COMMITTING:
9938       jam();
9939       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9940       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9941 	jam();
9942 	/*-------------------------------------------------------------------
9943 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9944 	 * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
9945 	 * COMMIT/ABORT DECISION.
9946 	 *------------------------------------------------------------------*/
9947 	tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
9948       }//for
9949       break;
9950     case OS_COMMITTED:
9951     case OS_COMPLETING:
9952       jam();
9953       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9954       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9955 	jam();
9956 	/*-------------------------------------------------------------------
9957 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9958 	 * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
9959 	 * COMPLETE MESSAGE.
9960 	 *------------------------------------------------------------------*/
9961 	tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
9962       }//for
9963       break;
9964     case OS_COMPLETED:
9965       jam();
9966       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
9967       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
9968 	jam();
9969 	/*-------------------------------------------------------------------
9970 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
9971 	 * IN THIS CASE ALL LQH'S ARE COMPLETED.
9972 	 *-------------------------------------------------------------------*/
9973 	tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
9974       }//for
9975       break;
9976     default:
9977       jam();
9978       sendSystemError(signal, __LINE__);
9979       break;
9980     }//switch
9981     if (tabortInd != ZCOMMIT_SETUP) {
9982       jam();
9983       for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
9984         hostptr.i = tcConnectptr.p->tcNodedata[Ti];
9985         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9986         if (hostptr.p->hostStatus != HS_ALIVE) {
9987           jam();
9988 	  /*-----------------------------------------------------------------
9989 	   * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
9990 	   *-----------------------------------------------------------------*/
9991           tabortInd = ZTRUE;
9992         }//if
9993       }//for
9994     }//if
9995     tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
9996     tcConnectptr.p->tcOprec = tcConnectptr.i;
9997     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
9998   } while (tcConnectptr.i != RNIL);
9999   apiConnectptr.p->tcBlockref = cownref;
10000   apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
10001   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10002   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10003   apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
10004   tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
10005 }//Dbtc::setupFailData()
10006 
10007 /*----------------------------------------------------------*/
10008 /*       UPDATE THE STATE OF THE API CONNECT FOR THIS PART.   */
10009 /*----------------------------------------------------------*/
updateApiStateFail(Signal * signal)10010 void Dbtc::updateApiStateFail(Signal* signal)
10011 {
10012   if(LqhTransConf::getMarkerFlag(treqinfo))
10013   {
10014     CommitAckMarkerPtr tmp;
10015     const Uint32 marker = apiConnectptr.p->commitAckMarker;
10016     if (marker == RNIL)
10017     {
10018       jam();
10019 
10020       m_commitAckMarkerHash.seize(tmp);
10021       ndbrequire(tmp.i != RNIL);
10022 
10023       apiConnectptr.p->commitAckMarker = tmp.i;
10024       tmp.p->transid1      = ttransid1;
10025       tmp.p->transid2      = ttransid2;
10026       tmp.p->apiNodeId     = refToNode(tapplRef);
10027       tmp.p->apiConnectPtr = apiConnectptr.i;
10028       tmp.p->m_commit_ack_marker_nodes.clear();
10029 #if defined VM_TRACE || defined ERROR_INSERT
10030       {
10031 	CommitAckMarkerPtr check;
10032 	ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
10033       }
10034 #endif
10035       m_commitAckMarkerHash.add(tmp);
10036     } else {
10037       jam();
10038       tmp.i = marker;
10039       tmp.p = m_commitAckMarkerHash.getPtr(marker);
10040 
10041       ndbassert(tmp.p->transid1 == ttransid1);
10042       ndbassert(tmp.p->transid2 == ttransid2);
10043     }
10044     tmp.p->m_commit_ack_marker_nodes.set(tnodeid);
10045   }
10046 
10047   switch (ttransStatus) {
10048   case LqhTransConf::Committed:
10049     jam();
10050     switch (apiConnectptr.p->apiConnectstate) {
10051     case CS_FAIL_COMMITTING:
10052     case CS_FAIL_COMMITTED:
10053       jam();
10054       ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
10055       break;
10056     case CS_FAIL_PREPARED:
10057       jam();
10058       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
10059       apiConnectptr.p->globalcheckpointid = tgci;
10060       break;
10061     case CS_FAIL_COMPLETED:
10062       jam();
10063       apiConnectptr.p->globalcheckpointid = tgci;
10064       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
10065       break;
10066     default:
10067       jam();
10068       systemErrorLab(signal, __LINE__);
10069       break;
10070     }//switch
10071     break;
10072   case LqhTransConf::Prepared:
10073     jam();
10074     switch (apiConnectptr.p->apiConnectstate) {
10075     case CS_FAIL_COMMITTED:
10076       jam();
10077       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
10078       break;
10079     case CS_FAIL_ABORTED:
10080       jam();
10081       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
10082       break;
10083     case CS_FAIL_COMMITTING:
10084     case CS_FAIL_PREPARED:
10085     case CS_FAIL_ABORTING:
10086       jam();
10087       /*empty*/;
10088       break;
10089     default:
10090       jam();
10091       systemErrorLab(signal, __LINE__);
10092       break;
10093     }//switch
10094     break;
10095   case LqhTransConf::Aborted:
10096     jam();
10097     switch (apiConnectptr.p->apiConnectstate) {
10098     case CS_FAIL_COMMITTING:
10099     case CS_FAIL_COMMITTED:
10100       jam();
10101       systemErrorLab(signal, __LINE__);
10102       break;
10103     case CS_FAIL_PREPARED:
10104       jam();
10105       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
10106       break;
10107     case CS_FAIL_ABORTING:
10108     case CS_FAIL_ABORTED:
10109       jam();
10110       /*empty*/;
10111       break;
10112     default:
10113       jam();
10114       systemErrorLab(signal, __LINE__);
10115       break;
10116     }//switch
10117     break;
10118   case LqhTransConf::Marker:
10119     jam();
10120     break;
10121   default:
10122     jam();
10123     systemErrorLab(signal, __LINE__);
10124     break;
10125   }//switch
10126 }//Dbtc::updateApiStateFail()
10127 
10128 /*------------------------------------------------------------*/
10129 /*               UPDATE_TC_STATE_FAIL                         */
10130 /*                                                            */
10131 /*       WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
10132 /*       WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY      */
10133 /*       BETWEEN THE DIFFERENT REPLICAS.                      */
10134 /*------------------------------------------------------------*/
updateTcStateFail(Signal * signal,Uint32 instanceKey)10135 void Dbtc::updateTcStateFail(Signal* signal, Uint32 instanceKey)
10136 {
10137   const Uint8 treplicaNo     = LqhTransConf::getReplicaNo(treqinfo);
10138   const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
10139   const Uint8 tdirtyOp       = LqhTransConf::getDirtyFlag(treqinfo);
10140 
10141   TcConnectRecord * regTcPtr = tcConnectptr.p;
10142 
10143   ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
10144   ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
10145   ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
10146   ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
10147 
10148   regTcPtr->tcNodedata[treplicaNo] = tnodeid;
10149   regTcPtr->failData[treplicaNo] = ttransStatus;
10150   ndbrequire(regTcPtr->lqhInstanceKey == instanceKey)
10151 }//Dbtc::updateTcStateFail()
10152 
execTCGETOPSIZEREQ(Signal * signal)10153 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
10154 {
10155   jamEntry();
10156   CRASH_INSERTION(8000);
10157 
10158   UintR Tuserpointer = signal->theData[0];         /* DBDIH POINTER         */
10159   BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
10160   signal->theData[0] = Tuserpointer;
10161   signal->theData[1] = coperationsize;
10162   sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
10163 }//Dbtc::execTCGETOPSIZEREQ()
10164 
execTC_CLOPSIZEREQ(Signal * signal)10165 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
10166 {
10167   jamEntry();
10168   CRASH_INSERTION(8001);
10169 
10170   tuserpointer = signal->theData[0];
10171   tusersblkref = signal->theData[1];
10172                                             /* DBDIH BLOCK REFERENCE         */
10173   coperationsize = 0;
10174   signal->theData[0] = tuserpointer;
10175   sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
10176 }//Dbtc::execTC_CLOPSIZEREQ()
10177 
10178 /* ######################################################################### */
10179 /* #######                        ERROR MODULE                       ####### */
10180 /* ######################################################################### */
tabStateErrorLab(Signal * signal)10181 void Dbtc::tabStateErrorLab(Signal* signal)
10182 {
10183   terrorCode = ZSTATE_ERROR;
10184   releaseAtErrorLab(signal);
10185 }//Dbtc::tabStateErrorLab()
10186 
wrongSchemaVersionErrorLab(Signal * signal)10187 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
10188 {
10189   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
10190 
10191   TableRecordPtr tabPtr;
10192   tabPtr.i = tcKeyReq->tableId;
10193   const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
10194   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
10195 
10196   terrorCode = tabPtr.p->getErrorCode(schemVer);
10197 
10198   abortErrorLab(signal);
10199 }//Dbtc::wrongSchemaVersionErrorLab()
10200 
noFreeConnectionErrorLab(Signal * signal)10201 void Dbtc::noFreeConnectionErrorLab(Signal* signal)
10202 {
10203   terrorCode = ZNO_FREE_TC_CONNECTION;
10204   abortErrorLab(signal);        /* RECORD. OTHERWISE GOTO ERRORHANDLING  */
10205 }//Dbtc::noFreeConnectionErrorLab()
10206 
aiErrorLab(Signal * signal)10207 void Dbtc::aiErrorLab(Signal* signal)
10208 {
10209   terrorCode = ZLENGTH_ERROR;
10210   abortErrorLab(signal);
10211 }//Dbtc::aiErrorLab()
10212 
seizeDatabuferrorLab(Signal * signal)10213 void Dbtc::seizeDatabuferrorLab(Signal* signal)
10214 {
10215   terrorCode = ZGET_DATAREC_ERROR;
10216   releaseAtErrorLab(signal);
10217 }//Dbtc::seizeDatabuferrorLab()
10218 
appendToSectionErrorLab(Signal * signal)10219 void Dbtc::appendToSectionErrorLab(Signal* signal)
10220 {
10221   terrorCode = ZGET_DATAREC_ERROR;
10222   releaseAtErrorLab(signal);
10223 }//Dbtc::appendToSectionErrorLab
10224 
releaseAtErrorLab(Signal * signal)10225 void Dbtc::releaseAtErrorLab(Signal* signal)
10226 {
10227   ptrGuard(tcConnectptr);
10228   tcConnectptr.p->tcConnectstate = OS_ABORTING;
10229   /*-------------------------------------------------------------------------*
10230    * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
10231    * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
10232    * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
10233    * TO HANDLE THIS PROBLEM.
10234    * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
10235    * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
10236    * ANY SIGNALS.
10237    *-------------------------------------------------------------------------*/
10238   tcConnectptr.p->noOfNodes = 0;
10239   abortErrorLab(signal);
10240 }//Dbtc::releaseAtErrorLab()
10241 
warningHandlerLab(Signal * signal,int line)10242 void Dbtc::warningHandlerLab(Signal* signal, int line)
10243 {
10244   ndbassert(false);
10245 }//Dbtc::warningHandlerLab()
10246 
systemErrorLab(Signal * signal,int line)10247 void Dbtc::systemErrorLab(Signal* signal, int line)
10248 {
10249   progError(line, NDBD_EXIT_NDBREQUIRE);
10250 }//Dbtc::systemErrorLab()
10251 
10252 
10253 #ifdef ERROR_INSERT
testFragmentDrop(Signal * signal)10254 bool Dbtc::testFragmentDrop(Signal* signal)
10255 {
10256   Uint32 fragIdToDrop= ~0;
10257   /* Drop some fragments to test the dropped fragment handling code */
10258   if (ERROR_INSERTED(8074))
10259     fragIdToDrop= 1;
10260   else if (ERROR_INSERTED(8075))
10261     fragIdToDrop= 2;
10262   else if (ERROR_INSERTED(8076))
10263     fragIdToDrop= 3;
10264 
10265   if ((signal->header.m_fragmentInfo == fragIdToDrop) ||
10266       ERROR_INSERTED(8077)) // Drop all fragments
10267   {
10268     /* This signal fragment should be dropped
10269      * Let's throw away the sections, and call the
10270      * signal dropped report handler
10271      * This code is replicating the effect of the code in
10272      * TransporterCallback::deliver_signal()
10273      */
10274     SectionHandle handle(this, signal);
10275     Uint32 secCount= handle.m_cnt;
10276     releaseSections(handle);
10277     SignalDroppedRep* rep = (SignalDroppedRep*)signal->theData;
10278     Uint32 gsn = signal->header.theVerId_signalNumber;
10279     Uint32 len = signal->header.theLength;
10280     Uint32 newLen= (len > 22 ? 22 : len);
10281     memmove(rep->originalData, signal->theData, (4 * newLen));
10282     rep->originalGsn = gsn;
10283     rep->originalLength = len;
10284     rep->originalSectionCount = secCount;
10285     signal->header.theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
10286     signal->header.theLength = newLen + 3;
10287     signal->header.m_noOfSections = 0;
10288 
10289     executeFunction(GSN_SIGNAL_DROPPED_REP, signal);
10290     return true;
10291   }
10292   return false;
10293 }
10294 #endif
10295 
10296 /* ######################################################################### *
10297  * #######                        SCAN MODULE                        ####### *
10298  * ######################################################################### *
10299 
10300   The application orders a scan of a table.  We divide the scan into a scan on
10301   each fragment.  The scan uses the primary replicas since the scan might be
10302   used for an update in a separate transaction.
10303 
10304   Scans are always done as a separate transaction.  Locks from the scan
10305   can be overtaken by another transaction.  Scans can never lock the entire
10306   table.  Locks are released immediately after the read has been verified
10307   by the application. There is not even an option to leave the locks.
10308   The reason is that this would hurt real-time behaviour too much.
10309 
10310   -#  The first step in handling a scan of a table is to receive all signals
10311       defining the scan. If failures occur during this step we release all
10312       resource and reply with SCAN_TABREF providing the error code.
10313       If system load is too high, the request will not be allowed.
10314 
10315   -#  The second step retrieves the number of fragments that exist in the
10316       table. It also ensures that the table actually exist.  After this,
10317       the scan is ready to be parallelised.  The idea is that the receiving
10318       process (hereafter called delivery process) will start up a number
10319       of scan processes.  Each of these scan processes will
10320       independently scan one fragment at a time.  The delivery
10321       process object is the scan record and the scan process object is
10322       the scan fragment record plus the scan operation record.
10323 
10324   -#  The third step is thus performed in parallel. In the third step each
10325       scan process retrieves the primary replica of the fragment it will
10326       scan.  Then it starts the scan as soon as the load on that node permits.
10327 
10328   The LQH returns either when it retrieved the maximum number of tuples or
10329   when it has retrived at least one tuple and is hindered by a lock to
10330   retrieve the next tuple.  This is to ensure that a scan process never
10331   can be involved in a deadlock situation.
10332 
10333   Tuples from each fragment scan are sent directly to API from TUP, and tuples
10334   from different fragments are delivered in parallel (so will be interleaved
10335   when received).
10336 
10337   When a batch of tuples from one fragment has been fully fetched, the scan of
10338   that fragment will not continue until the previous batch has been
10339   acknowledged by API with a SCAN_NEXTREQ signal.
10340 
10341 
10342   ERROR HANDLING
10343 
10344   As already mentioned it is rather easy to handle errors before the scan
10345   processes have started.  In this case it is enough to release the resources
10346   and send SCAN_TAB_REF.
10347 
10348   If an error occurs in any of the scan processes then we have to stop all
10349   scan processes. We do however only stop the delivery process and ask
10350   the api to order us to close the scan.  The reason is that we can easily
10351   enter into difficult timing problems since the application and this
10352   block is out of synch we will thus always start by report the error to
10353   the application and wait for a close request. This error report uses the
10354   SCAN_TABREF signal with a special error code that the api must check for.
10355 
10356 
10357   CLOSING AN ACTIVE SCAN
10358 
10359   The application can close a scan for several reasons before it is completed.
10360   One reason was mentioned above where an error in a scan process led to a
10361   request to close the scan. Another reason could simply be that the
10362   application found what it looked for and is thus not interested in the
10363   rest of the scan.
10364 
10365   IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
10366 
10367   When a close scan request is received, all scan processes are stopped and all
10368   resources belonging to those scan processes are released. Stopping the scan
10369   processes most often includes communication with an LQH where the local scan
10370   is controlled. Finally all resources belonging to the scan is released and
10371   the SCAN_TABCONF is sent with an indication of that the scan is closed.
10372 
10373 
10374   CLOSING A COMPLETED SCAN
10375 
10376   When all scan processes are completed then a report is sent to the
10377   application which indicates that no more tuples can be fetched.
10378   The application will send a close scan and the same action as when
10379   closing an active scan is performed.
10380   In this case it will of course not find any active scan processes.
10381   It will even find all scan processes already released.
10382 
10383   The reason for requiring the api to close the scan is the same as above.
10384   It is to avoid any timing problems due to that the api and this block
10385   is out of synch.
10386 
10387   * ######################################################################## */
execSCAN_TABREQ(Signal * signal)10388 void Dbtc::execSCAN_TABREQ(Signal* signal)
10389 {
10390   jamEntry();
10391 
10392 #ifdef ERROR_INSERT
10393   /* Test fragmented + dropped signal handling */
10394   if (ERROR_INSERTED(8074) ||
10395       ERROR_INSERTED(8075) ||
10396       ERROR_INSERTED(8076) ||
10397       ERROR_INSERTED(8077))
10398   {
10399     jam();
10400     if (testFragmentDrop(signal)) {
10401       jam();
10402       return;
10403     }
10404   } /* End of test fragmented + dropped signal handling */
10405 #endif
10406 
10407   /* Reassemble if the request was fragmented */
10408   if (!assembleFragments(signal)){
10409     jam();
10410     return;
10411   }
10412 
10413   const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
10414   const Uint32 ri = scanTabReq->requestInfo;
10415   const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
10416   const Uint32 transid1 = scanTabReq->transId1;
10417   const Uint32 transid2 = scanTabReq->transId2;
10418   const Uint32 tmpXX = scanTabReq->buddyConPtr;
10419   const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
10420   Uint32 currSavePointId = 0;
10421 
10422   Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
10423   Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
10424   Uint32 scanParallel = scanConcurrency;
10425   Uint32 errCode;
10426   ScanRecordPtr scanptr;
10427 
10428   /* Short SCANTABREQ has 1 section, Long has 2 or 3.
10429    * Section 0 : NDBAPI receiver ids (Mandatory)
10430    * Section 1 : ATTRINFO section (Mandatory for long SCAN_TABREQ
10431    * Section 2 : KEYINFO section (Optional for long SCAN_TABREQ
10432    */
10433   Uint32 numSections= signal->getNoOfSections();
10434   ndbassert( numSections >= 1 );
10435   bool isLongReq= numSections >= 2;
10436 
10437   SectionHandle handle(this, signal);
10438   SegmentedSectionPtr api_op_ptr;
10439   handle.getSection(api_op_ptr, 0);
10440   copy(&cdata[0], api_op_ptr);
10441 
10442   Uint32 aiLength= 0;
10443   Uint32 keyLen= 0;
10444 
10445   if (likely(isLongReq))
10446   {
10447     SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
10448     /* Long SCANTABREQ, determine Ai and Key length from sections */
10449     handle.getSection(attrInfoPtr, ScanTabReq::AttrInfoSectionNum);
10450     aiLength= attrInfoPtr.sz;
10451     if (numSections == 3)
10452     {
10453       handle.getSection(keyInfoPtr, ScanTabReq::KeyInfoSectionNum);
10454       keyLen= keyInfoPtr.sz;
10455     }
10456   }
10457   else
10458   {
10459     /* Short SCANTABREQ, get Ai and Key length from signal */
10460     aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
10461     keyLen = scanTabReq->attrLenKeyLen >> 16;
10462   }
10463 
10464 
10465   apiConnectptr.i = scanTabReq->apiConnectPtr;
10466   tabptr.i = scanTabReq->tableId;
10467 
10468   if (apiConnectptr.i >= capiConnectFilesize)
10469   {
10470     jam();
10471     releaseSections(handle);
10472     warningHandlerLab(signal, __LINE__);
10473     return;
10474   }//if
10475 
10476   ptrAss(apiConnectptr, apiConnectRecord);
10477   ApiConnectRecord * transP = apiConnectptr.p;
10478 
10479   if (transP->apiConnectstate != CS_CONNECTED) {
10480     jam();
10481     // could be left over from TCKEYREQ rollback
10482     if (transP->apiConnectstate == CS_ABORTING &&
10483 	transP->abortState == AS_IDLE) {
10484       jam();
10485     } else if(transP->apiConnectstate == CS_STARTED &&
10486 	      transP->firstTcConnect == RNIL){
10487       jam();
10488       // left over from simple/dirty read
10489     } else {
10490       jam();
10491       jamLine(transP->apiConnectstate);
10492       errCode = ZSTATE_ERROR;
10493       goto SCAN_TAB_error_no_state_change;
10494     }
10495   }
10496 
10497   if(tabptr.i >= ctabrecFilesize)
10498   {
10499     errCode = ZUNKNOWN_TABLE_ERROR;
10500     goto SCAN_TAB_error;
10501   }
10502 
10503   ptrAss(tabptr, tableRecord);
10504   if ((aiLength == 0) ||
10505       (!tabptr.p->checkTable(schemaVersion)) ||
10506       (scanConcurrency == 0) ||
10507       (cfirstfreeTcConnect == RNIL) ||
10508       (cfirstfreeScanrec == RNIL)) {
10509     goto SCAN_error_check;
10510   }
10511   if (buddyPtr != RNIL) {
10512     jam();
10513     ApiConnectRecordPtr buddyApiPtr;
10514     buddyApiPtr.i = buddyPtr;
10515     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
10516     if ((transid1 == buddyApiPtr.p->transid[0]) &&
10517 	(transid2 == buddyApiPtr.p->transid[1])) {
10518       jam();
10519 
10520       if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
10521 	// transaction has been aborted
10522 	jam();
10523 	errCode = buddyApiPtr.p->returncode;
10524 	goto SCAN_TAB_error;
10525       }//if
10526       currSavePointId = buddyApiPtr.p->currSavePointId;
10527       buddyApiPtr.p->currSavePointId++;
10528     }
10529   }
10530 
10531   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
10532       getNodeState().getSingleUserApi() !=
10533       refToNode(apiConnectptr.p->ndbapiBlockref))
10534   {
10535     errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
10536     goto SCAN_TAB_error;
10537   }
10538 
10539   seizeTcConnect(signal);
10540   tcConnectptr.p->apiConnect = apiConnectptr.i;
10541   tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
10542   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
10543 
10544   seizeCacheRecord(signal);
10545 
10546   if (likely(isLongReq))
10547   {
10548     /* We keep the AttrInfo and KeyInfo sections */
10549     cachePtr.p->attrInfoSectionI= handle.m_ptr[ScanTabReq::AttrInfoSectionNum].i;
10550     if (keyLen)
10551       cachePtr.p->keyInfoSectionI= handle.m_ptr[ScanTabReq::KeyInfoSectionNum].i;
10552   }
10553 
10554   releaseSection(handle.m_ptr[ScanTabReq::ReceiverIdSectionNum].i);
10555   handle.clear();
10556 
10557   cachePtr.p->keylen = keyLen;
10558   cachePtr.p->save1 = 0;
10559   cachePtr.p->distributionKey = scanTabReq->distributionKey;
10560   cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
10561   scanptr = seizeScanrec(signal);
10562 
10563   ndbrequire(transP->apiScanRec == RNIL);
10564   ndbrequire(scanptr.p->scanApiRec == RNIL);
10565 
10566   errCode = initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag, aiLength, keyLen);
10567   if (unlikely(errCode))
10568   {
10569     jam();
10570     goto SCAN_TAB_error;
10571   }
10572 
10573   transP->apiScanRec = scanptr.i;
10574   transP->returncode = 0;
10575   transP->transid[0] = transid1;
10576   transP->transid[1] = transid2;
10577   transP->buddyPtr   = buddyPtr;
10578 
10579   // The scan is started
10580   transP->apiConnectstate = CS_START_SCAN;
10581   transP->currSavePointId = currSavePointId;
10582 
10583   /**********************************************************
10584   * We start the timer on scanRec to be able to discover a
10585   * timeout in the API the API now is in charge!
10586   ***********************************************************/
10587   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10588   updateBuddyTimer(apiConnectptr);
10589 
10590   /***********************************************************
10591    * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
10592    * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
10593    * IF ANY TO RECEIVE.
10594    **********************************************************/
10595   scanptr.p->scanState = ScanRecord::WAIT_AI;
10596 
10597   if (ERROR_INSERTED(8038))
10598   {
10599     /**
10600      * Force API_FAILREQ
10601      */
10602     DisconnectRep * const  rep = (DisconnectRep *)signal->getDataPtrSend();
10603     rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
10604     rep->err = 8038;
10605 
10606     sendSignal(CMVMI_REF, GSN_DISCONNECT_REP, signal, 2, JBA);
10607     CLEAR_ERROR_INSERT_VALUE;
10608   }
10609 
10610   if (isLongReq)
10611   {
10612     /* All AttrInfo (and KeyInfo) has been received, continue
10613      * processing
10614      */
10615     diFcountReqLab(signal, scanptr);
10616   }
10617 
10618   return;
10619 
10620  SCAN_error_check:
10621   if (aiLength == 0) {
10622     jam();
10623     errCode = ZSCAN_AI_LEN_ERROR;
10624     goto SCAN_TAB_error;
10625   }//if
10626   if (!tabptr.p->checkTable(schemaVersion)){
10627     jam();
10628     errCode = tabptr.p->getErrorCode(schemaVersion);
10629     goto SCAN_TAB_error;
10630   }//if
10631   if (scanConcurrency == 0) {
10632     jam();
10633     errCode = ZNO_CONCURRENCY_ERROR;
10634     goto SCAN_TAB_error;
10635   }//if
10636   if (cfirstfreeTcConnect == RNIL) {
10637     jam();
10638     errCode = ZNO_FREE_TC_CONNECTION;
10639     goto SCAN_TAB_error;
10640   }//if
10641   ndbrequire(cfirstfreeScanrec == RNIL);
10642   jam();
10643   errCode = ZNO_SCANREC_ERROR;
10644   goto SCAN_TAB_error;
10645 
10646 SCAN_TAB_error:
10647   jam();
10648   /**
10649    * Prepare for up coming ATTRINFO/KEYINFO
10650    */
10651   transP->apiConnectstate = CS_ABORTING;
10652   transP->abortState = AS_IDLE;
10653   transP->transid[0] = transid1;
10654   transP->transid[1] = transid2;
10655 
10656 SCAN_TAB_error_no_state_change:
10657 
10658   releaseSections(handle);
10659 
10660   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
10661   ref->apiConnectPtr = transP->ndbapiConnect;
10662   ref->transId1 = transid1;
10663   ref->transId2 = transid2;
10664   ref->errorCode  = errCode;
10665   ref->closeNeeded = 0;
10666   sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
10667 	     signal, ScanTabRef::SignalLength, JBB);
10668   return;
10669 }//Dbtc::execSCAN_TABREQ()
10670 
10671 Uint32
initScanrec(ScanRecordPtr scanptr,const ScanTabReq * scanTabReq,UintR scanParallel,UintR noOprecPerFrag,Uint32 aiLength,Uint32 keyLength)10672 Dbtc::initScanrec(ScanRecordPtr scanptr,
10673 		  const ScanTabReq * scanTabReq,
10674 		  UintR scanParallel,
10675 		  UintR noOprecPerFrag,
10676 		  Uint32 aiLength,
10677 		  Uint32 keyLength)
10678 {
10679   const UintR ri = scanTabReq->requestInfo;
10680   scanptr.p->scanTcrec = tcConnectptr.i;
10681   scanptr.p->scanApiRec = apiConnectptr.i;
10682   scanptr.p->scanAiLength = aiLength;
10683   scanptr.p->scanKeyLen = keyLength;
10684   scanptr.p->scanTableref = tabptr.i;
10685   scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
10686   scanptr.p->scanParallel = scanParallel;
10687   scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
10688   scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
10689   scanptr.p->batch_size_rows = noOprecPerFrag;
10690   scanptr.p->m_scan_block_no = DBLQH;
10691 
10692   Uint32 tmp = 0;
10693   ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
10694   ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
10695   ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
10696   ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
10697   ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
10698   ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
10699   ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
10700   ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
10701   if (ScanTabReq::getViaSPJFlag(ri))
10702   {
10703     jam();
10704     scanptr.p->m_scan_block_no = DBSPJ;
10705   }
10706 
10707   scanptr.p->scanRequestInfo = tmp;
10708   scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
10709   scanptr.p->scanState = ScanRecord::RUNNING;
10710   scanptr.p->m_queued_count = 0;
10711   scanptr.p->m_scan_cookie = RNIL;
10712   scanptr.p->m_close_scan_req = false;
10713   scanptr.p->m_pass_all_confs =  ScanTabReq::getPassAllConfsFlag(ri);
10714   scanptr.p->m_4word_conf = ScanTabReq::get4WordConf(ri);
10715 
10716   ScanFragList list(c_scan_frag_pool,
10717 		    scanptr.p->m_running_scan_frags);
10718   for (Uint32 i = 0; i < scanParallel; i++) {
10719     jam();
10720     ScanFragRecPtr ptr;
10721     if (unlikely(list.seize(ptr) == false))
10722     {
10723       jam();
10724       goto errout;
10725     }
10726     ptr.p->scanFragState = ScanFragRec::IDLE;
10727     ptr.p->scanRec = scanptr.i;
10728     ptr.p->scanFragId = 0;
10729     ptr.p->m_apiPtr = cdata[i];
10730   }//for
10731 
10732   (* (ScanTabReq::getRangeScanFlag(ri) ?
10733       &c_counters.c_range_scan_count :
10734       &c_counters.c_scan_count))++;
10735   return 0;
10736 errout:
10737   list.release();
10738   return ZSCAN_FRAGREC_ERROR;
10739 }//Dbtc::initScanrec()
10740 
scanTabRefLab(Signal * signal,Uint32 errCode)10741 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
10742 {
10743   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
10744   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
10745   ref->transId1 = apiConnectptr.p->transid[0];
10746   ref->transId2 = apiConnectptr.p->transid[1];
10747   ref->errorCode  = errCode;
10748   ref->closeNeeded = 0;
10749   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
10750 	     signal, ScanTabRef::SignalLength, JBB);
10751 }//Dbtc::scanTabRefLab()
10752 
10753 /**
10754  * scanKeyinfoLab
10755  * Handle reception of KeyInfo for a Scan
10756  */
scanKeyinfoLab(Signal * signal)10757 void Dbtc::scanKeyinfoLab(Signal* signal)
10758 {
10759   /* Receive KEYINFO for a SCAN operation
10760    * Note that old NDBAPI nodes sometimes send header-only KEYINFO signals
10761    */
10762   CacheRecord * const regCachePtr = cachePtr.p;
10763   UintR TkeyLen = regCachePtr->keylen;
10764   UintR Tlen = regCachePtr->save1;
10765 
10766   Uint32 wordsInSignal= MIN(KeyInfo::DataLength,
10767                             (TkeyLen - Tlen));
10768 
10769   ndbassert( signal->getLength() ==
10770              (KeyInfo::HeaderLength + wordsInSignal) );
10771 
10772   if (unlikely (! appendToSection(regCachePtr->keyInfoSectionI,
10773                                   &signal->theData[KeyInfo::HeaderLength],
10774                                   wordsInSignal)))
10775   {
10776     jam();
10777     seizeDatabuferrorLab(signal);
10778     return;
10779   }
10780 
10781   Tlen+= wordsInSignal;
10782   regCachePtr->save1 = Tlen;
10783 
10784   if (Tlen < TkeyLen)
10785   {
10786     jam();
10787     /* More KeyInfo still to come - continue waiting */
10788     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10789     return;
10790   }
10791 
10792   /* All KeyInfo has been received, we will now start receiving
10793    * ATTRINFO
10794    */
10795   jam();
10796   ndbassert(Tlen == TkeyLen);
10797   return;
10798 } // scanKeyinfoLab
10799 
10800 /*---------------------------------------------------------------------------*/
10801 /*                                                                           */
10802 /*       RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST.                       */
10803 /*---------------------------------------------------------------------------*/
scanAttrinfoLab(Signal * signal,UintR Tlen)10804 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
10805 {
10806   ScanRecordPtr scanptr;
10807   scanptr.i = apiConnectptr.p->apiScanRec;
10808   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10809   tcConnectptr.i = scanptr.p->scanTcrec;
10810   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10811   cachePtr.i = apiConnectptr.p->cachePtr;
10812   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10813   CacheRecord * const regCachePtr = cachePtr.p;
10814   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
10815 
10816   regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
10817 
10818   if (unlikely(! appendToSection(regCachePtr->attrInfoSectionI,
10819                                  &signal->theData[AttrInfo::HeaderLength],
10820                                  Tlen)))
10821   {
10822     jam();
10823     abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
10824     return;
10825   }
10826 
10827   if (regCachePtr->currReclenAi == scanptr.p->scanAiLength)
10828   {
10829     /* We have now received all the signals defining this
10830      * scan.  We are ready to start executing the scan
10831      */
10832     diFcountReqLab(signal, scanptr);
10833     return;
10834   }
10835   else if (unlikely (regCachePtr->currReclenAi > scanptr.p->scanAiLength))
10836   {
10837     jam();
10838     abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
10839     return;
10840   }
10841 
10842   /* Still some ATTRINFO to arrive...*/
10843   return;
10844 }//Dbtc::scanAttrinfoLab()
10845 
diFcountReqLab(Signal * signal,ScanRecordPtr scanptr)10846 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
10847 {
10848   /**
10849    * Check so that the table is not being dropped
10850    */
10851   TableRecordPtr tabPtr;
10852   tabPtr.i = scanptr.p->scanTableref;
10853   tabPtr.p = &tableRecord[tabPtr.i];
10854   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
10855     ;
10856   } else {
10857     abortScanLab(signal, scanptr,
10858 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
10859 		 true);
10860     return;
10861   }
10862 
10863   scanptr.p->scanNextFragId = 0;
10864   scanptr.p->m_booked_fragments_count= 0;
10865   scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
10866 
10867   /*************************************************
10868    * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
10869    ***************************************************/
10870   DihScanTabReq * req = (DihScanTabReq*)signal->getDataPtrSend();
10871   req->senderRef = reference();
10872   req->senderData = tcConnectptr.i;
10873   req->tableId = scanptr.p->scanTableref;
10874   req->schemaTransId = 0;
10875   sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_REQ, signal,
10876              DihScanTabReq::SignalLength, JBB);
10877   return;
10878 }//Dbtc::diFcountReqLab()
10879 
10880 /********************************************************************
10881  * execDI_FCOUNTCONF
10882  *
10883  * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
10884  * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
10885  * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
10886  * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
10887  * CLOSES THE SCAN.
10888  ********************************************************************/
execDIH_SCAN_TAB_CONF(Signal * signal)10889 void Dbtc::execDIH_SCAN_TAB_CONF(Signal* signal)
10890 {
10891   jamEntry();
10892   DihScanTabConf * conf = (DihScanTabConf*)signal->getDataPtr();
10893   tcConnectptr.i = conf->senderData;
10894   Uint32 tfragCount = conf->fragmentCount;
10895   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10896   apiConnectptr.i = tcConnectptr.p->apiConnect;
10897   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10898   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
10899   ScanRecordPtr scanptr;
10900   scanptr.i = regApiPtr->apiScanRec;
10901   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10902   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
10903   scanptr.p->m_scan_cookie = conf->scanCookie;
10904 
10905   if (conf->reorgFlag)
10906   {
10907     jam();
10908     ScanFragReq::setReorgFlag(scanptr.p->scanRequestInfo, 1);
10909   }
10910   if (regApiPtr->apiFailState == ZTRUE) {
10911     jam();
10912     releaseScanResources(signal, scanptr, true);
10913     handleApiFailState(signal, apiConnectptr.i);
10914     return;
10915   }//if
10916   if (tfragCount == 0) {
10917     jam();
10918     abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
10919     return;
10920   }//if
10921 
10922   /**
10923    * Check so that the table is not being dropped
10924    */
10925   TableRecordPtr tabPtr;
10926   tabPtr.i = scanptr.p->scanTableref;
10927   tabPtr.p = &tableRecord[tabPtr.i];
10928   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
10929     ;
10930   } else {
10931     abortScanLab(signal, scanptr,
10932 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
10933 		 true);
10934     return;
10935   }
10936 
10937   cachePtr.i = regApiPtr->cachePtr;
10938   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10939   CacheRecord * regCachePtrP = cachePtr.p;
10940 
10941   Uint32 version = getNodeInfo(refToNode(regApiPtr->ndbapiBlockref)).m_version;
10942   if (unlikely(!ndb_scan_distributionkey(version)))
10943   {
10944     jam();
10945     regCachePtrP->distributionKeyIndicator = 0;
10946   }
10947   if (regCachePtrP->distributionKeyIndicator)
10948   {
10949     jam();
10950     ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType) ||
10951                tabPtr.p->get_user_defined_partitioning());
10952 
10953     DiGetNodesReq * req = (DiGetNodesReq *)&signal->theData[0];
10954     const DiGetNodesConf * get_conf = (DiGetNodesConf *)&signal->theData[0];
10955     req->tableId = tabPtr.i;
10956     req->hashValue = cachePtr.p->distributionKey;
10957     req->distr_key_indicator = tabPtr.p->get_user_defined_partitioning();
10958     * (EmulatedJamBuffer**)req->jamBuffer = jamBuffer();
10959     EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal,
10960                    DiGetNodesReq::SignalLength, 0);
10961     UintR TerrorIndicator = signal->theData[0];
10962     jamEntry();
10963     if (TerrorIndicator != 0)
10964     {
10965       jam();
10966       abortScanLab(signal, scanptr,
10967                    signal->theData[1],
10968                    true);
10969       return;
10970     }
10971 
10972     scanptr.p->scanNextFragId = get_conf->fragId;
10973     tfragCount = 1;
10974   }
10975 
10976   scanptr.p->scanParallel = tfragCount;
10977   scanptr.p->scanNoFrag = tfragCount;
10978   scanptr.p->scanState = ScanRecord::RUNNING;
10979 
10980   setApiConTimer(apiConnectptr.i, 0, __LINE__);
10981   updateBuddyTimer(apiConnectptr);
10982 
10983   ScanFragRecPtr ptr;
10984   ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
10985   for (list.first(ptr); !ptr.isNull() && tfragCount;
10986        list.next(ptr), tfragCount--){
10987     jam();
10988 
10989     ptr.p->lqhBlockref = 0;
10990     ptr.p->startFragTimer(ctcTimer);
10991     ptr.p->scanFragId = scanptr.p->scanNextFragId++;
10992     ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
10993     ptr.p->startFragTimer(ctcTimer);
10994 
10995 
10996     DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
10997     req->senderRef = reference();
10998     req->senderData = ptr.i;
10999     req->tableId = scanptr.p->scanTableref;
11000     req->fragId = ptr.p->scanFragId;
11001     req->scanCookie = scanptr.p->m_scan_cookie;
11002     sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11003                DihScanGetNodesReq::SignalLength, JBB);
11004   }//for
11005 
11006   ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
11007   for (; !ptr.isNull();)
11008   {
11009     ptr.p->m_ops = 0;
11010     ptr.p->m_totalLen = 0;
11011     ptr.p->m_scan_frag_conf_status = 1;
11012     ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
11013     ptr.p->stopFragTimer();
11014 
11015     ScanFragRecPtr tmp;
11016     tmp.i = ptr.i;
11017     tmp.p = ptr.p;
11018     list.next(ptr);
11019     list.remove(tmp);
11020     queued.add(tmp);
11021     scanptr.p->m_queued_count++;
11022   }
11023 }//Dbtc::execDI_FCOUNTCONF()
11024 
11025 /******************************************************
11026  * execDI_FCOUNTREF
11027  ******************************************************/
execDIH_SCAN_TAB_REF(Signal * signal)11028 void Dbtc::execDIH_SCAN_TAB_REF(Signal* signal)
11029 {
11030   jamEntry();
11031   DihScanTabRef * ref = (DihScanTabRef*)signal->getDataPtr();
11032   tcConnectptr.i = ref->senderData;
11033   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11034   const Uint32 errCode = ref->error;
11035   apiConnectptr.i = tcConnectptr.p->apiConnect;
11036   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11037   ScanRecordPtr scanptr;
11038   scanptr.i = apiConnectptr.p->apiScanRec;
11039   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11040   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
11041   if (apiConnectptr.p->apiFailState == ZTRUE) {
11042     jam();
11043     releaseScanResources(signal, scanptr, true);
11044     handleApiFailState(signal, apiConnectptr.i);
11045     return;
11046   }//if
11047   abortScanLab(signal, scanptr, errCode, true);
11048 }//Dbtc::execDI_FCOUNTREF()
11049 
abortScanLab(Signal * signal,ScanRecordPtr scanptr,Uint32 errCode,bool not_started)11050 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
11051 			bool not_started)
11052 {
11053   scanTabRefLab(signal, errCode);
11054   releaseScanResources(signal, scanptr, not_started);
11055 }//Dbtc::abortScanLab()
11056 
releaseScanResources(Signal * signal,ScanRecordPtr scanPtr,bool not_started)11057 void Dbtc::releaseScanResources(Signal* signal,
11058                                 ScanRecordPtr scanPtr,
11059 				bool not_started)
11060 {
11061   if (apiConnectptr.p->cachePtr != RNIL) {
11062     cachePtr.i = apiConnectptr.p->cachePtr;
11063     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11064     releaseKeys();
11065     releaseAttrinfo();
11066   }//if
11067   tcConnectptr.i = scanPtr.p->scanTcrec;
11068   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11069   releaseTcCon();
11070 
11071   if (not_started)
11072   {
11073     jam();
11074     ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
11075     ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
11076     run.release();
11077     queue.release();
11078   }
11079 
11080   ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
11081   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
11082   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
11083 
11084   ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
11085   ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
11086 
11087   DihScanTabCompleteRep* rep = (DihScanTabCompleteRep*)signal->getDataPtrSend();
11088   rep->tableId = scanPtr.p->scanTableref;
11089   rep->scanCookie = scanPtr.p->m_scan_cookie;
11090   sendSignal(cdihblockref, GSN_DIH_SCAN_TAB_COMPLETE_REP,
11091 	     signal, DihScanTabCompleteRep::SignalLength, JBB);
11092 
11093   // link into free list
11094   scanPtr.p->nextScan = cfirstfreeScanrec;
11095   scanPtr.p->scanState = ScanRecord::IDLE;
11096   scanPtr.p->scanTcrec = RNIL;
11097   scanPtr.p->scanApiRec = RNIL;
11098   cfirstfreeScanrec = scanPtr.i;
11099 
11100   apiConnectptr.p->apiScanRec = RNIL;
11101   apiConnectptr.p->apiConnectstate = CS_CONNECTED;
11102   setApiConTimer(apiConnectptr.i, 0, __LINE__);
11103 }//Dbtc::releaseScanResources()
11104 
11105 
11106 /****************************************************************
11107  * execDIGETPRIMCONF
11108  *
11109  * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT.
11110  * WE ARE NOW READY TO ASK  FOR PERMISSION TO LOAD THIS
11111  * SPECIFIC NODE WITH A SCAN OPERATION.
11112  ****************************************************************/
execDIH_SCAN_GET_NODES_CONF(Signal * signal)11113 void Dbtc::execDIH_SCAN_GET_NODES_CONF(Signal* signal)
11114 {
11115   jamEntry();
11116   DihScanGetNodesConf * conf = (DihScanGetNodesConf*)signal->getDataPtr();
11117   scanFragptr.i = conf->senderData;
11118   c_scan_frag_pool.getPtr(scanFragptr);
11119 
11120   tnodeid = conf->nodes[0];
11121   arrGuard(tnodeid, MAX_NDB_NODES);
11122 
11123   if(ERROR_INSERTED(8050) && tnodeid != getOwnNodeId())
11124   {
11125     /* Asked to scan a fragment which is not on the same node as the
11126      * TC - transaction hinting / scan partition pruning has failed
11127      * Used by testPartitioning.cpp
11128      */
11129     CRASH_INSERTION(8050);
11130   }
11131 
11132   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
11133   scanFragptr.p->stopFragTimer();
11134 
11135   ScanRecordPtr scanptr;
11136   scanptr.i = scanFragptr.p->scanRec;
11137   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11138 
11139   /**
11140    * This must be false as select count(*) otherwise
11141    *   can "pass" committing on backup fragments and
11142    *   get incorrect row count
11143    */
11144   if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
11145   {
11146     jam();
11147     Uint32 nodeid = getOwnNodeId();
11148     for(Uint32 i = 1; i<conf->count; i++)
11149     {
11150       if(conf->nodes[i] ==  nodeid)
11151       {
11152 	jam();
11153 	tnodeid = nodeid;
11154 	break;
11155       }
11156     }
11157   }
11158 
11159   {
11160     /**
11161      * Check table
11162      */
11163     TableRecordPtr tabPtr;
11164     tabPtr.i = scanptr.p->scanTableref;
11165     ptrAss(tabPtr, tableRecord);
11166     Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
11167     if (ERROR_INSERTED(8081) || tabPtr.p->checkTable(schemaVersion) == false)
11168     {
11169       jam();
11170       Uint32 err;
11171       if (ERROR_INSERTED(8081))
11172       {
11173         err = ZTIME_OUT_ERROR;
11174         CLEAR_ERROR_INSERT_VALUE;
11175       }
11176       else
11177       {
11178         err = tabPtr.p->getErrorCode(schemaVersion);
11179       }
11180       {
11181         ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11182         run.release(scanFragptr);
11183       }
11184       scanError(signal, scanptr, err);
11185       return;
11186     }
11187   }
11188 
11189   tcConnectptr.i = scanptr.p->scanTcrec;
11190   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11191   apiConnectptr.i = scanptr.p->scanApiRec;
11192   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11193   cachePtr.i = apiConnectptr.p->cachePtr;
11194   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11195   switch (scanptr.p->scanState) {
11196   case ScanRecord::CLOSING_SCAN:
11197     jam();
11198     updateBuddyTimer(apiConnectptr);
11199     {
11200       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11201       run.release(scanFragptr);
11202     }
11203     close_scan_req_send_conf(signal, scanptr);
11204     return;
11205   default:
11206     jam();
11207     /*empty*/;
11208     break;
11209   }//switch
11210 
11211   /* Send SCANFRAGREQ to LQH block
11212    * SCANFRAGREQ with optional KEYINFO and mandatory ATTRINFO are
11213    * now sent to LQH
11214    * This starts the scan on the given fragment.
11215    * If this is the last SCANFRAGREQ, sendScanFragReq will release
11216    * the KeyInfo and AttrInfo sections when sending.
11217    */
11218   Uint32 instanceKey = conf->instanceKey;
11219   scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
11220                                            instanceKey, tnodeid);
11221   if (scanptr.p->m_scan_block_no == DBSPJ)
11222   {
11223     // only 1 instance
11224     scanFragptr.p->lqhBlockref = numberToRef(scanptr.p->m_scan_block_no,
11225                                              tnodeid);
11226   }
11227   scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
11228 
11229   /* Determine whether this is the last scanFragReq
11230    * Handle normal scan-all-fragments and partition pruned
11231    * scan-one-fragment cases.
11232    *
11233    * (Note that this assumes that fragments are processed in order,
11234    * and that DIH_SCAN_GET_NODES_CONF signals are received in the
11235    * order that the DIH_SCAN_GET_NODES_REQs were sent)
11236    */
11237   bool isLastScanFragReq= ((scanptr.p->scanNextFragId >=
11238                             scanptr.p->scanNoFrag) &&
11239                            (scanFragptr.p->scanFragId ==
11240                             (scanptr.p->scanNextFragId - 1)));
11241 
11242   sendScanFragReq(signal, scanptr.p, scanFragptr.p, isLastScanFragReq);
11243 
11244   scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11245   scanFragptr.p->startFragTimer(ctcTimer);
11246   updateBuddyTimer(apiConnectptr);
11247   /*********************************************
11248    * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
11249    * WAIT FOR THE FIRST SCANNED RECORDS
11250    *********************************************/
11251 }//Dbtc::execDIGETPRIMCONF
11252 
11253 /***************************************************
11254  * execDIGETPRIMREF
11255  *
11256  * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
11257  * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
11258  * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
11259  ***************************************************/
execDIH_SCAN_GET_NODES_REF(Signal * signal)11260 void Dbtc::execDIH_SCAN_GET_NODES_REF(Signal* signal)
11261 {
11262   jamEntry();
11263   // tcConnectptr.i in theData[0] is not used.
11264   scanFragptr.i = signal->theData[1];
11265   const Uint32 errCode = signal->theData[2];
11266   c_scan_frag_pool.getPtr(scanFragptr);
11267   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
11268 
11269   ScanRecordPtr scanptr;
11270   scanptr.i = scanFragptr.p->scanRec;
11271   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11272 
11273   {
11274     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11275     run.release(scanFragptr);
11276   }
11277 
11278   scanError(signal, scanptr, errCode);
11279 }//Dbtc::execDIGETPRIMREF()
11280 
11281 /**
11282  * Dbtc::execSCAN_FRAGREF
11283  *  Our attempt to scan a fragment was refused
11284  *  set error code and close all other fragment
11285  *  scan's belonging to this scan
11286  */
execSCAN_FRAGREF(Signal * signal)11287 void Dbtc::execSCAN_FRAGREF(Signal* signal)
11288 {
11289   const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
11290 
11291   jamEntry();
11292   const Uint32 errCode = ref->errorCode;
11293 
11294   scanFragptr.i = ref->senderData;
11295   c_scan_frag_pool.getPtr(scanFragptr);
11296 
11297   ScanRecordPtr scanptr;
11298   scanptr.i = scanFragptr.p->scanRec;
11299   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11300 
11301   apiConnectptr.i = scanptr.p->scanApiRec;
11302   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11303 
11304   Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
11305   Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
11306   transid1 = transid1 | transid2;
11307   if (transid1 != 0) {
11308     jam();
11309     systemErrorLab(signal, __LINE__);
11310   }//if
11311 
11312   /**
11313    * Set errorcode, close connection to this lqh fragment,
11314    * stop fragment timer and call scanFragError to start
11315    * close of the other fragment scans
11316    */
11317   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
11318   scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
11319   scanFragptr.p->stopFragTimer();
11320   {
11321     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11322     run.release(scanFragptr);
11323   }
11324   scanError(signal, scanptr, errCode);
11325 }//Dbtc::execSCAN_FRAGREF()
11326 
11327 /**
11328  * Dbtc::scanError
11329  *
11330  * Called when an error occurs during
11331  */
scanError(Signal * signal,ScanRecordPtr scanptr,Uint32 errorCode)11332 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
11333 {
11334   jam();
11335   ScanRecord* scanP = scanptr.p;
11336 
11337   DEBUG("scanError, errorCode = "<< errorCode <<
11338 	", scanState = " << scanptr.p->scanState);
11339 
11340   apiConnectptr.i = scanP->scanApiRec;
11341   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11342   ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
11343 
11344   if(scanP->scanState == ScanRecord::CLOSING_SCAN){
11345     jam();
11346     close_scan_req_send_conf(signal, scanptr);
11347     return;
11348   }
11349 
11350   ndbrequire(scanP->scanState == ScanRecord::RUNNING);
11351 
11352   /**
11353    * Close scan wo/ having received an order to do so
11354    */
11355   close_scan_req(signal, scanptr, false);
11356 
11357   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
11358   if(apiFail){
11359     jam();
11360     return;
11361   }
11362 
11363   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11364   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11365   ref->transId1 = apiConnectptr.p->transid[0];
11366   ref->transId2 = apiConnectptr.p->transid[1];
11367   ref->errorCode  = errorCode;
11368   ref->closeNeeded = 1;
11369   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
11370 	     signal, ScanTabRef::SignalLength, JBB);
11371 }//Dbtc::scanError()
11372 
11373 /************************************************************
11374  * execSCAN_FRAGCONF
11375  *
11376  * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
11377  * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
11378  ************************************************************/
execSCAN_FRAGCONF(Signal * signal)11379 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
11380 {
11381   Uint32 transid1, transid2, total_len;
11382   jamEntry();
11383 
11384   const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
11385   const Uint32 noCompletedOps = conf->completedOps;
11386   const Uint32 status = conf->fragmentCompleted;
11387 
11388   scanFragptr.i = conf->senderData;
11389   c_scan_frag_pool.getPtr(scanFragptr);
11390 
11391   ScanRecordPtr scanptr;
11392   scanptr.i = scanFragptr.p->scanRec;
11393   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11394 
11395   apiConnectptr.i = scanptr.p->scanApiRec;
11396   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11397 
11398   transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
11399   transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
11400   total_len= conf->total_len;
11401   transid1 = transid1 | transid2;
11402   if (transid1 != 0) {
11403     jam();
11404     systemErrorLab(signal, __LINE__);
11405   }//if
11406 
11407   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
11408 
11409   if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
11410     jam();
11411     if(status == 0){
11412       /**
11413        * We have started closing = we sent a close -> ignore this
11414        */
11415       return;
11416     } else {
11417       jam();
11418       scanFragptr.p->stopFragTimer();
11419       scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
11420       {
11421         ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11422         run.release(scanFragptr);
11423       }
11424     }
11425     close_scan_req_send_conf(signal, scanptr);
11426     return;
11427   }
11428 
11429   if(noCompletedOps == 0 && status != 0 &&
11430      !scanptr.p->m_pass_all_confs &&
11431      scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
11432     /**
11433      * Start on next fragment. Don't do this if we scan via the SPJ block. In
11434      * that case, dropping the last SCAN_TABCONF message for a fragment would
11435      * mean dropping the 'nodeMask' (which is sent in ScanFragConf::total_len).
11436      * This would confuse the API with respect to which pushed operations that
11437      * would get new tuples in the next batch. If we use SPJ, we must thus
11438      * send SCAN_TABCONF and let the API ask for the next batch.
11439      */
11440     scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
11441     scanFragptr.p->startFragTimer(ctcTimer);
11442 
11443     tcConnectptr.i = scanptr.p->scanTcrec;
11444     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11445     scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
11446     DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
11447     req->senderRef = reference();
11448     req->senderData = scanFragptr.i;
11449     req->tableId = scanptr.p->scanTableref;
11450     req->fragId = scanFragptr.p->scanFragId;
11451     req->scanCookie = scanptr.p->m_scan_cookie;
11452     sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11453                DihScanGetNodesReq::SignalLength, JBB);
11454     return;
11455   }
11456  /*
11457   Uint32 totalLen = 0;
11458   for(Uint32 i = 0; i<noCompletedOps; i++){
11459     Uint32 tmp = conf->opReturnDataLen[i];
11460     totalLen += tmp;
11461   }
11462  */
11463   {
11464     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
11465     ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
11466 
11467     run.remove(scanFragptr);
11468     queued.add(scanFragptr);
11469     scanptr.p->m_queued_count++;
11470   }
11471 
11472   if (status != 0 &&
11473       scanptr.p->m_pass_all_confs &&
11474       scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count
11475       < scanptr.p->scanNoFrag){
11476     /**
11477      * nodeMask(=total_len) should be zero since there will be no more
11478      * rows from this fragment.
11479      */
11480     ndbrequire(total_len==0);
11481     /**
11482      * Now set it to one to tell the API that there may be more rows from
11483      * the next fragment.
11484      */
11485     total_len  = 1;
11486   }
11487 
11488   scanFragptr.p->m_scan_frag_conf_status = status;
11489   scanFragptr.p->m_ops = noCompletedOps;
11490   scanFragptr.p->m_totalLen = total_len;
11491   scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
11492   scanFragptr.p->stopFragTimer();
11493 
11494   if(scanptr.p->m_queued_count > /** Min */ 0){
11495     jam();
11496     sendScanTabConf(signal, scanptr);
11497   }
11498 }//Dbtc::execSCAN_FRAGCONF()
11499 
11500 /****************************************************************************
11501  * execSCAN_NEXTREQ
11502  *
11503  * THE APPLICATION HAS PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
11504  * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
11505  ****************************************************************************/
execSCAN_NEXTREQ(Signal * signal)11506 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
11507 {
11508   const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
11509   const UintR transid1 = req->transId1;
11510   const UintR transid2 = req->transId2;
11511   const UintR stopScan = req->stopScan;
11512 
11513   jamEntry();
11514 
11515   SectionHandle handle(this, signal);
11516   apiConnectptr.i = req->apiConnectPtr;
11517   if (apiConnectptr.i >= capiConnectFilesize) {
11518     jam();
11519     releaseSections(handle);
11520     warningHandlerLab(signal, __LINE__);
11521     return;
11522   }//if
11523   ptrAss(apiConnectptr, apiConnectRecord);
11524 
11525   /**
11526    * Check transid
11527    */
11528   const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
11529   const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
11530   if ((ctransid1 | ctransid2) != 0){
11531     releaseSections(handle);
11532     ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
11533     ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11534     ref->transId1 = transid1;
11535     ref->transId2 = transid2;
11536     ref->errorCode  = ZSTATE_ERROR;
11537     ref->closeNeeded = 0;
11538     sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
11539 	       signal, ScanTabRef::SignalLength, JBB);
11540     DEBUG("Wrong transid");
11541     return;
11542   }
11543 
11544   /**
11545    * Check state of API connection
11546    */
11547   if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
11548     jam();
11549     releaseSections(handle);
11550     if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
11551       jam();
11552       /*********************************************************************
11553        * The application sends a SCAN_NEXTREQ after experiencing a time-out.
11554        *  We will send a SCAN_TABREF to indicate a time-out occurred.
11555        *********************************************************************/
11556       DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
11557       ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
11558       ndbrequire(false); //B2 indication of strange things going on
11559       scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
11560       return;
11561     }
11562     DEBUG("scanTabRefLab: ZSTATE_ERROR");
11563     DEBUG("  apiConnectstate="<<apiConnectptr.p->apiConnectstate);
11564     ndbrequire(false); //B2 indication of strange things going on
11565     scanTabRefLab(signal, ZSTATE_ERROR);
11566     return;
11567   }//if
11568 
11569   /*******************************************************
11570    * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
11571    ********************************************************/
11572   // Stop the timer that is used to check for timeout in the API
11573   setApiConTimer(apiConnectptr.i, 0, __LINE__);
11574   ScanRecordPtr scanptr;
11575   scanptr.i = apiConnectptr.p->apiScanRec;
11576   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11577   ScanRecord* scanP = scanptr.p;
11578 
11579   /* Copy ReceiverIds to working space past end of signal
11580    * so that we don't overwrite them when sending signals
11581    */
11582   Uint32 len = 0;
11583   if (handle.m_cnt > 0)
11584   {
11585     jam();
11586     /* TODO : Add Dropped signal handling for SCAN_NEXTREQ */
11587     /* Receiver ids are in a long section */
11588     ndbrequire(signal->getLength() == ScanNextReq::SignalLength);
11589     ndbrequire(handle.m_cnt == 1);
11590     SegmentedSectionPtr receiverIdsSection;
11591     ndbrequire(handle.getSection(receiverIdsSection,
11592                                  ScanNextReq::ReceiverIdsSectionNum));
11593     len= receiverIdsSection.p->m_sz;
11594     ndbassert(len < (8192 - 25));
11595 
11596     copy(signal->getDataPtrSend()+25, receiverIdsSection);
11597     releaseSections(handle);
11598   }
11599   else
11600   {
11601     jam();
11602     len= signal->getLength() - ScanNextReq::SignalLength;
11603     memcpy(signal->getDataPtrSend()+25,
11604            signal->getDataPtr()+ ScanNextReq::SignalLength,
11605            4 * len);
11606   }
11607 
11608   if (stopScan == ZTRUE) {
11609     jam();
11610     /*********************************************************************
11611      * APPLICATION IS CLOSING THE SCAN.
11612      **********************************************************************/
11613     close_scan_req(signal, scanptr, true);
11614     return;
11615   }//if
11616 
11617   if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
11618     jam();
11619     /**
11620      * The scan is closing (typically due to error)
11621      *   but the API hasn't understood it yet
11622      *
11623      * Wait for API close request
11624      */
11625     return;
11626   }
11627 
11628   ScanFragNextReq tmp;
11629   tmp.requestInfo = 0;
11630   tmp.transId1 = apiConnectptr.p->transid[0];
11631   tmp.transId2 = apiConnectptr.p->transid[1];
11632   tmp.batch_size_rows = scanP->batch_size_rows;
11633   tmp.batch_size_bytes = scanP->batch_byte_size;
11634 
11635   ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
11636   ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
11637   for(Uint32 i = 0 ; i<len; i++){
11638     jam();
11639     scanFragptr.i = signal->theData[i+25];
11640     c_scan_frag_pool.getPtr(scanFragptr);
11641     ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
11642 
11643     scanFragptr.p->startFragTimer(ctcTimer);
11644     scanFragptr.p->m_ops = 0;
11645 
11646     if(scanFragptr.p->m_scan_frag_conf_status)
11647     {
11648       /**
11649        * last scan was complete
11650        */
11651       jam();
11652       ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
11653       jam();
11654       ndbassert(scanptr.p->m_booked_fragments_count);
11655       scanptr.p->m_booked_fragments_count--;
11656       scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
11657 
11658       tcConnectptr.i = scanptr.p->scanTcrec;
11659       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
11660       scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
11661 
11662       DihScanGetNodesReq* req = (DihScanGetNodesReq*)signal->getDataPtrSend();
11663       req->senderRef = reference();
11664       req->senderData = scanFragptr.i;
11665       req->tableId = scanptr.p->scanTableref;
11666       req->fragId = scanFragptr.p->scanFragId;
11667       req->scanCookie = scanptr.p->m_scan_cookie;
11668       sendSignal(cdihblockref, GSN_DIH_SCAN_GET_NODES_REQ, signal,
11669                  DihScanGetNodesReq::SignalLength, JBB);
11670     }
11671     else
11672     {
11673       jam();
11674       scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11675       ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
11676       * req = tmp;
11677       req->senderData = scanFragptr.i;
11678       sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11679 		 ScanFragNextReq::SignalLength, JBB);
11680     }
11681     delivered.remove(scanFragptr);
11682     running.add(scanFragptr);
11683   }//for
11684 
11685 }//Dbtc::execSCAN_NEXTREQ()
11686 
11687 void
close_scan_req(Signal * signal,ScanRecordPtr scanPtr,bool req_received)11688 Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
11689 
11690   ScanRecord* scanP = scanPtr.p;
11691   ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
11692   ScanRecord::ScanState old = scanPtr.p->scanState;
11693   scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
11694   scanPtr.p->m_close_scan_req = req_received;
11695 
11696   if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
11697   {
11698     jam();
11699     scanPtr.p->scanState = old;
11700     return; // Will continue on execDI_FCOUNTCONF
11701   }
11702 
11703   /**
11704    * Queue         : Action
11705    * ============= : =================
11706    * completed     : -
11707    * running       : close -> LQH
11708    * delivered w/  : close -> LQH
11709    * delivered wo/ : move to completed
11710    * queued w/     : close -> LQH
11711    * queued wo/    : move to completed
11712    */
11713 
11714   ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
11715   nextReq->requestInfo = ScanFragNextReq::ZCLOSE;
11716   nextReq->transId1 = apiConnectptr.p->transid[0];
11717   nextReq->transId2 = apiConnectptr.p->transid[1];
11718 
11719   {
11720     ScanFragRecPtr ptr;
11721     ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
11722     ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
11723     ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
11724 
11725     // Close running
11726     for(running.first(ptr); !ptr.isNull(); ){
11727       ScanFragRecPtr curr = ptr; // Remove while iterating...
11728       running.next(ptr);
11729 
11730       switch(curr.p->scanFragState){
11731       case ScanFragRec::IDLE:
11732 	jam(); // real early abort
11733 	ndbrequire(old == ScanRecord::WAIT_AI);
11734 	running.release(curr);
11735 	continue;
11736       case ScanFragRec::WAIT_GET_PRIMCONF:
11737 	jam();
11738 	continue;
11739       case ScanFragRec::LQH_ACTIVE:
11740 	jam();
11741 	break;
11742       default:
11743 	jamLine(curr.p->scanFragState);
11744 	ndbrequire(false);
11745       }
11746 
11747       curr.p->startFragTimer(ctcTimer);
11748       curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11749       nextReq->senderData = curr.i;
11750       sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11751 		 ScanFragNextReq::SignalLength, JBB);
11752     }
11753 
11754     // Close delivered
11755     for(delivered.first(ptr); !ptr.isNull(); ){
11756       jam();
11757       ScanFragRecPtr curr = ptr; // Remove while iterating...
11758       delivered.next(ptr);
11759 
11760       ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
11761       delivered.remove(curr);
11762 
11763       if (curr.p->m_scan_frag_conf_status == 0)
11764       {
11765 	jam();
11766 	running.add(curr);
11767 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11768 	curr.p->startFragTimer(ctcTimer);
11769 	nextReq->senderData = curr.i;
11770 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11771 		   ScanFragNextReq::SignalLength, JBB);
11772 
11773       }
11774       else
11775       {
11776 	jam();
11777 	c_scan_frag_pool.release(curr);
11778 	curr.p->scanFragState = ScanFragRec::COMPLETED;
11779 	curr.p->stopFragTimer();
11780       }
11781     }//for
11782 
11783     /**
11784      * All queued with data should be closed
11785      */
11786     for(queued.first(ptr); !ptr.isNull(); ){
11787       jam();
11788       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
11789       ScanFragRecPtr curr = ptr; // Remove while iterating...
11790       queued.next(ptr);
11791 
11792       queued.remove(curr);
11793       scanP->m_queued_count--;
11794 
11795       if (curr.p->m_scan_frag_conf_status == 0)
11796       {
11797 	jam();
11798 	running.add(curr);
11799 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
11800 	curr.p->startFragTimer(ctcTimer);
11801 	nextReq->senderData = curr.i;
11802 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
11803 		   ScanFragNextReq::SignalLength, JBB);
11804       }
11805       else
11806       {
11807 	jam();
11808 	c_scan_frag_pool.release(curr);
11809 	curr.p->scanFragState = ScanFragRec::COMPLETED;
11810 	curr.p->stopFragTimer();
11811       }
11812     }
11813   }
11814   close_scan_req_send_conf(signal, scanPtr);
11815 }
11816 
11817 void
close_scan_req_send_conf(Signal * signal,ScanRecordPtr scanPtr)11818 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
11819 
11820   jam();
11821 
11822   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
11823   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
11824   //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
11825 
11826 #if 0
11827   {
11828     ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
11829     ScanFragRecPtr ptr;
11830     for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
11831       ndbrequire(ptr.p->scanFragTimer == 0);
11832       ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
11833     }
11834   }
11835 #endif
11836 
11837   if(!scanPtr.p->m_running_scan_frags.isEmpty()){
11838     jam();
11839     return;
11840   }
11841 
11842   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
11843 
11844   if(!scanPtr.p->m_close_scan_req){
11845     jam();
11846     /**
11847      * The API hasn't order closing yet
11848      */
11849     return;
11850   }
11851 
11852   Uint32 ref = apiConnectptr.p->ndbapiBlockref;
11853   if(!apiFail && ref){
11854     jam();
11855     ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
11856     conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
11857     conf->requestInfo = ScanTabConf::EndOfData;
11858     conf->transId1 = apiConnectptr.p->transid[0];
11859     conf->transId2 = apiConnectptr.p->transid[1];
11860     sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
11861   }
11862 
11863   releaseScanResources(signal, scanPtr);
11864 
11865   if(apiFail){
11866     jam();
11867     /**
11868      * API has failed
11869      */
11870     handleApiFailState(signal, apiConnectptr.i);
11871   }
11872 }
11873 
11874 Dbtc::ScanRecordPtr
seizeScanrec(Signal * signal)11875 Dbtc::seizeScanrec(Signal* signal) {
11876   ScanRecordPtr scanptr;
11877   scanptr.i = cfirstfreeScanrec;
11878   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
11879   cfirstfreeScanrec = scanptr.p->nextScan;
11880   scanptr.p->nextScan = RNIL;
11881   ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
11882   return scanptr;
11883 }//Dbtc::seizeScanrec()
11884 
sendScanFragReq(Signal * signal,ScanRecord * scanP,ScanFragRec * scanFragP,bool isLastReq)11885 void Dbtc::sendScanFragReq(Signal* signal,
11886 			   ScanRecord* scanP,
11887 			   ScanFragRec* scanFragP,
11888                            bool isLastReq)
11889 {
11890   Uint32 version= getNodeInfo(refToNode(scanFragP->lqhBlockref)).m_version;
11891   bool longFragReq= ((version >= NDBD_LONG_SCANFRAGREQ) &&
11892                      (! ERROR_INSERTED(8070) &&
11893 		      ! ERROR_INSERTED(8088)));
11894   cachePtr.i = apiConnectptr.p->cachePtr;
11895   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
11896 
11897   Uint32 reqKeyLen = scanP->scanKeyLen;
11898 
11899   SectionHandle sections(this);
11900   sections.m_ptr[0].i = cachePtr.p->attrInfoSectionI;
11901   sections.m_cnt = 1;
11902 
11903   if (reqKeyLen > 0)
11904   {
11905     jam();
11906     ndbassert(cachePtr.p->keyInfoSectionI != RNIL);
11907     sections.m_ptr[1].i = cachePtr.p->keyInfoSectionI;
11908     sections.m_cnt = 2;
11909   }
11910 
11911   if (isLastReq)
11912   {
11913     /* This send will release these sections, remove our
11914      * references to them
11915      */
11916     cachePtr.p->attrInfoSectionI = RNIL;
11917     cachePtr.p->keyInfoSectionI = RNIL;
11918   }
11919 
11920   getSections(sections.m_cnt, sections.m_ptr);
11921 
11922   ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
11923   Uint32 requestInfo = scanP->scanRequestInfo;
11924   ScanFragReq::setScanPrio(requestInfo, 1);
11925   apiConnectptr.i = scanP->scanApiRec;
11926   req->tableId = scanP->scanTableref;
11927   req->schemaVersion = scanP->scanSchemaVersion;
11928   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11929   req->senderData = scanFragptr.i;
11930   req->requestInfo = requestInfo;
11931   req->fragmentNoKeyLen = scanFragP->scanFragId;
11932   req->resultRef = apiConnectptr.p->ndbapiBlockref;
11933   req->savePointId = apiConnectptr.p->currSavePointId;
11934   req->transId1 = apiConnectptr.p->transid[0];
11935   req->transId2 = apiConnectptr.p->transid[1];
11936   req->clientOpPtr = scanFragP->m_apiPtr;
11937   req->batch_size_rows= scanP->batch_size_rows;
11938   req->batch_size_bytes= scanP->batch_byte_size;
11939 
11940   if (likely(longFragReq))
11941   {
11942     jam();
11943     /* Send long, possibly fragmented SCAN_FRAGREQ */
11944 
11945     // TODO :
11946     //   1) Consider whether to adjust fragmentation threshold
11947     //      a) When to fragment signal vs fragment size
11948     //      b) Fragment size
11949     /* To reduce the copy burden we want to keep hold of the
11950      * AttrInfo and KeyInfo sections after sending them to
11951      * LQH.  To do this we perform the fragmented send inline,
11952      * so that all fragments are sent *now*.  This avoids any
11953      * problems with the fragmented send CONTINUE 'thread' using
11954      * the section while we hold or even release it.  The
11955      * signal receiver can still take realtime breaks when
11956      * receiving.
11957      *
11958      * Indicate to sendFirstFragment that we want to keep the
11959      * fragments, so it must not free them, unless this is the
11960      * last request in which case they can be freed.  If the
11961      * last request is a local send then a copy is avoided.
11962      */
11963     FragmentSendInfo fragSendInfo;
11964 
11965     sendFirstFragment(fragSendInfo,
11966                       NodeReceiverGroup(scanFragP->lqhBlockref),
11967                       GSN_SCAN_FRAGREQ,
11968                       signal,
11969                       ScanFragReq::SignalLength,
11970                       JBB,
11971                       &sections,
11972                       !isLastReq); // Keep sent sections unless
11973                                    // last send
11974 
11975     while (fragSendInfo.m_status != FragmentSendInfo::SendComplete)
11976     {
11977       jam();
11978       /* Send remaining fragments */
11979       sendNextSegmentedFragment(signal, fragSendInfo);
11980     }
11981 
11982     /* Clear handle, section deallocation handled elsewhere. */
11983     sections.clear();
11984   }
11985   else
11986   {
11987     jam();
11988     /* Short SCANFRAGREQ with separate KeyInfo and AttrInfo trains
11989      * Sent to older NDBD nodes during upgrade
11990      */
11991     Uint32 reqAttrLen = sections.m_ptr[0].sz;
11992     ScanFragReq::setAttrLen(req->requestInfo, reqAttrLen);
11993     req->fragmentNoKeyLen |= reqKeyLen;
11994     sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
11995                ScanFragReq::SignalLength, JBB);
11996     if(reqKeyLen > 0)
11997     {
11998       jam();
11999       tcConnectptr.i = scanFragptr.i;
12000       /* Build KeyInfo train from KeyInfo long signal section */
12001       sendKeyInfoTrain(signal,
12002                        scanFragP->lqhBlockref,
12003                        scanFragptr.i,
12004                        0, // Offset 0
12005                        sections.m_ptr[1].i);
12006     }
12007 
12008     if(ERROR_INSERTED(8035))
12009       globalTransporterRegistry.performSend();
12010 
12011     if (!ERROR_INSERTED(8088))
12012     {
12013       ndbrequire(sendAttrInfoTrain(signal,
12014                                    scanFragP->lqhBlockref,
12015                                    scanFragptr.i,
12016                                    0, // Offset 0
12017                                    sections.m_ptr[0].i));
12018     }
12019 
12020     if(ERROR_INSERTED(8035))
12021       globalTransporterRegistry.performSend();
12022 
12023     if (isLastReq)
12024     {
12025       /* Free the sections here */
12026       releaseSections(sections);
12027     }
12028     else
12029     {
12030       sections.clear();
12031     }
12032   }
12033 
12034   if (ERROR_INSERTED(8088))
12035   {
12036     signal->theData[0] = 9999;
12037     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
12038   }
12039 }//Dbtc::sendScanFragReq()
12040 
12041 
sendScanTabConf(Signal * signal,ScanRecordPtr scanPtr)12042 void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
12043   jam();
12044   Uint32* ops = signal->getDataPtrSend()+4;
12045   Uint32 op_count = scanPtr.p->m_queued_count;
12046 
12047   Uint32 words_per_op = 4;
12048   const Uint32 ref = apiConnectptr.p->ndbapiBlockref;
12049   if (!scanPtr.p->m_4word_conf)
12050   {
12051     jam();
12052     words_per_op = 3;
12053   }
12054 
12055   if (4 + words_per_op * op_count > 25)
12056   {
12057     jam();
12058     ops += 21;
12059   }
12060 
12061   int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
12062   Uint32 booked = scanPtr.p->m_booked_fragments_count;
12063 
12064   ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
12065   conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
12066   conf->requestInfo = op_count;
12067   conf->transId1 = apiConnectptr.p->transid[0];
12068   conf->transId2 = apiConnectptr.p->transid[1];
12069   ScanFragRecPtr ptr;
12070   {
12071     ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
12072     ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
12073     for(queued.first(ptr); !ptr.isNull(); ){
12074       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
12075       ScanFragRecPtr curr = ptr; // Remove while iterating...
12076       queued.next(ptr);
12077 
12078       bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
12079       if(curr.p->m_scan_frag_conf_status)
12080 	booked++;
12081 
12082       * ops++ = curr.p->m_apiPtr;
12083       * ops++ = done ? RNIL : curr.i;
12084       if (words_per_op == 4)
12085       {
12086         * ops++ = curr.p->m_ops;
12087         * ops++ = curr.p->m_totalLen;
12088       }
12089       else
12090       {
12091         * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
12092       }
12093 
12094       queued.remove(curr);
12095       if(!done){
12096 	delivered.add(curr);
12097 	curr.p->scanFragState = ScanFragRec::DELIVERED;
12098 	curr.p->stopFragTimer();
12099       } else {
12100 	c_scan_frag_pool.release(curr);
12101 	curr.p->scanFragState = ScanFragRec::COMPLETED;
12102 	curr.p->stopFragTimer();
12103       }
12104     }
12105   }
12106 
12107   bool release = false;
12108   scanPtr.p->m_booked_fragments_count = booked;
12109   if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
12110      scanPtr.p->m_running_scan_frags.isEmpty())
12111   {
12112     jam();
12113     release = true;
12114     conf->requestInfo = op_count | ScanTabConf::EndOfData;
12115   }
12116   else
12117   {
12118     if (scanPtr.p->m_running_scan_frags.isEmpty())
12119     {
12120       jam();
12121       /**
12122        * All scan frags delivered...waiting for API
12123        */
12124       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
12125     }
12126   }
12127 
12128   if (4 + words_per_op * op_count > 25)
12129   {
12130     jam();
12131     LinearSectionPtr ptr[3];
12132     ptr[0].p = signal->getDataPtrSend()+25;
12133     ptr[0].sz = words_per_op * op_count;
12134     sendSignal(ref, GSN_SCAN_TABCONF, signal,
12135                ScanTabConf::SignalLength, JBB, ptr, 1);
12136   }
12137   else
12138   {
12139     jam();
12140     sendSignal(ref, GSN_SCAN_TABCONF, signal,
12141 	       ScanTabConf::SignalLength + words_per_op * op_count, JBB);
12142   }
12143   scanPtr.p->m_queued_count = 0;
12144 
12145   if (release)
12146   {
12147     jam();
12148     releaseScanResources(signal, scanPtr);
12149   }
12150 
12151 }//Dbtc::sendScanTabConf()
12152 
12153 
gcpTcfinished(Signal * signal,Uint64 gci)12154 void Dbtc::gcpTcfinished(Signal* signal, Uint64 gci)
12155 {
12156   GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
12157   conf->senderData = c_gcp_data;
12158   conf->gci_hi = Uint32(gci >> 32);
12159   conf->gci_lo = Uint32(gci);
12160   sendSignal(c_gcp_ref, GSN_GCP_TCFINISHED, signal,
12161              GCPTCFinished::SignalLength, JBB);
12162 }//Dbtc::gcpTcfinished()
12163 
initApiConnect(Signal * signal)12164 void Dbtc::initApiConnect(Signal* signal)
12165 {
12166   Uint32 tiacTmp;
12167   Uint32 guard4;
12168 
12169   tiacTmp = capiConnectFilesize / 3;
12170   ndbrequire(tiacTmp > 0);
12171   guard4 = tiacTmp + 1;
12172   for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
12173     refresh_watch_dog();
12174     ptrAss(cachePtr, cacheRecord);
12175     cachePtr.p->nextCacheRec = cachePtr.i + 1;
12176   }//for
12177   cachePtr.i = tiacTmp;
12178   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12179   cachePtr.p->nextCacheRec = RNIL;
12180   cfirstfreeCacheRec = 0;
12181 
12182   guard4 = tiacTmp - 1;
12183   for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
12184     refresh_watch_dog();
12185     jam();
12186     ptrAss(apiConnectptr, apiConnectRecord);
12187     apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
12188     apiConnectptr.p->apiFailState = ZFALSE;
12189     setApiConTimer(apiConnectptr.i, 0, __LINE__);
12190     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12191     apiConnectptr.p->cachePtr = RNIL;
12192     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12193     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12194     apiConnectptr.p->commitAckMarker = RNIL;
12195     apiConnectptr.p->firstTcConnect = RNIL;
12196     apiConnectptr.p->lastTcConnect = RNIL;
12197     apiConnectptr.p->m_flags = 0;
12198     apiConnectptr.p->m_special_op_flags = 0;
12199     apiConnectptr.p->accumulatingIndexOp = RNIL;
12200     apiConnectptr.p->executingIndexOp = RNIL;
12201     apiConnectptr.p->buddyPtr = RNIL;
12202     apiConnectptr.p->currSavePointId = 0;
12203     apiConnectptr.p->m_transaction_nodes.clear();
12204     apiConnectptr.p->singleUserMode = 0;
12205   }//for
12206   apiConnectptr.i = tiacTmp - 1;
12207   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12208   apiConnectptr.p->nextApiConnect = RNIL;
12209   cfirstfreeApiConnect = 0;
12210   guard4 = (2 * tiacTmp) - 1;
12211   for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
12212     {
12213       refresh_watch_dog();
12214       jam();
12215       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12216       apiConnectptr.p->apiConnectstate = CS_RESTART;
12217       apiConnectptr.p->apiFailState = ZFALSE;
12218       setApiConTimer(apiConnectptr.i, 0, __LINE__);
12219       apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12220       apiConnectptr.p->cachePtr = RNIL;
12221       apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12222       apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12223       apiConnectptr.p->commitAckMarker = RNIL;
12224       apiConnectptr.p->firstTcConnect = RNIL;
12225       apiConnectptr.p->lastTcConnect = RNIL;
12226       apiConnectptr.p->m_flags = 0;
12227       apiConnectptr.p->m_special_op_flags = 0;
12228       apiConnectptr.p->accumulatingIndexOp = RNIL;
12229       apiConnectptr.p->executingIndexOp = RNIL;
12230       apiConnectptr.p->buddyPtr = RNIL;
12231       apiConnectptr.p->currSavePointId = 0;
12232       apiConnectptr.p->m_transaction_nodes.clear();
12233       apiConnectptr.p->singleUserMode = 0;
12234     }//for
12235   apiConnectptr.i = (2 * tiacTmp) - 1;
12236   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12237   apiConnectptr.p->nextApiConnect = RNIL;
12238   cfirstfreeApiConnectCopy = tiacTmp;
12239   guard4 = (3 * tiacTmp) - 1;
12240   for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
12241        apiConnectptr.i++) {
12242     refresh_watch_dog();
12243     jam();
12244     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12245     setApiConTimer(apiConnectptr.i, 0, __LINE__);
12246     apiConnectptr.p->apiFailState = ZFALSE;
12247     apiConnectptr.p->apiConnectstate = CS_RESTART;
12248     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12249     apiConnectptr.p->cachePtr = RNIL;
12250     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
12251     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
12252     apiConnectptr.p->commitAckMarker = RNIL;
12253     apiConnectptr.p->firstTcConnect = RNIL;
12254     apiConnectptr.p->lastTcConnect = RNIL;
12255     apiConnectptr.p->m_flags = 0;
12256     apiConnectptr.p->m_special_op_flags = 0;
12257     apiConnectptr.p->accumulatingIndexOp = RNIL;
12258     apiConnectptr.p->executingIndexOp = RNIL;
12259     apiConnectptr.p->buddyPtr = RNIL;
12260     apiConnectptr.p->currSavePointId = 0;
12261     apiConnectptr.p->m_transaction_nodes.clear();
12262     apiConnectptr.p->singleUserMode = 0;
12263   }//for
12264   apiConnectptr.i = (3 * tiacTmp) - 1;
12265   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12266   apiConnectptr.p->nextApiConnect = RNIL;
12267   cfirstfreeApiConnectFail = 2 * tiacTmp;
12268 }//Dbtc::initApiConnect()
12269 
initgcp(Signal * signal)12270 void Dbtc::initgcp(Signal* signal)
12271 {
12272   Ptr<GcpRecord> gcpPtr;
12273   ndbrequire(cgcpFilesize > 0);
12274   for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
12275     ptrAss(gcpPtr, gcpRecord);
12276     gcpPtr.p->nextGcp = gcpPtr.i + 1;
12277   }//for
12278   gcpPtr.i = cgcpFilesize - 1;
12279   ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
12280   gcpPtr.p->nextGcp = RNIL;
12281   cfirstfreeGcp = 0;
12282   cfirstgcp = RNIL;
12283   clastgcp = RNIL;
12284 }//Dbtc::initgcp()
12285 
inithost(Signal * signal)12286 void Dbtc::inithost(Signal* signal)
12287 {
12288   cpackedListIndex = 0;
12289   ndbrequire(chostFilesize > 0);
12290   for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
12291     jam();
12292     ptrAss(hostptr, hostRecord);
12293     hostptr.p->hostStatus = HS_DEAD;
12294     hostptr.p->inPackedList = false;
12295     hostptr.p->lqhTransStatus = LTS_IDLE;
12296     hostptr.p->noOfWordsTCKEYCONF = 0;
12297     hostptr.p->noOfPackedWordsLqh = 0;
12298     hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
12299     hostptr.p->m_nf_bits = 0;
12300   }//for
12301   c_alive_nodes.clear();
12302 }//Dbtc::inithost()
12303 
initialiseRecordsLab(Signal * signal,UintR Tdata0,Uint32 retRef,Uint32 retData)12304 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
12305 				Uint32 retRef, Uint32 retData)
12306 {
12307   switch (Tdata0) {
12308   case 0:
12309     jam();
12310     initApiConnect(signal);
12311     break;
12312   case 1:
12313     jam();
12314     // UNUSED Free to initialise something
12315     break;
12316   case 2:
12317     jam();
12318     // UNUSED Free to initialise something
12319     break;
12320   case 3:
12321     jam();
12322     initgcp(signal);
12323     break;
12324   case 4:
12325     jam();
12326     inithost(signal);
12327     break;
12328   case 5:
12329     jam();
12330     // UNUSED Free to initialise something
12331     break;
12332   case 6:
12333     jam();
12334     initTable(signal);
12335     break;
12336   case 7:
12337     jam();
12338     initialiseScanrec(signal);
12339     break;
12340   case 8:
12341     jam();
12342     initialiseScanOprec(signal);
12343     break;
12344   case 9:
12345     jam();
12346     initialiseScanFragrec(signal);
12347     break;
12348   case 10:
12349     jam();
12350     initialiseTcConnect(signal);
12351     break;
12352   case 11:
12353     jam();
12354     initTcFail(signal);
12355 
12356     {
12357       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
12358       conf->senderRef = reference();
12359       conf->senderData = retData;
12360       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
12361 		 ReadConfigConf::SignalLength, JBB);
12362     }
12363     return;
12364     break;
12365   default:
12366     jam();
12367     systemErrorLab(signal, __LINE__);
12368     return;
12369     break;
12370   }//switch
12371 
12372   signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
12373   signal->theData[1] = Tdata0 + 1;
12374   signal->theData[2] = 0;
12375   signal->theData[3] = retRef;
12376   signal->theData[4] = retData;
12377   sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
12378 }
12379 
12380 /* ========================================================================= */
12381 /* =======                       INITIALISE_SCANREC                  ======= */
12382 /*                                                                           */
12383 /* ========================================================================= */
initialiseScanrec(Signal * signal)12384 void Dbtc::initialiseScanrec(Signal* signal)
12385 {
12386   ScanRecordPtr scanptr;
12387   ndbrequire(cscanrecFileSize > 0);
12388   for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
12389     refresh_watch_dog();
12390     jam();
12391     ptrAss(scanptr, scanRecord);
12392     new (scanptr.p) ScanRecord();
12393     scanptr.p->scanState = ScanRecord::IDLE;
12394     scanptr.p->scanApiRec = RNIL;
12395     scanptr.p->nextScan = scanptr.i + 1;
12396   }//for
12397   scanptr.i = cscanrecFileSize - 1;
12398   ptrAss(scanptr, scanRecord);
12399   scanptr.p->nextScan = RNIL;
12400   cfirstfreeScanrec = 0;
12401 }//Dbtc::initialiseScanrec()
12402 
initialiseScanFragrec(Signal * signal)12403 void Dbtc::initialiseScanFragrec(Signal* signal)
12404 {
12405 }//Dbtc::initialiseScanFragrec()
12406 
initialiseScanOprec(Signal * signal)12407 void Dbtc::initialiseScanOprec(Signal* signal)
12408 {
12409 }//Dbtc::initialiseScanOprec()
12410 
initTable(Signal * signal)12411 void Dbtc::initTable(Signal* signal)
12412 {
12413 
12414   ndbrequire(ctabrecFilesize > 0);
12415   for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
12416     refresh_watch_dog();
12417     ptrAss(tabptr, tableRecord);
12418     tabptr.p->currentSchemaVersion = 0;
12419     tabptr.p->m_flags = 0;
12420     tabptr.p->set_storedTable(true);
12421     tabptr.p->tableType = 0;
12422     tabptr.p->set_enabled(false);
12423     tabptr.p->set_dropping(false);
12424     tabptr.p->noOfKeyAttr = 0;
12425     tabptr.p->hasCharAttr = 0;
12426     tabptr.p->noOfDistrKeys = 0;
12427     tabptr.p->hasVarKeys = 0;
12428   }//for
12429 }//Dbtc::initTable()
12430 
initialiseTcConnect(Signal * signal)12431 void Dbtc::initialiseTcConnect(Signal* signal)
12432 {
12433   ndbrequire(ctcConnectFilesize >= 2);
12434 
12435   // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
12436   Uint32 titcTmp = ctcConnectFilesize / 2;
12437   for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
12438     refresh_watch_dog();
12439     jam();
12440     ptrAss(tcConnectptr, tcConnectRecord);
12441     tcConnectptr.p->tcConnectstate = OS_RESTART;
12442     tcConnectptr.p->apiConnect = RNIL;
12443     tcConnectptr.p->noOfNodes = 0;
12444     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
12445     tcConnectptr.p->commitAckMarker = RNIL;
12446   }//for
12447   tcConnectptr.i = titcTmp - 1;
12448   ptrAss(tcConnectptr, tcConnectRecord);
12449   tcConnectptr.p->nextTcConnect = RNIL;
12450   cfirstfreeTcConnectFail = 0;
12451 
12452   // Place other half in cfirstfreeTcConnect list
12453   for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
12454        tcConnectptr.i++) {
12455     refresh_watch_dog();
12456     jam();
12457     ptrAss(tcConnectptr, tcConnectRecord);
12458     tcConnectptr.p->tcConnectstate = OS_RESTART;
12459     tcConnectptr.p->apiConnect = RNIL;
12460     tcConnectptr.p->noOfNodes = 0;
12461     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
12462     tcConnectptr.p->commitAckMarker = RNIL;
12463   }//for
12464   tcConnectptr.i = ctcConnectFilesize - 1;
12465   ptrAss(tcConnectptr, tcConnectRecord);
12466   tcConnectptr.p->nextTcConnect = RNIL;
12467   cfirstfreeTcConnect = titcTmp;
12468   c_counters.cconcurrentOp = 0;
12469 }//Dbtc::initialiseTcConnect()
12470 
12471 /* ------------------------------------------------------------------------- */
12472 /* ----     LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS  */
12473 /*          WAITING FOR COMPLETION.                                          */
12474 /* ------------------------------------------------------------------------- */
linkGciInGcilist(Ptr<GcpRecord> gcpPtr)12475 void Dbtc::linkGciInGcilist(Ptr<GcpRecord> gcpPtr)
12476 {
12477   GcpRecordPtr tmpGcpPointer;
12478   if (cfirstgcp == RNIL) {
12479     jam();
12480     cfirstgcp = gcpPtr.i;
12481   } else {
12482     jam();
12483     tmpGcpPointer.i = clastgcp;
12484     ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
12485     tmpGcpPointer.p->nextGcp = gcpPtr.i;
12486   }//if
12487   clastgcp = gcpPtr.i;
12488 }//Dbtc::linkGciInGcilist()
12489 
12490 /* ------------------------------------------------------------------------- */
12491 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS  --- */
12492 /* ------------------------------------------------------------------------- */
linkTcInConnectionlist(Signal * signal)12493 void Dbtc::linkTcInConnectionlist(Signal* signal)
12494 {
12495   /* POINTER FOR THE CONNECT_RECORD */
12496   TcConnectRecordPtr ltcTcConnectptr;
12497 
12498   tcConnectptr.p->nextTcConnect = RNIL;
12499   ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
12500   ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
12501   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
12502   if (ltcTcConnectptr.i == RNIL) {
12503     jam();
12504     apiConnectptr.p->firstTcConnect = tcConnectptr.i;
12505   } else {
12506     jam();
12507     ptrGuard(ltcTcConnectptr);
12508     ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
12509   }//if
12510 }//Dbtc::linkTcInConnectionlist()
12511 
12512 /*---------------------------------------------------------------------------*/
12513 /*                    RELEASE_ABORT_RESOURCES                                */
12514 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
12515 /* SENDS THE ABORT DECISION TO THE APPLICATION.                              */
12516 /*---------------------------------------------------------------------------*/
releaseAbortResources(Signal * signal)12517 void Dbtc::releaseAbortResources(Signal* signal)
12518 {
12519   TcConnectRecordPtr rarTcConnectptr;
12520 
12521   c_counters.cabortCount++;
12522   if (apiConnectptr.p->cachePtr != RNIL) {
12523     cachePtr.i = apiConnectptr.p->cachePtr;
12524     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
12525     releaseAttrinfo();
12526     releaseKeys();
12527   }//if
12528   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
12529   while (tcConnectptr.i != RNIL) {
12530     jam();
12531     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12532     // Clear any markers that were set in CS_RECEIVING state
12533     clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
12534     rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
12535     releaseTcCon();
12536     tcConnectptr.i = rarTcConnectptr.i;
12537   }//while
12538 
12539   Uint32 marker = apiConnectptr.p->commitAckMarker;
12540   if (marker != RNIL)
12541   {
12542     jam();
12543     m_commitAckMarkerHash.release(marker);
12544     apiConnectptr.p->commitAckMarker = RNIL;
12545   }
12546 
12547   apiConnectptr.p->firstTcConnect = RNIL;
12548   apiConnectptr.p->lastTcConnect = RNIL;
12549   apiConnectptr.p->m_transaction_nodes.clear();
12550   apiConnectptr.p->singleUserMode = 0;
12551 
12552   // MASV let state be CS_ABORTING until all
12553   // signals in the "air" have been received. Reset to CS_CONNECTED
12554   // will be done when a TCKEYREQ with start flag is recieved
12555   // or releaseApiCon is called
12556   // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
12557   apiConnectptr.p->apiConnectstate = CS_ABORTING;
12558   apiConnectptr.p->abortState = AS_IDLE;
12559   releaseAllSeizedIndexOperations(apiConnectptr.p);
12560 
12561   if (tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG) ||
12562       apiConnectptr.p->apiFailState == ZTRUE)
12563   {
12564     jam();
12565     bool ok = false;
12566     Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
12567     ReturnSignal ret = apiConnectptr.p->returnsignal;
12568     apiConnectptr.p->returnsignal = RS_NO_RETURN;
12569     tc_clearbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
12570     switch(ret){
12571     case RS_TCROLLBACKCONF:
12572       jam();
12573       ok = true;
12574       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
12575       signal->theData[1] = apiConnectptr.p->transid[0];
12576       signal->theData[2] = apiConnectptr.p->transid[1];
12577       sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
12578       break;
12579     case RS_TCROLLBACKREP:{
12580       jam();
12581       ok = true;
12582       TcRollbackRep * const tcRollbackRep =
12583 	(TcRollbackRep *) signal->getDataPtr();
12584 
12585       tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
12586       tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
12587       tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
12588       tcRollbackRep->returnCode = apiConnectptr.p->returncode;
12589       tcRollbackRep->errorData = apiConnectptr.p->errorData;
12590       sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
12591 		 TcRollbackRep::SignalLength, JBB);
12592     }
12593       break;
12594     case RS_NO_RETURN:
12595       jam();
12596       ok = true;
12597       break;
12598     case RS_TCKEYCONF:
12599     case RS_TC_COMMITCONF:
12600       break;
12601     }
12602     if(!ok){
12603       jam();
12604       ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
12605       sendSystemError(signal, __LINE__);
12606     }//if
12607 
12608   }
12609   setApiConTimer(apiConnectptr.i, 0,
12610 		 100000+c_apiConTimer_line[apiConnectptr.i]);
12611   if (apiConnectptr.p->apiFailState == ZTRUE) {
12612     jam();
12613     handleApiFailState(signal, apiConnectptr.i);
12614     return;
12615   }//if
12616 }//Dbtc::releaseAbortResources()
12617 
releaseApiCon(Signal * signal,UintR TapiConnectPtr)12618 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
12619 {
12620   ApiConnectRecordPtr TlocalApiConnectptr;
12621 
12622   TlocalApiConnectptr.i = TapiConnectPtr;
12623   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
12624   TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
12625   cfirstfreeApiConnect = TlocalApiConnectptr.i;
12626   setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
12627   TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
12628   ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
12629   ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
12630   TlocalApiConnectptr.p->ndbapiBlockref = 0;
12631 }//Dbtc::releaseApiCon()
12632 
releaseApiConnectFail(Signal * signal)12633 void Dbtc::releaseApiConnectFail(Signal* signal)
12634 {
12635   apiConnectptr.p->apiConnectstate = CS_RESTART;
12636   apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
12637   setApiConTimer(apiConnectptr.i, 0, __LINE__);
12638   apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
12639   cfirstfreeApiConnectFail = apiConnectptr.i;
12640   ndbrequire(apiConnectptr.p->commitAckMarker == RNIL);
12641 }//Dbtc::releaseApiConnectFail()
12642 
releaseKeys()12643 void Dbtc::releaseKeys()
12644 {
12645   Uint32 keyInfoSectionI= cachePtr.p->keyInfoSectionI;
12646 
12647   /* Release KeyInfo section if there is one */
12648   releaseSection(keyInfoSectionI);
12649   cachePtr.p->keyInfoSectionI= RNIL;
12650 
12651 }//Dbtc::releaseKeys()
12652 
releaseTcConnectFail(Signal * signal)12653 void Dbtc::releaseTcConnectFail(Signal* signal)
12654 {
12655   ptrGuard(tcConnectptr);
12656   tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
12657   cfirstfreeTcConnectFail = tcConnectptr.i;
12658 }//Dbtc::releaseTcConnectFail()
12659 
seizeApiConnect(Signal * signal)12660 void Dbtc::seizeApiConnect(Signal* signal)
12661 {
12662   if (cfirstfreeApiConnect != RNIL) {
12663     jam();
12664     terrorCode = ZOK;
12665     apiConnectptr.i = cfirstfreeApiConnect;     /* ASSIGN A FREE RECORD FROM */
12666     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12667     cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
12668     apiConnectptr.p->nextApiConnect = RNIL;
12669     setApiConTimer(apiConnectptr.i, 0, __LINE__);
12670     apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
12671     tc_clearbit(apiConnectptr.p->m_flags,
12672                 ApiConnectRecord::TF_TRIGGER_PENDING);
12673     apiConnectptr.p->m_special_op_flags = 0;
12674   } else {
12675     jam();
12676     terrorCode = ZNO_FREE_API_CONNECTION;
12677   }//if
12678 }//Dbtc::seizeApiConnect()
12679 
seizeApiConnectFail(Signal * signal)12680 void Dbtc::seizeApiConnectFail(Signal* signal)
12681 {
12682   apiConnectptr.i = cfirstfreeApiConnectFail;
12683   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
12684   cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
12685 }//Dbtc::seizeApiConnectFail()
12686 
seizeTcConnect(Signal * signal)12687 void Dbtc::seizeTcConnect(Signal* signal)
12688 {
12689   tcConnectptr.i = cfirstfreeTcConnect;
12690   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12691   cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
12692   c_counters.cconcurrentOp++;
12693   tcConnectptr.p->m_special_op_flags = 0;
12694   tcConnectptr.p->tcConnectstate = OS_ABORTING;
12695   tcConnectptr.p->noOfNodes = 0;
12696 }//Dbtc::seizeTcConnect()
12697 
seizeTcConnectFail(Signal * signal)12698 void Dbtc::seizeTcConnectFail(Signal* signal)
12699 {
12700   tcConnectptr.i = cfirstfreeTcConnectFail;
12701   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
12702   cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
12703 }//Dbtc::seizeTcConnectFail()
12704 
12705 /**
12706  * sendAttrInfoTrain
12707  * This method sends an ATTRINFO signal train using AttrInfo
12708  * from the section passed, starting at the supplied offset
12709  */
sendAttrInfoTrain(Signal * signal,UintR TBRef,Uint32 connectPtr,Uint32 offset,Uint32 attrInfoIVal)12710 bool Dbtc::sendAttrInfoTrain(Signal* signal,
12711                              UintR TBRef,
12712                              Uint32 connectPtr,
12713                              Uint32 offset,
12714                              Uint32 attrInfoIVal)
12715 {
12716   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
12717 
12718   ndbassert( attrInfoIVal != RNIL );
12719   SectionReader attrInfoReader(attrInfoIVal, getSectionSegmentPool());
12720   Uint32 attrInfoLength= attrInfoReader.getSize();
12721 
12722   ndbassert( offset < attrInfoLength );
12723   if (unlikely(! attrInfoReader.step( offset )))
12724     return false;
12725   attrInfoLength-= offset;
12726 
12727   signal->theData[0] = connectPtr;
12728   signal->theData[1] = regApiPtr->transid[0];
12729   signal->theData[2] = regApiPtr->transid[1];
12730 
12731   while (attrInfoLength != 0)
12732   {
12733     Uint32 dataInSignal= MIN(AttrInfo::DataLength, attrInfoLength);
12734 
12735     if (unlikely(! attrInfoReader.getWords(&signal->theData[3],
12736                                            dataInSignal)))
12737       return false;
12738 
12739     sendSignal(TBRef, GSN_ATTRINFO, signal,
12740                AttrInfo::HeaderLength + dataInSignal, JBB);
12741 
12742     attrInfoLength-= dataInSignal;
12743   }
12744   return true;
12745 } //Dbtc::sendAttrInfoTrain()
12746 
sendContinueTimeOutControl(Signal * signal,Uint32 TapiConPtr)12747 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
12748 {
12749   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
12750   signal->theData[1] = TapiConPtr;
12751   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
12752 }//Dbtc::sendContinueTimeOutControl()
12753 
sendSystemError(Signal * signal,int line)12754 void Dbtc::sendSystemError(Signal* signal, int line)
12755 {
12756   progError(line, NDBD_EXIT_NDBREQUIRE);
12757 }//Dbtc::sendSystemError()
12758 
12759 /* ========================================================================= */
12760 /* -------             LINK ACTUAL GCP OUT OF LIST                   ------- */
12761 /* ------------------------------------------------------------------------- */
unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)12762 void Dbtc::unlinkGcp(Ptr<GcpRecord> tmpGcpPtr)
12763 {
12764   ndbrequire(cfirstgcp == tmpGcpPtr.i);
12765 
12766   cfirstgcp = tmpGcpPtr.p->nextGcp;
12767   if (tmpGcpPtr.i == clastgcp) {
12768     jam();
12769     clastgcp = RNIL;
12770   }//if
12771 
12772   tmpGcpPtr.p->nextGcp = cfirstfreeGcp;
12773   cfirstfreeGcp = tmpGcpPtr.i;
12774 }//Dbtc::unlinkGcp()
12775 
12776 void
execDUMP_STATE_ORD(Signal * signal)12777 Dbtc::execDUMP_STATE_ORD(Signal* signal)
12778 {
12779   jamEntry();
12780   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
12781   Uint32 arg = signal->theData[0];
12782   if (signal->theData[0] == DumpStateOrd::CommitAckMarkersSize)
12783   {
12784     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
12785               m_commitAckMarkerPool.getNoOfFree(),
12786               m_commitAckMarkerPool.getSize());
12787     return;
12788   }
12789   if (signal->theData[0] == DumpStateOrd::CommitAckMarkersDump)
12790   {
12791     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
12792               m_commitAckMarkerPool.getNoOfFree(),
12793               m_commitAckMarkerPool.getSize());
12794     CommitAckMarkerIterator iter;
12795     for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
12796         m_commitAckMarkerHash.next(iter)){
12797       infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
12798                 " Api: %d %x %x %x %x bucket = %d",
12799                 iter.curr.i,
12800                 iter.curr.p->transid1,
12801                 iter.curr.p->transid2,
12802                 iter.curr.p->apiNodeId,
12803                 iter.curr.p->m_commit_ack_marker_nodes.getWord(0),
12804                 iter.curr.p->m_commit_ack_marker_nodes.getWord(1),
12805                 iter.curr.p->m_commit_ack_marker_nodes.getWord(2),
12806                 iter.curr.p->m_commit_ack_marker_nodes.getWord(3),
12807                 iter.bucket);
12808     }
12809     return;
12810   }
12811   // Dump all ScanFragRecs
12812   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
12813     Uint32 recordNo = 0;
12814     if (signal->getLength() == 1)
12815       infoEvent("TC: Dump all ScanFragRec - size: %d",
12816 		cscanFragrecFileSize);
12817     else if (signal->getLength() == 2)
12818       recordNo = dumpState->args[1];
12819     else
12820       return;
12821 
12822     dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
12823     dumpState->args[1] = recordNo;
12824     execDUMP_STATE_ORD(signal);
12825 
12826     if (recordNo < cscanFragrecFileSize-1){
12827       dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
12828       dumpState->args[1] = recordNo+1;
12829       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12830     }
12831   }
12832 
12833   // Dump one ScanFragRec
12834   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
12835     Uint32 recordNo = RNIL;
12836     if (signal->getLength() == 2)
12837       recordNo = dumpState->args[1];
12838     else
12839       return;
12840 
12841     if (recordNo >= cscanFragrecFileSize)
12842       return;
12843 
12844     ScanFragRecPtr sfp;
12845     sfp.i = recordNo;
12846     c_scan_frag_pool.getPtr(sfp);
12847     infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
12848 	      sfp.i,
12849 	      sfp.p->scanFragState,
12850 	      sfp.p->scanFragId);
12851     infoEvent(" nodeid=%d, timer=%d",
12852 	      refToNode(sfp.p->lqhBlockref),
12853 	      sfp.p->scanFragTimer);
12854   }
12855 
12856   // Dump all ScanRecords
12857   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
12858     Uint32 recordNo = 0;
12859     if (signal->getLength() == 1)
12860       infoEvent("TC: Dump all ScanRecord - size: %d",
12861 		cscanrecFileSize);
12862     else if (signal->getLength() == 2)
12863       recordNo = dumpState->args[1];
12864     else
12865       return;
12866 
12867     dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
12868     dumpState->args[1] = recordNo;
12869     execDUMP_STATE_ORD(signal);
12870 
12871     if (recordNo < cscanrecFileSize-1){
12872       dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
12873       dumpState->args[1] = recordNo+1;
12874       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12875     }
12876   }
12877 
12878   // Dump all active ScanRecords
12879   if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
12880     Uint32 recordNo = 0;
12881     if (signal->getLength() == 1)
12882       infoEvent("TC: Dump active ScanRecord - size: %d",
12883 		cscanrecFileSize);
12884     else if (signal->getLength() == 2)
12885       recordNo = dumpState->args[1];
12886     else
12887       return;
12888 
12889     ScanRecordPtr sp;
12890     sp.i = recordNo;
12891     ptrAss(sp, scanRecord);
12892     if (sp.p->scanState != ScanRecord::IDLE){
12893       dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
12894       dumpState->args[1] = recordNo;
12895       execDUMP_STATE_ORD(signal);
12896     }
12897 
12898     if (recordNo < cscanrecFileSize-1){
12899       dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
12900       dumpState->args[1] = recordNo+1;
12901       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12902     }
12903   }
12904 
12905   // Dump one ScanRecord
12906   // and associated ScanFragRec and ApiConnectRecord
12907   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
12908     Uint32 recordNo = RNIL;
12909     if (signal->getLength() == 2)
12910       recordNo = dumpState->args[1];
12911     else
12912       return;
12913 
12914     if (recordNo >= cscanrecFileSize)
12915       return;
12916 
12917     ScanRecordPtr sp;
12918     sp.i = recordNo;
12919     ptrAss(sp, scanRecord);
12920     infoEvent("Dbtc::ScanRecord[%d]: state=%d"
12921 	      "nextfrag=%d, nofrag=%d",
12922 	      sp.i,
12923 	      sp.p->scanState,
12924 	      sp.p->scanNextFragId,
12925 	      sp.p->scanNoFrag);
12926     infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
12927 	      sp.p->scanAiLength,
12928 	      sp.p->scanParallel,
12929 	      sp.p->scanReceivedOperations,
12930 	      sp.p->batch_size_rows);
12931     infoEvent(" schv=%d, tab=%d, sproc=%d",
12932 	      sp.p->scanSchemaVersion,
12933 	      sp.p->scanTableref,
12934 	      sp.p->scanStoredProcId);
12935     infoEvent(" apiRec=%d, next=%d",
12936 	      sp.p->scanApiRec, sp.p->nextScan);
12937 
12938     if (sp.p->scanState != ScanRecord::IDLE){
12939       // Request dump of ScanFragRec
12940       ScanFragRecPtr sfptr;
12941 #define DUMP_SFR(x){\
12942       ScanFragList list(c_scan_frag_pool, x);\
12943       for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
12944 	dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
12945 	dumpState->args[1] = sfptr.i;\
12946 	execDUMP_STATE_ORD(signal);\
12947       }}
12948 
12949       DUMP_SFR(sp.p->m_running_scan_frags);
12950       DUMP_SFR(sp.p->m_queued_scan_frags);
12951       DUMP_SFR(sp.p->m_delivered_scan_frags);
12952 
12953       // Request dump of ApiConnectRecord
12954       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
12955       dumpState->args[1] = sp.p->scanApiRec;
12956       execDUMP_STATE_ORD(signal);
12957     }
12958 
12959   }
12960 
12961   // Dump all ApiConnectRecord(s)
12962   if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
12963     Uint32 recordNo = 0;
12964     if (signal->getLength() == 1)
12965       infoEvent("TC: Dump all ApiConnectRecord - size: %d",
12966 		capiConnectFilesize);
12967     else if (signal->getLength() == 2)
12968       recordNo = dumpState->args[1];
12969     else
12970       return;
12971 
12972     dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
12973     dumpState->args[1] = recordNo;
12974     execDUMP_STATE_ORD(signal);
12975 
12976     if (recordNo < capiConnectFilesize-1){
12977       dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
12978       dumpState->args[1] = recordNo+1;
12979       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
12980     }
12981   }
12982 
12983   // Dump one ApiConnectRecord
12984   if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
12985     Uint32 recordNo = RNIL;
12986     if (signal->getLength() == 2)
12987       recordNo = dumpState->args[1];
12988     else
12989       return;
12990 
12991     if (recordNo >= capiConnectFilesize)
12992       return;
12993 
12994     ApiConnectRecordPtr ap;
12995     ap.i = recordNo;
12996     ptrAss(ap, apiConnectRecord);
12997     infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
12998 	      "apiFailState=%d",
12999 	      ap.i,
13000 	      ap.p->apiConnectstate,
13001 	      ap.p->abortState,
13002 	      ap.p->apiFailState);
13003     infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
13004 	      ap.p->transid[0],
13005 	      ap.p->transid[1],
13006 	      ap.p->ndbapiBlockref,
13007 	      ap.p->apiScanRec);
13008     infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
13009 	      "retsig=%d",
13010 	      ctcTimer, getApiConTimer(ap.i),
13011 	      ap.p->counter,
13012 	      ap.p->returncode,
13013 	      ap.p->returnsignal);
13014     infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
13015 	      "tckeyrec=%d",
13016 	      ap.p->lqhkeyconfrec,
13017 	      ap.p->lqhkeyreqrec,
13018 	      ap.p->tckeyrec);
13019     infoEvent(" next=%d ",
13020 	      ap.p->nextApiConnect);
13021   }
13022 
13023   if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
13024     jam();
13025     if(signal->getLength() > 1){
13026       set_timeout_value(signal->theData[1]);
13027     }
13028   }
13029 
13030   if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
13031     jam();
13032     if(signal->getLength() > 1){
13033       set_appl_timeout_value(signal->theData[1]);
13034     }
13035   }
13036 
13037   if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
13038   {
13039     static int frequency = 1;
13040     if (signal->getLength() > 1)
13041       frequency = signal->theData[1];
13042     else
13043       if (refToBlock(signal->getSendersBlockRef()) != DBTC)
13044 	frequency = 1;
13045 
13046     if (frequency)
13047     {
13048       dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
13049       execDUMP_STATE_ORD(signal);
13050       dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
13051 
13052       Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
13053       sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
13054     }
13055   }
13056 
13057   if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
13058   {
13059     infoEvent("IndexOpCount: pool: %d free: %d",
13060 	      c_theIndexOperationPool.getSize(),
13061 	      c_theIndexOperationPool.getNoOfFree());
13062   }
13063 
13064   if (dumpState->args[0] == 2514)
13065   {
13066     if (signal->getLength() == 2)
13067     {
13068       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
13069       execDUMP_STATE_ORD(signal);
13070     }
13071 
13072     NodeReceiverGroup rg(CMVMI, c_alive_nodes);
13073     dumpState->args[0] = 15;
13074     sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
13075 
13076     signal->theData[0] = 2515;
13077     sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, 1000, 1);
13078     return;
13079   }
13080 
13081   if (dumpState->args[0] == 2515)
13082   {
13083     NdbNodeBitmask mask = c_alive_nodes;
13084     mask.clear(getOwnNodeId());
13085     NodeReceiverGroup rg(NDBCNTR, mask);
13086 
13087     sendSignal(rg, GSN_SYSTEM_ERROR, signal, 1, JBB);
13088     sendSignalWithDelay(cownref, GSN_SYSTEM_ERROR, signal, 300, 1);
13089     return;
13090   }
13091 
13092   if (arg == 2550)
13093   {
13094     jam();
13095     Uint32 len = signal->getLength() - 1;
13096     if (len + 2 > 25)
13097     {
13098       jam();
13099       infoEvent("Too long filter");
13100       return;
13101     }
13102     if (validate_filter(signal))
13103     {
13104       jam();
13105       memmove(signal->theData + 2, signal->theData + 1, 4 * len);
13106       signal->theData[0] = 2551;
13107       signal->theData[1] = 0;    // record
13108       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 2, JBB);
13109 
13110       infoEvent("Starting dump of transactions");
13111     }
13112     return;
13113   }
13114 
13115   if (arg == 2551)
13116   {
13117     jam();
13118     Uint32 record = signal->theData[1];
13119     Uint32 len = signal->getLength();
13120     ndbassert(len > 1);
13121 
13122     ApiConnectRecordPtr ap;
13123     ap.i = record;
13124     ptrAss(ap, apiConnectRecord);
13125 
13126     bool print = false;
13127     for (Uint32 i = 0; i<32; i++)
13128     {
13129       jam();
13130       print = match_and_print(signal, ap);
13131 
13132       ap.i++;
13133       if (ap.i == capiConnectFilesize || print)
13134       {
13135 	jam();
13136 	break;
13137       }
13138 
13139       ptrAss(ap, apiConnectRecord);
13140     }
13141 
13142     if (ap.i == capiConnectFilesize)
13143     {
13144       jam();
13145       infoEvent("End of transaction dump");
13146       return;
13147     }
13148 
13149     signal->theData[1] = ap.i;
13150     if (print)
13151     {
13152       jam();
13153       sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
13154     }
13155     else
13156     {
13157       jam();
13158       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
13159     }
13160     return;
13161   }
13162 #ifdef ERROR_INSERT
13163   if (arg == 2552 || arg == 4002)
13164   {
13165     ndbrequire(m_commitAckMarkerPool.getNoOfFree() == m_commitAckMarkerPool.getSize());
13166     return;
13167   }
13168 #endif
13169 
13170   if (arg == 7019 && signal->getLength() == 2)
13171   {
13172     jam();
13173     Uint32 nodeId = signal->theData[1];
13174     if (nodeId < MAX_NODES && nodeId < NDB_ARRAY_SIZE(capiConnectClosing))
13175     {
13176       warningEvent(" DBTC: capiConnectClosing[%u]: %u",
13177                    nodeId, capiConnectClosing[nodeId]);
13178     }
13179     else
13180     {
13181       warningEvent(" DBTC: dump-7019 to unknown node: %u", nodeId);
13182     }
13183   }
13184 }//Dbtc::execDUMP_STATE_ORD()
13185 
execDBINFO_SCANREQ(Signal * signal)13186 void Dbtc::execDBINFO_SCANREQ(Signal *signal)
13187 {
13188   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
13189   const Ndbinfo::ScanCursor* cursor =
13190     CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
13191   Ndbinfo::Ratelimit rl;
13192 
13193   jamEntry();
13194 
13195   switch(req.tableId){
13196   case Ndbinfo::POOLS_TABLEID:
13197   {
13198     Ndbinfo::pool_entry pools[] =
13199     {
13200       { "Defined Trigger",
13201         c_theDefinedTriggerPool.getUsed(),
13202         c_theDefinedTriggerPool.getSize(),
13203         c_theDefinedTriggerPool.getEntrySize(),
13204         c_theDefinedTriggerPool.getUsedHi(),
13205         { CFG_DB_NO_TRIGGERS,0,0,0 }},
13206       { "Fired Trigger",
13207         c_theFiredTriggerPool.getUsed(),
13208         c_theFiredTriggerPool.getSize(),
13209         c_theFiredTriggerPool.getEntrySize(),
13210         c_theFiredTriggerPool.getUsedHi(),
13211         { CFG_DB_NO_TRIGGER_OPS,0,0,0 }},
13212       { "Index",
13213         c_theIndexPool.getUsed(),
13214         c_theIndexPool.getSize(),
13215         c_theIndexPool.getEntrySize(),
13216         c_theIndexPool.getUsedHi(),
13217         { CFG_DB_NO_TABLES,
13218           CFG_DB_NO_ORDERED_INDEXES,
13219           CFG_DB_NO_UNIQUE_HASH_INDEXES,0 }},
13220       { "Scan Fragment",
13221         c_scan_frag_pool.getUsed(),
13222         c_scan_frag_pool.getSize(),
13223         c_scan_frag_pool.getEntrySize(),
13224         c_scan_frag_pool.getUsedHi(),
13225         { CFG_DB_NO_LOCAL_SCANS,0,0,0 }},
13226       { "Commit ACK Marker",
13227         m_commitAckMarkerPool.getUsed(),
13228         m_commitAckMarkerPool.getSize(),
13229         m_commitAckMarkerPool.getEntrySize(),
13230         m_commitAckMarkerPool.getUsedHi(),
13231         { CFG_DB_NO_TRANSACTIONS,0,0,0 }},
13232       { "Index Op",
13233         c_theIndexOperationPool.getUsed(),
13234         c_theIndexOperationPool.getSize(),
13235         c_theIndexOperationPool.getEntrySize(),
13236         c_theIndexOperationPool.getUsedHi(),
13237         { CFG_DB_NO_INDEX_OPS,0,0,0 }},
13238       { "Operations",
13239         c_counters.cconcurrentOp,
13240         ctcConnectFilesize,
13241         sizeof(TcConnectRecord),
13242         0,
13243         { CFG_DB_NO_TRANSACTIONS,
13244           CFG_DB_NO_OPS,0,0 }},
13245       { NULL, 0,0,0,0,{0,0,0,0} }
13246     };
13247 
13248    const size_t num_config_params =
13249       sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
13250     Uint32 pool = cursor->data[0];
13251     BlockNumber bn = blockToMain(number());
13252     while(pools[pool].poolname)
13253     {
13254       jam();
13255       Ndbinfo::Row row(signal, req);
13256       row.write_uint32(getOwnNodeId());
13257       row.write_uint32(bn);           // block number
13258       row.write_uint32(instance());   // block instance
13259       row.write_string(pools[pool].poolname);
13260 
13261       row.write_uint64(pools[pool].used);
13262       row.write_uint64(pools[pool].total);
13263       row.write_uint64(pools[pool].used_hi);
13264       row.write_uint64(pools[pool].entry_size);
13265       for (size_t i = 0; i < num_config_params; i++)
13266         row.write_uint32(pools[pool].config_params[i]);
13267       ndbinfo_send_row(signal, req, row, rl);
13268       pool++;
13269       if (rl.need_break(req))
13270       {
13271         jam();
13272         ndbinfo_send_scan_break(signal, req, rl, pool);
13273         return;
13274       }
13275     }
13276     break;
13277   }
13278 
13279   case Ndbinfo::COUNTERS_TABLEID:
13280   {
13281     Ndbinfo::counter_entry counters[] = {
13282       { Ndbinfo::ATTRINFO_COUNTER, c_counters.cattrinfoCount },
13283       { Ndbinfo::TRANSACTIONS_COUNTER, c_counters.ctransCount },
13284       { Ndbinfo::COMMITS_COUNTER, c_counters.ccommitCount },
13285       { Ndbinfo::READS_COUNTER, c_counters.creadCount },
13286       { Ndbinfo::SIMPLE_READS_COUNTER, c_counters.csimpleReadCount },
13287       { Ndbinfo::WRITES_COUNTER, c_counters.cwriteCount },
13288       { Ndbinfo::ABORTS_COUNTER, c_counters.cabortCount },
13289       { Ndbinfo::TABLE_SCANS_COUNTER, c_counters.c_scan_count },
13290       { Ndbinfo::RANGE_SCANS_COUNTER, c_counters.c_range_scan_count }
13291     };
13292     const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
13293 
13294     Uint32 i = cursor->data[0];
13295     BlockNumber bn = blockToMain(number());
13296     while(i < num_counters)
13297     {
13298       jam();
13299       Ndbinfo::Row row(signal, req);
13300       row.write_uint32(getOwnNodeId());
13301       row.write_uint32(bn);           // block number
13302       row.write_uint32(instance());   // block instance
13303       row.write_uint32(counters[i].id);
13304 
13305       row.write_uint64(counters[i].val);
13306       ndbinfo_send_row(signal, req, row, rl);
13307       i++;
13308       if (rl.need_break(req))
13309       {
13310         jam();
13311         ndbinfo_send_scan_break(signal, req, rl, i);
13312         return;
13313       }
13314     }
13315 
13316     break;
13317   }
13318 
13319   default:
13320     break;
13321   }
13322 
13323   ndbinfo_send_scan_conf(signal, req, rl);
13324 }
13325 
13326 bool
validate_filter(Signal * signal)13327 Dbtc::validate_filter(Signal* signal)
13328 {
13329   Uint32 * start = signal->theData + 1;
13330   Uint32 * end = signal->theData + signal->getLength();
13331   if (start == end)
13332   {
13333     infoEvent("No filter specified, not listing...");
13334     return false;
13335   }
13336 
13337   while(start < end)
13338   {
13339     switch(* start){
13340     case 1: // API Node
13341     case 4: // Inactive time
13342       start += 2;
13343       break;
13344     case 2: // Transid
13345       start += 3;
13346       break;
13347     default:
13348       infoEvent("Invalid filter op: 0x%x pos: %ld",
13349 		* start,
13350 		(long int)(start - (signal->theData + 1)));
13351       return false;
13352     }
13353   }
13354 
13355   if (start != end)
13356   {
13357     infoEvent("Invalid filter, unexpected end");
13358     return false;
13359   }
13360 
13361   return true;
13362 }
13363 
13364 bool
match_and_print(Signal * signal,ApiConnectRecordPtr apiPtr)13365 Dbtc::match_and_print(Signal* signal, ApiConnectRecordPtr apiPtr)
13366 {
13367   Uint32 conState = apiPtr.p->apiConnectstate;
13368   if (conState == CS_CONNECTED ||
13369       conState == CS_DISCONNECTED ||
13370       conState == CS_RESTART)
13371     return false;
13372 
13373   Uint32 len = signal->getLength();
13374   Uint32* start = signal->theData + 2;
13375   Uint32* end = signal->theData + len;
13376   Uint32 apiTimer = getApiConTimer(apiPtr.i);
13377   while (start < end)
13378   {
13379     jam();
13380     switch(* start){
13381     case 1:
13382       jam();
13383       if (refToNode(apiPtr.p->ndbapiBlockref) != * (start + 1))
13384 	return false;
13385       start += 2;
13386       break;
13387     case 2:
13388       jam();
13389       if (apiPtr.p->transid[0] != * (start + 1) ||
13390 	  apiPtr.p->transid[1] != * (start + 2))
13391 	return false;
13392       start += 3;
13393       break;
13394     case 4:{
13395       jam();
13396       if (apiTimer == 0 || ((ctcTimer - apiTimer) / 100) < * (start + 1))
13397 	return false;
13398       start += 2;
13399       break;
13400     }
13401     default:
13402       ndbassert(false);
13403       return false;
13404     }
13405   }
13406 
13407   if (start != end)
13408   {
13409     ndbassert(false);
13410     return false;
13411   }
13412 
13413   /**
13414    * Do print
13415    */
13416   Uint32 *temp = signal->theData + 25;
13417   memcpy(temp, signal->theData, 4 * len);
13418 
13419   char state[10];
13420   const char *stateptr = "";
13421 
13422   switch(apiPtr.p->apiConnectstate){
13423   case CS_STARTED:
13424     stateptr = "Prepared";
13425     break;
13426   case CS_RECEIVING:
13427   case CS_REC_COMMITTING:
13428   case CS_START_COMMITTING:
13429     stateptr = "Running";
13430     break;
13431   case CS_COMMITTING:
13432     stateptr = "Committing";
13433     break;
13434   case CS_COMPLETING:
13435     stateptr = "Completing";
13436     break;
13437   case CS_PREPARE_TO_COMMIT:
13438     stateptr = "Prepare to commit";
13439     break;
13440   case CS_COMMIT_SENT:
13441     stateptr = "Commit sent";
13442     break;
13443   case CS_COMPLETE_SENT:
13444     stateptr = "Complete sent";
13445     break;
13446   case CS_ABORTING:
13447     stateptr = "Aborting";
13448     break;
13449   case CS_START_SCAN:
13450     stateptr = "Scanning";
13451     break;
13452   case CS_WAIT_ABORT_CONF:
13453   case CS_WAIT_COMMIT_CONF:
13454   case CS_WAIT_COMPLETE_CONF:
13455   case CS_FAIL_PREPARED:
13456   case CS_FAIL_COMMITTING:
13457   case CS_FAIL_COMMITTED:
13458   case CS_REC_PREPARING:
13459   case CS_START_PREPARING:
13460   case CS_PREPARED:
13461   case CS_RESTART:
13462   case CS_FAIL_ABORTED:
13463   case CS_DISCONNECTED:
13464   default:
13465     BaseString::snprintf(state, sizeof(state),
13466 			 "%u", apiPtr.p->apiConnectstate);
13467     stateptr = state;
13468     break;
13469   }
13470 
13471   char buf[100];
13472   BaseString::snprintf(buf, sizeof(buf),
13473 		       "TRX[%u]: API: %d(0x%x)"
13474 		       "transid: 0x%x 0x%x inactive: %u(%d) state: %s",
13475 		       apiPtr.i,
13476 		       refToNode(apiPtr.p->ndbapiBlockref),
13477 		       refToBlock(apiPtr.p->ndbapiBlockref),
13478 		       apiPtr.p->transid[0],
13479 		       apiPtr.p->transid[1],
13480 		       apiTimer ? (ctcTimer - apiTimer) / 100 : 0,
13481 		       c_apiConTimer_line[apiPtr.i],
13482 		       stateptr);
13483   infoEvent("%s", buf);
13484 
13485   memcpy(signal->theData, temp, 4*len);
13486   return true;
13487 }
13488 
execABORT_ALL_REQ(Signal * signal)13489 void Dbtc::execABORT_ALL_REQ(Signal* signal)
13490 {
13491   jamEntry();
13492   AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
13493   AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
13494 
13495   const Uint32 senderData = req->senderData;
13496   const BlockReference senderRef = req->senderRef;
13497 
13498   if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
13499     jam();
13500 
13501     ref->senderData = senderData;
13502     ref->errorCode = AbortAllRef::InvalidState;
13503     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13504 	       AbortAllRef::SignalLength, JBB);
13505     return;
13506   }
13507 
13508   if(c_abortRec.clientRef != 0){
13509     jam();
13510 
13511     ref->senderData = senderData;
13512     ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
13513     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13514 	       AbortAllRef::SignalLength, JBB);
13515     return;
13516   }
13517 
13518   if(refToNode(senderRef) != getOwnNodeId()){
13519     jam();
13520 
13521     ref->senderData = senderData;
13522     ref->errorCode = AbortAllRef::FunctionNotImplemented;
13523     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
13524 	       AbortAllRef::SignalLength, JBB);
13525     return;
13526   }
13527 
13528   c_abortRec.clientRef = senderRef;
13529   c_abortRec.clientData = senderData;
13530   c_abortRec.oldTimeOutValue = ctimeOutValue;
13531 
13532   ctimeOutValue = 0;
13533   const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
13534 
13535   checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
13536 }
13537 
checkAbortAllTimeout(Signal * signal,Uint32 sleepTime)13538 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
13539 {
13540 
13541   ndbrequire(c_abortRec.clientRef != 0);
13542 
13543   if(sleepTime > 0){
13544     jam();
13545 
13546     sleepTime -= 1;
13547     signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
13548     signal->theData[1] = sleepTime;
13549     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
13550     return;
13551   }
13552 
13553   AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
13554   conf->senderData = c_abortRec.clientData;
13555   sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
13556 	     AbortAllConf::SignalLength, JBB);
13557 
13558   ctimeOutValue = c_abortRec.oldTimeOutValue;
13559   c_abortRec.clientRef = 0;
13560 }
13561 
13562 /* **************************************************************** */
13563 /* ---------------------------------------------------------------- */
13564 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
13565 /* ---------------------------------------------------------------- */
13566 /* **************************************************************** */
13567 
execCREATE_TRIG_IMPL_REQ(Signal * signal)13568 void Dbtc::execCREATE_TRIG_IMPL_REQ(Signal* signal)
13569 {
13570   jamEntry();
13571   if (!assembleFragments(signal))
13572   {
13573     jam();
13574     return;
13575   }
13576 
13577   const CreateTrigImplReq* req = (const CreateTrigImplReq*)signal->getDataPtr();
13578   const Uint32 senderRef = req->senderRef;
13579   const Uint32 senderData = req->senderData;
13580 
13581   SectionHandle handle(this, signal);
13582   releaseSections(handle); // Not using mask
13583 
13584   TcDefinedTriggerData* triggerData;
13585   DefinedTriggerPtr triggerPtr;
13586 
13587   triggerPtr.i = req->triggerId;
13588   if (ERROR_INSERTED(8033) ||
13589       !c_theDefinedTriggers.seizeId(triggerPtr, req->triggerId)) {
13590     jam();
13591     CLEAR_ERROR_INSERT_VALUE;
13592     // Failed to allocate trigger record
13593 ref:
13594     CreateTrigImplRef* ref =  (CreateTrigImplRef*)signal->getDataPtrSend();
13595 
13596     ref->senderRef = reference();
13597     ref->senderData = senderData;
13598     ref->errorCode = CreateTrigImplRef::InconsistentTC;
13599     ref->errorLine = __LINE__;
13600     sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_REF,
13601                signal, CreateTrigImplRef::SignalLength, JBB);
13602     return;
13603   }
13604 
13605   triggerData = triggerPtr.p;
13606   triggerData->triggerId = req->triggerId;
13607   triggerData->triggerType = TriggerInfo::getTriggerType(req->triggerInfo);
13608   triggerData->triggerEvent = TriggerInfo::getTriggerEvent(req->triggerInfo);
13609   triggerData->oldTriggerIds[0] = RNIL;
13610   triggerData->oldTriggerIds[1] = RNIL;
13611 
13612   switch(triggerData->triggerType){
13613   case TriggerType::SECONDARY_INDEX:
13614     jam();
13615     triggerData->indexId = req->indexId;
13616     break;
13617   case TriggerType::REORG_TRIGGER:
13618     jam();
13619     triggerData->tableId = req->tableId;
13620     break;
13621   default:
13622     c_theDefinedTriggers.release(triggerPtr);
13623     goto ref;
13624   }
13625 
13626   if (unlikely(req->triggerId != req->upgradeExtra[1]))
13627   {
13628     /**
13629      * This is nasty upgrade for unique indexes
13630      */
13631     jam();
13632     ndbrequire(req->triggerId == req->upgradeExtra[0]);
13633     ndbrequire(triggerData->triggerType == TriggerType::SECONDARY_INDEX);
13634 
13635     DefinedTriggerPtr insertPtr = triggerPtr;
13636     DefinedTriggerPtr updatePtr;
13637     DefinedTriggerPtr deletePtr;
13638     if (c_theDefinedTriggers.seizeId(updatePtr, req->upgradeExtra[1]) == false)
13639     {
13640       jam();
13641       c_theDefinedTriggers.release(insertPtr);
13642       goto ref;
13643     }
13644 
13645     if (c_theDefinedTriggers.seizeId(deletePtr, req->upgradeExtra[2]) == false)
13646     {
13647       jam();
13648       c_theDefinedTriggers.release(insertPtr);
13649       c_theDefinedTriggers.release(updatePtr);
13650       goto ref;
13651     }
13652 
13653     insertPtr.p->triggerEvent = TriggerEvent::TE_INSERT;
13654 
13655     updatePtr.p->triggerId = req->upgradeExtra[1];
13656     updatePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
13657     updatePtr.p->triggerEvent = TriggerEvent::TE_UPDATE;
13658     updatePtr.p->oldTriggerIds[0] = RNIL;
13659     updatePtr.p->oldTriggerIds[1] = RNIL;
13660     updatePtr.p->indexId = req->indexId;
13661 
13662     deletePtr.p->triggerId = req->upgradeExtra[2];
13663     deletePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
13664     deletePtr.p->triggerEvent = TriggerEvent::TE_DELETE;
13665     deletePtr.p->oldTriggerIds[0] = RNIL;
13666     deletePtr.p->oldTriggerIds[1] = RNIL;
13667     deletePtr.p->indexId = req->indexId;
13668   }
13669 
13670   CreateTrigImplConf* conf = (CreateTrigImplConf*)signal->getDataPtrSend();
13671   conf->senderRef = reference();
13672   conf->senderData = senderData;
13673   sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_CONF,
13674              signal, CreateTrigImplConf::SignalLength, JBB);
13675 }
13676 
execDROP_TRIG_IMPL_REQ(Signal * signal)13677 void Dbtc::execDROP_TRIG_IMPL_REQ(Signal* signal)
13678 {
13679   jamEntry();
13680   const DropTrigImplReq* req = (const DropTrigImplReq*)signal->getDataPtr();
13681   const Uint32 senderRef = req->senderRef;
13682   const Uint32 senderData = req->senderData;
13683 
13684   DefinedTriggerPtr triggerPtr;
13685   triggerPtr.i = req->triggerId;
13686 
13687   if (ERROR_INSERTED(8035) ||
13688       ((triggerPtr.p = c_theDefinedTriggers.getPtr(req->triggerId)) == NULL))
13689   {
13690     jam();
13691     CLEAR_ERROR_INSERT_VALUE;
13692     // Failed to find find trigger record
13693     DropTrigImplRef* ref = (DropTrigImplRef*)signal->getDataPtrSend();
13694 
13695     ref->senderRef = reference();
13696     ref->senderData = senderData;
13697     ref->errorCode = DropTrigImplRef::InconsistentTC;
13698     ref->errorLine = __LINE__;
13699     sendSignal(senderRef, GSN_DROP_TRIG_IMPL_REF,
13700                signal, DropTrigImplRef::SignalLength, JBB);
13701     return;
13702   }
13703 
13704   if (unlikely(triggerPtr.p->oldTriggerIds[0] != RNIL))
13705   {
13706     jam();
13707     c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[0]);
13708     c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[1]);
13709   }
13710 
13711   // Release trigger record
13712   c_theDefinedTriggers.release(triggerPtr);
13713 
13714   DropTrigImplConf* conf = (DropTrigImplConf*)signal->getDataPtrSend();
13715 
13716   conf->senderRef = reference();
13717   conf->senderData = senderData;
13718 
13719   sendSignal(senderRef, GSN_DROP_TRIG_IMPL_CONF,
13720              signal, DropTrigImplConf::SignalLength, JBB);
13721 }
13722 
execCREATE_INDX_IMPL_REQ(Signal * signal)13723 void Dbtc::execCREATE_INDX_IMPL_REQ(Signal* signal)
13724 {
13725   jamEntry();
13726   const CreateIndxImplReq * const req =
13727     (const CreateIndxImplReq *)signal->getDataPtr();
13728   const Uint32 senderRef = req->senderRef;
13729   const Uint32 senderData = req->senderData;
13730   TcIndexData* indexData;
13731   TcIndexDataPtr indexPtr;
13732 
13733   SectionHandle handle(this, signal);
13734   if (ERROR_INSERTED(8034) ||
13735       !c_theIndexes.seizeId(indexPtr, req->indexId)) {
13736     jam();
13737     CLEAR_ERROR_INSERT_VALUE;
13738     // Failed to allocate index record
13739      CreateIndxImplRef * const ref =
13740        (CreateIndxImplRef *)signal->getDataPtrSend();
13741 
13742      ref->senderRef = reference();
13743      ref->senderData = senderData;
13744      ref->errorCode = CreateIndxImplRef::InconsistentTC;
13745      ref->errorLine = __LINE__;
13746      releaseSections(handle);
13747      sendSignal(senderRef, GSN_CREATE_INDX_IMPL_REF,
13748                 signal, CreateIndxImplRef::SignalLength, JBB);
13749      return;
13750   }
13751   indexData = indexPtr.p;
13752   // Indexes always start in state IS_BUILDING
13753   // Will become IS_ONLINE in execALTER_INDX_IMPL_REQ
13754   indexData->indexState = IS_BUILDING;
13755   indexData->indexId = indexPtr.i;
13756   indexData->primaryTableId = req->tableId;
13757 
13758   // So far need only attribute count
13759   SegmentedSectionPtr ssPtr;
13760   handle.getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
13761   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
13762   r0.reset(); // undo implicit first()
13763   if (!r0.getWord(&indexData->attributeList.sz) ||
13764       !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
13765     ndbrequire(false);
13766   }
13767   indexData->primaryKeyPos = indexData->attributeList.sz;
13768 
13769   releaseSections(handle);
13770 
13771   CreateIndxImplConf * const conf =
13772     (CreateIndxImplConf *)signal->getDataPtrSend();
13773 
13774   conf->senderRef = reference();
13775   conf->senderData = senderData;
13776   sendSignal(senderRef, GSN_CREATE_INDX_IMPL_CONF,
13777              signal, CreateIndxImplConf::SignalLength, JBB);
13778 }
13779 
execALTER_INDX_IMPL_REQ(Signal * signal)13780 void Dbtc::execALTER_INDX_IMPL_REQ(Signal* signal)
13781 {
13782   jamEntry();
13783   const AlterIndxImplReq * const req =
13784     (const AlterIndxImplReq *)signal->getDataPtr();
13785   const Uint32 senderRef = req->senderRef;
13786   const Uint32 senderData = req->senderData;
13787   TcIndexData* indexData;
13788   const Uint32 requestType = req->requestType;
13789   const Uint32 indexId = req->indexId;
13790 
13791   if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
13792     jam();
13793     // Failed to find index record
13794     AlterIndxImplRef * const ref =
13795       (AlterIndxImplRef *)signal->getDataPtrSend();
13796 
13797     ref->senderRef = reference();
13798     ref->senderData = senderData;
13799     ref->errorCode = AlterIndxImplRef::InconsistentTC;
13800     ref->errorLine = __LINE__;
13801 
13802     sendSignal(senderRef, GSN_ALTER_INDX_IMPL_REF,
13803 	       signal, AlterIndxImplRef::SignalLength, JBB);
13804     return;
13805   }
13806   // Found index record, alter it's state
13807   switch (requestType) {
13808   case AlterIndxImplReq::AlterIndexOnline:
13809     jam();
13810     indexData->indexState = IS_ONLINE;
13811     break;
13812   case AlterIndxImplReq::AlterIndexOffline:
13813     jam();
13814     indexData->indexState = IS_BUILDING; // wl3600_todo ??
13815     break;
13816   default:
13817     ndbrequire(false);
13818     break;
13819   }
13820   AlterIndxImplConf * const conf =
13821     (AlterIndxImplConf *)signal->getDataPtrSend();
13822 
13823   conf->senderRef = reference();
13824   conf->senderData = senderData;
13825   sendSignal(senderRef, GSN_ALTER_INDX_IMPL_CONF,
13826 	     signal, AlterIndxImplConf::SignalLength, JBB);
13827 }
13828 
execFIRE_TRIG_ORD(Signal * signal)13829 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
13830 {
13831   jamEntry();
13832   FireTrigOrd * const fireOrd =  (FireTrigOrd *)signal->getDataPtr();
13833   ApiConnectRecordPtr transPtr;
13834   TcConnectRecordPtr opPtr;
13835   bool transIdOk = true;
13836   /* Check the received transaction id
13837    * Older nodes do not send transid info in FIRE_TRIG_ORD
13838    */
13839   const Uint32 sourceNode = refToNode(signal->getSendersBlockRef());
13840   const Uint32 sourceNodeVersion = getNodeInfo(sourceNode).m_version;
13841   bool sigContainsTransId = ndb_fire_trig_ord_transid(sourceNodeVersion);
13842 
13843   /* Get triggering operation record */
13844   opPtr.i = fireOrd->getConnectionPtr();
13845   ptrCheckGuard(opPtr, ctcConnectFilesize, tcConnectRecord);
13846 
13847   /* Get transaction record */
13848   transPtr.i = opPtr.p->apiConnect;
13849   if (unlikely(transPtr.i == RNIL))
13850   {
13851     /* Looks like the connect record was released
13852      * Treat as a bad transid
13853      */
13854     transIdOk = false;
13855   }
13856   else
13857   {
13858     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
13859 
13860     /* Check if signal's trans id and operation's transid are aligned */
13861     transIdOk = (! sigContainsTransId) |
13862       (! ((fireOrd->m_transId1 ^ transPtr.p->transid[0]) |
13863           (fireOrd->m_transId2 ^ transPtr.p->transid[1])));
13864   }
13865 
13866   TcFiredTriggerData key;
13867   key.fireingOperation = opPtr.i;
13868   key.nodeId = refToNode(signal->getSendersBlockRef());
13869   FiredTriggerPtr trigPtr;
13870   if(likely(c_firedTriggerHash.find(trigPtr, key)))
13871   {
13872     jam();
13873     c_firedTriggerHash.remove(trigPtr);
13874 
13875     trigPtr.p->triggerType = (TriggerType::Value)fireOrd->m_triggerType;
13876     trigPtr.p->triggerEvent = (TriggerEvent::Value)fireOrd->m_triggerEvent;
13877 
13878     if (unlikely(signal->getLength() < FireTrigOrd::SignalLength))
13879     {
13880       jam();
13881       ndbrequire(! sigContainsTransId );
13882       Ptr<TcDefinedTriggerData> ptr;
13883       c_theDefinedTriggers.getPtr(ptr, trigPtr.p->triggerId);
13884       trigPtr.p->triggerType = ptr.p->triggerType;
13885       trigPtr.p->triggerEvent = ptr.p->triggerEvent;
13886     }
13887     trigPtr.p->fragId= fireOrd->fragId;
13888     bool ok = transIdOk;
13889     ok &= trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
13890     ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
13891     ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
13892 
13893     if (ERROR_INSERTED(8085))
13894     {
13895       ok = false;
13896     }
13897 
13898     if(likely( ok ))
13899     {
13900       jam();
13901       setApiConTimer(transPtr.i, ctcTimer, __LINE__);
13902       opPtr.p->noReceivedTriggers++;
13903       opPtr.p->triggerExecutionCount++; // Default 1 LQHKEYREQ per trigger
13904 
13905       // Insert fired trigger in execution queue
13906       transPtr.p->theFiredTriggers.add(trigPtr);
13907       if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
13908           transPtr.p->isExecutingDeferredTriggers()) {
13909 	executeTriggers(signal, &transPtr);
13910       }
13911       return;
13912     }
13913 
13914     /* Trigger entry found but either :
13915      *   - Overload resulted in loss of Trig_Attrinfo
13916      *     : Release resources + Abort transaction
13917      *   - Bad transaction id due to concurrent abort?
13918      *     : Release resources
13919      */
13920     jam();
13921     // Release trigger records
13922     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13923     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
13924     tmp1.release();
13925     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
13926     tmp2.release();
13927     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
13928     tmp3.release();
13929     c_theFiredTriggerPool.release(trigPtr);
13930   }
13931 
13932   /* Either no trigger entry found, or overload, or
13933    * bad transid
13934    * If transid is ok, abort the transaction.
13935    * else, return.
13936    * (Note small risk of 'abort of innocent' in upgrade
13937    *  scenario with no transid in FIRE_TRIG_ORD)
13938    */
13939   jam();
13940   if (transIdOk)
13941   {
13942     jam();
13943     abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
13944   }
13945 
13946   return;
13947 }
13948 
execTRIG_ATTRINFO(Signal * signal)13949 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
13950 {
13951   jamEntry();
13952   TrigAttrInfo * const trigAttrInfo =  (TrigAttrInfo *)signal->getDataPtr();
13953   Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
13954   const Uint32 *src = trigAttrInfo->getData();
13955   FiredTriggerPtr firedTrigPtr;
13956 
13957   TcFiredTriggerData key;
13958   key.fireingOperation = trigAttrInfo->getConnectionPtr();
13959   key.nodeId = refToNode(signal->getSendersBlockRef());
13960   if(!c_firedTriggerHash.find(firedTrigPtr, key)){
13961     jam();
13962     /* TODO : Node failure handling (use sig-train assembly) */
13963     if(!c_firedTriggerHash.seize(firedTrigPtr)){
13964       jam();
13965       /**
13966        * Will be handled when FIRE_TRIG_ORD arrives
13967        */
13968       ndbout_c("op: %d node: %d failed to seize",
13969 	       key.fireingOperation, key.nodeId);
13970       return;
13971     }
13972     ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
13973 	       firedTrigPtr.p->beforeValues.getSize() == 0 &&
13974 	       firedTrigPtr.p->afterValues.getSize() == 0);
13975 
13976     firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
13977     firedTrigPtr.p->fireingOperation = key.fireingOperation;
13978     firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
13979     c_firedTriggerHash.add(firedTrigPtr);
13980   }
13981 
13982   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13983   switch (trigAttrInfo->getAttrInfoType()) {
13984   case(TrigAttrInfo::PRIMARY_KEY):
13985     jam();
13986     {
13987       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
13988       buf.append(src, attrInfoLength);
13989     }
13990     break;
13991   case(TrigAttrInfo::BEFORE_VALUES):
13992     jam();
13993     {
13994       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
13995       buf.append(src, attrInfoLength);
13996     }
13997     break;
13998   case(TrigAttrInfo::AFTER_VALUES):
13999     jam();
14000     {
14001       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
14002       buf.append(src, attrInfoLength);
14003     }
14004     break;
14005   default:
14006     ndbrequire(false);
14007   }
14008 }
14009 
execDROP_INDX_IMPL_REQ(Signal * signal)14010 void Dbtc::execDROP_INDX_IMPL_REQ(Signal* signal)
14011 {
14012   jamEntry();
14013   const DropIndxImplReq * const req =
14014     (const DropIndxImplReq *)signal->getDataPtr();
14015   const Uint32 senderRef = req->senderRef;
14016   const Uint32 senderData = req->senderData;
14017   TcIndexData* indexData;
14018 
14019   if (ERROR_INSERTED(8036) ||
14020       (indexData = c_theIndexes.getPtr(req->indexId)) == NULL) {
14021     jam();
14022     CLEAR_ERROR_INSERT_VALUE;
14023     // Failed to find index record
14024     DropIndxImplRef * const ref =
14025       (DropIndxImplRef *)signal->getDataPtrSend();
14026 
14027     ref->senderRef = reference();
14028     ref->senderData = senderData;
14029     ref->errorCode = DropIndxImplRef::InconsistentTC;
14030     ref->errorLine = __LINE__;
14031     sendSignal(senderRef, GSN_DROP_INDX_IMPL_REF,
14032                signal, DropIndxImplRef::SignalLength, JBB);
14033     return;
14034   }
14035   // Release index record
14036   c_theIndexes.release(req->indexId);
14037 
14038   DropIndxImplConf * const conf =
14039     (DropIndxImplConf *)signal->getDataPtrSend();
14040 
14041   conf->senderRef = reference();
14042   conf->senderData = senderData;
14043   sendSignal(senderRef, GSN_DROP_INDX_IMPL_CONF,
14044              signal, DropIndxImplConf::SignalLength, JBB);
14045 }
14046 
execTCINDXREQ(Signal * signal)14047 void Dbtc::execTCINDXREQ(Signal* signal)
14048 {
14049   jamEntry();
14050 
14051   TcKeyReq * const tcIndxReq =  (TcKeyReq *)signal->getDataPtr();
14052   const UintR TapiIndex = tcIndxReq->apiConnectPtr;
14053   Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
14054   Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
14055   ApiConnectRecordPtr transPtr;
14056   bool isLongTcIndxReq= (signal->getNoOfSections() != 0);
14057   SectionHandle handle(this, signal);
14058 
14059   transPtr.i = TapiIndex;
14060   if (transPtr.i >= capiConnectFilesize) {
14061     jam();
14062     warningHandlerLab(signal, __LINE__);
14063     releaseSections(handle);
14064     return;
14065   }//if
14066   ptrAss(transPtr, apiConnectRecord);
14067   ApiConnectRecord * const regApiPtr = transPtr.p;
14068   // Seize index operation
14069   TcIndexOperationPtr indexOpPtr;
14070   /**
14071    * NOTE this if-statement is incorrect,
14072    * see bug#50648
14073    *
14074    * The correct if is
14075    *
14076    if (startFlag == 1 &&
14077        (regApiPtr->apiConnectstate == CS_CONNECTED ||
14078         (regApiPtr->apiConnectstate == CS_STARTED &&
14079          regApiPtr->firstTcConnect == RNIL) ||
14080         (regApiPtr->apiConnectstate == CS_ABORTING &&
14081          regApiPtr->abortState == AS_IDLE)))
14082    */
14083   if (((startFlag == 1) &&
14084        (regApiPtr->apiConnectstate == CS_CONNECTED ||
14085         (regApiPtr->apiConnectstate == CS_STARTED &&
14086          regApiPtr->firstTcConnect == RNIL))) ||
14087       (regApiPtr->apiConnectstate == CS_ABORTING &&
14088        regApiPtr->abortState == AS_IDLE))
14089   {
14090     jam();
14091     // This is a newly started transaction, clean-up from any
14092     // previous transaction.
14093     releaseAllSeizedIndexOperations(regApiPtr);
14094 
14095     regApiPtr->apiConnectstate = CS_STARTED;
14096     regApiPtr->transid[0] = tcIndxReq->transId1;
14097     regApiPtr->transid[1] = tcIndxReq->transId2;
14098   }//if
14099 
14100   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
14101       getNodeState().getSingleUserApi() !=
14102       refToNode(regApiPtr->ndbapiBlockref))
14103   {
14104     jam();
14105     releaseSections(handle);
14106     terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
14107     regApiPtr->m_flags |=
14108       TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
14109       ApiConnectRecord::TF_EXEC_FLAG : 0;
14110     apiConnectptr = transPtr;
14111     abortErrorLab(signal);
14112     return;
14113   }
14114 
14115   if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
14116     jam();
14117     releaseSections(handle);
14118     // Failed to allocate index operation
14119     terrorCode = 288;
14120     regApiPtr->m_flags |=
14121       TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
14122       ApiConnectRecord::TF_EXEC_FLAG : 0;
14123     apiConnectptr = transPtr;
14124     abortErrorLab(signal);
14125     return;
14126   }
14127   TcIndexOperation* indexOp = indexOpPtr.p;
14128   indexOp->indexOpId = indexOpPtr.i;
14129 
14130   // Save original signal
14131   indexOp->tcIndxReq = *tcIndxReq;
14132   indexOp->connectionIndex = TapiIndex;
14133   regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
14134 
14135   if (isLongTcIndxReq)
14136   {
14137     jam();
14138     /* KeyInfo and AttrInfo already received into sections */
14139     SegmentedSectionPtr keyInfoSection, attrInfoSection;
14140 
14141     /* Store i value for first long section of KeyInfo
14142      * and AttrInfo in Index operation
14143      */
14144     handle.getSection(keyInfoSection,
14145                       TcKeyReq::KeyInfoSectionNum);
14146 
14147     indexOp->keyInfoSectionIVal= keyInfoSection.i;
14148 
14149     if (handle.m_cnt == 2)
14150     {
14151       handle.getSection(attrInfoSection,
14152                         TcKeyReq::AttrInfoSectionNum);
14153       indexOp->attrInfoSectionIVal= attrInfoSection.i;
14154     }
14155 
14156     /* Detach sections from the handle
14157      * Success path code, or index operation cleanup is
14158      * now responsible for freeing the sections
14159      */
14160     handle.clear();
14161 
14162     /* All data received, process */
14163     readIndexTable(signal, regApiPtr, indexOp);
14164     return;
14165   }
14166   else
14167   {
14168     jam();
14169     /* Short TcIndxReq, build up KeyInfo and AttrInfo
14170      * sections from separate signals
14171      */
14172     Uint32 * dataPtr = &tcIndxReq->scanInfo;
14173     Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
14174     Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
14175 
14176     indexOp->pendingKeyInfo = indexLength;
14177     indexOp->pendingAttrInfo = attrLength;
14178 
14179     const Uint32 includedIndexLength = MIN(indexLength, TcKeyReq::MaxKeyInfo);
14180     const Uint32 includedAttrLength = MIN(attrLength, TcKeyReq::MaxAttrInfo);
14181     int ret;
14182 
14183     if ((ret = saveINDXKEYINFO(signal,
14184                                indexOp,
14185                                dataPtr,
14186                                includedIndexLength)) == 0)
14187     {
14188       jam();
14189       /* All KI + no AI received, process */
14190       readIndexTable(signal, regApiPtr, indexOp);
14191       return;
14192     }
14193     else if (ret == -1)
14194     {
14195       jam();
14196       return;
14197     }
14198 
14199     dataPtr += includedIndexLength;
14200 
14201     if (saveINDXATTRINFO(signal,
14202                          indexOp,
14203                          dataPtr,
14204                          includedAttrLength) == 0) {
14205       jam();
14206       /* All KI and AI received, process */
14207       readIndexTable(signal, regApiPtr, indexOp);
14208       return;
14209     }
14210   }
14211 }
14212 
execINDXKEYINFO(Signal * signal)14213 void Dbtc::execINDXKEYINFO(Signal* signal)
14214 {
14215   jamEntry();
14216   Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
14217   IndxKeyInfo * const indxKeyInfo =  (IndxKeyInfo *)signal->getDataPtr();
14218   const Uint32 *src = indxKeyInfo->getData();
14219   const UintR TconnectIndex = indxKeyInfo->connectPtr;
14220   ApiConnectRecordPtr transPtr;
14221   transPtr.i = TconnectIndex;
14222   if (transPtr.i >= capiConnectFilesize) {
14223     jam();
14224     warningHandlerLab(signal, __LINE__);
14225     return;
14226   }//if
14227   ptrAss(transPtr, apiConnectRecord);
14228   ApiConnectRecord * const regApiPtr = transPtr.p;
14229   TcIndexOperationPtr indexOpPtr;
14230   TcIndexOperation* indexOp;
14231 
14232   if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
14233   {
14234     TCKEY_abort(signal, 19);
14235     return;
14236   }
14237 
14238   if (regApiPtr->apiConnectstate == CS_ABORTING)
14239   {
14240     jam();
14241     return;
14242   }
14243 
14244   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
14245   {
14246     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14247 
14248     ndbassert( indexOp->pendingKeyInfo > 0 );
14249 
14250     if (saveINDXKEYINFO(signal,
14251 			indexOp,
14252 			src,
14253 			keyInfoLength) == 0) {
14254       jam();
14255       /* All KI + AI received, process */
14256       readIndexTable(signal, regApiPtr, indexOp);
14257     }
14258   }
14259 }
14260 
execINDXATTRINFO(Signal * signal)14261 void Dbtc::execINDXATTRINFO(Signal* signal)
14262 {
14263   jamEntry();
14264   Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
14265   IndxAttrInfo * const indxAttrInfo =  (IndxAttrInfo *)signal->getDataPtr();
14266   const Uint32 *src = indxAttrInfo->getData();
14267   const UintR TconnectIndex = indxAttrInfo->connectPtr;
14268   ApiConnectRecordPtr transPtr;
14269   transPtr.i = TconnectIndex;
14270   if (transPtr.i >= capiConnectFilesize) {
14271     jam();
14272     warningHandlerLab(signal, __LINE__);
14273     return;
14274   }//if
14275   ptrAss(transPtr, apiConnectRecord);
14276   ApiConnectRecord * const regApiPtr = transPtr.p;
14277   TcIndexOperationPtr indexOpPtr;
14278   TcIndexOperation* indexOp;
14279 
14280   if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
14281   {
14282     TCKEY_abort(signal, 19);
14283     return;
14284   }
14285 
14286   if (regApiPtr->apiConnectstate == CS_ABORTING)
14287   {
14288     jam();
14289     return;
14290   }
14291 
14292   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
14293   {
14294     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14295 
14296     ndbassert( indexOp->pendingAttrInfo > 0 );
14297 
14298     if (saveINDXATTRINFO(signal,
14299 			 indexOp,
14300 			 src,
14301 			 attrInfoLength) == 0) {
14302       jam();
14303       /* All KI + AI received, process */
14304       readIndexTable(signal, regApiPtr, indexOp);
14305       return;
14306     }
14307     return;
14308   }
14309 }
14310 
14311 /**
14312  * Save received KeyInfo
14313  * Return true if we have received all needed data
14314  */
14315 int
saveINDXKEYINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)14316 Dbtc::saveINDXKEYINFO(Signal* signal,
14317                       TcIndexOperation* indexOp,
14318                       const Uint32 *src,
14319                       Uint32 len)
14320 {
14321   if (ERROR_INSERTED(8052) ||
14322       ! appendToSection(indexOp->keyInfoSectionIVal,
14323                         src,
14324                         len))
14325   {
14326     jam();
14327     // Failed to seize keyInfo, abort transaction
14328 #ifdef VM_TRACE
14329     ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize buffer for KeyInfo\n");
14330 #endif
14331     // Abort transaction
14332     apiConnectptr.i = indexOp->connectionIndex;
14333     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14334     releaseIndexOperation(apiConnectptr.p, indexOp);
14335     terrorCode = 289;
14336     if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
14337       apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
14338     abortErrorLab(signal);
14339     return -1;
14340   }
14341   indexOp->pendingKeyInfo-= len;
14342 
14343   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
14344     jam();
14345     return 0;
14346   }
14347   return 1;
14348 }
14349 
receivedAllINDXKEYINFO(TcIndexOperation * indexOp)14350 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
14351 {
14352   return (indexOp->pendingKeyInfo == 0);
14353 }
14354 
14355 /**
14356  * Save signal INDXATTRINFO
14357  * Return true if we have received all needed data
14358  */
14359 int
saveINDXATTRINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)14360 Dbtc::saveINDXATTRINFO(Signal* signal,
14361                        TcIndexOperation* indexOp,
14362                        const Uint32 *src,
14363                        Uint32 len)
14364 {
14365   if (ERROR_INSERTED(8051) ||
14366       ! appendToSection(indexOp->attrInfoSectionIVal,
14367                         src,
14368                         len))
14369   {
14370     jam();
14371 #ifdef VM_TRACE
14372     ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize buffer for attrInfo\n");
14373 #endif
14374     apiConnectptr.i = indexOp->connectionIndex;
14375     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14376     releaseIndexOperation(apiConnectptr.p, indexOp);
14377     terrorCode = 289;
14378     if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
14379       apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
14380     abortErrorLab(signal);
14381     return -1;
14382   }
14383 
14384   indexOp->pendingAttrInfo-= len;
14385 
14386   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
14387     jam();
14388     return 0;
14389   }
14390   return 1;
14391 }
14392 
receivedAllINDXATTRINFO(TcIndexOperation * indexOp)14393 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
14394 {
14395   return (indexOp->pendingAttrInfo == 0);
14396 }
14397 
14398 #ifdef ERROR_INSERT
14399 extern bool ErrorImportActive;
14400 #endif
14401 
saveTRANSID_AI(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)14402 bool  Dbtc::saveTRANSID_AI(Signal* signal,
14403 			   TcIndexOperation* indexOp,
14404                            const Uint32 *src,
14405                            Uint32 len)
14406 {
14407   /* TransID_AI is received as a result of looking up a
14408    * unique index table
14409    * The unique index table is looked up using the index
14410    * key to receive a single attribute containing the
14411    * fragment holding the base table row and the base
14412    * table primary key.
14413    * This is later used to build a TCKEYREQ against the
14414    * base table.
14415    * In this method, we prepare a KEYINFO section for the
14416    * TCKEYREQ as we receive TRANSID_AI words.
14417    *
14418    * Expected TRANSID_AI words :
14419    *
14420    *   Word(s)  Description           States
14421    *
14422    *   0        Attribute header      ITAS_WAIT_HEADER
14423    *             containing length     -> ITAS_WAIT_FRAGID
14424    *
14425    *   1        Fragment Id           ITAS_WAIT_FRAGID
14426    *                                   -> ITAS_WAIT_KEY
14427    *
14428    *   [2..N]   Base table primary    ITAS_WAIT_KEY
14429    *            key info               -> [ ITAS_WAIT_KEY |
14430    *                                        ITAS_WAIT_KEY_FAIL ]
14431    *                                   -> ITAS_ALL_RECEIVED
14432    *
14433    * The outgoing KeyInfo section contains the base
14434    * table primary key info, with the fragment id passed
14435    * as the distribution key.
14436    * ITAS_WAIT_KEY_FAIL state is entered when there is no
14437    * space to store received TRANSID_AI information and
14438    * key collection must fail.  Transaction abort is performed
14439    * once all TRANSID_AI is received, and the system waits in
14440    * ITAS_WAIT_KEY_FAIL state until then.
14441    *
14442    */
14443   Uint32 remain= len;
14444 
14445   while (remain != 0)
14446   {
14447     switch(indexOp->transIdAIState) {
14448     case ITAS_WAIT_HEADER:
14449     {
14450       jam();
14451       ndbassert(indexOp->transIdAISectionIVal == RNIL);
14452       /* Look at the first AttributeHeader to get the
14453        * expected size of the primary key attribute
14454        */
14455       AttributeHeader* head = (AttributeHeader *) src;
14456       ndbassert(head->getHeaderSize() == 1);
14457       indexOp->pendingTransIdAI = 1 + head->getDataSize();
14458 
14459       src++;
14460       remain--;
14461       indexOp->transIdAIState = ITAS_WAIT_FRAGID;
14462       break;
14463     }
14464     case ITAS_WAIT_FRAGID:
14465     {
14466       jam();
14467       ndbassert(indexOp->transIdAISectionIVal == RNIL);
14468       /* Grab the fragment Id word */
14469       indexOp->fragmentId= *src;
14470 
14471       src++;
14472       remain--;
14473       indexOp->transIdAIState = ITAS_WAIT_KEY;
14474       break;
14475     }
14476     case ITAS_WAIT_KEY:
14477     {
14478       jam();
14479       /* Add key information to long section */
14480 #ifdef ERROR_INSERT
14481       if (ERROR_INSERTED(8066))
14482       {
14483         ErrorImportActive = true;
14484       }
14485 #endif
14486 
14487       bool res = appendToSection(indexOp->transIdAISectionIVal, src, remain);
14488 #ifdef ERROR_INSERT
14489       if (ERROR_INSERTED(8066))
14490       {
14491         ErrorImportActive = false;
14492       }
14493 #endif
14494 
14495       if (res)
14496       {
14497         jam();
14498         remain= 0;
14499         break;
14500       }
14501       else
14502       {
14503         jam();
14504 #ifdef VM_TRACE
14505         ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize buffer for TRANSID_AI\n");
14506 #endif
14507         indexOp->transIdAIState= ITAS_WAIT_KEY_FAIL;
14508         /* Fall through to ITAS_WAIT_KEY_FAIL state handling */
14509       }
14510     }
14511 
14512     case ITAS_WAIT_KEY_FAIL:
14513     {
14514       /* Failed when collecting key previously - if we have all the
14515        * TRANSID_AI now then we abort
14516        */
14517       if (indexOp->pendingTransIdAI > len)
14518       {
14519         /* Still some TransIdAI to arrive, keep waiting as if we had
14520          * stored it
14521          */
14522         remain= 0;
14523         break;
14524       }
14525 
14526       /* All TransIdAI has arrived, abort */
14527       apiConnectptr.i = indexOp->connectionIndex;
14528       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14529       releaseIndexOperation(apiConnectptr.p, indexOp);
14530       terrorCode = ZGET_DATAREC_ERROR;
14531       abortErrorLab(signal);
14532       return false;
14533     }
14534 
14535     case ITAS_ALL_RECEIVED:
14536       jam();
14537       // Fall through
14538     default:
14539       jam();
14540       /* Bad state, or bad state to receive TransId_Ai in */
14541       // Todo : Check error handling here.
14542 #ifdef VM_TRACE
14543       ndbout_c("Dbtc::saveTRANSID_AI: Bad state when receiving\n");
14544 #endif
14545       apiConnectptr.i = indexOp->connectionIndex;
14546       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14547       releaseIndexOperation(apiConnectptr.p, indexOp);
14548       terrorCode = 4349;
14549       abortErrorLab(signal);
14550       return false;
14551     } // switch
14552   } // while
14553 
14554   if ((indexOp->pendingTransIdAI-= len) == 0)
14555     indexOp->transIdAIState = ITAS_ALL_RECEIVED;
14556 
14557   return true;
14558 }
14559 
receivedAllTRANSID_AI(TcIndexOperation * indexOp)14560 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
14561 {
14562   return (indexOp->transIdAIState == ITAS_ALL_RECEIVED);
14563 }
14564 
14565 /**
14566  * Receive signal TCINDXCONF
14567  * This can be either the return of reading an index table
14568  * or performing an index operation
14569  */
execTCKEYCONF(Signal * signal)14570 void Dbtc::execTCKEYCONF(Signal* signal)
14571 {
14572   TcKeyConf * const tcKeyConf =  (TcKeyConf *)signal->getDataPtr();
14573   TcIndexOperationPtr indexOpPtr;
14574 
14575   jamEntry();
14576   indexOpPtr.i = tcKeyConf->apiConnectPtr;
14577   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14578   Uint32 confInfo = tcKeyConf->confInfo;
14579 
14580   /**
14581    * Check on TCKEYCONF whether the the transaction was committed
14582    */
14583   ndbassert(TcKeyConf::getCommitFlag(confInfo) == false);
14584 
14585   indexOpPtr.p = indexOp;
14586   if (!indexOp) {
14587     jam();
14588     // Missing index operation
14589     return;
14590   }
14591   const UintR TconnectIndex = indexOp->connectionIndex;
14592   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
14593   apiConnectptr.p = regApiPtr;
14594   apiConnectptr.i = TconnectIndex;
14595   switch(indexOp->indexOpState) {
14596   case(IOS_NOOP): {
14597     jam();
14598     // Should never happen, abort
14599     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14600 
14601     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14602     tcIndxRef->transId[0] = regApiPtr->transid[0];
14603     tcIndxRef->transId[1] = regApiPtr->transid[1];
14604     tcIndxRef->errorCode = 4349;
14605     tcIndxRef->errorData = 0;
14606     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14607 	       TcKeyRef::SignalLength, JBB);
14608     return;
14609   }
14610   case(IOS_INDEX_ACCESS): {
14611     jam();
14612     // Just waiting for the TRANSID_AI now
14613     indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
14614     break;
14615   }
14616   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
14617     jam();
14618     // Double TCKEYCONF, should never happen, abort
14619     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14620 
14621     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14622     tcIndxRef->transId[0] = regApiPtr->transid[0];
14623     tcIndxRef->transId[1] = regApiPtr->transid[1];
14624     tcIndxRef->errorCode = 4349;
14625     tcIndxRef->errorData = 0;
14626     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14627 	       TcKeyRef::SignalLength, JBB);
14628     return;
14629   }
14630   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14631     jam();
14632     // Continue with index operation
14633     executeIndexOperation(signal, regApiPtr, indexOp);
14634     break;
14635   }
14636   }
14637 }
14638 
execTCKEYREF(Signal * signal)14639 void Dbtc::execTCKEYREF(Signal* signal)
14640 {
14641   TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
14642   TcIndexOperationPtr indexOpPtr;
14643 
14644   jamEntry();
14645   indexOpPtr.i = tcKeyRef->connectPtr;
14646   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14647   indexOpPtr.p = indexOp;
14648   if (!indexOp) {
14649     jam();
14650     // Missing index operation
14651     return;
14652   }
14653   const UintR TconnectIndex = indexOp->connectionIndex;
14654   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
14655 
14656   switch(indexOp->indexOpState) {
14657   case(IOS_NOOP): {
14658     jam();
14659     // Should never happen, abort
14660     break;
14661   }
14662   case(IOS_INDEX_ACCESS):
14663   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
14664   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14665     jam();
14666     // Send TCINDXREF
14667 
14668     TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
14669     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14670 
14671     tcIndxRef->connectPtr = tcIndxReq->senderData;
14672     tcIndxRef->transId[0] = tcKeyRef->transId[0];
14673     tcIndxRef->transId[1] = tcKeyRef->transId[1];
14674     tcIndxRef->errorCode = tcKeyRef->errorCode;
14675     tcIndxRef->errorData = 0;
14676 
14677     releaseIndexOperation(regApiPtr, indexOp);
14678 
14679     sendSignal(regApiPtr->ndbapiBlockref,
14680                GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
14681     return;
14682   }
14683   }
14684 }
14685 
execTRANSID_AI_R(Signal * signal)14686 void Dbtc::execTRANSID_AI_R(Signal* signal){
14687   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
14688   Uint32 sigLen = signal->length();
14689   Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
14690   Uint32 recBlockref = transIdAI->attrData[dataLen];
14691 
14692   jamEntry();
14693 
14694   SectionHandle handle(this, signal);
14695 
14696   /**
14697    * Forward signal to final destination
14698    * Truncate last word since that was used to hold the final dest.
14699    */
14700   sendSignal(recBlockref, GSN_TRANSID_AI,
14701 	     signal, sigLen - 1, JBB,
14702 	     &handle);
14703 }
14704 
execKEYINFO20_R(Signal * signal)14705 void Dbtc::execKEYINFO20_R(Signal* signal){
14706   KeyInfo20 * const keyInfo =  (KeyInfo20 *)signal->getDataPtr();
14707   Uint32 sigLen = signal->length();
14708   Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
14709   Uint32 recBlockref = keyInfo->keyData[dataLen];
14710 
14711   jamEntry();
14712 
14713   SectionHandle handle(this, signal);
14714 
14715   /**
14716    * Forward signal to final destination
14717    * Truncate last word since that was used to hold the final dest.
14718    */
14719   sendSignal(recBlockref, GSN_KEYINFO20,
14720 	     signal, sigLen - 1, JBB,
14721 	     &handle);
14722 }
14723 
14724 
14725 /**
14726  * execTRANSID_AI
14727  *
14728  * TRANSID_AI are received as a result of performing a read on
14729  * the index table as part of a (unique) index operation.
14730  * The data received is the primary key of the base table
14731  * which is then used to perform the index operation on the
14732  * base table.
14733  */
execTRANSID_AI(Signal * signal)14734 void Dbtc::execTRANSID_AI(Signal* signal)
14735 {
14736   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
14737 
14738   jamEntry();
14739   TcIndexOperationPtr indexOpPtr;
14740   indexOpPtr.i = transIdAI->connectPtr;
14741   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14742   indexOpPtr.p = indexOp;
14743   if (!indexOp) {
14744     jam();
14745     // Missing index operation
14746   }
14747   const UintR TconnectIndex = indexOp->connectionIndex;
14748   ApiConnectRecordPtr transPtr;
14749 
14750   transPtr.i = TconnectIndex;
14751   ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
14752   ApiConnectRecord * const regApiPtr = transPtr.p;
14753 
14754   // Acccumulate attribute data
14755   SectionHandle handle(this, signal);
14756   bool longSignal = (handle.m_cnt == 1);
14757   if (longSignal)
14758   {
14759     SegmentedSectionPtr dataPtr;
14760     Uint32 dataLen;
14761     ndbrequire(handle.getSection(dataPtr, 0));
14762     dataLen = dataPtr.sz;
14763 
14764     SectionSegment * ptrP = dataPtr.p;
14765     while (dataLen > NDB_SECTION_SEGMENT_SZ)
14766     {
14767       if (!saveTRANSID_AI(signal, indexOp, &ptrP->theData[0],
14768                           NDB_SECTION_SEGMENT_SZ))
14769       {
14770         releaseSections(handle);
14771         goto save_error;
14772       }
14773       dataLen -= NDB_SECTION_SEGMENT_SZ;
14774       ptrP = g_sectionSegmentPool.getPtr(ptrP->m_nextSegment);
14775     }
14776     if (!saveTRANSID_AI(signal, indexOp, &ptrP->theData[0], dataLen))
14777     {
14778       releaseSections(handle);
14779       goto save_error;
14780     }
14781 
14782     releaseSections(handle);
14783   }
14784   else
14785   {
14786     /* Short TransId_AI signal */
14787     if (!saveTRANSID_AI(signal,
14788                         indexOp,
14789                         transIdAI->getData(),
14790                         signal->getLength() - TransIdAI::HeaderLength)) {
14791     save_error:
14792       jam();
14793       // Failed to allocate space for TransIdAI
14794       // Todo : How will this behave when transaction already aborted
14795       // in saveTRANSID_AI call?
14796       TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14797 
14798       tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14799       tcIndxRef->transId[0] = regApiPtr->transid[0];
14800       tcIndxRef->transId[1] = regApiPtr->transid[1];
14801       tcIndxRef->errorCode = ZGET_DATAREC_ERROR;
14802       tcIndxRef->errorData = 0;
14803       sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14804                  TcKeyRef::SignalLength, JBB);
14805       return;
14806     }
14807   }
14808 
14809   switch(indexOp->indexOpState) {
14810   case(IOS_NOOP): {
14811     jam();
14812     // Should never happen, abort
14813     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14814 
14815     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14816     tcIndxRef->transId[0] = regApiPtr->transid[0];
14817     tcIndxRef->transId[1] = regApiPtr->transid[1];
14818     tcIndxRef->errorCode = 4349;
14819     tcIndxRef->errorData = 0;
14820     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14821 	       TcKeyRef::SignalLength, JBB);
14822     return;
14823     break;
14824   }
14825   case(IOS_INDEX_ACCESS): {
14826     jam();
14827     // Check if all TRANSID_AI have been received
14828     if (receivedAllTRANSID_AI(indexOp)) {
14829       jam();
14830       // Just waiting for a TCKEYCONF now
14831       indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
14832     }
14833     // else waiting for either TRANSID_AI or TCKEYCONF
14834     break;
14835     }
14836   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
14837     jam();
14838 #ifdef VM_TRACE
14839     ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
14840 #endif
14841     /*
14842     // Too many TRANSID_AI
14843     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14844 
14845     tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
14846     tcIndxRef->transId[0] = regApiPtr->transid[0];
14847     tcIndxRef->transId[1] = regApiPtr->transid[1];
14848     tcIndxRef->errorCode = 4349;
14849     tcIndxRef->errorData = 0;
14850     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14851                TcKeyRef::SignalLength, JBB);
14852     */
14853     break;
14854   }
14855   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
14856     jam();
14857     // Check if all TRANSID_AI have been received
14858     if (receivedAllTRANSID_AI(indexOp)) {
14859       jam();
14860       // Continue with index operation
14861       executeIndexOperation(signal, regApiPtr, indexOp);
14862     }
14863     // else continue waiting for more TRANSID_AI
14864     break;
14865   }
14866   }
14867 }
14868 
execTCROLLBACKREP(Signal * signal)14869 void Dbtc::execTCROLLBACKREP(Signal* signal)
14870 {
14871   TcRollbackRep* tcRollbackRep =  (TcRollbackRep *)signal->getDataPtr();
14872   jamEntry();
14873   TcIndexOperationPtr indexOpPtr;
14874   indexOpPtr.i = tcRollbackRep->connectPtr;
14875   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
14876   indexOpPtr.p = indexOp;
14877   tcRollbackRep =  (TcRollbackRep *)signal->getDataPtrSend();
14878   tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
14879   sendSignal(apiConnectptr.p->ndbapiBlockref,
14880 	     GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
14881 }
14882 
14883 /**
14884  * Read index table with the index attributes as PK
14885  */
readIndexTable(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)14886 void Dbtc::readIndexTable(Signal* signal,
14887 			  ApiConnectRecord* regApiPtr,
14888 			  TcIndexOperation* indexOp)
14889 {
14890   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
14891   Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
14892   TcIndexData* indexData;
14893   Uint32 transId1 = indexOp->tcIndxReq.transId1;
14894   Uint32 transId2 = indexOp->tcIndxReq.transId2;
14895 
14896   const Operation_t opType =
14897     (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
14898 
14899   // Find index table
14900   if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
14901     // TODO : Free KeyInfo and AttrInfo sections here if necessary
14902     // How is this operation cleaned up?
14903     jam();
14904     // Failed to find index record
14905     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
14906 
14907     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
14908     tcIndxRef->transId[0] = regApiPtr->transid[0];
14909     tcIndxRef->transId[1] = regApiPtr->transid[1];
14910     tcIndxRef->errorCode = 4000;
14911     // tcIndxRef->errorData = ??; Where to find indexId
14912     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
14913 	       TcKeyRef::SignalLength, JBB);
14914     return;
14915   }
14916   tcKeyReq->transId1 = transId1;
14917   tcKeyReq->transId2 = transId2;
14918   tcKeyReq->tableId = indexData->indexId;
14919   tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
14920   TcKeyReq::setOperationType(tcKeyRequestInfo,
14921 			     opType == ZREAD ? ZREAD : ZREAD_EX);
14922   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0); // No AI in long TCKEYREQ
14923   TcKeyReq::setInterpretedFlag(tcKeyRequestInfo, 0);
14924   tcKeyReq->senderData = indexOp->indexOpId;
14925   indexOp->indexOpState = IOS_INDEX_ACCESS;
14926   regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
14927   regApiPtr->accumulatingIndexOp = RNIL;
14928   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_INDEX_TABLE_READ;
14929 
14930   if (ERROR_INSERTED(8037))
14931   {
14932     ndbout_c("shifting index version");
14933     tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
14934   }
14935   tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
14936   tcKeyReq->requestInfo = tcKeyRequestInfo;
14937 
14938   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
14939   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
14940 
14941   /* Long TCKEYREQ Signal sections
14942    * We attach the KeyInfo section received from the user, and
14943    * create a new AttrInfo section with just one AttributeHeader
14944    * to retrieve the base table primary key
14945    */
14946   Ptr<SectionSegment> indexLookupAttrInfoSection;
14947   Uint32 singleAIWord;
14948 
14949   AttributeHeader::init(&singleAIWord, indexData->primaryKeyPos, 0);
14950   if (! import(indexLookupAttrInfoSection,
14951                &singleAIWord,
14952                1))
14953   {
14954     jam();
14955     /* Error creating AttrInfo section to request primary
14956      * key from index table.
14957      */
14958     // TODO - verify error handling
14959 #ifdef VM_TRACE
14960     ndbout_c("Dbtc::readIndexTable: Failed to create AttrInfo section");
14961 #endif
14962     apiConnectptr.i = indexOp->connectionIndex;
14963     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
14964     releaseIndexOperation(apiConnectptr.p, indexOp);
14965     terrorCode = 4000;
14966     abortErrorLab(signal);
14967     return;
14968   }
14969 
14970   ndbassert(signal->header.m_noOfSections == 0);
14971 
14972   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
14973     = indexOp->keyInfoSectionIVal;
14974 
14975   /* We pass this section to TCKEYREQ next */
14976   indexOp->keyInfoSectionIVal= RNIL;
14977 
14978   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
14979     = indexLookupAttrInfoSection.i;
14980   signal->header.m_noOfSections= 2;
14981 
14982   /* Direct execute of long TCKEYREQ
14983    * TCKEYREQ is responsible for freeing the KeyInfo and
14984    * AttrInfo sections passed to it
14985    */
14986   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
14987   jamEntry();
14988 
14989   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
14990   {
14991     jam();
14992   }
14993   else
14994   {
14995     jam();
14996     /**
14997      * "Fool" TC not to start commiting transaction since it always will
14998      *   have one outstanding lqhkeyreq
14999      * This is later decreased when the index read is complete
15000      */
15001     regApiPtr->lqhkeyreqrec++;
15002 
15003     /**
15004      * Remember ptr to index read operation
15005      *   (used to set correct save point id on index operation later)
15006      */
15007     indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
15008   }
15009 
15010   return;
15011 }
15012 
15013 /**
15014  * Execute the index operation with the result from
15015  * the index table read as PK
15016  */
executeIndexOperation(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)15017 void Dbtc::executeIndexOperation(Signal* signal,
15018 				 ApiConnectRecord* regApiPtr,
15019 				 TcIndexOperation* indexOp) {
15020 
15021   TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
15022   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
15023   Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
15024   TcIndexData* indexData;
15025 
15026   // Find index table
15027   if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
15028     jam();
15029     // Failed to find index record
15030     // TODO : How is this operation cleaned up?
15031     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
15032 
15033     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
15034     tcIndxRef->transId[0] = regApiPtr->transid[0];
15035     tcIndxRef->transId[1] = regApiPtr->transid[1];
15036     tcIndxRef->errorCode = 4349;
15037     tcIndxRef->errorData = 0;
15038     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
15039 	       TcKeyRef::SignalLength, JBB);
15040     return;
15041   }
15042 
15043   // Find schema version of primary table
15044   TableRecordPtr tabPtr;
15045   tabPtr.i = indexData->primaryTableId;
15046   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
15047 
15048   tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
15049   tcKeyReq->attrLen = tcIndxReq->attrLen;
15050   tcKeyReq->tableId = indexData->primaryTableId;
15051   tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
15052   tcKeyReq->transId1 = regApiPtr->transid[0];
15053   tcKeyReq->transId2 = regApiPtr->transid[1];
15054   tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
15055 
15056   if (tabPtr.p->get_user_defined_partitioning())
15057   {
15058     jam();
15059     tcKeyReq->scanInfo = indexOp->fragmentId; // As read from Index table
15060     TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
15061   }
15062   regApiPtr->m_special_op_flags = 0;
15063   regApiPtr->executingIndexOp = 0;
15064 
15065   /* KeyInfo section
15066    * Get the KeyInfo we received from the index table lookup
15067    */
15068   SegmentedSectionPtr keyInfoFromTransIdAI;
15069 
15070   ndbassert( indexOp->transIdAISectionIVal != RNIL );
15071   getSection(keyInfoFromTransIdAI, indexOp->transIdAISectionIVal);
15072 
15073   ndbassert( signal->header.m_noOfSections == 0 );
15074   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
15075     = indexOp->transIdAISectionIVal;
15076   signal->header.m_noOfSections = 1;
15077 
15078   indexOp->transIdAISectionIVal = RNIL;
15079 
15080   /* AttrInfo section
15081    * Attach any AttrInfo section from original TCINDXREQ
15082    */
15083   if ( indexOp->attrInfoSectionIVal != RNIL )
15084   {
15085     jam();
15086     SegmentedSectionPtr attrInfoFromInitialReq;
15087 
15088     getSection(attrInfoFromInitialReq, indexOp->attrInfoSectionIVal);
15089     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
15090       = indexOp->attrInfoSectionIVal;
15091     signal->header.m_noOfSections = 2;
15092     indexOp->attrInfoSectionIVal = RNIL;
15093   }
15094 
15095   releaseIndexOperation(regApiPtr, indexOp);
15096 
15097   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyInfoFromTransIdAI.sz);
15098   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15099   TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
15100   TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
15101   tcKeyReq->requestInfo = tcKeyRequestInfo;
15102 
15103   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
15104   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
15105 
15106   /**
15107    * Decrease lqhkeyreqrec to compensate for addition
15108    *   during read of index table
15109    * I.e. let TC start committing when other operations has completed
15110    */
15111   regApiPtr->lqhkeyreqrec--;
15112 
15113   /**
15114    * Fix savepoint id -
15115    *   fix so that index operation has the same savepoint id
15116    *   as the read of the index table (TCINDXREQ)
15117    */
15118   TcConnectRecordPtr tmp;
15119   tmp.i = indexOp->indexReadTcConnect;
15120   ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
15121   const Uint32 currSavePointId = regApiPtr->currSavePointId;
15122   regApiPtr->currSavePointId = tmp.p->savePointId;
15123 
15124 #ifdef ERROR_INSERT
15125   bool err8072 = ERROR_INSERTED(8072);
15126   if (err8072)
15127   {
15128     CLEAR_ERROR_INSERT_VALUE;
15129   }
15130 #endif
15131 
15132   /* Execute TCKEYREQ now - it is now responsible for freeing
15133    * the KeyInfo and AttrInfo sections
15134    */
15135   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15136   jamEntry();
15137 
15138 #ifdef ERROR_INSERT
15139   if (err8072)
15140   {
15141     SET_ERROR_INSERT_VALUE(8072);
15142   }
15143 #endif
15144 
15145   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
15146   {
15147     // TODO : Presumably the abort cleans up the operation
15148     jam();
15149     return;
15150   }
15151 
15152   regApiPtr->currSavePointId = currSavePointId;
15153 
15154 }
15155 
seizeIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperationPtr & indexOpPtr)15156 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
15157 			       TcIndexOperationPtr& indexOpPtr)
15158 {
15159   if (regApiPtr->theSeizedIndexOperations.seize(indexOpPtr))
15160   {
15161     ndbassert(indexOpPtr.p->pendingKeyInfo == 0);
15162     ndbassert(indexOpPtr.p->keyInfoSectionIVal == RNIL);
15163     ndbassert(indexOpPtr.p->pendingAttrInfo == 0);
15164     ndbassert(indexOpPtr.p->attrInfoSectionIVal == RNIL);
15165     ndbassert(indexOpPtr.p->transIdAIState == ITAS_WAIT_HEADER);
15166     ndbassert(indexOpPtr.p->pendingTransIdAI == 0);
15167     ndbassert(indexOpPtr.p->transIdAISectionIVal == RNIL);
15168     return true;
15169   }
15170 
15171   return false;
15172 }
15173 
releaseIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)15174 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
15175 				 TcIndexOperation* indexOp)
15176 {
15177   indexOp->indexOpState = IOS_NOOP;
15178   indexOp->pendingKeyInfo = 0;
15179   releaseSection(indexOp->keyInfoSectionIVal);
15180   indexOp->keyInfoSectionIVal= RNIL;
15181   indexOp->pendingAttrInfo = 0;
15182   releaseSection(indexOp->attrInfoSectionIVal);
15183   indexOp->attrInfoSectionIVal= RNIL;
15184   indexOp->transIdAIState = ITAS_WAIT_HEADER;
15185   indexOp->pendingTransIdAI = 0;
15186   releaseSection(indexOp->transIdAISectionIVal);
15187   indexOp->transIdAISectionIVal= RNIL;
15188   regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
15189 }
15190 
releaseAllSeizedIndexOperations(ApiConnectRecord * regApiPtr)15191 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
15192 {
15193   TcIndexOperationPtr seizedIndexOpPtr;
15194 
15195   regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
15196   while(seizedIndexOpPtr.i != RNIL) {
15197     jam();
15198     TcIndexOperation* indexOp = seizedIndexOpPtr.p;
15199 
15200     indexOp->indexOpState = IOS_NOOP;
15201     indexOp->pendingKeyInfo = 0;
15202     releaseSection(indexOp->keyInfoSectionIVal);
15203     indexOp->keyInfoSectionIVal = RNIL;
15204     indexOp->pendingAttrInfo = 0;
15205     releaseSection(indexOp->attrInfoSectionIVal);
15206     indexOp->attrInfoSectionIVal = RNIL;
15207     indexOp->transIdAIState = ITAS_WAIT_HEADER;
15208     indexOp->pendingTransIdAI = 0;
15209     releaseSection(indexOp->transIdAISectionIVal);
15210     indexOp->transIdAISectionIVal = RNIL;
15211     regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
15212   }
15213   regApiPtr->theSeizedIndexOperations.release();
15214 }
15215 
saveTriggeringOpState(Signal * signal,TcConnectRecord * trigOp)15216 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
15217 {
15218   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
15219   copyFromToLen((UintR*)lqhKeyConf,
15220 		&trigOp->savedState[0],
15221                 LqhKeyConf::SignalLength);
15222 }
15223 
15224 void
trigger_op_finished(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * triggeringOp)15225 Dbtc::trigger_op_finished(Signal* signal, ApiConnectRecordPtr regApiPtr,
15226                           TcConnectRecord* triggeringOp)
15227 {
15228   if (!regApiPtr.p->isExecutingDeferredTriggers())
15229   {
15230     ndbassert(triggeringOp->triggerExecutionCount > 0);
15231     triggeringOp->triggerExecutionCount--;
15232     if (triggeringOp->triggerExecutionCount == 0)
15233     {
15234       /**
15235        * We have completed current trigger execution
15236        * Continue triggering operation
15237        */
15238       jam();
15239       continueTriggeringOp(signal, triggeringOp);
15240     }
15241   }
15242   else
15243   {
15244     jam();
15245     lqhKeyConf_checkTransactionState(signal, regApiPtr);
15246   }
15247 }
15248 
continueTriggeringOp(Signal * signal,TcConnectRecord * trigOp)15249 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
15250 {
15251   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
15252   copyFromToLen(&trigOp->savedState[0],
15253                 (UintR*)lqhKeyConf,
15254 		LqhKeyConf::SignalLength);
15255 
15256   ndbassert(trigOp->savedState[LqhKeyConf::SignalLength-1] != ~Uint32(0));
15257   trigOp->savedState[LqhKeyConf::SignalLength-1] = ~Uint32(0);
15258 
15259   lqhKeyConf->noFiredTriggers = 0;
15260   trigOp->noReceivedTriggers = 0;
15261 
15262   // All triggers executed successfully, continue operation
15263   execLQHKEYCONF(signal);
15264 }
15265 
executeTriggers(Signal * signal,ApiConnectRecordPtr * transPtr)15266 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
15267 {
15268   ApiConnectRecord* regApiPtr = transPtr->p;
15269   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
15270   TcConnectRecordPtr opPtr;
15271   FiredTriggerPtr trigPtr;
15272 
15273   if (!regApiPtr->theFiredTriggers.isEmpty()) {
15274     jam();
15275     if ((regApiPtr->apiConnectstate == CS_STARTED) ||
15276         (regApiPtr->apiConnectstate == CS_START_COMMITTING) ||
15277         (regApiPtr->apiConnectstate == CS_SEND_FIRE_TRIG_REQ) ||
15278         (regApiPtr->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ))
15279     {
15280       jam();
15281       regApiPtr->theFiredTriggers.first(trigPtr);
15282       while (trigPtr.i != RNIL) {
15283         jam();
15284         // Execute all ready triggers in parallel
15285         opPtr.i = trigPtr.p->fireingOperation;
15286         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
15287 	FiredTriggerPtr nextTrigPtr = trigPtr;
15288 	regApiPtr->theFiredTriggers.next(nextTrigPtr);
15289         if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers ||
15290             regApiPtr->isExecutingDeferredTriggers()) {
15291           jam();
15292           // Fireing operation is ready to have a trigger executing
15293           executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
15294           // Should allow for interleaving here by sending a CONTINUEB and
15295 	  // return
15296           // Release trigger records
15297 	  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15298 	  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
15299 	  tmp1.release();
15300 	  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
15301 	  tmp2.release();
15302 	  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
15303 	  tmp3.release();
15304           regApiPtr->theFiredTriggers.release(trigPtr);
15305         }
15306 	trigPtr = nextTrigPtr;
15307       }
15308       return;
15309     // No more triggers, continue transaction after last executed trigger has
15310     // reurned (in execLQHKEYCONF or execLQHKEYREF)
15311     } else {
15312 
15313       jam();
15314       /* Not in correct state to fire triggers yet, need to wait
15315        * (or keep waiting)
15316        */
15317 
15318       if ((regApiPtr->apiConnectstate == CS_RECEIVING) ||
15319           (regApiPtr->apiConnectstate == CS_REC_COMMITTING))
15320       {
15321         // Wait until transaction is ready to execute a trigger
15322         jam();
15323         if (!tc_testbit(regApiPtr->m_flags,
15324                         ApiConnectRecord::TF_TRIGGER_PENDING))
15325         {
15326           jam();
15327           regApiPtr->m_flags |= ApiConnectRecord::TF_TRIGGER_PENDING;
15328           signal->theData[0] = TcContinueB::TRIGGER_PENDING;
15329           signal->theData[1] = transPtr->i;
15330           signal->theData[2] = regApiPtr->transid[0];
15331           signal->theData[3] = regApiPtr->transid[1];
15332           sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
15333         }
15334         // else
15335         // We are already waiting for a pending trigger (CONTINUEB)
15336       }
15337       else
15338       {
15339         /* Transaction has started aborting.
15340          * Forget about unprocessed triggers
15341          */
15342         ndbrequire(regApiPtr->apiConnectstate == CS_ABORTING);
15343       }
15344     }
15345   }
15346 }
15347 
executeTrigger(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)15348 void Dbtc::executeTrigger(Signal* signal,
15349                           TcFiredTriggerData* firedTriggerData,
15350                           ApiConnectRecordPtr* transPtr,
15351                           TcConnectRecordPtr* opPtr)
15352 {
15353   TcDefinedTriggerData* definedTriggerData;
15354 
15355   if ((definedTriggerData =
15356        c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
15357       != NULL)
15358   {
15359     transPtr->p->pendingTriggers--;
15360     switch(firedTriggerData->triggerType) {
15361     case(TriggerType::SECONDARY_INDEX):
15362       jam();
15363       executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
15364                           transPtr, opPtr);
15365       break;
15366     case TriggerType::REORG_TRIGGER:
15367       jam();
15368       executeReorgTrigger(signal, definedTriggerData, firedTriggerData,
15369                           transPtr, opPtr);
15370       break;
15371     default:
15372       ndbrequire(false);
15373     }
15374   }
15375 }
15376 
executeIndexTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)15377 void Dbtc::executeIndexTrigger(Signal* signal,
15378                                TcDefinedTriggerData* definedTriggerData,
15379                                TcFiredTriggerData* firedTriggerData,
15380                                ApiConnectRecordPtr* transPtr,
15381                                TcConnectRecordPtr* opPtr)
15382 {
15383   TcIndexData* indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
15384   ndbassert(indexData != NULL);
15385 
15386   switch (firedTriggerData->triggerEvent) {
15387   case(TriggerEvent::TE_INSERT): {
15388     jam();
15389     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15390     break;
15391   }
15392   case(TriggerEvent::TE_DELETE): {
15393     jam();
15394     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15395     break;
15396   }
15397   case(TriggerEvent::TE_UPDATE): {
15398     jam();
15399     opPtr->p->triggerExecutionCount++; // One is already added...and this is 2
15400     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15401     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
15402     break;
15403   }
15404   default:
15405     ndbrequire(false);
15406   }
15407 }
15408 
releaseFiredTriggerData(DLFifoList<TcFiredTriggerData> * triggers)15409 void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
15410 {
15411   FiredTriggerPtr trigPtr;
15412 
15413   triggers->first(trigPtr);
15414   while (trigPtr.i != RNIL) {
15415     jam();
15416     // Release trigger records
15417 
15418     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15419     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
15420     tmp1.release();
15421     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
15422     tmp2.release();
15423     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
15424     tmp3.release();
15425 
15426     triggers->next(trigPtr);
15427   }
15428   triggers->release();
15429 }
15430 
15431 /**
15432  * abortTransFromTrigger
15433  *
15434  * This method is called when there is a problem with trigger
15435  * handling and the transaction should be aborted with the
15436  * given error code
15437  */
abortTransFromTrigger(Signal * signal,const ApiConnectRecordPtr & transPtr,Uint32 error)15438 void Dbtc::abortTransFromTrigger(Signal* signal,
15439                                  const ApiConnectRecordPtr& transPtr,
15440                                  Uint32 error)
15441 {
15442   jam();
15443   terrorCode = error;
15444 
15445   apiConnectptr = transPtr;
15446 
15447   abortErrorLab(signal);
15448 }
15449 
15450 /**
15451  * appendAttrDataToSection
15452  *
15453  * Copy data in AttrInfo form from the given databuffer
15454  * to the given section IVal (can be RNIL).
15455  * If attribute headers are to be copied they will be
15456  * renumbered consecutively, starting with the given
15457  * attrId.
15458  * hasNull is updated to indicate whether any Nulls
15459  * were encountered.
15460  */
appendAttrDataToSection(Uint32 & sectionIVal,DataBuffer<11> & values,bool withHeaders,Uint32 & attrId,bool & hasNull)15461 bool Dbtc::appendAttrDataToSection(Uint32& sectionIVal,
15462                                    DataBuffer<11>& values,
15463                                    bool withHeaders,
15464                                    Uint32& attrId,
15465                                    bool& hasNull)
15466 {
15467   AttributeBuffer::DataBufferIterator iter;
15468   bool moreData= values.first(iter);
15469   hasNull= false;
15470   const Uint32 segSize= values.getSegmentSize(); // 11
15471 
15472   while (moreData)
15473   {
15474     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
15475     Uint32 dataSize= attrHeader->getDataSize();
15476     hasNull |= (dataSize == 0);
15477 
15478     if (withHeaders)
15479     {
15480       AttributeHeader ah(*iter.data);
15481       ah.setAttributeId(attrId); // Renumber AttrIds
15482       if (unlikely(!appendToSection(sectionIVal,
15483                                     &ah.m_value,
15484                                     1)))
15485       {
15486         releaseSection(sectionIVal);
15487         sectionIVal= RNIL;
15488         return false;
15489       }
15490     }
15491 
15492     moreData= values.next(iter, 1);
15493 
15494     while (dataSize)
15495     {
15496       ndbrequire(moreData);
15497       /* Copy as many contiguous words as possible */
15498       Uint32 contigLeft= segSize - iter.ind;
15499       ndbassert(contigLeft);
15500       Uint32 contigValid= MIN(dataSize, contigLeft);
15501 
15502       if (unlikely(!appendToSection(sectionIVal,
15503                                     iter.data,
15504                                     contigValid)))
15505       {
15506         releaseSection(sectionIVal);
15507         sectionIVal= RNIL;
15508         return false;
15509       }
15510       moreData= values.next(iter, contigValid);
15511       dataSize-= contigValid;
15512     }
15513     attrId++;
15514   }
15515 
15516   return true;
15517 }
15518 
insertIntoIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)15519 void Dbtc::insertIntoIndexTable(Signal* signal,
15520                                 TcFiredTriggerData* firedTriggerData,
15521                                 ApiConnectRecordPtr* transPtr,
15522                                 TcConnectRecordPtr* opPtr,
15523                                 TcIndexData* indexData)
15524 {
15525   ApiConnectRecord* regApiPtr = transPtr->p;
15526   TcConnectRecord* opRecord = opPtr->p;
15527   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
15528   Uint32 tcKeyRequestInfo = 0;
15529   TableRecordPtr indexTabPtr;
15530 
15531   jam();
15532 
15533   indexTabPtr.i = indexData->indexId;
15534   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
15535   tcKeyReq->apiConnectPtr = transPtr->i;
15536   tcKeyReq->senderData = opPtr->i;
15537 
15538   /* Key for insert to unique index table is the afterValues from the
15539    * base table operation (from update or insert on base).
15540    * Data for insert to unique index table is the afterValues from the
15541    * base table operation plus the fragment id and packed keyValues from
15542    * the base table operation
15543    */
15544   // Calculate key length and renumber attribute id:s
15545   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15546   LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
15547   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
15548 
15549   if (afterValues.getSize() == 0)
15550   {
15551     jam();
15552     ndbrequire(tc_testbit(regApiPtr->m_flags,
15553                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
15554     trigger_op_finished(signal, *transPtr, opRecord);
15555     return;
15556   }
15557 
15558   Uint32 keyIVal= RNIL;
15559   Uint32 attrIVal= RNIL;
15560   bool appendOk= false;
15561   do
15562   {
15563     Uint32 attrId= 0;
15564     bool hasNull= false;
15565 
15566     /* Build Insert KeyInfo section from aftervalues */
15567     if (unlikely(! appendAttrDataToSection(keyIVal,
15568                                            afterValues,
15569                                            false, // No AttributeHeaders
15570                                            attrId,
15571                                            hasNull)))
15572     {
15573       jam();
15574       break;
15575     }
15576 
15577     if(ERROR_INSERTED(8086))
15578     {
15579       /* Simulate SS exhaustion */
15580       break;
15581     }
15582 
15583     /* If there's Nulls in the values that become the index table's
15584      * PK then we skip this insert
15585      */
15586     if (hasNull)
15587     {
15588       jam();
15589       releaseSection(keyIVal);
15590       trigger_op_finished(signal, *transPtr, opRecord);
15591       return;
15592     }
15593 
15594     /* Build Insert AttrInfo section from aftervalues,
15595      * fragment id + keyvalues
15596      */
15597     AttributeHeader ah(attrId, 0); // Length tbd.
15598     attrId= 0;
15599     if (unlikely((! appendAttrDataToSection(attrIVal,
15600                                             afterValues,
15601                                             true, // Include AttributeHeaders,
15602                                             attrId,
15603                                             hasNull)) ||
15604                  (! appendToSection(attrIVal,
15605                                     &ah.m_value,
15606                                     1))))
15607     {
15608       jam();
15609       break;
15610     }
15611 
15612     AttributeHeader* pkHeader= (AttributeHeader*) getLastWordPtr(attrIVal);
15613     Uint32 startSz= getSectionSz(attrIVal);
15614     if (unlikely((! appendToSection(attrIVal,
15615                                     &firedTriggerData->fragId,
15616                                     1)) ||
15617                  (! appendAttrDataToSection(attrIVal,
15618                                             keyValues,
15619                                             false, // No AttributeHeaders
15620                                             attrId,
15621                                             hasNull))))
15622     {
15623       jam();
15624       break;
15625     }
15626 
15627     appendOk= true;
15628 
15629     /* Now go back and set pk header length */
15630     pkHeader->setDataSize(getSectionSz(attrIVal) - startSz);
15631   } while(0);
15632 
15633   if (unlikely(!appendOk))
15634   {
15635     /* Some failure building up KeyInfo and AttrInfo */
15636     releaseSection(keyIVal);
15637     releaseSection(attrIVal);
15638     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15639     return;
15640   }
15641 
15642   /* Now build TcKeyReq for insert */
15643   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15644   tcKeyReq->attrLen = 0;
15645   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15646   tcKeyReq->tableId = indexData->indexId;
15647   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
15648   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
15649   tcKeyReq->transId1 = regApiPtr->transid[0];
15650   tcKeyReq->transId2 = regApiPtr->transid[1];
15651   tcKeyReq->requestInfo = tcKeyRequestInfo;
15652 
15653   /* Attach Key and AttrInfo sections to signal */
15654   ndbrequire(signal->header.m_noOfSections == 0);
15655   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15656   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
15657   signal->header.m_noOfSections= 2;
15658 
15659   /*
15660    * Fix savepoint id -
15661    *   fix so that insert has same savepoint id as triggering operation
15662    */
15663   const Uint32 currSavePointId = regApiPtr->currSavePointId;
15664   regApiPtr->currSavePointId = opRecord->savePointId;
15665   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
15666   /* Pass trigger Id via ApiConnectRecord (nasty) */
15667   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15668   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15669 
15670   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15671   jamEntry();
15672 
15673   /*
15674    * Restore ApiConnectRecord state
15675    */
15676   regApiPtr->currSavePointId = currSavePointId;
15677   regApiPtr->immediateTriggerId = RNIL;
15678 }
15679 
deleteFromIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)15680 void Dbtc::deleteFromIndexTable(Signal* signal,
15681                                 TcFiredTriggerData* firedTriggerData,
15682                                 ApiConnectRecordPtr* transPtr,
15683                                 TcConnectRecordPtr* opPtr,
15684                                 TcIndexData* indexData)
15685 {
15686   ApiConnectRecord* regApiPtr = transPtr->p;
15687   TcConnectRecord* opRecord = opPtr->p;
15688   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
15689   Uint32 tcKeyRequestInfo = 0;
15690   TableRecordPtr indexTabPtr;
15691 
15692   indexTabPtr.i = indexData->indexId;
15693   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
15694   tcKeyReq->apiConnectPtr = transPtr->i;
15695   tcKeyReq->senderData = opPtr->i;
15696 
15697   // Calculate key length and renumber attribute id:s
15698   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15699   LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
15700 
15701   Uint32 keyIVal= RNIL;
15702   Uint32 attrId= 0;
15703   bool hasNull= false;
15704 
15705   if (beforeValues.getSize() == 0)
15706   {
15707     jam();
15708     ndbrequire(tc_testbit(regApiPtr->m_flags,
15709                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
15710     trigger_op_finished(signal, *transPtr, opRecord);
15711     return;
15712   }
15713 
15714   /* Build Delete KeyInfo section from beforevalues */
15715   if (unlikely((! appendAttrDataToSection(keyIVal,
15716                                           beforeValues,
15717                                           false, // No AttributeHeaders
15718                                           attrId,
15719                                           hasNull)) ||
15720                ERROR_INSERTED(8086)))
15721   {
15722     jam();
15723     releaseSection(keyIVal);
15724     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15725     return;
15726   }
15727 
15728   /* If there's Nulls in the values that become the index table's
15729    * PK then we skip this delete
15730    */
15731   if (hasNull)
15732   {
15733     jam();
15734     releaseSection(keyIVal);
15735     trigger_op_finished(signal, *transPtr, opRecord);
15736     return;
15737   }
15738 
15739   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15740   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15741   tcKeyReq->attrLen = 0;
15742   tcKeyReq->tableId = indexData->indexId;
15743   TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
15744   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
15745   tcKeyReq->transId1 = regApiPtr->transid[0];
15746   tcKeyReq->transId2 = regApiPtr->transid[1];
15747   tcKeyReq->requestInfo = tcKeyRequestInfo;
15748 
15749   /* Attach KeyInfo section to signal */
15750   ndbrequire(signal->header.m_noOfSections == 0);
15751   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15752   signal->header.m_noOfSections= 1;
15753 
15754   /**
15755    * Fix savepoint id -
15756    *   fix so that delete has same savepoint id as triggering operation
15757    */
15758   const Uint32 currSavePointId = regApiPtr->currSavePointId;
15759   regApiPtr->currSavePointId = opRecord->savePointId;
15760   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
15761   /* Pass trigger Id via ApiConnectRecord (nasty) */
15762   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15763   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15764   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15765   jamEntry();
15766 
15767   /*
15768    * Restore ApiConnectRecord state
15769    */
15770   regApiPtr->currSavePointId = currSavePointId;
15771   regApiPtr->immediateTriggerId = RNIL;
15772 }
15773 
15774 Uint32
getErrorCode(Uint32 schemaVersion) const15775 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
15776   if(!get_enabled())
15777     return ZNO_SUCH_TABLE;
15778   if(get_dropping())
15779     return ZDROP_TABLE_IN_PROGRESS;
15780   if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
15781     return ZWRONG_SCHEMA_VERSION_ERROR;
15782   ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
15783 			      __FILE__, __LINE__);
15784   return 0;
15785 }
15786 
executeReorgTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)15787 void Dbtc::executeReorgTrigger(Signal* signal,
15788                                TcDefinedTriggerData* definedTriggerData,
15789                                TcFiredTriggerData* firedTriggerData,
15790                                ApiConnectRecordPtr* transPtr,
15791                                TcConnectRecordPtr* opPtr)
15792 {
15793 
15794   ApiConnectRecord* regApiPtr = transPtr->p;
15795   TcConnectRecord* opRecord = opPtr->p;
15796   TcKeyReq * tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
15797 
15798   tcKeyReq->apiConnectPtr = transPtr->i;
15799   tcKeyReq->senderData = opPtr->i;
15800 
15801   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
15802   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
15803   LocalDataBuffer<11> attrValues(pool, firedTriggerData->afterValues);
15804 
15805   Uint32 optype;
15806   bool sendAttrInfo= true;
15807 
15808   switch (firedTriggerData->triggerEvent) {
15809   case TriggerEvent::TE_INSERT:
15810     optype = ZINSERT;
15811     break;
15812   case TriggerEvent::TE_UPDATE:
15813     /**
15814      * Only update should be write, as COPY is done as update
15815      *   a (maybe) better solution would be to have a different
15816      *   trigger event for COPY
15817      */
15818     optype = ZWRITE;
15819     break;
15820   case TriggerEvent::TE_DELETE:
15821     optype = ZDELETE;
15822     sendAttrInfo= false;
15823     break;
15824   default:
15825     ndbrequire(false);
15826   }
15827 
15828   Ptr<TableRecord> tablePtr;
15829   tablePtr.i = definedTriggerData->tableId;
15830   ptrCheckGuard(tablePtr, ctabrecFilesize, tableRecord);
15831   Uint32 tableVersion = tablePtr.p->currentSchemaVersion;
15832 
15833   Uint32 tcKeyRequestInfo = 0;
15834   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
15835   TcKeyReq::setOperationType(tcKeyRequestInfo, optype);
15836   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
15837   tcKeyReq->attrLen = 0;
15838   tcKeyReq->tableId = tablePtr.i;
15839   tcKeyReq->requestInfo = tcKeyRequestInfo;
15840   tcKeyReq->tableSchemaVersion = tableVersion;
15841   tcKeyReq->transId1 = regApiPtr->transid[0];
15842   tcKeyReq->transId2 = regApiPtr->transid[1];
15843 
15844   Uint32 keyIVal= RNIL;
15845   Uint32 attrIVal= RNIL;
15846   Uint32 attrId= 0;
15847   bool hasNull= false;
15848 
15849   /* Prepare KeyInfo section */
15850   if (unlikely(!appendAttrDataToSection(keyIVal,
15851                                         keyValues,
15852                                         false, // No AttributeHeaders
15853                                         attrId,
15854                                         hasNull)))
15855   {
15856     releaseSection(keyIVal);
15857     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15858     return;
15859   }
15860 
15861   ndbrequire(!hasNull);
15862 
15863   if (sendAttrInfo)
15864   {
15865     /* Prepare AttrInfo section from Key values and
15866      * After values
15867      */
15868     LocalDataBuffer<11>::Iterator attrIter;
15869     LocalDataBuffer<11>* buffers[2];
15870     buffers[0]= &keyValues;
15871     buffers[1]= &attrValues;
15872     const Uint32 segSize= keyValues.getSegmentSize(); // 11
15873     for (int buf=0; buf < 2; buf++)
15874     {
15875       Uint32 dataSize= buffers[buf]->getSize();
15876       bool moreData= buffers[buf]->first(attrIter);
15877 
15878       while(dataSize)
15879       {
15880         ndbrequire(moreData);
15881         Uint32 contigLeft= segSize - attrIter.ind;
15882         Uint32 contigValid= MIN(dataSize, contigLeft);
15883 
15884         if (unlikely(!appendToSection(attrIVal,
15885                                       attrIter.data,
15886                                       contigValid)))
15887         {
15888           releaseSection(keyIVal);
15889           releaseSection(attrIVal);
15890           abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
15891           return;
15892         }
15893         moreData= buffers[buf]->next(attrIter, contigValid);
15894         dataSize-= contigValid;
15895       }
15896       ndbassert(!moreData);
15897     }
15898   }
15899 
15900   /* Attach Key and optional AttrInfo sections to signal */
15901   ndbrequire(signal->header.m_noOfSections == 0);
15902   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
15903   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
15904   signal->header.m_noOfSections= sendAttrInfo? 2 : 1;
15905 
15906   /**
15907    * Fix savepoint id -
15908    *   fix so that the op has same savepoint id as triggering operation
15909    */
15910   const Uint32 currSavePointId = regApiPtr->currSavePointId;
15911   regApiPtr->currSavePointId = opRecord->savePointId;
15912   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_TRIGGER;
15913   /* Pass trigger Id via ApiConnectRecord (nasty) */
15914   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
15915 
15916   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
15917   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
15918   jamEntry();
15919 
15920   /*
15921    * Restore ApiConnectRecord state
15922    */
15923   regApiPtr->currSavePointId = currSavePointId;
15924   regApiPtr->immediateTriggerId = RNIL;
15925 }
15926 
15927 void
execROUTE_ORD(Signal * signal)15928 Dbtc::execROUTE_ORD(Signal* signal)
15929 {
15930   jamEntry();
15931   if(!assembleFragments(signal)){
15932     jam();
15933     return;
15934   }
15935 
15936   SectionHandle handle(this, signal);
15937 
15938   RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
15939   Uint32 dstRef = ord->dstRef;
15940   Uint32 srcRef = ord->srcRef;
15941   Uint32 gsn = ord->gsn;
15942 
15943   if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
15944   {
15945     jam();
15946     Uint32 secCount = handle.m_cnt;
15947     ndbrequire(secCount >= 1 && secCount <= 3);
15948 
15949     jamLine(secCount);
15950 
15951     /**
15952      * Put section 0 in signal->theData
15953      */
15954     Uint32 sigLen = handle.m_ptr[0].sz;
15955     ndbrequire(sigLen <= 25);
15956     copy(signal->theData, handle.m_ptr[0]);
15957 
15958     SegmentedSectionPtr save = handle.m_ptr[0];
15959     for (Uint32 i = 0; i < secCount - 1; i++)
15960       handle.m_ptr[i] = handle.m_ptr[i+1];
15961     handle.m_cnt--;
15962 
15963     sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle);
15964 
15965     handle.m_cnt = 1;
15966     handle.m_ptr[0] = save;
15967     releaseSections(handle);
15968     return ;
15969   }
15970 
15971   releaseSections(handle);
15972   warningEvent("Unable to route GSN: %d from %x to %x",
15973 	       gsn, srcRef, dstRef);
15974 
15975 }
15976