1 /* Copyright (c) 2003-2008 MySQL AB
2    Use is subject to license terms
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA */
16 
17 #define DBTC_C
18 
19 #include "Dbtc.hpp"
20 #include "md5_hash.hpp"
21 #include <RefConvert.hpp>
22 #include <ndb_limits.h>
23 #include <my_sys.h>
24 #include <ndb_rand.h>
25 
26 #include <signaldata/EventReport.hpp>
27 #include <signaldata/TcKeyReq.hpp>
28 #include <signaldata/TcKeyConf.hpp>
29 #include <signaldata/TcKeyRef.hpp>
30 #include <signaldata/KeyInfo.hpp>
31 #include <signaldata/AttrInfo.hpp>
32 #include <signaldata/TransIdAI.hpp>
33 #include <signaldata/TcRollbackRep.hpp>
34 #include <signaldata/NodeFailRep.hpp>
35 #include <signaldata/ReadNodesConf.hpp>
36 #include <signaldata/NFCompleteRep.hpp>
37 #include <signaldata/LqhKey.hpp>
38 #include <signaldata/TcCommit.hpp>
39 #include <signaldata/TcContinueB.hpp>
40 #include <signaldata/TcKeyFailConf.hpp>
41 #include <signaldata/AbortAll.hpp>
42 #include <signaldata/DihFragCount.hpp>
43 #include <signaldata/ScanFrag.hpp>
44 #include <signaldata/ScanTab.hpp>
45 #include <signaldata/PrepDropTab.hpp>
46 #include <signaldata/DropTab.hpp>
47 #include <signaldata/AlterTab.hpp>
48 #include <signaldata/CreateTrig.hpp>
49 #include <signaldata/DropTrig.hpp>
50 #include <signaldata/FireTrigOrd.hpp>
51 #include <signaldata/TrigAttrInfo.hpp>
52 #include <signaldata/CreateIndx.hpp>
53 #include <signaldata/DropIndx.hpp>
54 #include <signaldata/AlterIndx.hpp>
55 #include <signaldata/ScanTab.hpp>
56 #include <signaldata/SystemError.hpp>
57 #include <signaldata/DumpStateOrd.hpp>
58 #include <signaldata/DisconnectRep.hpp>
59 #include <signaldata/TcHbRep.hpp>
60 
61 #include <signaldata/PrepDropTab.hpp>
62 #include <signaldata/DropTab.hpp>
63 #include <signaldata/TcIndx.hpp>
64 #include <signaldata/IndxKeyInfo.hpp>
65 #include <signaldata/IndxAttrInfo.hpp>
66 #include <signaldata/PackedSignal.hpp>
67 #include <AttributeHeader.hpp>
68 #include <signaldata/DictTabInfo.hpp>
69 #include <AttributeDescriptor.hpp>
70 #include <SectionReader.hpp>
71 #include <KeyDescriptor.hpp>
72 
73 #include <NdbOut.hpp>
74 #include <DebuggerNames.hpp>
75 
76 #include <signaldata/RouteOrd.hpp>
77 
78 // Use DEBUG to print messages that should be
79 // seen only when we debug the product
80 #ifdef VM_TRACE
81 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
82 #else
83 #define DEBUG(x)
84 #endif
85 
86 #define INTERNAL_TRIGGER_TCKEYREQ_JBA 0
87 
88 #ifdef VM_TRACE
89 NdbOut &
operator <<(NdbOut & out,Dbtc::ConnectionState state)90 operator<<(NdbOut& out, Dbtc::ConnectionState state){
91   switch(state){
92   case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
93   case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
94   case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
95   case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
96   case Dbtc::CS_PREPARED: out << "CS_PREPARED"; break;
97   case Dbtc::CS_START_PREPARING: out << "CS_START_PREPARING"; break;
98   case Dbtc::CS_REC_PREPARING: out << "CS_REC_PREPARING"; break;
99   case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
100   case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
101   case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
102   case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
103   case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
104   case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
105   case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
106   case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
107   case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
108   case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
109   case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
110   case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
111   case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
112   case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
113   case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
114   case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
115   case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
116   case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
117   case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
118   default:
119     out << "Unknown: " << (int)state; break;
120   }
121   return out;
122 }
123 NdbOut &
operator <<(NdbOut & out,Dbtc::OperationState state)124 operator<<(NdbOut& out, Dbtc::OperationState state){
125   out << (int)state;
126   return out;
127 }
128 NdbOut &
operator <<(NdbOut & out,Dbtc::AbortState state)129 operator<<(NdbOut& out, Dbtc::AbortState state){
130   out << (int)state;
131   return out;
132 }
133 NdbOut &
operator <<(NdbOut & out,Dbtc::ReturnSignal state)134 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
135   out << (int)state;
136   return out;
137 }
138 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanRecord::ScanState state)139 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
140   out << (int)state;
141   return out;
142 }
143 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanFragRec::ScanFragState state)144 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
145   out << (int)state;
146   return out;
147 }
148 #endif
149 
150 void
updateBuddyTimer(ApiConnectRecordPtr apiPtr)151 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
152 {
153   if (apiPtr.p->buddyPtr != RNIL) {
154     jam();
155     ApiConnectRecordPtr buddyApiPtr;
156     buddyApiPtr.i = apiPtr.p->buddyPtr;
157     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
158     if (getApiConTimer(buddyApiPtr.i) != 0) {
159       if ((apiPtr.p->transid[0] == buddyApiPtr.p->transid[0]) &&
160           (apiPtr.p->transid[1] == buddyApiPtr.p->transid[1])) {
161         jam();
162         setApiConTimer(buddyApiPtr.i, ctcTimer, __LINE__);
163       } else {
164         jam();
165         // Not a buddy anymore since not the same transid
166         apiPtr.p->buddyPtr = RNIL;
167       }//if
168     }//if
169   }//if
170 }
171 
execCONTINUEB(Signal * signal)172 void Dbtc::execCONTINUEB(Signal* signal)
173 {
174   UintR tcase;
175 
176   jamEntry();
177   tcase = signal->theData[0];
178   UintR Tdata0 = signal->theData[1];
179   UintR Tdata1 = signal->theData[2];
180   UintR Tdata2 = signal->theData[3];
181   switch (tcase) {
182   case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
183     jam();
184     ndbrequire(false);
185     return;
186   case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
187     jam();
188     tcNodeFailptr.i = Tdata0;
189     ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
190     completeTransAtTakeOverLab(signal, Tdata1);
191     return;
192   case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
193     jam();
194     timeOutLoopStartLab(signal, Tdata0);
195     return;
196   case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
197     jam();
198     tnodeid = Tdata0;
199     tcNodeFailptr.i = 0;
200     ptrAss(tcNodeFailptr, tcFailRecord);
201     nodeTakeOverCompletedLab(signal);
202     return;
203   case TcContinueB::ZINITIALISE_RECORDS:
204     jam();
205     initialiseRecordsLab(signal, Tdata0, Tdata2, signal->theData[4]);
206     return;
207   case TcContinueB::ZSEND_COMMIT_LOOP:
208     jam();
209     apiConnectptr.i = Tdata0;
210     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
211     tcConnectptr.i = Tdata1;
212     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
213     commit020Lab(signal);
214     return;
215   case TcContinueB::ZSEND_COMPLETE_LOOP:
216     jam();
217     apiConnectptr.i = Tdata0;
218     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
219     tcConnectptr.i = Tdata1;
220     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
221     complete010Lab(signal);
222     return;
223   case TcContinueB::ZHANDLE_FAILED_API_NODE:
224     jam();
225     handleFailedApiNode(signal, Tdata0, Tdata1);
226     return;
227   case TcContinueB::ZTRANS_EVENT_REP:
228     jam();
229     /* -------------------------------------------------------------------- */
230     // Report information about transaction activity once per second.
231     /* -------------------------------------------------------------------- */
232     if (c_counters.c_trans_status == TransCounters::Timer){
233       Uint32 len = c_counters.report(signal);
234       sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
235 
236       c_counters.reset();
237       signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
238       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
239     }
240     return;
241   case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
242     jam();
243     timeOutLoopStartFragLab(signal, Tdata0);
244     return;
245   case TcContinueB::ZABORT_BREAK:
246     jam();
247     tcConnectptr.i = Tdata0;
248     apiConnectptr.i = Tdata1;
249     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
250     apiConnectptr.p->counter--;
251     abort015Lab(signal);
252     return;
253   case TcContinueB::ZABORT_TIMEOUT_BREAK:
254     jam();
255     tcConnectptr.i = Tdata0;
256     apiConnectptr.i = Tdata1;
257     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
258     apiConnectptr.p->counter--;
259     sendAbortedAfterTimeout(signal, 1);
260     return;
261   case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
262     jam();
263     removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
264     return;
265   case TcContinueB::ZWAIT_ABORT_ALL:
266     jam();
267     checkAbortAllTimeout(signal, Tdata0);
268     return;
269   case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
270     jam();
271     checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
272     return;
273   case TcContinueB::ZNF_CHECK_TRANSACTIONS:
274     jam();
275     nodeFailCheckTransactions(signal, Tdata0, Tdata1);
276     return;
277   case TcContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH:
278     jam();
279     checkWaitDropTabFailedLqh(signal, Tdata0, Tdata1);
280     return;
281   case TcContinueB::TRIGGER_PENDING:
282     jam();
283     ApiConnectRecordPtr transPtr;
284     transPtr.i = Tdata0;
285     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
286     transPtr.p->triggerPending = false;
287     executeTriggers(signal, &transPtr);
288     return;
289   case TcContinueB::DelayTCKEYCONF:
290     jam();
291     apiConnectptr.i = Tdata0;
292     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
293     sendtckeyconf(signal, Tdata1);
294     return;
295   default:
296     ndbrequire(false);
297   }//switch
298 }
299 
execDIGETNODESREF(Signal * signal)300 void Dbtc::execDIGETNODESREF(Signal* signal)
301 {
302   jamEntry();
303   terrorCode = signal->theData[1];
304   releaseAtErrorLab(signal);
305 }
306 
execINCL_NODEREQ(Signal * signal)307 void Dbtc::execINCL_NODEREQ(Signal* signal)
308 {
309   jamEntry();
310   tblockref = signal->theData[0];
311   hostptr.i = signal->theData[1];
312   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
313   hostptr.p->hostStatus = HS_ALIVE;
314   c_alive_nodes.set(hostptr.i);
315 
316   signal->theData[0] = hostptr.i;
317   signal->theData[1] = cownref;
318 
319   if (ERROR_INSERTED(8039))
320   {
321     CLEAR_ERROR_INSERT_VALUE;
322     Uint32 save = signal->theData[0];
323     signal->theData[0] = 9999;
324     sendSignal(numberToRef(CMVMI, hostptr.i),
325 	       GSN_NDB_TAMPER, signal, 1, JBB);
326     signal->theData[0] = save;
327     sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
328     return;
329   }
330 
331   sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
332 }
333 
execREAD_NODESREF(Signal * signal)334 void Dbtc::execREAD_NODESREF(Signal* signal)
335 {
336   jamEntry();
337   ndbrequire(false);
338 }
339 
execTC_SCHVERREQ(Signal * signal)340 void Dbtc::execTC_SCHVERREQ(Signal* signal)
341 {
342   jamEntry();
343   if (! assembleFragments(signal)) {
344     jam();
345     return;
346   }
347   tabptr.i = signal->theData[0];
348   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
349   tabptr.p->currentSchemaVersion = signal->theData[1];
350   tabptr.p->m_flags = 0;
351   tabptr.p->set_storedTable((bool)signal->theData[2]);
352   BlockReference retRef = signal->theData[3];
353   tabptr.p->tableType = (Uint8)signal->theData[4];
354   BlockReference retPtr = signal->theData[5];
355   Uint32 noOfKeyAttr = signal->theData[6];
356   tabptr.p->singleUserMode = (Uint8)signal->theData[7];
357   ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
358 
359   const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
360   ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
361 
362   ndbrequire(tabptr.p->get_enabled() == false);
363   tabptr.p->set_enabled(true);
364   tabptr.p->set_dropping(false);
365   tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
366   tabptr.p->hasCharAttr = desc->hasCharAttr;
367   tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
368   tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
369   signal->theData[0] = tabptr.i;
370   signal->theData[1] = retPtr;
371   sendSignal(retRef, GSN_TC_SCHVERCONF, signal, 2, JBB);
372 }//Dbtc::execTC_SCHVERREQ()
373 
374 void
execPREP_DROP_TAB_REQ(Signal * signal)375 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
376 {
377   jamEntry();
378 
379   PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
380 
381   TableRecordPtr tabPtr;
382   tabPtr.i = req->tableId;
383   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
384 
385   Uint32 senderRef = req->senderRef;
386   Uint32 senderData = req->senderData;
387 
388   if(!tabPtr.p->get_enabled()){
389     jam();
390     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
391     ref->senderRef = reference();
392     ref->senderData = senderData;
393     ref->tableId = tabPtr.i;
394     ref->errorCode = PrepDropTabRef::NoSuchTable;
395     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
396 	       PrepDropTabRef::SignalLength, JBB);
397     return;
398   }
399 
400   if(tabPtr.p->get_dropping()){
401     jam();
402     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
403     ref->senderRef = reference();
404     ref->senderData = senderData;
405     ref->tableId = tabPtr.i;
406     ref->errorCode = PrepDropTabRef::DropInProgress;
407     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
408 	       PrepDropTabRef::SignalLength, JBB);
409     return;
410   }
411 
412   tabPtr.p->set_dropping(true);
413   tabPtr.p->dropTable.senderRef = senderRef;
414   tabPtr.p->dropTable.senderData = senderData;
415 
416   {
417     WaitDropTabReq * req = (WaitDropTabReq*)signal->getDataPtrSend();
418     req->tableId = tabPtr.i;
419     req->senderRef = reference();
420 
421     HostRecordPtr hostPtr;
422     tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor();
423     for (hostPtr.i = 1; hostPtr.i < MAX_NDB_NODES; hostPtr.i++) {
424       jam();
425       ptrAss(hostPtr, hostRecord);
426       if (hostPtr.p->hostStatus == HS_ALIVE) {
427 	jam();
428 	tabPtr.p->dropTable.waitDropTabCount.setWaitingFor(hostPtr.i);
429 	sendSignal(calcLqhBlockRef(hostPtr.i), GSN_WAIT_DROP_TAB_REQ,
430 		   signal, WaitDropTabReq::SignalLength, JBB);
431       }//for
432     }//if
433 
434     ndbrequire(tabPtr.p->dropTable.waitDropTabCount.done() != true);
435   }
436 }
437 
438 void
execWAIT_DROP_TAB_CONF(Signal * signal)439 Dbtc::execWAIT_DROP_TAB_CONF(Signal* signal)
440 {
441   jamEntry();
442   WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
443 
444   TableRecordPtr tabPtr;
445   tabPtr.i = conf->tableId;
446   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
447 
448   ndbrequire(tabPtr.p->get_dropping() == true);
449   Uint32 nodeId = refToNode(conf->senderRef);
450   tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
451 
452   if(!tabPtr.p->dropTable.waitDropTabCount.done()){
453     jam();
454     return;
455   }
456 
457   {
458     PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
459     conf->tableId = tabPtr.i;
460     conf->senderRef = reference();
461     conf->senderData = tabPtr.p->dropTable.senderData;
462     sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
463 	       PrepDropTabConf::SignalLength, JBB);
464     tabPtr.p->dropTable.senderRef = 0;
465   }
466 }
467 
468 void
execWAIT_DROP_TAB_REF(Signal * signal)469 Dbtc::execWAIT_DROP_TAB_REF(Signal* signal)
470 {
471   jamEntry();
472   WaitDropTabRef * ref = (WaitDropTabRef*)signal->getDataPtr();
473 
474   TableRecordPtr tabPtr;
475   tabPtr.i = ref->tableId;
476   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
477 
478   ndbrequire(tabPtr.p->get_dropping() == true);
479   Uint32 nodeId = refToNode(ref->senderRef);
480   tabPtr.p->dropTable.waitDropTabCount.clearWaitingFor(nodeId);
481 
482   ndbrequire(ref->errorCode == WaitDropTabRef::NoSuchTable ||
483 	     ref->errorCode == WaitDropTabRef::NF_FakeErrorREF);
484 
485   if(!tabPtr.p->dropTable.waitDropTabCount.done()){
486     jam();
487     return;
488   }
489 
490   {
491     PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
492     conf->tableId = tabPtr.i;
493     conf->senderRef = reference();
494     conf->senderData = tabPtr.p->dropTable.senderData;
495     sendSignal(tabPtr.p->dropTable.senderRef, GSN_PREP_DROP_TAB_CONF, signal,
496 	       PrepDropTabConf::SignalLength, JBB);
497     tabPtr.p->dropTable.senderRef = 0;
498   }
499 }
500 
501 void
checkWaitDropTabFailedLqh(Signal * signal,Uint32 nodeId,Uint32 tableId)502 Dbtc::checkWaitDropTabFailedLqh(Signal* signal, Uint32 nodeId, Uint32 tableId)
503 {
504 
505   TableRecordPtr tabPtr;
506   tabPtr.i = tableId;
507 
508   WaitDropTabConf * conf = (WaitDropTabConf*)signal->getDataPtr();
509   conf->tableId = tableId;
510 
511   const Uint32 RT_BREAK = 16;
512   for(Uint32 i = 0; i<RT_BREAK && tabPtr.i < ctabrecFilesize; i++, tabPtr.i++){
513     jam();
514     ptrAss(tabPtr, tableRecord);
515     if(tabPtr.p->get_enabled() && tabPtr.p->get_dropping()){
516       if(tabPtr.p->dropTable.waitDropTabCount.isWaitingFor(nodeId)){
517         jam();
518 	conf->senderRef = calcLqhBlockRef(nodeId);
519 	execWAIT_DROP_TAB_CONF(signal);
520 	tabPtr.i++;
521 	break;
522       }
523     }
524   }
525 
526   if(tabPtr.i == ctabrecFilesize){
527     /**
528      * Finished
529      */
530     jam();
531     checkNodeFailComplete(signal, nodeId, HostRecord::NF_CHECK_DROP_TAB);
532     return;
533   }
534 
535   signal->theData[0] = TcContinueB::CHECK_WAIT_DROP_TAB_FAILED_LQH;
536   signal->theData[1] = nodeId;
537   signal->theData[2] = tabPtr.i;
538   sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
539 }
540 
541 void
execDROP_TAB_REQ(Signal * signal)542 Dbtc::execDROP_TAB_REQ(Signal* signal)
543 {
544   jamEntry();
545 
546   DropTabReq* req = (DropTabReq*)signal->getDataPtr();
547 
548   TableRecordPtr tabPtr;
549   tabPtr.i = req->tableId;
550   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
551 
552   Uint32 senderRef = req->senderRef;
553   Uint32 senderData = req->senderData;
554   DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
555 
556   if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
557     jam();
558     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
559     ref->senderRef = reference();
560     ref->senderData = senderData;
561     ref->tableId = tabPtr.i;
562     ref->errorCode = DropTabRef::NoSuchTable;
563     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
564 	       DropTabRef::SignalLength, JBB);
565     return;
566   }
567 
568   if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
569     jam();
570     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
571     ref->senderRef = reference();
572     ref->senderData = senderData;
573     ref->tableId = tabPtr.i;
574     ref->errorCode = DropTabRef::DropWoPrep;
575     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
576 	       DropTabRef::SignalLength, JBB);
577     return;
578   }
579 
580   tabPtr.p->set_enabled(false);
581   tabPtr.p->set_dropping(false);
582 
583   DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
584   conf->tableId = tabPtr.i;
585   conf->senderRef = reference();
586   conf->senderData = senderData;
587   sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
588 	     PrepDropTabConf::SignalLength, JBB);
589 }
590 
execALTER_TAB_REQ(Signal * signal)591 void Dbtc::execALTER_TAB_REQ(Signal * signal)
592 {
593   AlterTabReq* const req = (AlterTabReq*)signal->getDataPtr();
594   const Uint32 senderRef = req->senderRef;
595   const Uint32 senderData = req->senderData;
596   const Uint32 changeMask = req->changeMask;
597   const Uint32 tableId = req->tableId;
598   const Uint32 tableVersion = req->tableVersion;
599   const Uint32 gci = req->gci;
600   AlterTabReq::RequestType requestType =
601     (AlterTabReq::RequestType) req->requestType;
602 
603   TableRecordPtr tabPtr;
604   tabPtr.i = req->tableId;
605   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
606   tabPtr.p->currentSchemaVersion = tableVersion;
607 
608   // Request handled successfully
609   AlterTabConf * conf = (AlterTabConf*)signal->getDataPtrSend();
610   conf->senderRef = reference();
611   conf->senderData = senderData;
612   conf->changeMask = changeMask;
613   conf->tableId = tableId;
614   conf->tableVersion = tableVersion;
615   conf->gci = gci;
616   conf->requestType = requestType;
617   sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
618 	     AlterTabConf::SignalLength, JBB);
619 }
620 
621 /* ***************************************************************************/
622 /*                                START / RESTART                            */
623 /* ***************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)624 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
625 {
626   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
627   Uint32 ref = req->senderRef;
628   Uint32 senderData = req->senderData;
629   ndbrequire(req->noOfParameters == 0);
630 
631   jamEntry();
632 
633   const ndb_mgm_configuration_iterator * p =
634     m_ctx.m_config.getOwnConfigIterator();
635   ndbrequire(p != 0);
636 
637   initData();
638 
639   UintR apiConnect;
640   UintR tcConnect;
641   UintR tables;
642   UintR localScan;
643   UintR tcScan;
644 
645   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_API_CONNECT, &apiConnect));
646   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TC_CONNECT, &tcConnect));
647   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
648   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_LOCAL_SCAN, &localScan));
649   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_SCAN, &tcScan));
650 
651   ccacheFilesize = (apiConnect/3) + 1;
652   capiConnectFilesize = apiConnect;
653   ctcConnectFilesize  = tcConnect;
654   ctabrecFilesize     = tables;
655   cscanrecFileSize = tcScan;
656   cscanFragrecFileSize = localScan;
657 
658   initRecords();
659   initialiseRecordsLab(signal, 0, ref, senderData);
660 
661   Uint32 val = 3000;
662   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
663   set_timeout_value(val);
664 
665   val = 1500;
666   ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
667   cDbHbInterval = (val < 10) ? 10 : val;
668 
669   val = 3000;
670   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
671   set_appl_timeout_value(val);
672 
673   val = 1;
674   //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
675   set_no_parallel_takeover(val);
676 
677   ctimeOutCheckDelay = 50; // 500ms
678 }//Dbtc::execSIZEALT_REP()
679 
execSTTOR(Signal * signal)680 void Dbtc::execSTTOR(Signal* signal)
681 {
682   Uint16 tphase;
683 
684   jamEntry();
685                                                      /* START CASE */
686   tphase = signal->theData[1];
687   csignalKey = signal->theData[6];
688   switch (tphase) {
689   case ZSPH1:
690     jam();
691     startphase1x010Lab(signal);
692     return;
693   default:
694     jam();
695     sttorryLab(signal); /* START PHASE 255 */
696     return;
697   }//switch
698 }//Dbtc::execSTTOR()
699 
sttorryLab(Signal * signal)700 void Dbtc::sttorryLab(Signal* signal)
701 {
702   signal->theData[0] = csignalKey;
703   signal->theData[1] = 3;    /* BLOCK CATEGORY */
704   signal->theData[2] = 2;    /* SIGNAL VERSION NUMBER */
705   signal->theData[3] = ZSPH1;
706   signal->theData[4] = 255;
707   sendSignal(NDBCNTR_REF, GSN_STTORRY, signal, 5, JBB);
708 }//Dbtc::sttorryLab()
709 
710 /* ***************************************************************************/
711 /*                          INTERNAL  START / RESTART                        */
712 /*****************************************************************************/
execNDB_STTOR(Signal * signal)713 void Dbtc::execNDB_STTOR(Signal* signal)
714 {
715   Uint16 tndbstartphase;
716   Uint16 tstarttype;
717 
718   jamEntry();
719   tusersblkref = signal->theData[0];
720   tnodeid = signal->theData[1];
721   tndbstartphase = signal->theData[2];   /* START PHASE      */
722   tstarttype = signal->theData[3];       /* START TYPE       */
723   switch (tndbstartphase) {
724   case ZINTSPH1:
725     jam();
726     intstartphase1x010Lab(signal);
727     return;
728   case ZINTSPH2:
729     jam();
730     intstartphase2x010Lab(signal);
731     return;
732   case ZINTSPH3:
733     jam();
734     intstartphase3x010Lab(signal);      /* SEIZE CONNECT RECORD IN EACH LQH*/
735 // Start transaction event reporting.
736     c_counters.c_trans_status = TransCounters::Timer;
737     c_counters.reset();
738     signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
739     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, 1);
740     return;
741   case ZINTSPH6:
742     jam();
743     csystemStart = SSS_TRUE;
744     break;
745   default:
746     jam();
747     break;
748   }//switch
749   ndbsttorry010Lab(signal);
750   return;
751 }//Dbtc::execNDB_STTOR()
752 
ndbsttorry010Lab(Signal * signal)753 void Dbtc::ndbsttorry010Lab(Signal* signal)
754 {
755   signal->theData[0] = cownref;
756   sendSignal(cndbcntrblockref, GSN_NDB_STTORRY, signal, 1, JBB);
757 }//Dbtc::ndbsttorry010Lab()
758 
759 void
set_timeout_value(Uint32 timeOut)760 Dbtc::set_timeout_value(Uint32 timeOut)
761 {
762   timeOut = timeOut / 10;
763   if (timeOut < 2) {
764     jam();
765     timeOut = 100;
766   }//if
767   ctimeOutValue = timeOut;
768 }
769 
770 void
set_appl_timeout_value(Uint32 timeOut)771 Dbtc::set_appl_timeout_value(Uint32 timeOut)
772 {
773   if (timeOut)
774   {
775     timeOut /= 10;
776     if (timeOut < ctimeOutValue) {
777       jam();
778       c_appl_timeout_value = ctimeOutValue;
779     }//if
780   }
781   c_appl_timeout_value = timeOut;
782 }
783 
784 void
set_no_parallel_takeover(Uint32 noParallelTakeOver)785 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
786 {
787   if (noParallelTakeOver == 0) {
788     jam();
789     noParallelTakeOver = 1;
790   } else if (noParallelTakeOver > MAX_NDB_NODES) {
791     jam();
792     noParallelTakeOver = MAX_NDB_NODES;
793   }//if
794   cnoParallelTakeOver = noParallelTakeOver;
795 }
796 
797 /* ***************************************************************************/
798 /*                        S T A R T P H A S E 1 X                            */
799 /*                     INITIALISE BLOCKREF AND BLOCKNUMBERS                  */
800 /* ***************************************************************************/
startphase1x010Lab(Signal * signal)801 void Dbtc::startphase1x010Lab(Signal* signal)
802 {
803   csystemStart = SSS_FALSE;
804   ctimeOutCheckCounter = 0;
805   ctimeOutCheckFragCounter = 0;
806   ctimeOutMissedHeartbeats = 0;
807   ctimeOutCheckHeartbeat = 0;
808   ctimeOutCheckLastHeartbeat = 0;
809   ctimeOutCheckActive = TOCS_FALSE;
810   ctimeOutCheckFragActive = TOCS_FALSE;
811   sttorryLab(signal);
812 }//Dbtc::startphase1x010Lab()
813 
814 /*****************************************************************************/
815 /*                        I N T S T A R T P H A S E 1 X                      */
816 /*                         INITIALISE ALL RECORDS.                           */
817 /*****************************************************************************/
intstartphase1x010Lab(Signal * signal)818 void Dbtc::intstartphase1x010Lab(Signal* signal)
819 {
820   cownNodeid = tnodeid;
821   cownref =          calcTcBlockRef(cownNodeid);
822   clqhblockref =     calcLqhBlockRef(cownNodeid);
823   cdihblockref =     calcDihBlockRef(cownNodeid);
824   cdictblockref =    calcDictBlockRef(cownNodeid);
825   cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
826   cerrorBlockref   = calcNdbCntrBlockRef(cownNodeid);
827   coperationsize = 0;
828   cfailure_nr = 0;
829   ndbsttorry010Lab(signal);
830 }//Dbtc::intstartphase1x010Lab()
831 
832 /*****************************************************************************/
833 /*                         I N T S T A R T P H A S E 2 X                     */
834 /*                          SET-UP LOCAL CONNECTIONS.                        */
835 /*****************************************************************************/
intstartphase2x010Lab(Signal * signal)836 void Dbtc::intstartphase2x010Lab(Signal* signal)
837 {
838   tcConnectptr.i = cfirstfreeTcConnect;
839   intstartphase2x020Lab(signal);
840 }//Dbtc::intstartphase2x010Lab()
841 
intstartphase2x020Lab(Signal * signal)842 void Dbtc::intstartphase2x020Lab(Signal* signal)
843 {
844   if (tcConnectptr.i == RNIL) {
845     jam();
846     ndbsttorry010Lab(signal);
847     return;
848   }//if
849   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
850   tcConnectptr.p->tcConnectstate = OS_CONNECTING_DICT;
851 /* ****************** */
852 /*     DISEIZEREQ   < */
853 /* ****************** */
854   signal->theData[0] = tcConnectptr.i;
855   signal->theData[1] = cownref;
856   sendSignal(cdihblockref, GSN_DISEIZEREQ, signal, 2, JBB);
857 }//Dbtc::intstartphase2x020Lab()
858 
execDISEIZECONF(Signal * signal)859 void Dbtc::execDISEIZECONF(Signal* signal)
860 {
861   jamEntry();
862   tcConnectptr.i = signal->theData[0];
863   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
864   tcConnectptr.p->dihConnectptr = signal->theData[1];
865   tcConnectptr.i = tcConnectptr.p->nextTcConnect;
866   intstartphase2x020Lab(signal);
867 }//Dbtc::execDISEIZECONF()
868 
869 /*****************************************************************************/
870 /*                         I N T S T A R T P H A S E 3 X                     */
871 /*                        PREPARE DISTRIBUTED CONNECTIONS                    */
872 /*****************************************************************************/
intstartphase3x010Lab(Signal * signal)873 void Dbtc::intstartphase3x010Lab(Signal* signal)
874 {
875   signal->theData[0] = cownref;
876   sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
877 }//Dbtc::intstartphase3x010Lab()
878 
execREAD_NODESCONF(Signal * signal)879 void Dbtc::execREAD_NODESCONF(Signal* signal)
880 {
881   UintR guard0;
882 
883   jamEntry();
884 
885   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
886 
887   csystemnodes  = readNodes->noOfNodes;
888   cmasterNodeId = readNodes->masterNodeId;
889 
890   con_lineNodes = 0;
891   arrGuard(csystemnodes, MAX_NDB_NODES);
892   guard0 = csystemnodes - 1;
893   arrGuard(guard0, MAX_NDB_NODES);       // Check not zero nodes
894 
895   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
896     jam();
897     if (NodeBitmask::get(readNodes->allNodes, i)) {
898       hostptr.i = i;
899       ptrCheckGuard(hostptr, chostFilesize, hostRecord);
900 
901       if (NodeBitmask::get(readNodes->inactiveNodes, i)) {
902         jam();
903         hostptr.p->hostStatus = HS_DEAD;
904       } else {
905         jam();
906         con_lineNodes++;
907         hostptr.p->hostStatus = HS_ALIVE;
908 	c_alive_nodes.set(i);
909       }//if
910     }//if
911   }//for
912   ndbsttorry010Lab(signal);
913 }//Dbtc::execREAD_NODESCONF()
914 
915 /*****************************************************************************/
916 /*                     A P I _ F A I L R E Q                                 */
917 // An API node has failed for some reason. We need to disconnect all API
918 // connections to the API node. This also includes
919 /*****************************************************************************/
execAPI_FAILREQ(Signal * signal)920 void Dbtc::execAPI_FAILREQ(Signal* signal)
921 {
922   /***************************************************************************
923    * Set the block reference to return API_FAILCONF to. Set the number of api
924    * connects currently closing to one to indicate that we are still in the
925    * process of going through the api connect records. Thus checking for zero
926    * can only be true after all api connect records have been checked.
927    **************************************************************************/
928   jamEntry();
929   capiFailRef = signal->theData[1];
930   arrGuard(signal->theData[0], MAX_NODES);
931   capiConnectClosing[signal->theData[0]] = 1;
932   handleFailedApiNode(signal, signal->theData[0], (UintR)0);
933 }
934 
935 void
handleFailedApiNode(Signal * signal,UintR TapiFailedNode,UintR TapiConnectPtr)936 Dbtc::handleFailedApiNode(Signal* signal,
937                           UintR TapiFailedNode,
938                           UintR TapiConnectPtr)
939 {
940   UintR TloopCount = 0;
941   arrGuard(TapiFailedNode, MAX_NODES);
942   apiConnectptr.i = TapiConnectPtr;
943   do {
944     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
945     const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
946     if (TapiNode == TapiFailedNode) {
947 #ifdef VM_TRACE
948       if (apiConnectptr.p->apiFailState != ZFALSE) {
949         ndbout << "Error in previous API fail handling discovered" << endl
950 	       << "  apiConnectptr.i = " << apiConnectptr.i << endl
951 	       << "  apiConnectstate = " << apiConnectptr.p->apiConnectstate
952 	       << endl
953 	       << "  ndbapiBlockref = " << hex
954 	       << apiConnectptr.p->ndbapiBlockref << endl
955 	       << "  apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
956 	       << endl;
957 	if (apiConnectptr.p->lastTcConnect != RNIL){
958 	  jam();
959 	  tcConnectptr.i = apiConnectptr.p->lastTcConnect;
960 	  ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
961 	  ndbout << "  tcConnectptr.i = " << tcConnectptr.i << endl
962 		 << "  tcConnectstate = " << tcConnectptr.p->tcConnectstate
963 		 << endl;
964 	}
965       }//if
966 #endif
967 
968       apiConnectptr.p->returnsignal = RS_NO_RETURN;
969       /***********************************************************************/
970       // The connected node is the failed node.
971       /**********************************************************************/
972       switch(apiConnectptr.p->apiConnectstate) {
973       case CS_DISCONNECTED:
974         /*********************************************************************/
975         // These states do not need any special handling.
976         // Simply continue with the next.
977         /*********************************************************************/
978         jam();
979         break;
980       case CS_ABORTING:
981         /*********************************************************************/
982         // This could actually mean that the API connection is already
983         // ready to release if the abortState is IDLE.
984         /*********************************************************************/
985         if (apiConnectptr.p->abortState == AS_IDLE) {
986           jam();
987           releaseApiCon(signal, apiConnectptr.i);
988         } else {
989           jam();
990           capiConnectClosing[TapiFailedNode]++;
991           apiConnectptr.p->apiFailState = ZTRUE;
992         }//if
993         break;
994       case CS_WAIT_ABORT_CONF:
995       case CS_WAIT_COMMIT_CONF:
996       case CS_START_COMMITTING:
997       case CS_PREPARE_TO_COMMIT:
998       case CS_COMMITTING:
999       case CS_COMMIT_SENT:
1000         /*********************************************************************/
1001         // These states indicate that an abort process or commit process is
1002         // already ongoing. We will set a state in the api record indicating
1003         // that the API node has failed.
1004         // Also we will increase the number of outstanding api records to
1005         // wait for before we can respond with API_FAILCONF.
1006         /*********************************************************************/
1007         jam();
1008         capiConnectClosing[TapiFailedNode]++;
1009         apiConnectptr.p->apiFailState = ZTRUE;
1010         break;
1011       case CS_START_SCAN:
1012         /*********************************************************************/
1013         // The api record was performing a scan operation. We need to check
1014         // on the scan state. Since completing a scan process might involve
1015         // sending several signals we will increase the loop count by 64.
1016         /*********************************************************************/
1017         jam();
1018 
1019 	apiConnectptr.p->apiFailState = ZTRUE;
1020 	capiConnectClosing[TapiFailedNode]++;
1021 
1022 	ScanRecordPtr scanPtr;
1023 	scanPtr.i = apiConnectptr.p->apiScanRec;
1024 	ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
1025 	close_scan_req(signal, scanPtr, true);
1026 
1027         TloopCount += 64;
1028         break;
1029       case CS_CONNECTED:
1030       case CS_REC_COMMITTING:
1031       case CS_RECEIVING:
1032       case CS_STARTED:
1033         /*********************************************************************/
1034         // The api record was in the process of performing a transaction but
1035         // had not yet sent all information.
1036         // We need to initiate an ABORT since the API will not provide any
1037         // more information.
1038         // Since the abort can send many signals we will insert a real-time
1039         // break after checking this record.
1040         /*********************************************************************/
1041         jam();
1042         apiConnectptr.p->apiFailState = ZTRUE;
1043         capiConnectClosing[TapiFailedNode]++;
1044         abort010Lab(signal);
1045         TloopCount = 256;
1046         break;
1047       case CS_PREPARED:
1048         jam();
1049       case CS_REC_PREPARING:
1050         jam();
1051       case CS_START_PREPARING:
1052         jam();
1053         /*********************************************************************/
1054         // Not implemented yet.
1055         /*********************************************************************/
1056         systemErrorLab(signal, __LINE__);
1057         break;
1058       case CS_RESTART:
1059         jam();
1060       case CS_COMPLETING:
1061         jam();
1062       case CS_COMPLETE_SENT:
1063         jam();
1064       case CS_WAIT_COMPLETE_CONF:
1065         jam();
1066       case CS_FAIL_ABORTING:
1067         jam();
1068       case CS_FAIL_ABORTED:
1069         jam();
1070       case CS_FAIL_PREPARED:
1071         jam();
1072       case CS_FAIL_COMMITTING:
1073         jam();
1074       case CS_FAIL_COMMITTED:
1075         /*********************************************************************/
1076         // These states are only valid on copy and fail API connections.
1077         /*********************************************************************/
1078       default:
1079         jam();
1080         systemErrorLab(signal, __LINE__);
1081         break;
1082       }//switch
1083     } else {
1084       jam();
1085     }//if
1086     apiConnectptr.i++;
1087     if (apiConnectptr.i > ((capiConnectFilesize / 3) - 1)) {
1088       jam();
1089       /**
1090        * Finished with scanning connection record
1091        *
1092        * Now scan markers
1093        */
1094       removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1095       return;
1096     }//if
1097   } while (TloopCount++ < 256);
1098   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1099   signal->theData[1] = TapiFailedNode;
1100   signal->theData[2] = apiConnectptr.i;
1101   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1102 }//Dbtc::handleFailedApiNode()
1103 
1104 void
removeMarkerForFailedAPI(Signal * signal,Uint32 nodeId,Uint32 startBucket)1105 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1106                                Uint32 nodeId,
1107                                Uint32 startBucket)
1108 {
1109   TcFailRecordPtr node_fail_ptr;
1110   node_fail_ptr.i = 0;
1111   ptrAss(node_fail_ptr, tcFailRecord);
1112   if(node_fail_ptr.p->failStatus != FS_IDLE) {
1113     jam();
1114     DEBUG("Restarting removeMarkerForFailedAPI");
1115     /**
1116      * TC take-over in progress
1117      *   needs to restart as this
1118      *   creates new markers
1119      */
1120     signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1121     signal->theData[1] = nodeId;
1122     signal->theData[2] = 0;
1123     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1124     return;
1125   }
1126 
1127   CommitAckMarkerIterator iter;
1128   m_commitAckMarkerHash.next(startBucket, iter);
1129 
1130   const Uint32 RT_BREAK = 256;
1131   for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1132     jam();
1133 
1134     if(iter.curr.i == RNIL){
1135       jam();
1136       /**
1137        * Done with iteration
1138        */
1139       capiConnectClosing[nodeId]--;
1140       if (capiConnectClosing[nodeId] == 0) {
1141         jam();
1142         /********************************************************************/
1143         // No outstanding ABORT or COMMIT's of this failed API node.
1144         // We can respond with API_FAILCONF
1145         /********************************************************************/
1146         signal->theData[0] = nodeId;
1147         signal->theData[1] = cownref;
1148         sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
1149       }
1150       return;
1151     }
1152 
1153     if(iter.curr.p->apiNodeId == nodeId){
1154       jam();
1155 
1156       /**
1157        * Check so that the record is not still in use
1158        *
1159        */
1160       ApiConnectRecordPtr apiConnectPtr;
1161       apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1162       ptrCheckGuard(apiConnectPtr, capiConnectFilesize, apiConnectRecord);
1163       if(apiConnectPtr.p->commitAckMarker == iter.curr.i){
1164 	jam();
1165         /**
1166          * The record is still active
1167          *
1168          * Don't remove it, but continueb instead
1169          */
1170 	break;
1171       }
1172       sendRemoveMarkers(signal, iter.curr.p);
1173       m_commitAckMarkerHash.release(iter.curr);
1174 
1175       break;
1176     }
1177     m_commitAckMarkerHash.next(iter);
1178   }
1179 
1180   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1181   signal->theData[1] = nodeId;
1182   signal->theData[2] = iter.bucket;
1183   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1184 }
1185 
handleApiFailState(Signal * signal,UintR TapiConnectptr)1186 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1187 {
1188   ApiConnectRecordPtr TlocalApiConnectptr;
1189   UintR TfailedApiNode;
1190 
1191   TlocalApiConnectptr.i = TapiConnectptr;
1192   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
1193   TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1194   arrGuard(TfailedApiNode, MAX_NODES);
1195   capiConnectClosing[TfailedApiNode]--;
1196   releaseApiCon(signal, TapiConnectptr);
1197   TlocalApiConnectptr.p->apiFailState = ZFALSE;
1198   if (capiConnectClosing[TfailedApiNode] == 0) {
1199     jam();
1200     signal->theData[0] = TfailedApiNode;
1201     signal->theData[1] = cownref;
1202     sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
1203   }//if
1204 }//Dbtc::handleApiFailState()
1205 
1206 /****************************************************************************
1207  *                                T C S E I Z E R E Q
1208  * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1209  * TRANSACTION
1210  * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1211  * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1212  ****************************************************************************/
execTCSEIZEREQ(Signal * signal)1213 void Dbtc::execTCSEIZEREQ(Signal* signal)
1214 {
1215   UintR tapiPointer;
1216   BlockReference tapiBlockref;       /* SENDER BLOCK REFERENCE*/
1217 
1218   jamEntry();
1219   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1220   tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1221 
1222   const NodeState::StartLevel sl =
1223     (NodeState::StartLevel)getNodeState().startLevel;
1224 
1225   const NodeId senderNodeId = refToNode(tapiBlockref);
1226   const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1227 
1228   {
1229     {
1230       if (!(sl == NodeState::SL_STARTED ||
1231 	    (sl == NodeState::SL_STARTING && local == true))) {
1232 	jam();
1233 
1234 	Uint32 errCode = 0;
1235 	if(!local)
1236 	  {
1237 	    switch(sl){
1238 	    case NodeState::SL_STARTING:
1239 	      errCode = ZSYSTEM_NOT_STARTED_ERROR;
1240 	      break;
1241 	    case NodeState::SL_STOPPING_1:
1242 	    case NodeState::SL_STOPPING_2:
1243               if (getNodeState().getSingleUserMode())
1244                 break;
1245 	    case NodeState::SL_STOPPING_3:
1246 	    case NodeState::SL_STOPPING_4:
1247 	      if(getNodeState().stopping.systemShutdown)
1248 		errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1249 	      else
1250 		errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1251 	      break;
1252 	    case NodeState::SL_SINGLEUSER:
1253 	      break;
1254 	    default:
1255 	      errCode = ZWRONG_STATE;
1256 	      break;
1257 	    }
1258             if (errCode)
1259             {
1260               signal->theData[0] = tapiPointer;
1261               signal->theData[1] = errCode;
1262               sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1263               return;
1264             }
1265 	  }//if (!(sl == SL_SINGLEUSER))
1266       } //if
1267     }
1268   }
1269 
1270   seizeApiConnect(signal);
1271   if (terrorCode == ZOK) {
1272     jam();
1273     apiConnectptr.p->ndbapiConnect = tapiPointer;
1274     apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1275     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1276     signal->theData[1] = apiConnectptr.i;
1277     sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 2, JBB);
1278     return;
1279   }
1280 
1281   signal->theData[0] = tapiPointer;
1282   signal->theData[1] = terrorCode;
1283   sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1284 }//Dbtc::execTCSEIZEREQ()
1285 
1286 /****************************************************************************/
1287 /*                    T C R E L E A S E Q                                   */
1288 /*                  REQUEST TO RELEASE A CONNECT RECORD                     */
1289 /****************************************************************************/
execTCRELEASEREQ(Signal * signal)1290 void Dbtc::execTCRELEASEREQ(Signal* signal)
1291 {
1292   UintR tapiPointer;
1293   BlockReference tapiBlockref;     /* SENDER BLOCK REFERENCE*/
1294 
1295   jamEntry();
1296   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1297   tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1298   tuserpointer = signal->theData[2];
1299   if (tapiPointer >= capiConnectFilesize) {
1300     jam();
1301     signal->theData[0] = tuserpointer;
1302     signal->theData[1] = ZINVALID_CONNECTION;
1303     signal->theData[2] = __LINE__;
1304     sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1305     return;
1306   } else {
1307     jam();
1308     apiConnectptr.i = tapiPointer;
1309   }//if
1310   ptrAss(apiConnectptr, apiConnectRecord);
1311   if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED) {
1312     jam();
1313     signal->theData[0] = tuserpointer;
1314     sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1315   } else {
1316     if (tapiBlockref == apiConnectptr.p->ndbapiBlockref) {
1317       if (apiConnectptr.p->apiConnectstate == CS_CONNECTED ||
1318 	  (apiConnectptr.p->apiConnectstate == CS_ABORTING &&
1319 	   apiConnectptr.p->abortState == AS_IDLE) ||
1320 	  (apiConnectptr.p->apiConnectstate == CS_STARTED &&
1321 	   apiConnectptr.p->firstTcConnect == RNIL))
1322       {
1323         jam();                                   /* JUST REPLY OK */
1324 	apiConnectptr.p->m_transaction_nodes.clear();
1325         releaseApiCon(signal, apiConnectptr.i);
1326         signal->theData[0] = tuserpointer;
1327         sendSignal(tapiBlockref,
1328                    GSN_TCRELEASECONF, signal, 1, JBB);
1329       } else {
1330         jam();
1331         signal->theData[0] = tuserpointer;
1332         signal->theData[1] = ZINVALID_CONNECTION;
1333 	signal->theData[2] = __LINE__;
1334 	signal->theData[3] = apiConnectptr.p->apiConnectstate;
1335         sendSignal(tapiBlockref,
1336                    GSN_TCRELEASEREF, signal, 4, JBB);
1337       }
1338     } else {
1339       jam();
1340       signal->theData[0] = tuserpointer;
1341       signal->theData[1] = ZINVALID_CONNECTION;
1342       signal->theData[2] = __LINE__;
1343       signal->theData[3] = tapiBlockref;
1344       signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1345       sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1346     }//if
1347   }//if
1348 }//Dbtc::execTCRELEASEREQ()
1349 
1350 /****************************************************************************/
1351 // Error Handling for TCKEYREQ messages
1352 /****************************************************************************/
signalErrorRefuseLab(Signal * signal)1353 void Dbtc::signalErrorRefuseLab(Signal* signal)
1354 {
1355   ptrGuard(apiConnectptr);
1356   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1357     jam();
1358     apiConnectptr.p->abortState = AS_IDLE;
1359     apiConnectptr.p->apiConnectstate = CS_ABORTING;
1360   }//if
1361   sendSignalErrorRefuseLab(signal);
1362 }//Dbtc::signalErrorRefuseLab()
1363 
sendSignalErrorRefuseLab(Signal * signal)1364 void Dbtc::sendSignalErrorRefuseLab(Signal* signal)
1365 {
1366   ndbassert(false);
1367   ptrGuard(apiConnectptr);
1368   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1369     jam();
1370     ndbrequire(false);
1371     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1372     signal->theData[1] = signal->theData[ttransid_ptr];
1373     signal->theData[2] = signal->theData[ttransid_ptr + 1];
1374     signal->theData[3] = ZSIGNAL_ERROR;
1375     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1376 	       signal, 4, JBB);
1377   }
1378 }//Dbtc::sendSignalErrorRefuseLab()
1379 
abortBeginErrorLab(Signal * signal)1380 void Dbtc::abortBeginErrorLab(Signal* signal)
1381 {
1382   apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1383   apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1384   abortErrorLab(signal);
1385 }//Dbtc::abortBeginErrorLab()
1386 
printState(Signal * signal,int place)1387 void Dbtc::printState(Signal* signal, int place)
1388 {
1389 #ifdef VM_TRACE // Change to if 0 to disable these printouts
1390   ndbout << "-- Dbtc::printState -- " << endl;
1391   ndbout << "Received from place = " << place
1392 	 << " apiConnectptr.i = " << apiConnectptr.i
1393 	 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
1394   ndbout << "ctcTimer = " << ctcTimer
1395 	 << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
1396 	 << " Transid = " << apiConnectptr.p->transid[0]
1397 	 << " " << apiConnectptr.p->transid[1] << endl;
1398   ndbout << " apiTimer = " << getApiConTimer(apiConnectptr.i)
1399 	 << " counter = " << apiConnectptr.p->counter
1400 	 << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
1401 	 << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec << endl;
1402   ndbout << "abortState = " << apiConnectptr.p->abortState
1403 	 << " apiScanRec = " << apiConnectptr.p->apiScanRec
1404 	 << " returncode = " << apiConnectptr.p->returncode << endl;
1405   ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
1406 	 << " returnsignal = " << apiConnectptr.p->returnsignal
1407 	 << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
1408   if (apiConnectptr.p->cachePtr != RNIL) {
1409     jam();
1410     CacheRecord *localCacheRecord = cacheRecord;
1411     UintR TcacheFilesize = ccacheFilesize;
1412     UintR TcachePtr = apiConnectptr.p->cachePtr;
1413     if (TcachePtr < TcacheFilesize) {
1414       jam();
1415       CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1416       ndbout << "currReclenAi = " << regCachePtr->currReclenAi
1417 	     << " attrlength = " << regCachePtr->attrlength
1418 	     << " tableref = " << regCachePtr->tableref
1419 	     << " keylen = " << regCachePtr->keylen << endl;
1420     } else {
1421       jam();
1422       systemErrorLab(signal, __LINE__);
1423     }//if
1424   }//if
1425 #endif
1426   return;
1427 }//Dbtc::printState()
1428 
1429 void
TCKEY_abort(Signal * signal,int place)1430 Dbtc::TCKEY_abort(Signal* signal, int place)
1431 {
1432   switch (place) {
1433   case 0:
1434     jam();
1435     terrorCode = ZSTATE_ERROR;
1436     apiConnectptr.p->firstTcConnect = RNIL;
1437     printState(signal, 4);
1438     abortBeginErrorLab(signal);
1439     return;
1440   case 1:
1441     jam();
1442     printState(signal, 3);
1443     sendSignalErrorRefuseLab(signal);
1444     return;
1445   case 2:{
1446     printState(signal, 6);
1447     const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
1448     const Uint32 t1 = tcKeyReq->transId1;
1449     const Uint32 t2 = tcKeyReq->transId2;
1450     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1451     signal->theData[1] = t1;
1452     signal->theData[2] = t2;
1453     signal->theData[3] = ZABORT_ERROR;
1454     ndbrequire(false);
1455     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1456 	       signal, 4, JBB);
1457     return;
1458   }
1459   case 3:
1460     jam();
1461     printState(signal, 7);
1462     noFreeConnectionErrorLab(signal);
1463     return;
1464   case 4:
1465     jam();
1466     terrorCode = ZERO_KEYLEN_ERROR;
1467     releaseAtErrorLab(signal);
1468     return;
1469   case 5:
1470     jam();
1471     terrorCode = ZNO_AI_WITH_UPDATE;
1472     releaseAtErrorLab(signal);
1473     return;
1474   case 6:
1475     jam();
1476     warningHandlerLab(signal, __LINE__);
1477     return;
1478 
1479   case 7:
1480     jam();
1481     tabStateErrorLab(signal);
1482     return;
1483 
1484   case 8:
1485     jam();
1486     wrongSchemaVersionErrorLab(signal);
1487     return;
1488 
1489   case 9:
1490     jam();
1491     terrorCode = ZSTATE_ERROR;
1492     releaseAtErrorLab(signal);
1493     return;
1494 
1495   case 10:
1496     jam();
1497     systemErrorLab(signal, __LINE__);
1498     return;
1499 
1500   case 11:
1501     jam();
1502     terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
1503     releaseAtErrorLab(signal);
1504     return;
1505 
1506   case 12:
1507     jam();
1508     terrorCode = ZSIMPLE_READ_WITHOUT_AI;
1509     releaseAtErrorLab(signal);
1510     return;
1511 
1512   case 13:
1513     jam();
1514     switch (tcConnectptr.p->tcConnectstate) {
1515     case OS_WAIT_KEYINFO:
1516       jam();
1517       printState(signal, 8);
1518       terrorCode = ZSTATE_ERROR;
1519       abortErrorLab(signal);
1520       return;
1521     default:
1522       jam();
1523       /********************************************************************/
1524       /*       MISMATCH BETWEEN STATE ON API CONNECTION AND THIS          */
1525       /*       PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB   */
1526       /*       INTERNAL ERROR.                                            */
1527       /********************************************************************/
1528       systemErrorLab(signal, __LINE__);
1529       return;
1530     }//switch
1531     return;
1532 
1533   case 15:
1534     jam();
1535     terrorCode = ZSCAN_NODE_ERROR;
1536     releaseAtErrorLab(signal);
1537     return;
1538 
1539   case 16:
1540     jam();
1541     systemErrorLab(signal, __LINE__);
1542     return;
1543 
1544   case 17:
1545     jam();
1546     systemErrorLab(signal, __LINE__);
1547     return;
1548 
1549   case 18:
1550     jam();
1551     warningHandlerLab(signal, __LINE__);
1552     return;
1553 
1554   case 19:
1555     jam();
1556     return;
1557 
1558   case 20:
1559     jam();
1560     warningHandlerLab(signal, __LINE__);
1561     return;
1562 
1563   case 21:
1564     jam();
1565     systemErrorLab(signal, __LINE__);
1566     return;
1567 
1568   case 22:
1569     jam();
1570     systemErrorLab(signal, __LINE__);
1571     return;
1572 
1573   case 23:
1574     jam();
1575     systemErrorLab(signal, __LINE__);
1576     return;
1577 
1578   case 24:
1579     jam();
1580     seizeAttrbuferrorLab(signal);
1581     return;
1582 
1583   case 25:
1584     jam();
1585     warningHandlerLab(signal, __LINE__);
1586     return;
1587 
1588   case 26:
1589     jam();
1590     return;
1591 
1592   case 27:
1593     systemErrorLab(signal, __LINE__);
1594     jam();
1595     return;
1596 
1597   case 28:
1598     jam();
1599     // NOT USED
1600     return;
1601 
1602   case 29:
1603     jam();
1604     systemErrorLab(signal, __LINE__);
1605     return;
1606 
1607   case 30:
1608     jam();
1609     systemErrorLab(signal, __LINE__);
1610     return;
1611 
1612   case 31:
1613     jam();
1614     systemErrorLab(signal, __LINE__);
1615     return;
1616 
1617   case 32:
1618     jam();
1619     systemErrorLab(signal, __LINE__);
1620     return;
1621 
1622   case 33:
1623     jam();
1624     systemErrorLab(signal, __LINE__);
1625     return;
1626 
1627   case 34:
1628     jam();
1629     systemErrorLab(signal, __LINE__);
1630     return;
1631 
1632   case 35:
1633     jam();
1634     systemErrorLab(signal, __LINE__);
1635     return;
1636 
1637   case 36:
1638     jam();
1639     systemErrorLab(signal, __LINE__);
1640     return;
1641 
1642   case 37:
1643     jam();
1644     systemErrorLab(signal, __LINE__);
1645     return;
1646 
1647   case 38:
1648     jam();
1649     systemErrorLab(signal, __LINE__);
1650     return;
1651 
1652   case 39:
1653     jam();
1654     systemErrorLab(signal, __LINE__);
1655     return;
1656 
1657   case 40:
1658     jam();
1659     systemErrorLab(signal, __LINE__);
1660     return;
1661 
1662   case 41:
1663     jam();
1664     systemErrorLab(signal, __LINE__);
1665     return;
1666 
1667   case 42:
1668     jam();
1669     systemErrorLab(signal, __LINE__);
1670     return;
1671 
1672   case 43:
1673     jam();
1674     systemErrorLab(signal, __LINE__);
1675     return;
1676 
1677   case 44:
1678     jam();
1679     systemErrorLab(signal, __LINE__);
1680     return;
1681 
1682   case 45:
1683     jam();
1684     systemErrorLab(signal, __LINE__);
1685     return;
1686 
1687   case 46:
1688     jam();
1689     systemErrorLab(signal, __LINE__);
1690     return;
1691 
1692   case 47:
1693     jam();
1694     terrorCode = apiConnectptr.p->returncode;
1695     releaseAtErrorLab(signal);
1696     return;
1697 
1698   case 48:
1699     jam();
1700     terrorCode = ZCOMMIT_TYPE_ERROR;
1701     releaseAtErrorLab(signal);
1702     return;
1703 
1704   case 49:
1705     jam();
1706     abortErrorLab(signal);
1707     return;
1708 
1709   case 50:
1710     jam();
1711     systemErrorLab(signal, __LINE__);
1712     return;
1713 
1714   case 51:
1715     jam();
1716     abortErrorLab(signal);
1717     return;
1718 
1719   case 52:
1720     jam();
1721     abortErrorLab(signal);
1722     return;
1723 
1724   case 53:
1725     jam();
1726     abortErrorLab(signal);
1727     return;
1728 
1729   case 54:
1730     jam();
1731     abortErrorLab(signal);
1732     return;
1733 
1734   case 55:
1735     jam();
1736     printState(signal, 5);
1737     sendSignalErrorRefuseLab(signal);
1738     return;
1739 
1740   case 56:{
1741     jam();
1742     terrorCode = ZNO_FREE_TC_MARKER;
1743     abortErrorLab(signal);
1744     return;
1745   }
1746   case 57:{
1747     jam();
1748     /**
1749      * Initialize object before starting error handling
1750      */
1751     initApiConnectRec(signal, apiConnectptr.p, true);
1752 start_failure:
1753     switch(getNodeState().startLevel){
1754     case NodeState::SL_STOPPING_2:
1755       if (getNodeState().getSingleUserMode())
1756       {
1757         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1758         break;
1759       }
1760     case NodeState::SL_STOPPING_3:
1761     case NodeState::SL_STOPPING_4:
1762       if(getNodeState().stopping.systemShutdown)
1763 	terrorCode  = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1764       else
1765 	terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1766       break;
1767     case NodeState::SL_SINGLEUSER:
1768       terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1769       break;
1770     case NodeState::SL_STOPPING_1:
1771       if (getNodeState().getSingleUserMode())
1772       {
1773         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
1774         break;
1775       }
1776     default:
1777       terrorCode = ZWRONG_STATE;
1778       break;
1779     }
1780     abortErrorLab(signal);
1781     return;
1782   }
1783 
1784   case 58:{
1785     jam();
1786     releaseAtErrorLab(signal);
1787     return;
1788   }
1789 
1790   case 59:{
1791     jam();
1792     terrorCode = ZABORTINPROGRESS;
1793     abortErrorLab(signal);
1794     return;
1795   }
1796 
1797   case 60:
1798   {
1799     jam();
1800     initApiConnectRec(signal, apiConnectptr.p, true);
1801     apiConnectptr.p->m_exec_flag = 1;
1802     goto start_failure;
1803   }
1804   default:
1805     jam();
1806     systemErrorLab(signal, __LINE__);
1807     return;
1808   }//switch
1809 }
1810 
1811 static
1812 inline
1813 bool
compare_transid(Uint32 * val0,Uint32 * val1)1814 compare_transid(Uint32* val0, Uint32* val1)
1815 {
1816   Uint32 tmp0 = val0[0] ^ val1[0];
1817   Uint32 tmp1 = val0[1] ^ val1[1];
1818   return (tmp0 | tmp1) == 0;
1819 }
1820 
execKEYINFO(Signal * signal)1821 void Dbtc::execKEYINFO(Signal* signal)
1822 {
1823   jamEntry();
1824   apiConnectptr.i = signal->theData[0];
1825   tmaxData = 20;
1826   if (apiConnectptr.i >= capiConnectFilesize) {
1827     TCKEY_abort(signal, 18);
1828     return;
1829   }//if
1830   ptrAss(apiConnectptr, apiConnectRecord);
1831   ttransid_ptr = 1;
1832   if (compare_transid(apiConnectptr.p->transid, signal->theData+1) == false)
1833   {
1834     TCKEY_abort(signal, 19);
1835     return;
1836   }//if
1837   switch (apiConnectptr.p->apiConnectstate) {
1838   case CS_RECEIVING:
1839   case CS_REC_COMMITTING:
1840   case CS_START_SCAN:
1841     jam();
1842     /*empty*/;
1843     break;
1844                 /* OK */
1845   case CS_ABORTING:
1846     jam();
1847     return;     /* IGNORE */
1848   case CS_CONNECTED:
1849     jam();
1850     /****************************************************************>*/
1851     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
1852     /*       SET STATE TO ABORTING.                                   */
1853     /****************************************************************>*/
1854     printState(signal, 11);
1855     signalErrorRefuseLab(signal);
1856     return;
1857   case CS_STARTED:
1858     jam();
1859     /****************************************************************>*/
1860     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
1861     /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
1862     /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
1863     /****************************************************************>*/
1864     terrorCode = ZSIGNAL_ERROR;
1865     printState(signal, 2);
1866     abortErrorLab(signal);
1867     return;
1868   default:
1869     jam();
1870     warningHandlerLab(signal, __LINE__);
1871     return;
1872   }//switch
1873 
1874   CacheRecord *localCacheRecord = cacheRecord;
1875   UintR TcacheFilesize = ccacheFilesize;
1876   UintR TcachePtr = apiConnectptr.p->cachePtr;
1877   UintR TtcTimer = ctcTimer;
1878   CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
1879   if (TcachePtr >= TcacheFilesize) {
1880     TCKEY_abort(signal, 42);
1881     return;
1882   }//if
1883   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
1884   cachePtr.i = TcachePtr;
1885   cachePtr.p = regCachePtr;
1886 
1887   tcConnectptr.i = apiConnectptr.p->lastTcConnect;
1888   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
1889   switch (tcConnectptr.p->tcConnectstate) {
1890   case OS_WAIT_KEYINFO:
1891     jam();
1892     tckeyreq020Lab(signal);
1893     return;
1894   case OS_WAIT_SCAN:
1895     break;
1896   default:
1897     jam();
1898     terrorCode = ZSTATE_ERROR;
1899     abortErrorLab(signal);
1900     return;
1901   }//switch
1902 
1903   UintR TdataPos = 0;
1904   UintR TkeyLen = regCachePtr->keylen;
1905   UintR Tlen = regCachePtr->save1;
1906 
1907   do {
1908     if (cfirstfreeDatabuf == RNIL) {
1909       jam();
1910       seizeDatabuferrorLab(signal);
1911       return;
1912     }//if
1913     linkKeybuf(signal);
1914     arrGuard(TdataPos, 19);
1915     databufptr.p->data[0] = signal->theData[TdataPos + 3];
1916     databufptr.p->data[1] = signal->theData[TdataPos + 4];
1917     databufptr.p->data[2] = signal->theData[TdataPos + 5];
1918     databufptr.p->data[3] = signal->theData[TdataPos + 6];
1919     Tlen = Tlen + 4;
1920     TdataPos = TdataPos + 4;
1921     if (Tlen < TkeyLen) {
1922       jam();
1923       if (TdataPos >= tmaxData) {
1924         jam();
1925 	/*----------------------------------------------------*/
1926 	/** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9     **/
1927 	/** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP    **/
1928 	/** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE       **/
1929 	/** PROGRAM RETURNS TO LABEL TCKEYREQ020             **/
1930 	/*----------------------------------------------------*/
1931         setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
1932         regCachePtr->save1 = Tlen;
1933         return;
1934       }//if
1935     } else {
1936       jam();
1937       return;
1938     }//if
1939   } while (1);
1940   return;
1941 }//Dbtc::execKEYINFO()
1942 
1943 /*---------------------------------------------------------------------------*/
1944 /*                                                                           */
1945 /* MORE THAN FOUR WORDS OF KEY DATA. WE NEED TO PACK THIS IN KEYINFO SIGNALS.*/
1946 /* WE WILL ALWAYS PACK 4 WORDS AT A TIME.                                    */
1947 /*---------------------------------------------------------------------------*/
packKeyData000Lab(Signal * signal,BlockReference TBRef,Uint32 totalLen)1948 void Dbtc::packKeyData000Lab(Signal* signal,
1949                              BlockReference TBRef,
1950 			     Uint32 totalLen)
1951 {
1952   CacheRecord * const regCachePtr = cachePtr.p;
1953 
1954   jam();
1955   Uint32 len = 0;
1956   databufptr.i = regCachePtr->firstKeybuf;
1957   signal->theData[0] = tcConnectptr.i;
1958   signal->theData[1] = apiConnectptr.p->transid[0];
1959   signal->theData[2] = apiConnectptr.p->transid[1];
1960   Uint32 * dst = signal->theData+3;
1961   ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
1962 
1963   do {
1964     jam();
1965     databufptr.i = databufptr.p->nextDatabuf;
1966     dst[len + 0] = databufptr.p->data[0];
1967     dst[len + 1] = databufptr.p->data[1];
1968     dst[len + 2] = databufptr.p->data[2];
1969     dst[len + 3] = databufptr.p->data[3];
1970     len += 4;
1971     if (totalLen <= 4) {
1972       jam();
1973       /*---------------------------------------------------------------------*/
1974       /*       LAST PACK OF KEY DATA HAVE BEEN SENT                          */
1975       /*---------------------------------------------------------------------*/
1976       /*       THERE WERE UNSENT INFORMATION, SEND IT.                       */
1977       /*---------------------------------------------------------------------*/
1978       sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
1979       return;
1980     } else if(len == KeyInfo::DataLength){
1981       jam();
1982       len = 0;
1983       sendSignal(TBRef, GSN_KEYINFO, signal, 3 + KeyInfo::DataLength, JBB);
1984     }
1985     totalLen -= 4;
1986     ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
1987   } while (1);
1988 }//Dbtc::packKeyData000Lab()
1989 
tckeyreq020Lab(Signal * signal)1990 void Dbtc::tckeyreq020Lab(Signal* signal)
1991 {
1992   CacheRecord * const regCachePtr = cachePtr.p;
1993   UintR TdataPos = 0;
1994   UintR TkeyLen = regCachePtr->keylen;
1995   UintR Tlen = regCachePtr->save1;
1996 
1997   do {
1998     if (cfirstfreeDatabuf == RNIL) {
1999       jam();
2000       seizeDatabuferrorLab(signal);
2001       return;
2002     }//if
2003     linkKeybuf(signal);
2004     arrGuard(TdataPos, 19);
2005     databufptr.p->data[0] = signal->theData[TdataPos + 3];
2006     databufptr.p->data[1] = signal->theData[TdataPos + 4];
2007     databufptr.p->data[2] = signal->theData[TdataPos + 5];
2008     databufptr.p->data[3] = signal->theData[TdataPos + 6];
2009     Tlen = Tlen + 4;
2010     TdataPos = TdataPos + 4;
2011     if (Tlen < TkeyLen) {
2012       jam();
2013       if (TdataPos >= tmaxData) {
2014         jam();
2015 	/*----------------------------------------------------*/
2016 	/** EXIT AND WAIT FOR SIGNAL KEYINFO OR KEYINFO9     **/
2017 	/** WHEN EITHER OF THE SIGNALS IS RECEIVED A JUMP    **/
2018 	/** TO LABEL "KEYINFO_LABEL" IS DONE. THEN THE       **/
2019 	/** PROGRAM RETURNS TO LABEL TCKEYREQ020             **/
2020 	/*----------------------------------------------------*/
2021         setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2022         regCachePtr->save1 = Tlen;
2023         tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2024         return;
2025       }//if
2026     } else {
2027       jam();
2028       tckeyreq050Lab(signal);
2029       return;
2030     }//if
2031   } while (1);
2032   return;
2033 }//Dbtc::tckeyreq020Lab()
2034 
2035 /* ------------------------------------------------------------------------- */
2036 /* -------        SAVE ATTRIBUTE INFORMATION IN OPERATION RECORD     ------- */
2037 /* ------------------------------------------------------------------------- */
saveAttrbuf(Signal * signal)2038 void Dbtc::saveAttrbuf(Signal* signal)
2039 {
2040   CacheRecord * const regCachePtr = cachePtr.p;
2041   UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
2042   UintR TattrbufFilesize = cattrbufFilesize;
2043   UintR TTcfirstAttrbuf = regCachePtr->firstAttrbuf;
2044   UintR Tlen = signal->length() - 3;
2045   AttrbufRecord *localAttrbufRecord = attrbufRecord;
2046 
2047   AttrbufRecord * const regAttrPtr = &localAttrbufRecord[TfirstfreeAttrbuf];
2048   if (TfirstfreeAttrbuf >= TattrbufFilesize) {
2049     TCKEY_abort(signal, 21);
2050     return;
2051   }//if
2052   UintR Tnext = regAttrPtr->attrbuf[ZINBUF_NEXT];
2053   if (TTcfirstAttrbuf == RNIL) {
2054     jam();
2055     regCachePtr->firstAttrbuf = TfirstfreeAttrbuf;
2056   } else {
2057     AttrbufRecordPtr saAttrbufptr;
2058 
2059     saAttrbufptr.i = regCachePtr->lastAttrbuf;
2060     jam();
2061     if (saAttrbufptr.i >= TattrbufFilesize) {
2062       TCKEY_abort(signal, 22);
2063       return;
2064     }//if
2065     saAttrbufptr.p = &localAttrbufRecord[saAttrbufptr.i];
2066     saAttrbufptr.p->attrbuf[ZINBUF_NEXT] = TfirstfreeAttrbuf;
2067   }//if
2068 
2069   cfirstfreeAttrbuf = Tnext;
2070   regAttrPtr->attrbuf[ZINBUF_NEXT] = RNIL;
2071   regCachePtr->lastAttrbuf = TfirstfreeAttrbuf;
2072   regAttrPtr->attrbuf[ZINBUF_DATA_LEN] = Tlen;
2073 
2074   UintR Tdata1 = signal->theData[3];
2075   UintR Tdata2 = signal->theData[4];
2076   UintR Tdata3 = signal->theData[5];
2077   UintR Tdata4 = signal->theData[6];
2078   UintR Tdata5 = signal->theData[7];
2079   UintR Tdata6 = signal->theData[8];
2080   UintR Tdata7 = signal->theData[9];
2081   UintR Tdata8 = signal->theData[10];
2082 
2083   regAttrPtr->attrbuf[0] = Tdata1;
2084   regAttrPtr->attrbuf[1] = Tdata2;
2085   regAttrPtr->attrbuf[2] = Tdata3;
2086   regAttrPtr->attrbuf[3] = Tdata4;
2087   regAttrPtr->attrbuf[4] = Tdata5;
2088   regAttrPtr->attrbuf[5] = Tdata6;
2089   regAttrPtr->attrbuf[6] = Tdata7;
2090   regAttrPtr->attrbuf[7] = Tdata8;
2091 
2092   if (Tlen > 8) {
2093 
2094     Tdata1 = signal->theData[11];
2095     Tdata2 = signal->theData[12];
2096     Tdata3 = signal->theData[13];
2097     Tdata4 = signal->theData[14];
2098     Tdata5 = signal->theData[15];
2099     Tdata6 = signal->theData[16];
2100     Tdata7 = signal->theData[17];
2101 
2102     regAttrPtr->attrbuf[8] = Tdata1;
2103     regAttrPtr->attrbuf[9] = Tdata2;
2104     regAttrPtr->attrbuf[10] = Tdata3;
2105     regAttrPtr->attrbuf[11] = Tdata4;
2106     regAttrPtr->attrbuf[12] = Tdata5;
2107     regAttrPtr->attrbuf[13] = Tdata6;
2108     regAttrPtr->attrbuf[14] = Tdata7;
2109     jam();
2110     if (Tlen > 15) {
2111 
2112       Tdata1 = signal->theData[18];
2113       Tdata2 = signal->theData[19];
2114       Tdata3 = signal->theData[20];
2115       Tdata4 = signal->theData[21];
2116       Tdata5 = signal->theData[22];
2117       Tdata6 = signal->theData[23];
2118       Tdata7 = signal->theData[24];
2119 
2120       jam();
2121       regAttrPtr->attrbuf[15] = Tdata1;
2122       regAttrPtr->attrbuf[16] = Tdata2;
2123       regAttrPtr->attrbuf[17] = Tdata3;
2124       regAttrPtr->attrbuf[18] = Tdata4;
2125       regAttrPtr->attrbuf[19] = Tdata5;
2126       regAttrPtr->attrbuf[20] = Tdata6;
2127       regAttrPtr->attrbuf[21] = Tdata7;
2128     }//if
2129   }//if
2130 }//Dbtc::saveAttrbuf()
2131 
execATTRINFO(Signal * signal)2132 void Dbtc::execATTRINFO(Signal* signal)
2133 {
2134   UintR Tdata1 = signal->theData[0];
2135   UintR Tlength = signal->length();
2136   UintR TapiConnectFilesize = capiConnectFilesize;
2137   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2138 
2139   jamEntry();
2140   apiConnectptr.i = Tdata1;
2141   ttransid_ptr = 1;
2142   if (Tdata1 >= TapiConnectFilesize) {
2143     DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2144     TCKEY_abort(signal, 18);
2145     return;
2146   }//if
2147 
2148   ApiConnectRecord * const regApiPtr = &localApiConnectRecord[Tdata1];
2149   apiConnectptr.p = regApiPtr;
2150 
2151   if (compare_transid(regApiPtr->transid, signal->theData+1) == false)
2152   {
2153     DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2154 	  << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2155     TCKEY_abort(signal, 19);
2156     return;
2157   }//if
2158   if (Tlength < 4) {
2159     DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2160     TCKEY_abort(signal, 20);
2161     return;
2162   }
2163   Tlength -= 3;
2164   UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2165   UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2166   UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2167 
2168   if (TcompBOTH) {
2169     jam();
2170     if (ERROR_INSERTED(8015)) {
2171       CLEAR_ERROR_INSERT_VALUE;
2172       return;
2173     }//if
2174     if (ERROR_INSERTED(8016)) {
2175       CLEAR_ERROR_INSERT_VALUE;
2176       return;
2177     }//if
2178     CacheRecord *localCacheRecord = cacheRecord;
2179     UintR TcacheFilesize = ccacheFilesize;
2180     UintR TcachePtr = regApiPtr->cachePtr;
2181     UintR TtcTimer = ctcTimer;
2182     CacheRecord * const regCachePtr = &localCacheRecord[TcachePtr];
2183     if (TcachePtr >= TcacheFilesize) {
2184       TCKEY_abort(signal, 43);
2185       return;
2186     }//if
2187     UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
2188     UintR TcurrReclenAi = regCachePtr->currReclenAi;
2189     UintR TattrLen = regCachePtr->attrlength;
2190 
2191     setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
2192     cachePtr.i = TcachePtr;
2193     cachePtr.p = regCachePtr;
2194     TcurrReclenAi = TcurrReclenAi + Tlength;
2195     regCachePtr->currReclenAi = TcurrReclenAi;
2196     int TattrlengthRemain = TattrLen - TcurrReclenAi;
2197 
2198     if (TfirstfreeAttrbuf == RNIL) {
2199       DEBUG("No more attrinfo buffers");
2200       TCKEY_abort(signal, 24);
2201       return;
2202     }//if
2203     saveAttrbuf(signal);
2204     if (TattrlengthRemain == 0) {
2205       /****************************************************************>*/
2206       /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS       */
2207       /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2208       /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2209       /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER          */
2210       /* OPERATIONS.                                                     */
2211       /****************************************************************>*/
2212       UintR TlastConnect = regApiPtr->lastTcConnect;
2213       if (TcompRECEIVING) {
2214         jam();
2215         regApiPtr->apiConnectstate = CS_STARTED;
2216       } else {
2217         jam();
2218         regApiPtr->apiConnectstate = CS_START_COMMITTING;
2219       }//if
2220       tcConnectptr.i = TlastConnect;
2221       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2222       attrinfoDihReceivedLab(signal);
2223     } else if (TattrlengthRemain < 0) {
2224       jam();
2225       DEBUG("ATTRINFO wrong total length="<<Tlength
2226 	    <<", TattrlengthRemain="<<TattrlengthRemain
2227 	    <<", TattrLen="<<TattrLen
2228 	    <<", TcurrReclenAi="<<TcurrReclenAi);
2229       tcConnectptr.i = regApiPtr->lastTcConnect;
2230       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
2231       aiErrorLab(signal);
2232     }//if
2233     return;
2234   } else if (regApiPtr->apiConnectstate == CS_START_SCAN) {
2235     jam();
2236     scanAttrinfoLab(signal, Tlength);
2237     return;
2238   } else {
2239     switch (regApiPtr->apiConnectstate) {
2240     case CS_ABORTING:
2241       jam();
2242       /* JUST IGNORE THE SIGNAL*/
2243       // DEBUG("Drop ATTRINFO, CS_ABORTING");
2244       return;
2245     case CS_CONNECTED:
2246       jam();
2247       /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2248       // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2249       return;
2250     case CS_STARTED:
2251       jam();
2252       /****************************************************************>*/
2253       /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2254       /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
2255       /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
2256       /****************************************************************>*/
2257       terrorCode = ZSIGNAL_ERROR;
2258       printState(signal, 1);
2259       abortErrorLab(signal);
2260       return;
2261     default:
2262       jam();
2263       /****************************************************************>*/
2264       /*       SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2265       /*       SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED.    */
2266       /****************************************************************>*/
2267       DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2268       printState(signal, 9);
2269       return;
2270     }//switch
2271   }//if
2272 }//Dbtc::execATTRINFO()
2273 
2274 /* *********************************************************************>> */
2275 /*                                                                        */
2276 /*       MODULE: HASH MODULE                                              */
2277 /*       DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION                 */
2278 /* *********************************************************************> */
hash(Signal * signal)2279 void Dbtc::hash(Signal* signal)
2280 {
2281   DatabufRecordPtr locDatabufptr;
2282   UintR ti;
2283   UintR  Tdata0;
2284   UintR  Tdata1;
2285   UintR  Tdata2;
2286   UintR  Tdata3;
2287   UintR*  Tdata32;
2288 
2289   CacheRecord * const regCachePtr = cachePtr.p;
2290   Tdata32 = signal->theData;
2291 
2292   Tdata0 = regCachePtr->keydata[0];
2293   Tdata1 = regCachePtr->keydata[1];
2294   Tdata2 = regCachePtr->keydata[2];
2295   Tdata3 = regCachePtr->keydata[3];
2296   Tdata32[0] = Tdata0;
2297   Tdata32[1] = Tdata1;
2298   Tdata32[2] = Tdata2;
2299   Tdata32[3] = Tdata3;
2300   if (regCachePtr->keylen > 4) {
2301     locDatabufptr.i = regCachePtr->firstKeybuf;
2302     ti = 4;
2303     while (locDatabufptr.i != RNIL) {
2304       ptrCheckGuard(locDatabufptr, cdatabufFilesize, databufRecord);
2305       Tdata0 = locDatabufptr.p->data[0];
2306       Tdata1 = locDatabufptr.p->data[1];
2307       Tdata2 = locDatabufptr.p->data[2];
2308       Tdata3 = locDatabufptr.p->data[3];
2309       Tdata32[ti    ] = Tdata0;
2310       Tdata32[ti + 1] = Tdata1;
2311       Tdata32[ti + 2] = Tdata2;
2312       Tdata32[ti + 3] = Tdata3;
2313       locDatabufptr.i = locDatabufptr.p->nextDatabuf;
2314       ti += 4;
2315     }//while
2316   }//if
2317 
2318   UintR keylen = (UintR)regCachePtr->keylen;
2319   Uint32 distKey = regCachePtr->distributionKeyIndicator;
2320 
2321   Uint32 tmp[4];
2322   if(!regCachePtr->m_special_hash)
2323   {
2324     md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2325   }
2326   else
2327   {
2328     handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2329   }
2330 
2331   thashValue = tmp[0];
2332   if (distKey){
2333     jam();
2334     tdistrHashValue = regCachePtr->distributionKey;
2335   } else {
2336     jam();
2337     tdistrHashValue = tmp[1];
2338   }//if
2339 }//Dbtc::hash()
2340 
2341 bool
handle_special_hash(Uint32 dstHash[4],Uint32 * src,Uint32 srcLen,Uint32 tabPtrI,bool distr)2342 Dbtc::handle_special_hash(Uint32 dstHash[4], Uint32* src, Uint32 srcLen,
2343 			  Uint32 tabPtrI,
2344 			  bool distr)
2345 {
2346   Uint64 Tmp[MAX_KEY_SIZE_IN_WORDS * MAX_XFRM_MULTIPLY];
2347   const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2348   const bool hasVarKeys = tabPtrP->hasVarKeys;
2349   const bool hasCharAttr = tabPtrP->hasCharAttr;
2350   const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2351 
2352   Uint32 *dst = (Uint32*)Tmp;
2353   Uint32 dstPos = 0;
2354   Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2355   Uint32 * keyPartLenPtr;
2356   if(hasCharAttr || (compute_distkey && hasVarKeys))
2357   {
2358     keyPartLenPtr = keyPartLen;
2359     dstPos = xfrm_key(tabPtrI, src, dst, sizeof(Tmp) >> 2, keyPartLenPtr);
2360     if (unlikely(dstPos == 0))
2361     {
2362       goto error;
2363     }
2364   }
2365   else
2366   {
2367     dst = src;
2368     dstPos = srcLen;
2369     keyPartLenPtr = 0;
2370   }
2371 
2372   md5_hash(dstHash, (Uint64*)dst, dstPos);
2373 
2374   if(compute_distkey)
2375   {
2376     jam();
2377 
2378     Uint32 tmp[4];
2379     Uint32 len = create_distr_key(tabPtrI, dst, keyPartLenPtr);
2380     md5_hash(tmp, (Uint64*)dst, len);
2381     dstHash[1] = tmp[1];
2382   }
2383   return true;  // success
2384 
2385 error:
2386   terrorCode = ZINVALID_KEY;
2387   return false;
2388 }
2389 
2390 /*
2391 INIT_API_CONNECT_REC
2392 ---------------------------
2393 */
2394 /* ========================================================================= */
2395 /* =======                       INIT_API_CONNECT_REC                ======= */
2396 /*                                                                           */
2397 /* ========================================================================= */
initApiConnectRec(Signal * signal,ApiConnectRecord * const regApiPtr,bool releaseIndexOperations)2398 void Dbtc::initApiConnectRec(Signal* signal,
2399                              ApiConnectRecord * const regApiPtr,
2400 			     bool releaseIndexOperations)
2401 {
2402   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2403   UintR TfailureNr = cfailure_nr;
2404   UintR TtransCount = c_counters.ctransCount;
2405   UintR Ttransid0 = tcKeyReq->transId1;
2406   UintR Ttransid1 = tcKeyReq->transId2;
2407 
2408   regApiPtr->m_exec_flag = 0;
2409   regApiPtr->returncode = 0;
2410   regApiPtr->returnsignal = RS_TCKEYCONF;
2411   ndbassert(regApiPtr->firstTcConnect == RNIL);
2412   regApiPtr->firstTcConnect = RNIL;
2413   regApiPtr->lastTcConnect = RNIL;
2414   regApiPtr->globalcheckpointid = 0;
2415   regApiPtr->lqhkeyconfrec = 0;
2416   regApiPtr->lqhkeyreqrec = 0;
2417   regApiPtr->tckeyrec = 0;
2418   regApiPtr->tcindxrec = 0;
2419   regApiPtr->failureNr = TfailureNr;
2420   regApiPtr->transid[0] = Ttransid0;
2421   regApiPtr->transid[1] = Ttransid1;
2422   regApiPtr->commitAckMarker = RNIL;
2423   regApiPtr->buddyPtr = RNIL;
2424   regApiPtr->currSavePointId = 0;
2425   regApiPtr->m_transaction_nodes.clear();
2426   regApiPtr->singleUserMode = 0;
2427   // Trigger data
2428   releaseFiredTriggerData(&regApiPtr->theFiredTriggers),
2429   // Index data
2430   regApiPtr->indexOpReturn = false;
2431   regApiPtr->noIndexOp = 0;
2432   if(releaseIndexOperations)
2433     releaseAllSeizedIndexOperations(regApiPtr);
2434 
2435   c_counters.ctransCount = TtransCount + 1;
2436 }//Dbtc::initApiConnectRec()
2437 
2438 int
seizeTcRecord(Signal * signal)2439 Dbtc::seizeTcRecord(Signal* signal)
2440 {
2441   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2442   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
2443   UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
2444   UintR TtcConnectFilesize = ctcConnectFilesize;
2445   tcConnectptr.i = TfirstfreeTcConnect;
2446   if (TfirstfreeTcConnect >= TtcConnectFilesize) {
2447     int place = 3;
2448     if (TfirstfreeTcConnect != RNIL) {
2449       place = 10;
2450     }//if
2451     TCKEY_abort(signal, place);
2452     return 1;
2453   }//if
2454   //--------------------------------------------------------------------------
2455   // Optimised version of ptrAss(tcConnectptr, tcConnectRecord)
2456   //--------------------------------------------------------------------------
2457   TcConnectRecord * const regTcPtr =
2458                            &localTcConnectRecord[TfirstfreeTcConnect];
2459 
2460   UintR TconcurrentOp = c_counters.cconcurrentOp;
2461   UintR TlastTcConnect = regApiPtr->lastTcConnect;
2462   UintR TtcConnectptrIndex = tcConnectptr.i;
2463   TcConnectRecordPtr tmpTcConnectptr;
2464 
2465   cfirstfreeTcConnect = regTcPtr->nextTcConnect;
2466   tcConnectptr.p = regTcPtr;
2467 
2468   c_counters.cconcurrentOp = TconcurrentOp + 1;
2469   regTcPtr->prevTcConnect = TlastTcConnect;
2470   regTcPtr->nextTcConnect = RNIL;
2471   regTcPtr->accumulatingTriggerData.i = RNIL;
2472   regTcPtr->accumulatingTriggerData.p = NULL;
2473   regTcPtr->noFiredTriggers = 0;
2474   regTcPtr->noReceivedTriggers = 0;
2475   regTcPtr->triggerExecutionCount = 0;
2476   regTcPtr->triggeringOperation = RNIL;
2477   regTcPtr->isIndexOp = false;
2478   regTcPtr->indexOp = RNIL;
2479   regTcPtr->currentIndexId = RNIL;
2480 
2481   regApiPtr->lastTcConnect = TtcConnectptrIndex;
2482 
2483   if (TlastTcConnect == RNIL) {
2484     jam();
2485     regApiPtr->firstTcConnect = TtcConnectptrIndex;
2486   } else {
2487     tmpTcConnectptr.i = TlastTcConnect;
2488     jam();
2489     ptrCheckGuard(tmpTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
2490     tmpTcConnectptr.p->nextTcConnect = TtcConnectptrIndex;
2491   }//if
2492   return 0;
2493 }//Dbtc::seizeTcRecord()
2494 
2495 int
seizeCacheRecord(Signal * signal)2496 Dbtc::seizeCacheRecord(Signal* signal)
2497 {
2498   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2499   UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
2500   UintR TcacheFilesize = ccacheFilesize;
2501   CacheRecord *localCacheRecord = cacheRecord;
2502   if (TfirstfreeCacheRec >= TcacheFilesize) {
2503     TCKEY_abort(signal, 41);
2504     return 1;
2505   }//if
2506   CacheRecord * const regCachePtr = &localCacheRecord[TfirstfreeCacheRec];
2507 
2508   regApiPtr->cachePtr = TfirstfreeCacheRec;
2509   cfirstfreeCacheRec = regCachePtr->nextCacheRec;
2510   cachePtr.i = TfirstfreeCacheRec;
2511   cachePtr.p = regCachePtr;
2512 
2513 #ifdef VM_TRACE
2514   // This is a good place to check that resources have
2515   // been properly released from CacheRecord
2516   ndbrequire(regCachePtr->firstKeybuf == RNIL);
2517   ndbrequire(regCachePtr->lastKeybuf == RNIL);
2518 #endif
2519   regCachePtr->firstKeybuf = RNIL;
2520   regCachePtr->lastKeybuf = RNIL;
2521   regCachePtr->firstAttrbuf = RNIL;
2522   regCachePtr->lastAttrbuf = RNIL;
2523   regCachePtr->currReclenAi = 0;
2524   return 0;
2525 }//Dbtc::seizeCacheRecord()
2526 
2527 /*****************************************************************************/
2528 /*                               T C K E Y R E Q                             */
2529 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN      */
2530 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST   */
2531 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES       */
2532 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA                */
2533 /*****************************************************************************/
execTCKEYREQ(Signal * signal)2534 void Dbtc::execTCKEYREQ(Signal* signal)
2535 {
2536   Uint32 sendersNodeId = refToNode(signal->getSendersBlockRef());
2537   UintR compare_transid1, compare_transid2;
2538   UintR titcLenAiInTckeyreq;
2539   UintR TkeyLength;
2540   const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
2541   UintR Treqinfo;
2542 
2543   jamEntry();
2544   /*-------------------------------------------------------------------------
2545    * Common error routines are used for several signals, they need to know
2546    * where to find the transaction identifier in the signal.
2547    *-------------------------------------------------------------------------*/
2548   const UintR TapiIndex = tcKeyReq->apiConnectPtr;
2549   const UintR TapiMaxIndex = capiConnectFilesize;
2550   const UintR TtabIndex = tcKeyReq->tableId;
2551   const UintR TtabMaxIndex = ctabrecFilesize;
2552   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
2553 
2554   ttransid_ptr = 6;
2555   apiConnectptr.i = TapiIndex;
2556   if (TapiIndex >= TapiMaxIndex) {
2557     TCKEY_abort(signal, 6);
2558     return;
2559   }//if
2560   if (TtabIndex >= TtabMaxIndex) {
2561     TCKEY_abort(signal, 7);
2562     return;
2563   }//if
2564 
2565   Treqinfo = tcKeyReq->requestInfo;
2566   //--------------------------------------------------------------------------
2567   // Optimised version of ptrAss(tabptr, tableRecord)
2568   // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
2569   //--------------------------------------------------------------------------
2570   ApiConnectRecord * const regApiPtr = &localApiConnectRecord[TapiIndex];
2571   apiConnectptr.p = regApiPtr;
2572 
2573   Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
2574   Uint32 TexecFlag = TcKeyReq::getExecuteFlag(Treqinfo);
2575 
2576   Uint8 isIndexOp = regApiPtr->isIndexOp;
2577   bool isIndexOpReturn = regApiPtr->indexOpReturn;
2578   regApiPtr->isIndexOp = false; // Reset marker
2579   regApiPtr->m_exec_flag |= TexecFlag;
2580   TableRecordPtr localTabptr;
2581   localTabptr.i = TtabIndex;
2582   localTabptr.p = &tableRecord[TtabIndex];
2583   switch (regApiPtr->apiConnectstate) {
2584   case CS_CONNECTED:{
2585     if (TstartFlag == 1 && getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2586       //---------------------------------------------------------------------
2587       // Initialise API connect record if transaction is started.
2588       //---------------------------------------------------------------------
2589       jam();
2590       initApiConnectRec(signal, regApiPtr);
2591       regApiPtr->m_exec_flag = TexecFlag;
2592     } else {
2593       if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == true){
2594 	/*------------------------------------------------------------------
2595 	 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
2596 	 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
2597 	 * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
2598 	 *-----------------------------------------------------------------*/
2599 	TCKEY_abort(signal, 0);
2600 	return;
2601       } else {
2602 	/**
2603 	 * getAllowStartTransaction(sendersNodeId) == false
2604 	 */
2605 	TCKEY_abort(signal, TexecFlag ? 60 : 57);
2606 	return;
2607       }//if
2608     }
2609   }
2610   break;
2611   case CS_STARTED:
2612     if(TstartFlag == 1 && regApiPtr->firstTcConnect == RNIL)
2613     {
2614       /**
2615        * If last operation in last transaction was a simple/dirty read
2616        *  it does not have to be committed or rollbacked hence,
2617        *  the state will be CS_STARTED
2618        */
2619       jam();
2620       if (unlikely(getNodeState().getSingleUserMode()) &&
2621           getNodeState().getSingleUserApi() != sendersNodeId &&
2622           !localTabptr.p->singleUserMode)
2623       {
2624 	TCKEY_abort(signal, TexecFlag ? 60 : 57);
2625         return;
2626       }
2627       initApiConnectRec(signal, regApiPtr);
2628       regApiPtr->m_exec_flag = TexecFlag;
2629     } else {
2630       //----------------------------------------------------------------------
2631       // Transaction is started already.
2632       // Check that the operation is on the same transaction.
2633       //-----------------------------------------------------------------------
2634       compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
2635       compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
2636       jam();
2637       compare_transid1 = compare_transid1 | compare_transid2;
2638       if (compare_transid1 != 0) {
2639 	TCKEY_abort(signal, 1);
2640 	return;
2641       }//if
2642     }
2643     break;
2644   case CS_ABORTING:
2645     if (regApiPtr->abortState == AS_IDLE) {
2646       if (TstartFlag == 1) {
2647         if(getAllowStartTransaction(sendersNodeId, localTabptr.p->singleUserMode) == false){
2648           TCKEY_abort(signal, TexecFlag ? 60 : 57);
2649           return;
2650         }
2651 	//--------------------------------------------------------------------
2652 	// Previous transaction had been aborted and the abort was completed.
2653 	// It is then OK to start a new transaction again.
2654 	//--------------------------------------------------------------------
2655         jam();
2656         initApiConnectRec(signal, regApiPtr);
2657 	regApiPtr->m_exec_flag = TexecFlag;
2658       } else if(TexecFlag) {
2659 	TCKEY_abort(signal, 59);
2660 	return;
2661       } else {
2662 	//--------------------------------------------------------------------
2663 	// The current transaction was aborted successfully.
2664 	// We will not do anything before we receive an operation
2665 	// with a start indicator. We will ignore this signal.
2666 	//--------------------------------------------------------------------
2667 	jam();
2668 	DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
2669         return;
2670       }//if
2671     } else {
2672       //----------------------------------------------------------------------
2673       // Previous transaction is still aborting
2674       //----------------------------------------------------------------------
2675       jam();
2676       if (TstartFlag == 1) {
2677 	//--------------------------------------------------------------------
2678 	// If a new transaction tries to start while the old is
2679 	// still aborting, we will report this to the starting API.
2680 	//--------------------------------------------------------------------
2681         TCKEY_abort(signal, 2);
2682         return;
2683       } else if(TexecFlag) {
2684         TCKEY_abort(signal, 59);
2685         return;
2686       }
2687       //----------------------------------------------------------------------
2688       // Ignore signals without start indicator set when aborting transaction.
2689       //----------------------------------------------------------------------
2690       DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
2691       return;
2692     }//if
2693     break;
2694   case CS_START_COMMITTING:
2695     jam();
2696     if(isIndexOpReturn || TcKeyReq::getExecutingTrigger(Treqinfo)){
2697       break;
2698     }
2699   default:
2700     jam();
2701     /*----------------------------------------------------------------------
2702      * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
2703      * WHEN IT WAS NOT EXPECTED TO.
2704      * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
2705      * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
2706      * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
2707      * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
2708      * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
2709      *---------------------------------------------------------------------*/
2710     TCKEY_abort(signal, 55);
2711     return;
2712   }//switch
2713 
2714   if (localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)) {
2715     ;
2716   } else {
2717     /*-----------------------------------------------------------------------*/
2718     /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT.  */
2719     /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED.                          */
2720     /*-----------------------------------------------------------------------*/
2721     TCKEY_abort(signal, 8);
2722     return;
2723   }//if
2724 
2725   //-------------------------------------------------------------------------
2726   // Error Insertion for testing purposes. Test to see what happens when no
2727   // more TC records available.
2728   //-------------------------------------------------------------------------
2729   if (ERROR_INSERTED(8032)) {
2730     TCKEY_abort(signal, 3);
2731     return;
2732   }//if
2733 
2734   if (seizeTcRecord(signal) != 0) {
2735     return;
2736   }//if
2737 
2738   if (seizeCacheRecord(signal) != 0) {
2739     return;
2740   }//if
2741 
2742   TcConnectRecord * const regTcPtr = tcConnectptr.p;
2743   CacheRecord * const regCachePtr = cachePtr.p;
2744 
2745   /*
2746     INIT_TC_CONNECT_REC
2747     -------------------------
2748   */
2749   /* ---------------------------------------------------------------------- */
2750   /* -------     INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS   ------- */
2751   /*                                                                        */
2752   /* ---------------------------------------------------------------------- */
2753 
2754   UintR TapiVersionNo = TcKeyReq::getAPIVersion(tcKeyReq->attrLen);
2755   UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
2756   regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
2757   regCachePtr->apiVersionNo = TapiVersionNo;
2758 
2759   UintR TapiConnectptrIndex = apiConnectptr.i;
2760   UintR TsenderData = tcKeyReq->senderData;
2761   UintR TattrLen = TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
2762   UintR TattrinfoCount = c_counters.cattrinfoCount;
2763 
2764   regTcPtr->apiConnect = TapiConnectptrIndex;
2765   regTcPtr->clientData = TsenderData;
2766   regTcPtr->commitAckMarker = RNIL;
2767   regTcPtr->isIndexOp = isIndexOp;
2768   regTcPtr->indexOp = regApiPtr->executingIndexOp;
2769   regTcPtr->savePointId = regApiPtr->currSavePointId;
2770   regApiPtr->executingIndexOp = RNIL;
2771 
2772   regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
2773 
2774   if (TcKeyReq::getExecutingTrigger(Treqinfo)) {
2775     // Save the TcOperationPtr for fireing operation
2776     regTcPtr->triggeringOperation = TsenderData;
2777   }
2778 
2779   if (TexecFlag){
2780     Uint32 currSPId = regApiPtr->currSavePointId;
2781     regApiPtr->currSavePointId = ++currSPId;
2782   }
2783 
2784   regCachePtr->attrlength = TattrLen;
2785   c_counters.cattrinfoCount = TattrinfoCount + TattrLen;
2786 
2787   UintR TtabptrIndex = localTabptr.i;
2788   UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
2789   Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
2790   regCachePtr->tableref = TtabptrIndex;
2791   regCachePtr->schemaVersion = TtableSchemaVersion;
2792   regTcPtr->operation = TOperationType;
2793 
2794   Uint8 TSimpleFlag         = TcKeyReq::getSimpleFlag(Treqinfo);
2795   Uint8 TDirtyFlag          = TcKeyReq::getDirtyFlag(Treqinfo);
2796   Uint8 TInterpretedFlag    = TcKeyReq::getInterpretedFlag(Treqinfo);
2797   Uint8 TDistrKeyFlag       = TcKeyReq::getDistributionKeyFlag(Treqinfo);
2798   Uint8 TNoDiskFlag         = TcKeyReq::getNoDiskFlag(Treqinfo);
2799   Uint8 TexecuteFlag        = TexecFlag;
2800 
2801   regTcPtr->dirtyOp  = TDirtyFlag;
2802   regTcPtr->opSimple = TSimpleFlag;
2803   regCachePtr->opExec   = TInterpretedFlag;
2804   regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
2805   regCachePtr->m_no_disk_flag = TNoDiskFlag;
2806 
2807   //-------------------------------------------------------------
2808   // The next step is to read the upto three conditional words.
2809   //-------------------------------------------------------------
2810   Uint32 TkeyIndex;
2811   Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
2812   {
2813     Uint32  TDistrGHIndex    = TcKeyReq::getScanIndFlag(Treqinfo);
2814     Uint32  TDistrKeyIndex   = TDistrGHIndex;
2815 
2816     Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
2817 
2818     regCachePtr->scanTakeOverInd = TDistrGHIndex;
2819     regCachePtr->scanInfo = TscanInfo;
2820 
2821     regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
2822 
2823     TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
2824   }
2825   Uint32* TkeyDataPtr = &TOptionalDataPtr[TkeyIndex];
2826 
2827   UintR Tdata1 = TkeyDataPtr[0];
2828   UintR Tdata2 = TkeyDataPtr[1];
2829   UintR Tdata3 = TkeyDataPtr[2];
2830   UintR Tdata4 = TkeyDataPtr[3];
2831   UintR Tdata5;
2832 
2833   regCachePtr->keydata[0] = Tdata1;
2834   regCachePtr->keydata[1] = Tdata2;
2835   regCachePtr->keydata[2] = Tdata3;
2836   regCachePtr->keydata[3] = Tdata4;
2837 
2838   TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
2839   Uint32 TAIDataIndex;
2840   if (TkeyLength > 8) {
2841     TAIDataIndex = TkeyIndex + 8;
2842   } else {
2843     if (TkeyLength == 0) {
2844       TCKEY_abort(signal, 4);
2845       return;
2846     }//if
2847     TAIDataIndex = TkeyIndex + TkeyLength;
2848   }//if
2849   Uint32* TAIDataPtr = &TOptionalDataPtr[TAIDataIndex];
2850 
2851   titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
2852   regCachePtr->keylen = TkeyLength;
2853   regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
2854   regCachePtr->currReclenAi = titcLenAiInTckeyreq;
2855   regCachePtr->m_special_hash =
2856     localTabptr.p->hasCharAttr | (localTabptr.p->noOfDistrKeys > 0);
2857   Tdata1 = TAIDataPtr[0];
2858   Tdata2 = TAIDataPtr[1];
2859   Tdata3 = TAIDataPtr[2];
2860   Tdata4 = TAIDataPtr[3];
2861   Tdata5 = TAIDataPtr[4];
2862 
2863   regCachePtr->attrinfo0     = Tdata1;
2864   regCachePtr->attrinfo15[0] = Tdata2;
2865   regCachePtr->attrinfo15[1] = Tdata3;
2866   regCachePtr->attrinfo15[2] = Tdata4;
2867   regCachePtr->attrinfo15[3] = Tdata5;
2868 
2869   if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
2870     Uint32 TreadCount = c_counters.creadCount;
2871     jam();
2872     c_counters.creadCount = TreadCount + 1;
2873   } else {
2874     if(regApiPtr->commitAckMarker == RNIL){
2875       jam();
2876       CommitAckMarkerPtr tmp;
2877       if(!m_commitAckMarkerHash.seize(tmp)){
2878         TCKEY_abort(signal, 56);
2879         return;
2880       } else {
2881         regTcPtr->commitAckMarker = tmp.i;
2882         regApiPtr->commitAckMarker = tmp.i;
2883         tmp.p->transid1      = tcKeyReq->transId1;
2884         tmp.p->transid2      = tcKeyReq->transId2;
2885         tmp.p->apiNodeId     = refToNode(regApiPtr->ndbapiBlockref);
2886         tmp.p->apiConnectPtr = TapiIndex;
2887         tmp.p->noOfLqhs      = 0;
2888 #if defined VM_TRACE || defined ERROR_INSERT
2889 	{
2890 	  CommitAckMarkerPtr check;
2891 	  ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
2892 	}
2893 #endif
2894         m_commitAckMarkerHash.add(tmp);
2895       }
2896     }
2897 
2898     UintR TwriteCount = c_counters.cwriteCount;
2899     UintR Toperationsize = coperationsize;
2900     /* --------------------------------------------------------------------
2901      *   THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
2902      *   THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
2903      *   TEMP TABLES DON'T PARTICIPATE.
2904      * -------------------------------------------------------------------- */
2905     if (localTabptr.p->get_storedTable()) {
2906       coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
2907     }
2908     c_counters.cwriteCount = TwriteCount + 1;
2909     switch (TOperationType) {
2910     case ZUPDATE:
2911     case ZINSERT:
2912     case ZDELETE:
2913     case ZWRITE:
2914       jam();
2915       break;
2916     default:
2917       TCKEY_abort(signal, 9);
2918       return;
2919     }//switch
2920   }//if
2921 
2922   Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
2923   regTcPtr->m_execAbortOption = TabortOption;
2924 
2925   /*-------------------------------------------------------------------------
2926    * Check error handling per operation
2927    * If CommitFlag is set state accordingly and check for early abort
2928    *------------------------------------------------------------------------*/
2929   if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
2930     ndbrequire(TexecuteFlag);
2931     regApiPtr->apiConnectstate = CS_REC_COMMITTING;
2932   } else {
2933     /* ---------------------------------------------------------------------
2934      *       PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
2935      * ---------------------------------------------------------------------
2936      *       ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
2937      * IF PREPARE TRANSACTION THEN
2938      *   API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
2939      * SET STATE TO PREPARING
2940      * --------------------------------------------------------------------- */
2941     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
2942       jam();
2943       // Trigger execution at commit
2944       regApiPtr->apiConnectstate = CS_REC_COMMITTING;
2945     } else {
2946       jam();
2947       regApiPtr->apiConnectstate = CS_RECEIVING;
2948     }//if
2949   }//if
2950   if (TkeyLength <= 4) {
2951     tckeyreq050Lab(signal);
2952     return;
2953   } else {
2954     if (cfirstfreeDatabuf != RNIL) {
2955       jam();
2956       linkKeybuf(signal);
2957       Tdata1 = TkeyDataPtr[4];
2958       Tdata2 = TkeyDataPtr[5];
2959       Tdata3 = TkeyDataPtr[6];
2960       Tdata4 = TkeyDataPtr[7];
2961 
2962       DatabufRecord * const regDataPtr = databufptr.p;
2963       regDataPtr->data[0] = Tdata1;
2964       regDataPtr->data[1] = Tdata2;
2965       regDataPtr->data[2] = Tdata3;
2966       regDataPtr->data[3] = Tdata4;
2967     } else {
2968       jam();
2969       seizeDatabuferrorLab(signal);
2970       return;
2971     }//if
2972     if (TkeyLength <= 8) {
2973       jam();
2974       tckeyreq050Lab(signal);
2975       return;
2976     } else {
2977       jam();
2978       /* --------------------------------------------------------------------
2979        * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
2980        * SAVE STATE AND WAIT FOR KEYINFO
2981        * --------------------------------------------------------------------*/
2982       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
2983       regCachePtr->save1 = 8;
2984       regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
2985       return;
2986     }//if
2987   }//if
2988   return;
2989 }//Dbtc::execTCKEYREQ()
2990 
tckeyreq050Lab(Signal * signal)2991 void Dbtc::tckeyreq050Lab(Signal* signal)
2992 {
2993   UintR tnoOfBackup;
2994   UintR tnoOfStandby;
2995   UintR tnodeinfo;
2996 
2997   terrorCode = 0;
2998 
2999   hash(signal); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
3000 
3001   if (unlikely(terrorCode))
3002   {
3003     releaseAtErrorLab(signal);
3004     return;
3005   }
3006 
3007   CacheRecord * const regCachePtr = cachePtr.p;
3008   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3009   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3010 
3011   UintR TtcTimer = ctcTimer;
3012   UintR ThashValue = thashValue;
3013   UintR TdistrHashValue = tdistrHashValue;
3014   UintR TdihConnectptr = regTcPtr->dihConnectptr;
3015   UintR Ttableref = regCachePtr->tableref;
3016 
3017   TableRecordPtr localTabptr;
3018   localTabptr.i = Ttableref;
3019   localTabptr.p = &tableRecord[localTabptr.i];
3020   Uint32 schemaVersion = regCachePtr->schemaVersion;
3021   if(localTabptr.p->checkTable(schemaVersion)){
3022     ;
3023   } else {
3024     terrorCode = localTabptr.p->getErrorCode(schemaVersion);
3025     TCKEY_abort(signal, 58);
3026     return;
3027   }
3028 
3029   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3030   regCachePtr->hashValue = ThashValue;
3031 
3032   signal->theData[0] = TdihConnectptr;
3033   signal->theData[1] = Ttableref;
3034   signal->theData[2] = TdistrHashValue;
3035   signal->theData[3] = 0;
3036   signal->theData[4] = 0;
3037   signal->theData[5] = 0;
3038   signal->theData[6] = 0;
3039 
3040   /*-------------------------------------------------------------*/
3041   /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
3042   /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE   */
3043   /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION.   */
3044   /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
3045   /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
3046   /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB.            */
3047   /*-------------------------------------------------------------*/
3048   EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
3049   UintR TerrorIndicator = signal->theData[0];
3050   jamEntry();
3051   if (TerrorIndicator != 0) {
3052     execDIGETNODESREF(signal);
3053     return;
3054   }
3055 
3056   if(ERROR_INSERTED(8050) && signal->theData[3] != getOwnNodeId())
3057   {
3058     ndbassert(false);
3059     signal->theData[1] = 626;
3060     execDIGETNODESREF(signal);
3061     return;
3062   }
3063 
3064   /****************>>*/
3065   /* DIGETNODESCONF >*/
3066   /* ***************>*/
3067 
3068   UintR Tdata1 = signal->theData[1];
3069   UintR Tdata2 = signal->theData[2];
3070   UintR Tdata3 = signal->theData[3];
3071   UintR Tdata4 = signal->theData[4];
3072   UintR Tdata5 = signal->theData[5];
3073   UintR Tdata6 = signal->theData[6];
3074 
3075   regCachePtr->fragmentid = Tdata1;
3076   tnodeinfo = Tdata2;
3077 
3078   regTcPtr->tcNodedata[0] = Tdata3;
3079   regTcPtr->tcNodedata[1] = Tdata4;
3080   regTcPtr->tcNodedata[2] = Tdata5;
3081   regTcPtr->tcNodedata[3] = Tdata6;
3082 
3083   Uint8 Toperation = regTcPtr->operation;
3084   Uint8 Tdirty = regTcPtr->dirtyOp;
3085   tnoOfBackup = tnodeinfo & 3;
3086   tnoOfStandby = (tnodeinfo >> 8) & 3;
3087 
3088   regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
3089   if (Toperation == ZREAD || Toperation == ZREAD_EX) {
3090     if (Tdirty == 1) {
3091       jam();
3092       /*-------------------------------------------------------------*/
3093       /*       A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND       */
3094       /*       BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS      */
3095       /*       NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION   */
3096       /*       WITH SIMPLE READS.                                    */
3097       /*-------------------------------------------------------------*/
3098       arrGuard(tnoOfBackup, MAX_REPLICAS);
3099       UintR Tindex;
3100       UintR TownNode = cownNodeid;
3101       for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
3102         UintR Tnode = regTcPtr->tcNodedata[Tindex];
3103         jam();
3104         if (Tnode == TownNode) {
3105           jam();
3106           regTcPtr->tcNodedata[0] = Tnode;
3107         }//if
3108       }//for
3109       if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
3110       {
3111 	for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
3112 	{
3113 	  UintR Tnode = regTcPtr->tcNodedata[Tindex];
3114 	  jam();
3115 	  if (Tnode != TownNode) {
3116 	    jam();
3117 	    regTcPtr->tcNodedata[0] = Tnode;
3118 	    ndbout_c("Choosing %d", Tnode);
3119 	  }//if
3120 	}//for
3121       }
3122     }//if
3123     jam();
3124     regTcPtr->lastReplicaNo = 0;
3125     regTcPtr->noOfNodes = 1;
3126   } else {
3127     UintR TlastReplicaNo;
3128     jam();
3129     TlastReplicaNo = tnoOfBackup + tnoOfStandby;
3130     regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
3131     regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
3132   }//if
3133   if (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength) {
3134     /****************************************************************>*/
3135     /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS      */
3136     /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
3137     /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
3138     /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER         */
3139     /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
3140     /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET.                */
3141     /****************************************************************>*/
3142     switch (regApiPtr->apiConnectstate) {
3143     case CS_RECEIVING:
3144       jam();
3145       regApiPtr->apiConnectstate = CS_STARTED;
3146       break;
3147     case CS_REC_COMMITTING:
3148       jam();
3149       regApiPtr->apiConnectstate = CS_START_COMMITTING;
3150       break;
3151     default:
3152       jam();
3153       systemErrorLab(signal, __LINE__);
3154       return;
3155     }//switch
3156     attrinfoDihReceivedLab(signal);
3157     return;
3158   } else {
3159     if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength) {
3160       TtcTimer = ctcTimer;
3161       jam();
3162       setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3163       regTcPtr->tcConnectstate = OS_WAIT_ATTR;
3164       return;
3165     } else {
3166       TCKEY_abort(signal, 11);
3167       return;
3168     }//if
3169   }//if
3170   return;
3171 }//Dbtc::tckeyreq050Lab()
3172 
attrinfoDihReceivedLab(Signal * signal)3173 void Dbtc::attrinfoDihReceivedLab(Signal* signal)
3174 {
3175   CacheRecord * const regCachePtr = cachePtr.p;
3176   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3177   Uint16 Tnode = regTcPtr->tcNodedata[0];
3178 
3179   TableRecordPtr localTabptr;
3180   localTabptr.i = regCachePtr->tableref;
3181   localTabptr.p = &tableRecord[localTabptr.i];
3182 
3183   if(localTabptr.p->checkTable(regCachePtr->schemaVersion)){
3184     ;
3185   } else {
3186     terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
3187     TCKEY_abort(signal, 58);
3188     return;
3189   }
3190   arrGuard(Tnode, MAX_NDB_NODES);
3191   packLqhkeyreq(signal, calcLqhBlockRef(Tnode));
3192 }//Dbtc::attrinfoDihReceivedLab()
3193 
packLqhkeyreq(Signal * signal,BlockReference TBRef)3194 void Dbtc::packLqhkeyreq(Signal* signal,
3195                          BlockReference TBRef)
3196 {
3197   CacheRecord * const regCachePtr = cachePtr.p;
3198   UintR Tkeylen = regCachePtr->keylen;
3199   UintR TfirstAttrbuf = regCachePtr->firstAttrbuf;
3200   sendlqhkeyreq(signal, TBRef);
3201   if (Tkeylen > 4) {
3202     packKeyData000Lab(signal, TBRef, Tkeylen - 4);
3203     releaseKeys();
3204   }//if
3205   packLqhkeyreq040Lab(signal,
3206                       TfirstAttrbuf,
3207                       TBRef);
3208 }//Dbtc::packLqhkeyreq()
3209 
sendlqhkeyreq(Signal * signal,BlockReference TBRef)3210 void Dbtc::sendlqhkeyreq(Signal* signal,
3211                          BlockReference TBRef)
3212 {
3213   UintR tslrAttrLen;
3214   UintR Tdata10;
3215   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3216   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3217   CacheRecord * const regCachePtr = cachePtr.p;
3218   Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
3219   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
3220 #ifdef ERROR_INSERT
3221   if (ERROR_INSERTED(8002)) {
3222     systemErrorLab(signal, __LINE__);
3223   }//if
3224   if (ERROR_INSERTED(8007)) {
3225     if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3226       CLEAR_ERROR_INSERT_VALUE;
3227       return;
3228     }//if
3229   }//if
3230   if (ERROR_INSERTED(8008)) {
3231     if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3232       CLEAR_ERROR_INSERT_VALUE;
3233       return;
3234     }//if
3235   }//if
3236   if (ERROR_INSERTED(8009)) {
3237     if (apiConnectptr.p->apiConnectstate == CS_STARTED) {
3238       return;
3239     }//if
3240   }//if
3241   if (ERROR_INSERTED(8010)) {
3242     if (apiConnectptr.p->apiConnectstate == CS_START_COMMITTING) {
3243       return;
3244     }//if
3245   }//if
3246 #endif
3247 
3248   tslrAttrLen = 0;
3249   LqhKeyReq::setAttrLen(tslrAttrLen, regCachePtr->attrlength);
3250   /* ---------------------------------------------------------------------- */
3251   // Bit16 == 0 since StoredProcedures are not yet supported.
3252   /* ---------------------------------------------------------------------- */
3253   LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
3254   LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
3255 
3256   Tdata10 = 0;
3257   sig0 = regTcPtr->opSimple;
3258   sig1 = regTcPtr->operation;
3259   sig2 = regTcPtr->dirtyOp;
3260   bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
3261   LqhKeyReq::setKeyLen(Tdata10, regCachePtr->keylen);
3262   LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
3263   if (unlikely(version < NDBD_ROWID_VERSION))
3264   {
3265     Uint32 op = regTcPtr->operation;
3266     Uint32 lock = (Operation_t) op == ZREAD_EX ? ZUPDATE : (Operation_t) op == ZWRITE ? ZINSERT : (Operation_t) op;
3267     LqhKeyReq::setLockType(Tdata10, lock);
3268   }
3269   /* ---------------------------------------------------------------------- */
3270   // Indicate Application Reference is present in bit 15
3271   /* ---------------------------------------------------------------------- */
3272   LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
3273   LqhKeyReq::setDirtyFlag(Tdata10, sig2);
3274   LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
3275   LqhKeyReq::setSimpleFlag(Tdata10, sig0);
3276   LqhKeyReq::setOperation(Tdata10, sig1);
3277   LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
3278 
3279   /* -----------------------------------------------------------------------
3280    * Sequential Number of first LQH = 0, bit 22-23
3281    * IF ATTRIBUTE INFORMATION IS SENT IN TCKEYREQ,
3282    * IT IS ALSO SENT IN LQHKEYREQ
3283    * ----------------------------------------------------------------------- */
3284   LqhKeyReq::setAIInLqhKeyReq(Tdata10, regCachePtr->lenAiInTckeyreq);
3285   /* -----------------------------------------------------------------------
3286    * Bit 27 == 0 since TC record is the same as the client record.
3287    * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
3288    * ----------------------------------------------------------------------- */
3289   //LqhKeyReq::setAPIVersion(Tdata10, regCachePtr->apiVersionNo);
3290   Uint32 commitAckMarker = regTcPtr->commitAckMarker;
3291   const Uint32 noOfLqhs = regTcPtr->noOfNodes;
3292   if(commitAckMarker != RNIL){
3293     jam();
3294     LqhKeyReq::setMarkerFlag(Tdata10, 1);
3295 
3296     CommitAckMarker * tmp = m_commitAckMarkerHash.getPtr(commitAckMarker);
3297 
3298     /**
3299      * Populate LQH array
3300      */
3301     tmp->noOfLqhs = noOfLqhs;
3302     for(Uint32 i = 0; i<noOfLqhs; i++){
3303       tmp->lqhNodeId[i] = regTcPtr->tcNodedata[i];
3304     }
3305   }
3306 
3307   /* ************************************************************> */
3308   /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT    */
3309   /* IS SENT TO A PRIMARY NODE.                                    */
3310   /* ************************************************************> */
3311 
3312   LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
3313 
3314   sig0 = tcConnectptr.i;
3315   sig2 = regCachePtr->hashValue;
3316   sig4 = cownref;
3317   sig5 = regTcPtr->savePointId;
3318 
3319   lqhKeyReq->clientConnectPtr = sig0;
3320   lqhKeyReq->attrLen = tslrAttrLen;
3321   lqhKeyReq->hashValue = sig2;
3322   lqhKeyReq->requestInfo = Tdata10;
3323   lqhKeyReq->tcBlockref = sig4;
3324   lqhKeyReq->savePointId = sig5;
3325 
3326   sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
3327   sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
3328   sig2 = regApiPtr->transid[0];
3329   sig3 = regApiPtr->transid[1];
3330   sig4 = (regTcPtr->isIndexOp == 2) ? reference() : regApiPtr->ndbapiBlockref;
3331   sig5 = regTcPtr->clientData;
3332   sig6 = regCachePtr->scanInfo;
3333 
3334   if (! dirtyRead)
3335   {
3336     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
3337     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
3338     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
3339     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
3340   }
3341 
3342   lqhKeyReq->tableSchemaVersion = sig0;
3343   lqhKeyReq->fragmentData = sig1;
3344   lqhKeyReq->transId1 = sig2;
3345   lqhKeyReq->transId2 = sig3;
3346   lqhKeyReq->scanInfo = sig6;
3347 
3348   lqhKeyReq->variableData[0] = sig4;
3349   lqhKeyReq->variableData[1] = sig5;
3350 
3351   UintR nextPos = 2;
3352 
3353   if (regTcPtr->lastReplicaNo > 1) {
3354     sig0 = (UintR)regTcPtr->tcNodedata[2] +
3355            (UintR)(regTcPtr->tcNodedata[3] << 16);
3356     lqhKeyReq->variableData[nextPos] = sig0;
3357     nextPos++;
3358   }//if
3359 
3360   sig0 = regCachePtr->keydata[0];
3361   sig1 = regCachePtr->keydata[1];
3362   sig2 = regCachePtr->keydata[2];
3363   sig3 = regCachePtr->keydata[3];
3364   UintR Tkeylen = regCachePtr->keylen;
3365 
3366   lqhKeyReq->variableData[nextPos + 0] = sig0;
3367   lqhKeyReq->variableData[nextPos + 1] = sig1;
3368   lqhKeyReq->variableData[nextPos + 2] = sig2;
3369   lqhKeyReq->variableData[nextPos + 3] = sig3;
3370 
3371   if (Tkeylen < 4) {
3372     nextPos += Tkeylen;
3373   } else {
3374     nextPos += 4;
3375   }//if
3376 
3377   sig0 = regCachePtr->attrinfo0;
3378   sig1 = regCachePtr->attrinfo15[0];
3379   sig2 = regCachePtr->attrinfo15[1];
3380   sig3 = regCachePtr->attrinfo15[2];
3381   sig4 = regCachePtr->attrinfo15[3];
3382   UintR TlenAi = regCachePtr->lenAiInTckeyreq;
3383 
3384   lqhKeyReq->variableData[nextPos + 0] = sig0;
3385   lqhKeyReq->variableData[nextPos + 1] = sig1;
3386   lqhKeyReq->variableData[nextPos + 2] = sig2;
3387   lqhKeyReq->variableData[nextPos + 3] = sig3;
3388   lqhKeyReq->variableData[nextPos + 4] = sig4;
3389 
3390   nextPos += TlenAi;
3391 
3392   // Reset trigger count
3393   regTcPtr->accumulatingTriggerData.i = RNIL;
3394   regTcPtr->accumulatingTriggerData.p = NULL;
3395   regTcPtr->noFiredTriggers = 0;
3396   regTcPtr->triggerExecutionCount = 0;
3397 
3398   sendSignal(TBRef, GSN_LQHKEYREQ, signal,
3399              nextPos + LqhKeyReq::FixedSignalLength, JBB);
3400 }//Dbtc::sendlqhkeyreq()
3401 
packLqhkeyreq040Lab(Signal * signal,UintR anAttrBufIndex,BlockReference TBRef)3402 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
3403                                UintR anAttrBufIndex,
3404                                BlockReference TBRef)
3405 {
3406   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3407 #ifdef ERROR_INSERT
3408   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3409   if (ERROR_INSERTED(8009)) {
3410     if (regApiPtr->apiConnectstate == CS_STARTED) {
3411       attrbufptr.i = RNIL;
3412       CLEAR_ERROR_INSERT_VALUE;
3413       return;
3414     }//if
3415   }//if
3416   if (ERROR_INSERTED(8010)) {
3417     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3418       attrbufptr.i = RNIL;
3419       CLEAR_ERROR_INSERT_VALUE;
3420       return;
3421     }//if
3422   }//if
3423 #endif
3424 
3425   UintR TattrbufFilesize = cattrbufFilesize;
3426   AttrbufRecord *localAttrbufRecord = attrbufRecord;
3427   while (1) {
3428     if (anAttrBufIndex == RNIL) {
3429       UintR TtcTimer = ctcTimer;
3430       UintR Tread = (regTcPtr->operation == ZREAD);
3431       UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
3432       UintR Tboth = Tread & Tdirty;
3433       setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3434       jam();
3435       /*--------------------------------------------------------------------
3436        *   WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
3437        *---------------------------------------------------------------------*/
3438       releaseAttrinfo();
3439       if (Tboth) {
3440         jam();
3441         releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
3442         return;
3443       }//if
3444       regTcPtr->tcConnectstate = OS_OPERATING;
3445       return;
3446     }//if
3447     if (anAttrBufIndex < TattrbufFilesize) {
3448       AttrbufRecord * const regAttrPtr = &localAttrbufRecord[anAttrBufIndex];
3449       anAttrBufIndex = regAttrPtr->attrbuf[ZINBUF_NEXT];
3450       sendAttrinfo(signal,
3451                    tcConnectptr.i,
3452                    regAttrPtr,
3453                    TBRef);
3454     } else {
3455       TCKEY_abort(signal, 17);
3456       return;
3457     }//if
3458   }//while
3459 }//Dbtc::packLqhkeyreq040Lab()
3460 
3461 /* ========================================================================= */
3462 /* -------      RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD  ------- */
3463 /* ========================================================================= */
releaseAttrinfo()3464 void Dbtc::releaseAttrinfo()
3465 {
3466   UintR Tmp;
3467   AttrbufRecordPtr Tattrbufptr;
3468   CacheRecord * const regCachePtr = cachePtr.p;
3469   UintR TattrbufFilesize = cattrbufFilesize;
3470   UintR TfirstfreeAttrbuf = cfirstfreeAttrbuf;
3471   Tattrbufptr.i = regCachePtr->firstAttrbuf;
3472   AttrbufRecord *localAttrbufRecord = attrbufRecord;
3473 
3474   while (Tattrbufptr.i < TattrbufFilesize) {
3475     Tattrbufptr.p = &localAttrbufRecord[Tattrbufptr.i];
3476     Tmp = Tattrbufptr.p->attrbuf[ZINBUF_NEXT];
3477     Tattrbufptr.p->attrbuf[ZINBUF_NEXT] = TfirstfreeAttrbuf;
3478     TfirstfreeAttrbuf = Tattrbufptr.i;
3479     Tattrbufptr.i = Tmp;
3480     jam();
3481   }//while
3482   if (Tattrbufptr.i == RNIL) {
3483 //---------------------------------------------------
3484 // Now we will release the cache record at the same
3485 // time as releasing the attrinfo records.
3486 //---------------------------------------------------
3487     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3488     UintR TfirstfreeCacheRec = cfirstfreeCacheRec;
3489     UintR TCacheIndex = cachePtr.i;
3490     cfirstfreeAttrbuf = TfirstfreeAttrbuf;
3491     regCachePtr->nextCacheRec = TfirstfreeCacheRec;
3492     cfirstfreeCacheRec = TCacheIndex;
3493     regApiPtr->cachePtr = RNIL;
3494     return;
3495   }//if
3496   systemErrorLab(0, __LINE__);
3497   return;
3498 }//Dbtc::releaseAttrinfo()
3499 
3500 /* ========================================================================= */
3501 /* -------   RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION     ------- */
3502 /* ========================================================================= */
releaseDirtyRead(Signal * signal,ApiConnectRecordPtr regApiPtr,TcConnectRecord * regTcPtr)3503 void Dbtc::releaseDirtyRead(Signal* signal,
3504                             ApiConnectRecordPtr regApiPtr,
3505                             TcConnectRecord* regTcPtr)
3506 {
3507   Uint32 Ttckeyrec = regApiPtr.p->tckeyrec;
3508   Uint32 TclientData = regTcPtr->clientData;
3509   Uint32 Tnode = regTcPtr->tcNodedata[0];
3510   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3511   Uint32 TsimpleReadCount = c_counters.csimpleReadCount;
3512   ConnectionState state = regApiPtr.p->apiConnectstate;
3513 
3514   regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3515   regApiPtr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
3516   regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3517 
3518   unlinkReadyTcCon(signal);
3519   releaseTcCon();
3520 
3521   /**
3522    * No LQHKEYCONF in Simple/Dirty read
3523    * Therefore decrese no LQHKEYCONF(REF) we are waiting for
3524    */
3525   c_counters.csimpleReadCount = TsimpleReadCount + 1;
3526   regApiPtr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
3527 
3528   if(Tlqhkeyreqrec == 0)
3529   {
3530     /**
3531      * Special case of lqhKeyConf_checkTransactionState:
3532      * - commit with zero operations: handle only for simple read
3533      */
3534     sendtckeyconf(signal, state == CS_START_COMMITTING);
3535     regApiPtr.p->apiConnectstate =
3536       (state == CS_START_COMMITTING ? CS_CONNECTED : state);
3537     setApiConTimer(regApiPtr.i, 0, __LINE__);
3538 
3539     return;
3540   }
3541 
3542   /**
3543    * Emulate LQHKEYCONF
3544    */
3545   lqhKeyConf_checkTransactionState(signal, regApiPtr);
3546 }//Dbtc::releaseDirtyRead()
3547 
3548 /* ------------------------------------------------------------------------- */
3549 /* -------        CHECK IF ALL TC CONNECTIONS ARE COMPLETED          ------- */
3550 /* ------------------------------------------------------------------------- */
unlinkReadyTcCon(Signal * signal)3551 void Dbtc::unlinkReadyTcCon(Signal* signal)
3552 {
3553   TcConnectRecordPtr urtTcConnectptr;
3554 
3555   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3556   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3557   UintR TtcConnectFilesize = ctcConnectFilesize;
3558   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3559   if (regTcPtr->prevTcConnect != RNIL) {
3560     jam();
3561     urtTcConnectptr.i = regTcPtr->prevTcConnect;
3562     ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3563     urtTcConnectptr.p->nextTcConnect = regTcPtr->nextTcConnect;
3564   } else {
3565     jam();
3566     regApiPtr->firstTcConnect = regTcPtr->nextTcConnect;
3567   }//if
3568   if (regTcPtr->nextTcConnect != RNIL) {
3569     jam();
3570     urtTcConnectptr.i = regTcPtr->nextTcConnect;
3571     ptrCheckGuard(urtTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
3572     urtTcConnectptr.p->prevTcConnect = regTcPtr->prevTcConnect;
3573   } else {
3574     jam();
3575     regApiPtr->lastTcConnect = tcConnectptr.p->prevTcConnect;
3576   }//if
3577 }//Dbtc::unlinkReadyTcCon()
3578 
releaseTcCon()3579 void Dbtc::releaseTcCon()
3580 {
3581   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3582   UintR TfirstfreeTcConnect = cfirstfreeTcConnect;
3583   UintR TconcurrentOp = c_counters.cconcurrentOp;
3584   UintR TtcConnectptrIndex = tcConnectptr.i;
3585 
3586   regTcPtr->tcConnectstate = OS_CONNECTED;
3587   regTcPtr->nextTcConnect = TfirstfreeTcConnect;
3588   regTcPtr->apiConnect = RNIL;
3589   regTcPtr->isIndexOp = false;
3590   regTcPtr->indexOp = RNIL;
3591   cfirstfreeTcConnect = TtcConnectptrIndex;
3592   c_counters.cconcurrentOp = TconcurrentOp - 1;
3593 }//Dbtc::releaseTcCon()
3594 
execPACKED_SIGNAL(Signal * signal)3595 void Dbtc::execPACKED_SIGNAL(Signal* signal)
3596 {
3597   LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
3598 
3599   UintR Ti;
3600   UintR Tstep = 0;
3601   UintR Tlength;
3602   UintR TpackedData[28];
3603   UintR Tdata1, Tdata2, Tdata3, Tdata4;
3604 
3605   jamEntry();
3606   Tlength = signal->length();
3607   if (Tlength > 25) {
3608     jam();
3609     systemErrorLab(signal, __LINE__);
3610     return;
3611   }//if
3612   Uint32* TpackDataPtr;
3613   for (Ti = 0; Ti < Tlength; Ti += 4) {
3614     Uint32* TsigDataPtr = &signal->theData[Ti];
3615     Tdata1 = TsigDataPtr[0];
3616     Tdata2 = TsigDataPtr[1];
3617     Tdata3 = TsigDataPtr[2];
3618     Tdata4 = TsigDataPtr[3];
3619 
3620     TpackDataPtr = &TpackedData[Ti];
3621     TpackDataPtr[0] = Tdata1;
3622     TpackDataPtr[1] = Tdata2;
3623     TpackDataPtr[2] = Tdata3;
3624     TpackDataPtr[3] = Tdata4;
3625   }//for
3626   while (Tlength > Tstep) {
3627 
3628     TpackDataPtr = &TpackedData[Tstep];
3629     Tdata1 = TpackDataPtr[0];
3630     Tdata2 = TpackDataPtr[1];
3631     Tdata3 = TpackDataPtr[2];
3632 
3633     lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
3634     lqhKeyConf->opPtr = Tdata2;
3635     lqhKeyConf->userRef = Tdata3;
3636 
3637     switch (Tdata1 >> 28) {
3638     case ZCOMMITTED:
3639       signal->header.theLength = 3;
3640       execCOMMITTED(signal);
3641       Tstep += 3;
3642       break;
3643     case ZCOMPLETED:
3644       signal->header.theLength = 3;
3645       execCOMPLETED(signal);
3646       Tstep += 3;
3647       break;
3648     case ZLQHKEYCONF:
3649       jam();
3650       Tdata1 = TpackDataPtr[3];
3651       Tdata2 = TpackDataPtr[4];
3652       Tdata3 = TpackDataPtr[5];
3653       Tdata4 = TpackDataPtr[6];
3654 
3655       lqhKeyConf->readLen = Tdata1;
3656       lqhKeyConf->transId1 = Tdata2;
3657       lqhKeyConf->transId2 = Tdata3;
3658       lqhKeyConf->noFiredTriggers = Tdata4;
3659       signal->header.theLength = LqhKeyConf::SignalLength;
3660       execLQHKEYCONF(signal);
3661       Tstep += LqhKeyConf::SignalLength;
3662       break;
3663     default:
3664       systemErrorLab(signal, __LINE__);
3665       return;
3666     }//switch
3667   }//while
3668   return;
3669 }//Dbtc::execPACKED_SIGNAL()
3670 
execLQHKEYCONF(Signal * signal)3671 void Dbtc::execLQHKEYCONF(Signal* signal)
3672 {
3673   const LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
3674   UintR compare_transid1, compare_transid2;
3675   BlockReference tlastLqhBlockref;
3676   UintR tlastLqhConnect;
3677   UintR treadlenAi;
3678   UintR TtcConnectptrIndex;
3679   UintR TtcConnectFilesize = ctcConnectFilesize;
3680 
3681   tlastLqhConnect = lqhKeyConf->connectPtr;
3682   TtcConnectptrIndex = lqhKeyConf->opPtr;
3683   tlastLqhBlockref = lqhKeyConf->userRef;
3684   treadlenAi = lqhKeyConf->readLen;
3685   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
3686 
3687   /*------------------------------------------------------------------------
3688    * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
3689    * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
3690    * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
3691    * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
3692    * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
3693    * OPERATIONS ON THE LQH CONNECT RECORD.
3694    *------------------------------------------------------------------------
3695    * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
3696    * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
3697    * PROBLEM  WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
3698    * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
3699    * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
3700    * BEFORE ACCEPTING THIS SIGNAL.
3701    * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
3702    * this.
3703    * This is more reason to ignore the signal if not all states are correct.
3704    *------------------------------------------------------------------------*/
3705   if (TtcConnectptrIndex >= TtcConnectFilesize) {
3706     TCKEY_abort(signal, 25);
3707     return;
3708   }//if
3709   TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
3710   OperationState TtcConnectstate = regTcPtr->tcConnectstate;
3711   tcConnectptr.i = TtcConnectptrIndex;
3712   tcConnectptr.p = regTcPtr;
3713   if (TtcConnectstate != OS_OPERATING) {
3714     warningReport(signal, 23);
3715     return;
3716   }//if
3717   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
3718   UintR TapiConnectptrIndex = regTcPtr->apiConnect;
3719   UintR TapiConnectFilesize = capiConnectFilesize;
3720   UintR Ttrans1 = lqhKeyConf->transId1;
3721   UintR Ttrans2 = lqhKeyConf->transId2;
3722   Uint32 noFired = lqhKeyConf->noFiredTriggers;
3723 
3724   if (TapiConnectptrIndex >= TapiConnectFilesize) {
3725     TCKEY_abort(signal, 29);
3726     return;
3727   }//if
3728   Ptr<ApiConnectRecord> regApiPtr;
3729   regApiPtr.i = TapiConnectptrIndex;
3730   regApiPtr.p = &localApiConnectRecord[TapiConnectptrIndex];
3731   apiConnectptr.i = TapiConnectptrIndex;
3732   apiConnectptr.p = regApiPtr.p;
3733   compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
3734   compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
3735   compare_transid1 = compare_transid1 | compare_transid2;
3736   if (compare_transid1 != 0) {
3737     warningReport(signal, 24);
3738     return;
3739   }//if
3740 
3741 #ifdef ERROR_INSERT
3742   if (ERROR_INSERTED(8029)) {
3743     systemErrorLab(signal, __LINE__);
3744   }//if
3745   if (ERROR_INSERTED(8003)) {
3746     if (regApiPtr.p->apiConnectstate == CS_STARTED) {
3747       CLEAR_ERROR_INSERT_VALUE;
3748       return;
3749     }//if
3750   }//if
3751   if (ERROR_INSERTED(8004)) {
3752     if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
3753       CLEAR_ERROR_INSERT_VALUE;
3754       return;
3755     }//if
3756   }//if
3757   if (ERROR_INSERTED(8005)) {
3758     if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
3759       CLEAR_ERROR_INSERT_VALUE;
3760       return;
3761     }//if
3762   }//if
3763   if (ERROR_INSERTED(8006)) {
3764     if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
3765       CLEAR_ERROR_INSERT_VALUE;
3766       return;
3767     }//if
3768   }//if
3769   if (ERROR_INSERTED(8023)) {
3770     SET_ERROR_INSERT_VALUE(8024);
3771     return;
3772   }//if
3773 #endif
3774   UintR TtcTimer = ctcTimer;
3775   regTcPtr->lastLqhCon = tlastLqhConnect;
3776   regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
3777   regTcPtr->noFiredTriggers = noFired;
3778 
3779   UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
3780   UintR TclientData = regTcPtr->clientData;
3781   UintR TdirtyOp = regTcPtr->dirtyOp;
3782   Uint32 TopSimple = regTcPtr->opSimple;
3783   Uint32 Toperation = regTcPtr->operation;
3784   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
3785   if (Ttckeyrec > (ZTCOPCONF_SIZE - 2)) {
3786     TCKEY_abort(signal, 30);
3787     return;
3788   }
3789   if (TapiConnectstate == CS_ABORTING) {
3790     warningReport(signal, 27);
3791     return;
3792   }//if
3793 
3794   setApiConTimer(apiConnectptr.i, TtcTimer, __LINE__);
3795 
3796   if (regTcPtr->isIndexOp) {
3797     jam();
3798     // This was an internal TCKEYREQ
3799     // will be returned unpacked
3800     regTcPtr->attrInfoLen = treadlenAi;
3801   } else {
3802     if (noFired == 0 && regTcPtr->triggeringOperation == RNIL) {
3803       jam();
3804       /*
3805        * Skip counting triggering operations the first round
3806        * since they will enter execLQHKEYCONF a second time
3807        * Skip counting internally generated TcKeyReq
3808        */
3809       regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
3810       regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
3811       regApiPtr.p->tckeyrec = Ttckeyrec + 2;
3812     }//if
3813   }//if
3814   if (TdirtyOp == ZTRUE)
3815   {
3816     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3817     jam();
3818     releaseDirtyWrite(signal);
3819     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
3820   }
3821   else if (Toperation == ZREAD && TopSimple)
3822   {
3823     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3824     jam();
3825     unlinkReadyTcCon(signal);
3826     releaseTcCon();
3827     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
3828   }
3829   else
3830   {
3831     jam();
3832     if (noFired == 0) {
3833       jam();
3834       // No triggers to execute
3835       UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
3836       regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
3837       regTcPtr->tcConnectstate = OS_PREPARED;
3838     }
3839   }//if
3840 
3841   /**
3842    * And now decide what to do next
3843    */
3844   if (regTcPtr->triggeringOperation != RNIL) {
3845     jam();
3846     // This operation was created by a trigger execting operation
3847     // Restart it if we have executed all it's triggers
3848     TcConnectRecordPtr opPtr;
3849 
3850     opPtr.i = regTcPtr->triggeringOperation;
3851     ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
3852     opPtr.p->triggerExecutionCount--;
3853     if (opPtr.p->triggerExecutionCount == 0) {
3854       /*
3855       We have completed current trigger execution
3856       Continue triggering operation
3857       */
3858       jam();
3859       continueTriggeringOp(signal, opPtr.p);
3860     }
3861   } else if (noFired == 0) {
3862     // This operation did not fire any triggers, finish operation
3863     jam();
3864     if (regTcPtr->isIndexOp) {
3865       jam();
3866       setupIndexOpReturn(regApiPtr.p, regTcPtr);
3867     }
3868     lqhKeyConf_checkTransactionState(signal, regApiPtr);
3869   } else {
3870     // We have fired triggers
3871     jam();
3872     saveTriggeringOpState(signal, regTcPtr);
3873     if (regTcPtr->noReceivedTriggers == noFired)
3874     {
3875       // We have received all data
3876       jam();
3877       executeTriggers(signal, &regApiPtr);
3878     }
3879     // else wait for more trigger data
3880   }
3881 }//Dbtc::execLQHKEYCONF()
3882 
setupIndexOpReturn(ApiConnectRecord * regApiPtr,TcConnectRecord * regTcPtr)3883 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
3884 			      TcConnectRecord* regTcPtr)
3885 {
3886   regApiPtr->indexOpReturn = true;
3887   regApiPtr->indexOp = regTcPtr->indexOp;
3888   regApiPtr->clientData = regTcPtr->clientData;
3889   regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
3890 }
3891 
3892 /**
3893  * lqhKeyConf_checkTransactionState
3894  *
3895  * This functions checks state variables, and
3896  *   decides if it should wait for more LQHKEYCONF signals
3897  *   or if it should start commiting
3898  */
3899 void
lqhKeyConf_checkTransactionState(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)3900 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
3901 				       Ptr<ApiConnectRecord> regApiPtr)
3902 {
3903 /*---------------------------------------------------------------*/
3904 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
3905 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN   */
3906 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE   */
3907 /* WHOLE TRANSACTION                                             */
3908 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF  */
3909 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
3910 /* TRANSACTION                                                   */
3911 /*---------------------------------------------------------------*/
3912   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
3913   UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
3914   UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
3915   int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
3916 
3917   switch (TapiConnectstate) {
3918   case CS_START_COMMITTING:
3919     if (TnoOfOutStanding == 0) {
3920       jam();
3921       diverify010Lab(signal);
3922       return;
3923     } else if (TnoOfOutStanding > 0) {
3924       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
3925         jam();
3926         sendtckeyconf(signal, 0);
3927         return;
3928       } else if (regApiPtr.p->indexOpReturn) {
3929 	jam();
3930         sendtckeyconf(signal, 0);
3931         return;
3932       }//if
3933       jam();
3934       return;
3935     } else {
3936       TCKEY_abort(signal, 44);
3937       return;
3938     }//if
3939     return;
3940   case CS_STARTED:
3941   case CS_RECEIVING:
3942     if (TnoOfOutStanding == 0) {
3943       jam();
3944       sendtckeyconf(signal, 2);
3945       return;
3946     } else {
3947       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
3948         jam();
3949         sendtckeyconf(signal, 0);
3950         return;
3951       } else if (regApiPtr.p->indexOpReturn) {
3952 	jam();
3953         sendtckeyconf(signal, 0);
3954         return;
3955 	}//if
3956       jam();
3957     }//if
3958     return;
3959   case CS_REC_COMMITTING:
3960     if (TnoOfOutStanding > 0) {
3961       if (regApiPtr.p->tckeyrec == ZTCOPCONF_SIZE) {
3962         jam();
3963         sendtckeyconf(signal, 0);
3964         return;
3965       } else if (regApiPtr.p->indexOpReturn) {
3966         jam();
3967         sendtckeyconf(signal, 0);
3968         return;
3969       }//if
3970       jam();
3971       return;
3972     }//if
3973     TCKEY_abort(signal, 45);
3974     return;
3975   case CS_CONNECTED:
3976     jam();
3977 /*---------------------------------------------------------------*/
3978 /*       WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY     */
3979 /*       CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE        */
3980 /*       COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS.   */
3981 /*---------------------------------------------------------------*/
3982     regApiPtr.p->tckeyrec = 0;
3983     return;
3984   default:
3985     TCKEY_abort(signal, 46);
3986     return;
3987   }//switch
3988 }//Dbtc::lqhKeyConf_checkTransactionState()
3989 
sendtckeyconf(Signal * signal,UintR TcommitFlag)3990 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag)
3991 {
3992   if(ERROR_INSERTED(8049)){
3993     CLEAR_ERROR_INSERT_VALUE;
3994     signal->theData[0] = TcContinueB::DelayTCKEYCONF;
3995     signal->theData[1] = apiConnectptr.i;
3996     signal->theData[2] = TcommitFlag;
3997     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
3998     return;
3999   }
4000 
4001   HostRecordPtr localHostptr;
4002   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4003   const UintR TopWords = (UintR)regApiPtr->tckeyrec;
4004   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
4005   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
4006   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
4007   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
4008   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
4009   ptrAss(localHostptr, hostRecord);
4010   UintR TcurrLen = localHostptr.p->noOfWordsTCKEYCONF;
4011   UintR confInfo = 0;
4012   TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
4013   TcKeyConf::setMarkerFlag(confInfo, Tmarker);
4014   const UintR TpacketLen = 6 + TopWords;
4015   regApiPtr->tckeyrec = 0;
4016 
4017   if (regApiPtr->indexOpReturn) {
4018     jam();
4019     // Return internally generated TCKEY
4020     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4021     TcKeyConf::setNoOfOperations(confInfo, 1);
4022     tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
4023     tcKeyConf->gci = regApiPtr->globalcheckpointid;
4024     tcKeyConf->confInfo = confInfo;
4025     tcKeyConf->transId1 = regApiPtr->transid[0];
4026     tcKeyConf->transId2 = regApiPtr->transid[1];
4027     tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
4028     tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
4029     Uint32 sigLen = TcKeyConf::StaticLength + TcKeyConf::OperationLength;
4030     EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
4031     regApiPtr->indexOpReturn = false;
4032     if (TopWords == 0) {
4033       jam();
4034       return; // No queued TcKeyConf
4035     }//if
4036   }//if
4037   if(TcommitFlag){
4038     jam();
4039     regApiPtr->m_exec_flag = 0;
4040   }
4041   TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
4042   if ((TpacketLen > 25) || !is_api){
4043     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
4044 
4045     jam();
4046     tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4047     tcKeyConf->gci = regApiPtr->globalcheckpointid;;
4048     tcKeyConf->confInfo = confInfo;
4049     tcKeyConf->transId1 = regApiPtr->transid[0];
4050     tcKeyConf->transId2 = regApiPtr->transid[1];
4051     copyFromToLen(&regApiPtr->tcSendArray[0],
4052 		  (UintR*)&tcKeyConf->operations,
4053 		  (UintR)ZTCOPCONF_SIZE);
4054     sendSignal(regApiPtr->ndbapiBlockref,
4055 	       GSN_TCKEYCONF, signal, (TpacketLen - 1), JBB);
4056     return;
4057   } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
4058     jam();
4059     sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
4060     TcurrLen = 0;
4061   } else {
4062     jam();
4063     updatePackedList(signal, localHostptr.p, localHostptr.i);
4064   }//if
4065   // -------------------------------------------------------------------------
4066   // The header contains the block reference of receiver plus the real signal
4067   // length - 3, since we have the real signal length plus one additional word
4068   // for the header we have to do - 4.
4069   // -------------------------------------------------------------------------
4070   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
4071   UintR Tpack1 = regApiPtr->ndbapiConnect;
4072   UintR Tpack2 = regApiPtr->globalcheckpointid;
4073   UintR Tpack3 = confInfo;
4074   UintR Tpack4 = regApiPtr->transid[0];
4075   UintR Tpack5 = regApiPtr->transid[1];
4076 
4077   localHostptr.p->noOfWordsTCKEYCONF = TcurrLen + TpacketLen;
4078 
4079   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 0] = Tpack0;
4080   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 1] = Tpack1;
4081   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 2] = Tpack2;
4082   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 3] = Tpack3;
4083   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 4] = Tpack4;
4084   localHostptr.p->packedWordsTCKEYCONF[TcurrLen + 5] = Tpack5;
4085 
4086   UintR Ti;
4087   for (Ti = 6; Ti < TpacketLen; Ti++) {
4088     localHostptr.p->packedWordsTCKEYCONF[TcurrLen + Ti] =
4089       regApiPtr->tcSendArray[Ti - 6];
4090   }//for
4091 }//Dbtc::sendtckeyconf()
4092 
copyFromToLen(UintR * sourceBuffer,UintR * destBuffer,UintR Tlen)4093 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
4094 {
4095   UintR Tindex = 0;
4096   UintR Ti;
4097   while (Tlen >= 4) {
4098     UintR Tdata0 = sourceBuffer[Tindex + 0];
4099     UintR Tdata1 = sourceBuffer[Tindex + 1];
4100     UintR Tdata2 = sourceBuffer[Tindex + 2];
4101     UintR Tdata3 = sourceBuffer[Tindex + 3];
4102     Tlen -= 4;
4103     destBuffer[Tindex + 0] = Tdata0;
4104     destBuffer[Tindex + 1] = Tdata1;
4105     destBuffer[Tindex + 2] = Tdata2;
4106     destBuffer[Tindex + 3] = Tdata3;
4107     Tindex += 4;
4108   }//while
4109   for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
4110     destBuffer[Tindex] = sourceBuffer[Tindex];
4111   }//for
4112 }//Dbtc::copyFromToLen()
4113 
execSEND_PACKED(Signal * signal)4114 void Dbtc::execSEND_PACKED(Signal* signal)
4115 {
4116   HostRecordPtr Thostptr;
4117   HostRecord *localHostRecord = hostRecord;
4118   UintR i;
4119   UintR TpackedListIndex = cpackedListIndex;
4120   jamEntry();
4121   for (i = 0; i < TpackedListIndex; i++) {
4122     Thostptr.i = cpackedList[i];
4123     ptrAss(Thostptr, localHostRecord);
4124     arrGuard(Thostptr.i - 1, MAX_NODES - 1);
4125     UintR TnoOfPackedWordsLqh = Thostptr.p->noOfPackedWordsLqh;
4126     UintR TnoOfWordsTCKEYCONF = Thostptr.p->noOfWordsTCKEYCONF;
4127     UintR TnoOfWordsTCINDXCONF = Thostptr.p->noOfWordsTCINDXCONF;
4128     jam();
4129     if (TnoOfPackedWordsLqh > 0) {
4130       jam();
4131       sendPackedSignalLqh(signal, Thostptr.p);
4132     }//if
4133     if (TnoOfWordsTCKEYCONF > 0) {
4134       jam();
4135       sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4136     }//if
4137     if (TnoOfWordsTCINDXCONF > 0) {
4138       jam();
4139       sendPackedTCINDXCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
4140     }//if
4141     Thostptr.p->inPackedList = false;
4142   }//for
4143   cpackedListIndex = 0;
4144   return;
4145 }//Dbtc::execSEND_PACKED()
4146 
4147 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 ahostIndex)4148 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
4149 {
4150   if (ahostptr->inPackedList == false) {
4151     UintR TpackedListIndex = cpackedListIndex;
4152     jam();
4153     ahostptr->inPackedList = true;
4154     cpackedList[TpackedListIndex] = ahostIndex;
4155     cpackedListIndex = TpackedListIndex + 1;
4156   }//if
4157 }//Dbtc::updatePackedList()
4158 
sendPackedSignalLqh(Signal * signal,HostRecord * ahostptr)4159 void Dbtc::sendPackedSignalLqh(Signal* signal, HostRecord * ahostptr)
4160 {
4161   UintR Tj;
4162   UintR TnoOfWords = ahostptr->noOfPackedWordsLqh;
4163   for (Tj = 0; Tj < TnoOfWords; Tj += 4) {
4164     UintR sig0 = ahostptr->packedWordsLqh[Tj + 0];
4165     UintR sig1 = ahostptr->packedWordsLqh[Tj + 1];
4166     UintR sig2 = ahostptr->packedWordsLqh[Tj + 2];
4167     UintR sig3 = ahostptr->packedWordsLqh[Tj + 3];
4168     signal->theData[Tj + 0] = sig0;
4169     signal->theData[Tj + 1] = sig1;
4170     signal->theData[Tj + 2] = sig2;
4171     signal->theData[Tj + 3] = sig3;
4172   }//for
4173   ahostptr->noOfPackedWordsLqh = 0;
4174   sendSignal(ahostptr->hostLqhBlockRef,
4175              GSN_PACKED_SIGNAL,
4176              signal,
4177              TnoOfWords,
4178              JBB);
4179 }//Dbtc::sendPackedSignalLqh()
4180 
sendPackedTCKEYCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)4181 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
4182                                HostRecord * ahostptr,
4183                                UintR hostId)
4184 {
4185   UintR Tj;
4186   UintR TnoOfWords = ahostptr->noOfWordsTCKEYCONF;
4187   BlockReference TBref = numberToRef(API_PACKED, hostId);
4188   for (Tj = 0; Tj < ahostptr->noOfWordsTCKEYCONF; Tj += 4) {
4189     UintR sig0 = ahostptr->packedWordsTCKEYCONF[Tj + 0];
4190     UintR sig1 = ahostptr->packedWordsTCKEYCONF[Tj + 1];
4191     UintR sig2 = ahostptr->packedWordsTCKEYCONF[Tj + 2];
4192     UintR sig3 = ahostptr->packedWordsTCKEYCONF[Tj + 3];
4193     signal->theData[Tj + 0] = sig0;
4194     signal->theData[Tj + 1] = sig1;
4195     signal->theData[Tj + 2] = sig2;
4196     signal->theData[Tj + 3] = sig3;
4197   }//for
4198   ahostptr->noOfWordsTCKEYCONF = 0;
4199   sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
4200 }//Dbtc::sendPackedTCKEYCONF()
4201 
sendPackedTCINDXCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)4202 void Dbtc::sendPackedTCINDXCONF(Signal* signal,
4203                                 HostRecord * ahostptr,
4204                                 UintR hostId)
4205 {
4206   UintR Tj;
4207   UintR TnoOfWords = ahostptr->noOfWordsTCINDXCONF;
4208   BlockReference TBref = numberToRef(API_PACKED, hostId);
4209   for (Tj = 0; Tj < ahostptr->noOfWordsTCINDXCONF; Tj += 4) {
4210     UintR sig0 = ahostptr->packedWordsTCINDXCONF[Tj + 0];
4211     UintR sig1 = ahostptr->packedWordsTCINDXCONF[Tj + 1];
4212     UintR sig2 = ahostptr->packedWordsTCINDXCONF[Tj + 2];
4213     UintR sig3 = ahostptr->packedWordsTCINDXCONF[Tj + 3];
4214     signal->theData[Tj + 0] = sig0;
4215     signal->theData[Tj + 1] = sig1;
4216     signal->theData[Tj + 2] = sig2;
4217     signal->theData[Tj + 3] = sig3;
4218   }//for
4219   ahostptr->noOfWordsTCINDXCONF = 0;
4220   sendSignal(TBref, GSN_TCINDXCONF, signal, TnoOfWords, JBB);
4221 }//Dbtc::sendPackedTCINDXCONF()
4222 
4223 /*
4224 4.3.11 DIVERIFY
4225 ---------------
4226 */
4227 /*****************************************************************************/
4228 /*                               D I V E R I F Y                             */
4229 /*                                                                           */
4230 /*****************************************************************************/
diverify010Lab(Signal * signal)4231 void Dbtc::diverify010Lab(Signal* signal)
4232 {
4233   UintR TfirstfreeApiConnectCopy = cfirstfreeApiConnectCopy;
4234   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4235   signal->theData[0] = apiConnectptr.i;
4236   if (ERROR_INSERTED(8022)) {
4237     jam();
4238     systemErrorLab(signal, __LINE__);
4239   }//if
4240 
4241   if (regApiPtr->lqhkeyreqrec)
4242   {
4243     if (TfirstfreeApiConnectCopy != RNIL) {
4244       seizeApiConnectCopy(signal);
4245       regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
4246       /*-----------------------------------------------------------------------
4247        * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
4248        * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
4249        * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
4250        * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
4251        *---------------------------------------------------------------------*/
4252       EXECUTE_DIRECT(DBDIH, GSN_DIVERIFYREQ, signal, 1);
4253       if (signal->theData[2] == 0) {
4254         execDIVERIFYCONF(signal);
4255       }
4256       return;
4257     } else {
4258       /*-----------------------------------------------------------------------
4259        * There were no free copy connections available. We must abort the
4260        * transaction since otherwise we will have a problem with the report
4261        * to the application.
4262        * This should more or less not happen but if it happens we do
4263        * not want to crash and we do not want to create code to handle it
4264        * properly since it is difficult to test it and will be complex to
4265        * handle a problem more or less not occurring.
4266        *---------------------------------------------------------------------*/
4267       terrorCode = ZSEIZE_API_COPY_ERROR;
4268       abortErrorLab(signal);
4269       return;
4270     }
4271   }
4272   else
4273   {
4274     jam();
4275     sendtckeyconf(signal, 1);
4276     regApiPtr->apiConnectstate = CS_CONNECTED;
4277     regApiPtr->m_transaction_nodes.clear();
4278     setApiConTimer(apiConnectptr.i, 0,__LINE__);
4279   }
4280 }//Dbtc::diverify010Lab()
4281 
4282 /* ------------------------------------------------------------------------- */
4283 /* -------                  SEIZE_API_CONNECT                        ------- */
4284 /*                  SEIZE CONNECT RECORD FOR A REQUEST                       */
4285 /* ------------------------------------------------------------------------- */
seizeApiConnectCopy(Signal * signal)4286 void Dbtc::seizeApiConnectCopy(Signal* signal)
4287 {
4288   ApiConnectRecordPtr locApiConnectptr;
4289 
4290   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4291   UintR TapiConnectFilesize = capiConnectFilesize;
4292   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4293 
4294   locApiConnectptr.i = cfirstfreeApiConnectCopy;
4295   ptrCheckGuard(locApiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4296   cfirstfreeApiConnectCopy = locApiConnectptr.p->nextApiConnect;
4297   locApiConnectptr.p->nextApiConnect = RNIL;
4298   regApiPtr->apiCopyRecord = locApiConnectptr.i;
4299   regApiPtr->triggerPending = false;
4300   regApiPtr->isIndexOp = false;
4301 }//Dbtc::seizeApiConnectCopy()
4302 
execDIVERIFYCONF(Signal * signal)4303 void Dbtc::execDIVERIFYCONF(Signal* signal)
4304 {
4305   UintR TapiConnectptrIndex = signal->theData[0];
4306   UintR TapiConnectFilesize = capiConnectFilesize;
4307   UintR Tgci = signal->theData[1];
4308   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4309 
4310   jamEntry();
4311   if (ERROR_INSERTED(8017)) {
4312     CLEAR_ERROR_INSERT_VALUE;
4313     return;
4314   }//if
4315   if (TapiConnectptrIndex >= TapiConnectFilesize) {
4316     TCKEY_abort(signal, 31);
4317     return;
4318   }//if
4319   ApiConnectRecord * const regApiPtr =
4320                             &localApiConnectRecord[TapiConnectptrIndex];
4321   ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
4322   UintR TApifailureNr = regApiPtr->failureNr;
4323   UintR Tfailure_nr = cfailure_nr;
4324   apiConnectptr.i = TapiConnectptrIndex;
4325   apiConnectptr.p = regApiPtr;
4326   if (TapiConnectstate != CS_PREPARE_TO_COMMIT) {
4327     TCKEY_abort(signal, 32);
4328     return;
4329   }//if
4330   /*--------------------------------------------------------------------------
4331    * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
4332    * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
4333    * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
4334    * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
4335    * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
4336    *-------------------------------------------------------------------------*/
4337   if (TApifailureNr != Tfailure_nr) {
4338     DIVER_node_fail_handling(signal, Tgci);
4339     return;
4340   }//if
4341   commitGciHandling(signal, Tgci);
4342 
4343   /**************************************************************************
4344    *                                 C O M M I T
4345    * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
4346    **************************************************************************/
4347 
4348   UintR TtcConnectptrIndex = regApiPtr->firstTcConnect;
4349   UintR TtcConnectFilesize = ctcConnectFilesize;
4350   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4351 
4352   regApiPtr->counter = regApiPtr->lqhkeyconfrec;
4353   regApiPtr->apiConnectstate = CS_COMMITTING;
4354   if (TtcConnectptrIndex >= TtcConnectFilesize) {
4355     TCKEY_abort(signal, 33);
4356     return;
4357   }//if
4358   TcConnectRecord* const regTcPtr = &localTcConnectRecord[TtcConnectptrIndex];
4359   tcConnectptr.i = TtcConnectptrIndex;
4360   tcConnectptr.p = regTcPtr;
4361   commit020Lab(signal);
4362 }//Dbtc::execDIVERIFYCONF()
4363 
4364 /*--------------------------------------------------------------------------*/
4365 /*                             COMMIT_GCI_HANDLING                          */
4366 /*       SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT.       */
4367 /*--------------------------------------------------------------------------*/
commitGciHandling(Signal * signal,UintR Tgci)4368 void Dbtc::commitGciHandling(Signal* signal, UintR Tgci)
4369 {
4370   GcpRecordPtr localGcpPointer;
4371 
4372   UintR TgcpFilesize = cgcpFilesize;
4373   UintR Tfirstgcp = cfirstgcp;
4374   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4375   GcpRecord *localGcpRecord = gcpRecord;
4376 
4377   regApiPtr->globalcheckpointid = Tgci;
4378   if (Tfirstgcp != RNIL) {
4379     /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
4380     localGcpPointer.i = Tfirstgcp;
4381     ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
4382     do {
4383       if (regApiPtr->globalcheckpointid == localGcpPointer.p->gcpId) {
4384         jam();
4385         gcpPtr.i = localGcpPointer.i;
4386         gcpPtr.p = localGcpPointer.p;
4387         linkApiToGcp(signal);
4388         return;
4389       } else {
4390         localGcpPointer.i = localGcpPointer.p->nextGcp;
4391         jam();
4392         if (localGcpPointer.i != RNIL) {
4393           jam();
4394           ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
4395           continue;
4396         }//if
4397       }//if
4398       seizeGcp(signal);
4399       linkApiToGcp(signal);
4400       return;
4401     } while (1);
4402   } else {
4403     jam();
4404     seizeGcp(signal);
4405     linkApiToGcp(signal);
4406   }//if
4407 }//Dbtc::commitGciHandling()
4408 
4409 /* --------------------------------------------------------------------------*/
4410 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
4411 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS   */
4412 /* LINKED OUT OF THE LIST.                                                   */
4413 /*---------------------------------------------------------------------------*/
linkApiToGcp(Signal * signal)4414 void Dbtc::linkApiToGcp(Signal* signal)
4415 {
4416   ApiConnectRecordPtr localApiConnectptr;
4417   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4418   GcpRecord * const regGcpPtr = gcpPtr.p;
4419   UintR TapiConnectptrIndex = apiConnectptr.i;
4420   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4421 
4422   regApiPtr->nextGcpConnect = RNIL;
4423   if (regGcpPtr->firstApiConnect == RNIL) {
4424     regGcpPtr->firstApiConnect = TapiConnectptrIndex;
4425     jam();
4426   } else {
4427     UintR TapiConnectFilesize = capiConnectFilesize;
4428     localApiConnectptr.i = regGcpPtr->lastApiConnect;
4429     jam();
4430     ptrCheckGuard(localApiConnectptr,
4431                   TapiConnectFilesize, localApiConnectRecord);
4432     localApiConnectptr.p->nextGcpConnect = TapiConnectptrIndex;
4433   }//if
4434   UintR TlastApiConnect = regGcpPtr->lastApiConnect;
4435   regApiPtr->gcpPointer = gcpPtr.i;
4436   regApiPtr->prevGcpConnect = TlastApiConnect;
4437   regGcpPtr->lastApiConnect = TapiConnectptrIndex;
4438 }//Dbtc::linkApiToGcp()
4439 
seizeGcp(Signal * signal)4440 void Dbtc::seizeGcp(Signal* signal)
4441 {
4442   GcpRecordPtr tmpGcpPointer;
4443   GcpRecordPtr localGcpPointer;
4444 
4445   UintR Tfirstgcp = cfirstgcp;
4446   UintR Tglobalcheckpointid = apiConnectptr.p->globalcheckpointid;
4447   UintR TgcpFilesize = cgcpFilesize;
4448   GcpRecord *localGcpRecord = gcpRecord;
4449 
4450   localGcpPointer.i = cfirstfreeGcp;
4451   ptrCheckGuard(localGcpPointer, TgcpFilesize, localGcpRecord);
4452   UintR TfirstfreeGcp = localGcpPointer.p->nextGcp;
4453   localGcpPointer.p->gcpId = Tglobalcheckpointid;
4454   localGcpPointer.p->nextGcp = RNIL;
4455   localGcpPointer.p->firstApiConnect = RNIL;
4456   localGcpPointer.p->lastApiConnect = RNIL;
4457   localGcpPointer.p->gcpNomoretransRec = ZFALSE;
4458   cfirstfreeGcp = TfirstfreeGcp;
4459 
4460   if (Tfirstgcp == RNIL) {
4461     jam();
4462     cfirstgcp = localGcpPointer.i;
4463   } else {
4464     tmpGcpPointer.i = clastgcp;
4465     jam();
4466     ptrCheckGuard(tmpGcpPointer, TgcpFilesize, localGcpRecord);
4467     tmpGcpPointer.p->nextGcp = localGcpPointer.i;
4468   }//if
4469   clastgcp = localGcpPointer.i;
4470   gcpPtr = localGcpPointer;
4471 }//Dbtc::seizeGcp()
4472 
4473 /*---------------------------------------------------------------------------*/
4474 // Send COMMIT messages to all LQH operations involved in the transaction.
4475 /*---------------------------------------------------------------------------*/
commit020Lab(Signal * signal)4476 void Dbtc::commit020Lab(Signal* signal)
4477 {
4478   TcConnectRecordPtr localTcConnectptr;
4479   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4480   UintR TtcConnectFilesize = ctcConnectFilesize;
4481   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4482 
4483   localTcConnectptr.p = tcConnectptr.p;
4484   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
4485   UintR Tcount = 0;
4486   do {
4487     /*-----------------------------------------------------------------------
4488      * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
4489      *-----------------------------------------------------------------------*/
4490     /* *********< */
4491     /*  COMMIT  < */
4492     /* *********< */
4493     localTcConnectptr.i = localTcConnectptr.p->nextTcConnect;
4494     localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
4495     sendCommitLqh(signal, localTcConnectptr.p);
4496 
4497     if (localTcConnectptr.i != RNIL) {
4498       Tcount = Tcount + 1;
4499       if (Tcount < 16 && !ERROR_INSERTED(8057)) {
4500         ptrCheckGuard(localTcConnectptr,
4501                       TtcConnectFilesize, localTcConnectRecord);
4502         jam();
4503         continue;
4504       } else {
4505         jam();
4506         if (ERROR_INSERTED(8014)) {
4507           CLEAR_ERROR_INSERT_VALUE;
4508           return;
4509         }//if
4510         signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
4511         signal->theData[1] = apiConnectptr.i;
4512         signal->theData[2] = localTcConnectptr.i;
4513         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
4514         return;
4515       }//if
4516     } else {
4517       jam();
4518       if (ERROR_INSERTED(8057))
4519         CLEAR_ERROR_INSERT_VALUE;
4520 
4521       regApiPtr->apiConnectstate = CS_COMMIT_SENT;
4522       return;
4523     }//if
4524   } while (1);
4525 }//Dbtc::commit020Lab()
4526 
sendCommitLqh(Signal * signal,TcConnectRecord * const regTcPtr)4527 void Dbtc::sendCommitLqh(Signal* signal,
4528                          TcConnectRecord * const regTcPtr)
4529 {
4530   HostRecordPtr Thostptr;
4531   UintR ThostFilesize = chostFilesize;
4532   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4533   Thostptr.i = regTcPtr->lastLqhNodeId;
4534   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
4535   if (Thostptr.p->noOfPackedWordsLqh > 21) {
4536     jam();
4537     sendPackedSignalLqh(signal, Thostptr.p);
4538   } else {
4539     jam();
4540     updatePackedList(signal, Thostptr.p, Thostptr.i);
4541   }//if
4542   UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
4543   UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
4544   UintR Tdata1 = regTcPtr->lastLqhCon;
4545   UintR Tdata2 = regApiPtr->globalcheckpointid;
4546   UintR Tdata3 = regApiPtr->transid[0];
4547   UintR Tdata4 = regApiPtr->transid[1];
4548 
4549   TDataPtr[0] = Tdata1 | (ZCOMMIT << 28);
4550   TDataPtr[1] = Tdata2;
4551   TDataPtr[2] = Tdata3;
4552   TDataPtr[3] = Tdata4;
4553   Thostptr.p->noOfPackedWordsLqh = Tindex + 4;
4554 }//Dbtc::sendCommitLqh()
4555 
4556 void
DIVER_node_fail_handling(Signal * signal,UintR Tgci)4557 Dbtc::DIVER_node_fail_handling(Signal* signal, UintR Tgci)
4558 {
4559   /*------------------------------------------------------------------------
4560    * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
4561    * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
4562    * ABORT AND THE COMMIT CASES WE NEED  TO SET-UP THE DATA FOR THE
4563    * ABORT/COMMIT/COMPLETE  HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
4564    *------------------------------------------------------------------------*/
4565   tabortInd = ZFALSE;
4566   setupFailData(signal);
4567   if (false && tabortInd == ZFALSE) {
4568     jam();
4569     commitGciHandling(signal, Tgci);
4570     toCommitHandlingLab(signal);
4571   } else {
4572     jam();
4573     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
4574     apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
4575     toAbortHandlingLab(signal);
4576   }//if
4577   return;
4578 }//Dbtc::DIVER_node_fail_handling()
4579 
4580 
4581 /* ------------------------------------------------------------------------- */
4582 /* -------                       ENTER COMMITTED                     ------- */
4583 /*                                                                           */
4584 /* ------------------------------------------------------------------------- */
execCOMMITTED(Signal * signal)4585 void Dbtc::execCOMMITTED(Signal* signal)
4586 {
4587   TcConnectRecordPtr localTcConnectptr;
4588   ApiConnectRecordPtr localApiConnectptr;
4589 
4590   UintR TtcConnectFilesize = ctcConnectFilesize;
4591   UintR TapiConnectFilesize = capiConnectFilesize;
4592   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4593   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4594 
4595 #ifdef ERROR_INSERT
4596   if (ERROR_INSERTED(8018)) {
4597     CLEAR_ERROR_INSERT_VALUE;
4598     return;
4599   }//if
4600   if (ERROR_INSERTED(8030)) {
4601     systemErrorLab(signal, __LINE__);
4602   }//if
4603   if (ERROR_INSERTED(8025)) {
4604     SET_ERROR_INSERT_VALUE(8026);
4605     return;
4606   }//if
4607   if (ERROR_INSERTED(8041)) {
4608     CLEAR_ERROR_INSERT_VALUE;
4609     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
4610     return;
4611   }//if
4612   if (ERROR_INSERTED(8042)) {
4613     SET_ERROR_INSERT_VALUE(8046);
4614     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
4615     return;
4616   }//if
4617 #endif
4618   localTcConnectptr.i = signal->theData[0];
4619   jamEntry();
4620   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4621   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
4622   if (localTcConnectptr.p->tcConnectstate != OS_COMMITTING) {
4623     warningReport(signal, 4);
4624     return;
4625   }//if
4626   ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
4627 		localApiConnectRecord);
4628   UintR Tcounter = localApiConnectptr.p->counter - 1;
4629   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
4630   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
4631   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
4632   Tdata1 = Tdata1 | Tdata2;
4633   bool TcheckCondition =
4634     (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
4635 
4636   setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
4637   localApiConnectptr.p->counter = Tcounter;
4638   localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
4639   if (Tdata1 != 0) {
4640     warningReport(signal, 5);
4641     return;
4642   }//if
4643   if (TcheckCondition) {
4644     jam();
4645     /*-------------------------------------------------------*/
4646     // We have not sent all COMMIT requests yet. We could be
4647     // in the state that all sent are COMMITTED but we are
4648     // still waiting for a CONTINUEB to send the rest of the
4649     // COMMIT requests.
4650     /*-------------------------------------------------------*/
4651     return;
4652   }//if
4653   if (ERROR_INSERTED(8020)) {
4654     jam();
4655     systemErrorLab(signal, __LINE__);
4656   }//if
4657   /*-------------------------------------------------------*/
4658   /* THE ENTIRE TRANSACTION IS NOW COMMITED                */
4659   /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION.  */
4660   /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
4661   /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A     */
4662   /* NEW API CONNECT RECORD.                               */
4663   /*-------------------------------------------------------*/
4664 
4665   apiConnectptr = localApiConnectptr;
4666   sendApiCommit(signal);
4667 
4668   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4669   localTcConnectptr.i = regApiPtr->firstTcConnect;
4670   UintR Tlqhkeyconfrec = regApiPtr->lqhkeyconfrec;
4671   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4672   regApiPtr->counter = Tlqhkeyconfrec;
4673 
4674   tcConnectptr = localTcConnectptr;
4675   complete010Lab(signal);
4676   return;
4677 
4678 }//Dbtc::execCOMMITTED()
4679 
4680 /*-------------------------------------------------------*/
4681 /*                       SEND_API_COMMIT                 */
4682 /*       SEND COMMIT DECISION TO THE API.                */
4683 /*-------------------------------------------------------*/
sendApiCommit(Signal * signal)4684 void Dbtc::sendApiCommit(Signal* signal)
4685 {
4686   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4687 
4688   if (regApiPtr->returnsignal == RS_TCKEYCONF) {
4689     sendtckeyconf(signal, 1);
4690   } else if (regApiPtr->returnsignal == RS_TC_COMMITCONF) {
4691     jam();
4692     TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
4693     if(regApiPtr->commitAckMarker == RNIL){
4694       jam();
4695       commitConf->apiConnectPtr = regApiPtr->ndbapiConnect;
4696     } else {
4697       jam();
4698       commitConf->apiConnectPtr = regApiPtr->ndbapiConnect | 1;
4699     }
4700     commitConf->transId1 = regApiPtr->transid[0];
4701     commitConf->transId2 = regApiPtr->transid[1];
4702     commitConf->gci = regApiPtr->globalcheckpointid;
4703 
4704     sendSignal(regApiPtr->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
4705 	       TcCommitConf::SignalLength, JBB);
4706   } else if (regApiPtr->returnsignal == RS_NO_RETURN) {
4707     jam();
4708   } else {
4709     TCKEY_abort(signal, 37);
4710     return;
4711   }//if
4712   UintR TapiConnectFilesize = capiConnectFilesize;
4713   UintR TcommitCount = c_counters.ccommitCount;
4714   UintR TapiIndex = apiConnectptr.i;
4715   UintR TnewApiIndex = regApiPtr->apiCopyRecord;
4716   UintR TapiFailState = regApiPtr->apiFailState;
4717   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4718 
4719   tmpApiConnectptr.p = apiConnectptr.p;
4720   tmpApiConnectptr.i = TapiIndex;
4721   c_counters.ccommitCount = TcommitCount + 1;
4722   apiConnectptr.i = TnewApiIndex;
4723   ptrCheckGuard(apiConnectptr, TapiConnectFilesize, localApiConnectRecord);
4724   copyApi(signal);
4725   if (TapiFailState != ZTRUE) {
4726     return;
4727   } else {
4728     jam();
4729     handleApiFailState(signal, tmpApiConnectptr.i);
4730     return;
4731   }//if
4732 }//Dbtc::sendApiCommit()
4733 
4734 /* ========================================================================= */
4735 /* =======                  COPY_API                                 ======= */
4736 /*   COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT                */
4737 /*   IS PREPARED TO RECEIVE A NEW TRANSACTION.                               */
4738 /*===========================================================================*/
copyApi(Signal * signal)4739 void Dbtc::copyApi(Signal* signal)
4740 {
4741   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4742   ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p;
4743 
4744   UintR TndbapiConnect = regTmpApiPtr->ndbapiConnect;
4745   UintR TfirstTcConnect = regTmpApiPtr->firstTcConnect;
4746   UintR Ttransid1 = regTmpApiPtr->transid[0];
4747   UintR Ttransid2 = regTmpApiPtr->transid[1];
4748   UintR Tlqhkeyconfrec = regTmpApiPtr->lqhkeyconfrec;
4749   UintR TgcpPointer = regTmpApiPtr->gcpPointer;
4750   UintR TgcpFilesize = cgcpFilesize;
4751   UintR TcommitAckMarker = regTmpApiPtr->commitAckMarker;
4752   NdbNodeBitmask Tnodes = regTmpApiPtr->m_transaction_nodes;
4753   GcpRecord *localGcpRecord = gcpRecord;
4754 
4755   regApiPtr->ndbapiBlockref = regTmpApiPtr->ndbapiBlockref;
4756   regApiPtr->ndbapiConnect = TndbapiConnect;
4757   regApiPtr->firstTcConnect = TfirstTcConnect;
4758   regApiPtr->apiConnectstate = CS_COMPLETING;
4759   regApiPtr->transid[0] = Ttransid1;
4760   regApiPtr->transid[1] = Ttransid2;
4761   regApiPtr->lqhkeyconfrec = Tlqhkeyconfrec;
4762   regApiPtr->commitAckMarker = TcommitAckMarker;
4763   regApiPtr->m_transaction_nodes = Tnodes;
4764   regApiPtr->singleUserMode = 0;
4765 
4766   gcpPtr.i = TgcpPointer;
4767   ptrCheckGuard(gcpPtr, TgcpFilesize, localGcpRecord);
4768   unlinkApiConnect(signal);
4769   linkApiToGcp(signal);
4770   setApiConTimer(tmpApiConnectptr.i, 0, __LINE__);
4771   regTmpApiPtr->apiConnectstate = CS_CONNECTED;
4772   regTmpApiPtr->commitAckMarker = RNIL;
4773   regTmpApiPtr->firstTcConnect = RNIL;
4774   regTmpApiPtr->lastTcConnect = RNIL;
4775   regTmpApiPtr->m_transaction_nodes.clear();
4776   regTmpApiPtr->singleUserMode = 0;
4777   releaseAllSeizedIndexOperations(regTmpApiPtr);
4778 }//Dbtc::copyApi()
4779 
unlinkApiConnect(Signal * signal)4780 void Dbtc::unlinkApiConnect(Signal* signal)
4781 {
4782   ApiConnectRecordPtr localApiConnectptr;
4783   ApiConnectRecord * const regTmpApiPtr = tmpApiConnectptr.p;
4784   UintR TapiConnectFilesize = capiConnectFilesize;
4785   UintR TprevGcpConnect = regTmpApiPtr->prevGcpConnect;
4786   UintR TnextGcpConnect = regTmpApiPtr->nextGcpConnect;
4787   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4788 
4789   if (TprevGcpConnect == RNIL) {
4790     gcpPtr.p->firstApiConnect = TnextGcpConnect;
4791     jam();
4792   } else {
4793     localApiConnectptr.i = TprevGcpConnect;
4794     jam();
4795     ptrCheckGuard(localApiConnectptr,
4796                   TapiConnectFilesize, localApiConnectRecord);
4797     localApiConnectptr.p->nextGcpConnect = TnextGcpConnect;
4798   }//if
4799   if (TnextGcpConnect == RNIL) {
4800     gcpPtr.p->lastApiConnect = TprevGcpConnect;
4801     jam();
4802   } else {
4803     localApiConnectptr.i = TnextGcpConnect;
4804     jam();
4805     ptrCheckGuard(localApiConnectptr,
4806                   TapiConnectFilesize, localApiConnectRecord);
4807     localApiConnectptr.p->prevGcpConnect = TprevGcpConnect;
4808   }//if
4809 }//Dbtc::unlinkApiConnect()
4810 
complete010Lab(Signal * signal)4811 void Dbtc::complete010Lab(Signal* signal)
4812 {
4813   TcConnectRecordPtr localTcConnectptr;
4814   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4815   UintR TtcConnectFilesize = ctcConnectFilesize;
4816   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4817 
4818   localTcConnectptr.p = tcConnectptr.p;
4819   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
4820   UintR TapiConnectptrIndex = apiConnectptr.i;
4821   UintR Tcount = 0;
4822   do {
4823     localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
4824     localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
4825 
4826     /* ************ */
4827     /*  COMPLETE  < */
4828     /* ************ */
4829     const Uint32 nextTcConnect = localTcConnectptr.p->nextTcConnect;
4830     sendCompleteLqh(signal, localTcConnectptr.p);
4831     localTcConnectptr.i = nextTcConnect;
4832     if (localTcConnectptr.i != RNIL) {
4833       Tcount++;
4834       if (Tcount < 16) {
4835         ptrCheckGuard(localTcConnectptr,
4836                       TtcConnectFilesize, localTcConnectRecord);
4837         jam();
4838         continue;
4839       } else {
4840         jam();
4841         if (ERROR_INSERTED(8013)) {
4842           CLEAR_ERROR_INSERT_VALUE;
4843           return;
4844         }//if
4845         signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
4846         signal->theData[1] = apiConnectptr.i;
4847         signal->theData[2] = localTcConnectptr.i;
4848         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
4849         return;
4850       }//if
4851     } else {
4852       jam();
4853       regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
4854       return;
4855     }//if
4856   } while (1);
4857 }//Dbtc::complete010Lab()
4858 
sendCompleteLqh(Signal * signal,TcConnectRecord * const regTcPtr)4859 void Dbtc::sendCompleteLqh(Signal* signal,
4860                            TcConnectRecord * const regTcPtr)
4861 {
4862   HostRecordPtr Thostptr;
4863   UintR ThostFilesize = chostFilesize;
4864   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4865   Thostptr.i = regTcPtr->lastLqhNodeId;
4866   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
4867   if (Thostptr.p->noOfPackedWordsLqh > 22) {
4868     jam();
4869     sendPackedSignalLqh(signal, Thostptr.p);
4870   } else {
4871     jam();
4872     updatePackedList(signal, Thostptr.p, Thostptr.i);
4873   }//if
4874 
4875   UintR Tindex = Thostptr.p->noOfPackedWordsLqh;
4876   UintR* TDataPtr = &Thostptr.p->packedWordsLqh[Tindex];
4877   UintR Tdata1 = regTcPtr->lastLqhCon | (ZCOMPLETE << 28);
4878   UintR Tdata2 = regApiPtr->transid[0];
4879   UintR Tdata3 = regApiPtr->transid[1];
4880 
4881   TDataPtr[0] = Tdata1;
4882   TDataPtr[1] = Tdata2;
4883   TDataPtr[2] = Tdata3;
4884   Thostptr.p->noOfPackedWordsLqh = Tindex + 3;
4885 }//Dbtc::sendCompleteLqh()
4886 
4887 void
execTC_COMMIT_ACK(Signal * signal)4888 Dbtc::execTC_COMMIT_ACK(Signal* signal){
4889   jamEntry();
4890 
4891   CommitAckMarker key;
4892   key.transid1 = signal->theData[0];
4893   key.transid2 = signal->theData[1];
4894 
4895   CommitAckMarkerPtr removedMarker;
4896   m_commitAckMarkerHash.remove(removedMarker, key);
4897   if (removedMarker.i == RNIL) {
4898     jam();
4899     warningHandlerLab(signal, __LINE__);
4900     return;
4901   }//if
4902   sendRemoveMarkers(signal, removedMarker.p);
4903   m_commitAckMarkerPool.release(removedMarker);
4904 }
4905 
4906 void
sendRemoveMarkers(Signal * signal,const CommitAckMarker * marker)4907 Dbtc::sendRemoveMarkers(Signal* signal, const CommitAckMarker * marker){
4908   jam();
4909   const Uint32 noOfLqhs = marker->noOfLqhs;
4910   const Uint32 transId1 = marker->transid1;
4911   const Uint32 transId2 = marker->transid2;
4912 
4913   for(Uint32 i = 0; i<noOfLqhs; i++){
4914     jam();
4915     const NodeId nodeId = marker->lqhNodeId[i];
4916     sendRemoveMarker(signal, nodeId, transId1, transId2);
4917   }
4918 }
4919 
4920 void
sendRemoveMarker(Signal * signal,NodeId nodeId,Uint32 transid1,Uint32 transid2)4921 Dbtc::sendRemoveMarker(Signal* signal,
4922                        NodeId nodeId,
4923                        Uint32 transid1,
4924                        Uint32 transid2){
4925   /**
4926    * Seize host ptr
4927    */
4928   HostRecordPtr hostPtr;
4929   const UintR ThostFilesize = chostFilesize;
4930   hostPtr.i = nodeId;
4931   ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
4932 
4933   if (hostPtr.p->noOfPackedWordsLqh > (25 - 3)){
4934     jam();
4935     sendPackedSignalLqh(signal, hostPtr.p);
4936   } else {
4937     jam();
4938     updatePackedList(signal, hostPtr.p, hostPtr.i);
4939   }//if
4940 
4941   UintR  numWord = hostPtr.p->noOfPackedWordsLqh;
4942   UintR* dataPtr = &hostPtr.p->packedWordsLqh[numWord];
4943 
4944   dataPtr[0] = (ZREMOVE_MARKER << 28);
4945   dataPtr[1] = transid1;
4946   dataPtr[2] = transid2;
4947   hostPtr.p->noOfPackedWordsLqh = numWord + 3;
4948 }
4949 
execCOMPLETED(Signal * signal)4950 void Dbtc::execCOMPLETED(Signal* signal)
4951 {
4952   TcConnectRecordPtr localTcConnectptr;
4953   ApiConnectRecordPtr localApiConnectptr;
4954 
4955   UintR TtcConnectFilesize = ctcConnectFilesize;
4956   UintR TapiConnectFilesize = capiConnectFilesize;
4957   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
4958   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
4959 
4960 #ifdef ERROR_INSERT
4961   if (ERROR_INSERTED(8031)) {
4962     systemErrorLab(signal, __LINE__);
4963   }//if
4964   if (ERROR_INSERTED(8019)) {
4965     CLEAR_ERROR_INSERT_VALUE;
4966     return;
4967   }//if
4968   if (ERROR_INSERTED(8027)) {
4969     SET_ERROR_INSERT_VALUE(8028);
4970     return;
4971   }//if
4972   if (ERROR_INSERTED(8043)) {
4973     CLEAR_ERROR_INSERT_VALUE;
4974     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
4975     return;
4976   }//if
4977   if (ERROR_INSERTED(8044)) {
4978     SET_ERROR_INSERT_VALUE(8047);
4979     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
4980     return;
4981   }//if
4982 #endif
4983   localTcConnectptr.i = signal->theData[0];
4984   jamEntry();
4985   ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
4986   bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
4987   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
4988   if (Tcond1) {
4989     warningReport(signal, 6);
4990     return;
4991   }//if
4992   ptrCheckGuard(localApiConnectptr, TapiConnectFilesize,
4993 		localApiConnectRecord);
4994   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
4995   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
4996   UintR Tcounter = localApiConnectptr.p->counter - 1;
4997   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
4998   Tdata1 = Tdata1 | Tdata2;
4999   bool TcheckCondition =
5000     (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
5001   if (Tdata1 != 0) {
5002     warningReport(signal, 7);
5003     return;
5004   }//if
5005   setApiConTimer(localApiConnectptr.i, ctcTimer, __LINE__);
5006   localApiConnectptr.p->counter = Tcounter;
5007   localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
5008   localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
5009   if (TcheckCondition) {
5010     jam();
5011     /*-------------------------------------------------------*/
5012     // We have not sent all COMPLETE requests yet. We could be
5013     // in the state that all sent are COMPLETED but we are
5014     // still waiting for a CONTINUEB to send the rest of the
5015     // COMPLETE requests.
5016     /*-------------------------------------------------------*/
5017     return;
5018   }//if
5019   if (ERROR_INSERTED(8021)) {
5020     jam();
5021     systemErrorLab(signal, __LINE__);
5022   }//if
5023   apiConnectptr = localApiConnectptr;
5024   releaseTransResources(signal);
5025 }//Dbtc::execCOMPLETED()
5026 
5027 /*---------------------------------------------------------------------------*/
5028 /*                               RELEASE_TRANS_RESOURCES                     */
5029 /*       RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION.       */
5030 /*---------------------------------------------------------------------------*/
releaseTransResources(Signal * signal)5031 void Dbtc::releaseTransResources(Signal* signal)
5032 {
5033   TcConnectRecordPtr localTcConnectptr;
5034   UintR TtcConnectFilesize = ctcConnectFilesize;
5035   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5036   apiConnectptr.p->m_transaction_nodes.clear();
5037   localTcConnectptr.i = apiConnectptr.p->firstTcConnect;
5038   do {
5039     jam();
5040     ptrCheckGuard(localTcConnectptr, TtcConnectFilesize, localTcConnectRecord);
5041     UintR rtrTcConnectptrIndex = localTcConnectptr.p->nextTcConnect;
5042     tcConnectptr.i = localTcConnectptr.i;
5043     tcConnectptr.p = localTcConnectptr.p;
5044     localTcConnectptr.i = rtrTcConnectptrIndex;
5045     releaseTcCon();
5046   } while (localTcConnectptr.i != RNIL);
5047   handleGcp(signal);
5048   releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
5049   releaseAllSeizedIndexOperations(apiConnectptr.p);
5050   releaseApiConCopy(signal);
5051 }//Dbtc::releaseTransResources()
5052 
5053 /* *********************************************************************>> */
5054 /*       MODULE: HANDLE_GCP                                                */
5055 /*       DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
5056 /*       OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC   */
5057 /*       SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
5058 /*       GLOBAL CHECKPOINT HAVE COMPLETED.                                 */
5059 /* *********************************************************************>> */
handleGcp(Signal * signal)5060 void Dbtc::handleGcp(Signal* signal)
5061 {
5062   GcpRecord *localGcpRecord = gcpRecord;
5063   GcpRecordPtr localGcpPtr;
5064   UintR TapiConnectptrIndex = apiConnectptr.i;
5065   UintR TgcpFilesize = cgcpFilesize;
5066   localGcpPtr.i = apiConnectptr.p->gcpPointer;
5067   tmpApiConnectptr.i = TapiConnectptrIndex;
5068   tmpApiConnectptr.p = apiConnectptr.p;
5069   ptrCheckGuard(localGcpPtr, TgcpFilesize, localGcpRecord);
5070   gcpPtr.i = localGcpPtr.i;
5071   gcpPtr.p = localGcpPtr.p;
5072   unlinkApiConnect(signal);
5073   if (localGcpPtr.p->firstApiConnect == RNIL) {
5074     if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
5075       jam();
5076       tcheckGcpId = localGcpPtr.p->gcpId;
5077       gcpTcfinished(signal);
5078       unlinkGcp(signal);
5079     }//if
5080   }//if
5081 }//Dbtc::handleGcp()
5082 
releaseApiConCopy(Signal * signal)5083 void Dbtc::releaseApiConCopy(Signal* signal)
5084 {
5085   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5086   UintR TfirstfreeApiConnectCopyOld = cfirstfreeApiConnectCopy;
5087   cfirstfreeApiConnectCopy = apiConnectptr.i;
5088   regApiPtr->nextApiConnect = TfirstfreeApiConnectCopyOld;
5089   setApiConTimer(apiConnectptr.i, 0, __LINE__);
5090   regApiPtr->apiConnectstate = CS_RESTART;
5091 }//Dbtc::releaseApiConCopy()
5092 
5093 /* ========================================================================= */
5094 /* -------  RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
5095 /* ========================================================================= */
releaseDirtyWrite(Signal * signal)5096 void Dbtc::releaseDirtyWrite(Signal* signal)
5097 {
5098   unlinkReadyTcCon(signal);
5099   releaseTcCon();
5100   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5101   if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
5102     if (regApiPtr->firstTcConnect == RNIL) {
5103       jam();
5104       regApiPtr->apiConnectstate = CS_CONNECTED;
5105       setApiConTimer(apiConnectptr.i, 0, __LINE__);
5106       sendtckeyconf(signal, 1);
5107     }//if
5108   }//if
5109 }//Dbtc::releaseDirtyWrite()
5110 
5111 /*****************************************************************************
5112  *                               L Q H K E Y R E F
5113  * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
5114  * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
5115  * TCROLLBACKREP WILL BE SENT TO THE API.
5116  *
5117  * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
5118  * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
5119  * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
5120  * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
5121  * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
5122  * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
5123  * "REC_LQHREFUSE",
5124  * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
5125  * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
5126  *****************************************************************************/
execLQHKEYREF(Signal * signal)5127 void Dbtc::execLQHKEYREF(Signal* signal)
5128 {
5129   const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
5130   Uint32 indexId = 0;
5131   jamEntry();
5132 
5133   UintR compare_transid1, compare_transid2;
5134   UintR TtcConnectFilesize = ctcConnectFilesize;
5135   /*-------------------------------------------------------------------------
5136    *
5137    * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
5138    * TRANSACTION PARTS ACTIVE ANYMORE.
5139    * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
5140    *-------------------------------------------------------------------------*/
5141   if (lqhKeyRef->connectPtr < TtcConnectFilesize) {
5142     /*-----------------------------------------------------------------------
5143      * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
5144      * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
5145      * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
5146      * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
5147      * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
5148      * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
5149      * ALREADY COMPLETED (ABORTED).
5150      *-----------------------------------------------------------------------*/
5151     tcConnectptr.i = lqhKeyRef->connectPtr;
5152     Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
5153     ptrAss(tcConnectptr, tcConnectRecord);
5154     TcConnectRecord * const regTcPtr = tcConnectptr.p;
5155     if (regTcPtr->tcConnectstate == OS_OPERATING) {
5156       Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
5157       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
5158       ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5159       compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
5160       compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
5161       compare_transid1 = compare_transid1 | compare_transid2;
5162       if (compare_transid1 != 0) {
5163 	warningReport(signal, 25);
5164 	return;
5165       }//if
5166 
5167       const ConnectionState state = regApiPtr->apiConnectstate;
5168       const Uint32 triggeringOp = regTcPtr->triggeringOperation;
5169       if (triggeringOp != RNIL) {
5170         jam();
5171 	// This operation was created by a trigger execting operation
5172 	TcConnectRecordPtr opPtr;
5173 	TcConnectRecord *localTcConnectRecord = tcConnectRecord;
5174 
5175 	const Uint32 currentIndexId = regTcPtr->currentIndexId;
5176 	ndbassert(currentIndexId != 0); // Only index triggers so far
5177 
5178 	opPtr.i = triggeringOp;
5179 	ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
5180 
5181 	// The operation executed an index trigger
5182         TcIndexData* indexData = c_theIndexes.getPtr(currentIndexId);
5183         indexId = indexData->indexId;
5184         regApiPtr->errorData = indexId;
5185 	const Uint32 opType = regTcPtr->operation;
5186 	if (errCode == ZALREADYEXIST)
5187 	  errCode = terrorCode = ZNOTUNIQUE;
5188 	else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
5189 	  jam();
5190 	  /**
5191 	   * "Normal path"
5192 	   */
5193 	  // fall-through
5194 	} else {
5195 	  jam();
5196 	  /** ZDELETE && NOT_FOUND */
5197 	  if(indexData->indexState == IS_BUILDING && state != CS_ABORTING){
5198 	    jam();
5199 	    /**
5200 	     * Ignore error
5201 	     */
5202 	    regApiPtr->lqhkeyconfrec++;
5203 
5204 	    unlinkReadyTcCon(signal);
5205 	    releaseTcCon();
5206 
5207 	    opPtr.p->triggerExecutionCount--;
5208 	    if (opPtr.p->triggerExecutionCount == 0) {
5209 	      /**
5210 	       * We have completed current trigger execution
5211 	       * Continue triggering operation
5212 	       */
5213 	      jam();
5214 	      continueTriggeringOp(signal, opPtr.p);
5215 	    }
5216 	    return;
5217 	  }
5218 	}
5219       }
5220 
5221       Uint32 marker = regTcPtr->commitAckMarker;
5222       markOperationAborted(regApiPtr, regTcPtr);
5223 
5224       if(regApiPtr->apiConnectstate == CS_ABORTING){
5225 	/**
5226 	 * We're already aborting' so don't send an "extra" TCKEYREF
5227 	 */
5228 	jam();
5229 	return;
5230       }
5231 
5232       const Uint32 abort = regTcPtr->m_execAbortOption;
5233       if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
5234 	/**
5235 	 * No error is allowed on this operation
5236 	 */
5237 	TCKEY_abort(signal, 49);
5238 	return;
5239       }//if
5240 
5241       if (marker != RNIL){
5242 	/**
5243 	 * This was an insert/update/delete/write which failed
5244 	 *   that contained the marker
5245 	 * Currently unsupported to place new marker
5246 	 */
5247 	TCKEY_abort(signal, 49);
5248 	return;
5249       }
5250 
5251       /* Only ref in certain situations */
5252       {
5253 	const Uint32 opType = regTcPtr->operation;
5254 	if (   (opType == ZDELETE && errCode != ZNOT_FOUND)
5255 	    || (opType == ZINSERT && errCode != ZALREADYEXIST)
5256 	    || (opType == ZUPDATE && errCode != ZNOT_FOUND)
5257 	    || (opType == ZWRITE  && errCode != 839 && errCode != 840))
5258 	{
5259 	  TCKEY_abort(signal, 49);
5260 	  return;
5261 	}
5262       }
5263 
5264       /* *************** */
5265       /*    TCKEYREF   < */
5266       /* *************** */
5267       TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
5268       tcKeyRef->transId[0] = regApiPtr->transid[0];
5269       tcKeyRef->transId[1] = regApiPtr->transid[1];
5270       tcKeyRef->errorCode = terrorCode;
5271       bool isIndexOp = regTcPtr->isIndexOp;
5272       Uint32 indexOp = tcConnectptr.p->indexOp;
5273       Uint32 clientData = regTcPtr->clientData;
5274       unlinkReadyTcCon(signal);   /* LINK TC CONNECT RECORD OUT OF  */
5275       releaseTcCon();       /* RELEASE THE TC CONNECT RECORD  */
5276       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5277       if (isIndexOp) {
5278         jam();
5279 	regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
5280 	tcKeyRef->connectPtr = indexOp;
5281         tcKeyRef->errorData = indexId;
5282 	EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
5283 	apiConnectptr.i = save;
5284 	apiConnectptr.p = regApiPtr;
5285       } else {
5286         jam();
5287 	tcKeyRef->connectPtr = clientData;
5288         tcKeyRef->errorData = indexId;
5289 	sendSignal(regApiPtr->ndbapiBlockref,
5290 		   GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
5291       }//if
5292 
5293       /*---------------------------------------------------------------------
5294        * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
5295        * LQHKEYREQ THAT HAVE RETURNED.
5296        * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
5297        * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
5298        *---------------------------------------------------------------------*/
5299       regApiPtr->lqhkeyreqrec--;
5300       if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
5301 	if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
5302           jam();
5303           diverify010Lab(signal);
5304 	  return;
5305 	} else if (regApiPtr->tckeyrec > 0 || regApiPtr->m_exec_flag) {
5306 	  jam();
5307 	  sendtckeyconf(signal, 2);
5308 	  return;
5309 	}
5310       }//if
5311       return;
5312 
5313     } else {
5314       warningReport(signal, 26);
5315     }//if
5316   } else {
5317     errorReport(signal, 6);
5318   }//if
5319   return;
5320 }//Dbtc::execLQHKEYREF()
5321 
clearCommitAckMarker(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)5322 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
5323 				TcConnectRecord * const regTcPtr)
5324 {
5325   const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
5326   if (regApiPtr->commitAckMarker == RNIL)
5327     ndbassert(commitAckMarker == RNIL);
5328   if (commitAckMarker != RNIL)
5329     ndbassert(regApiPtr->commitAckMarker != RNIL);
5330   if(commitAckMarker != RNIL){
5331     jam();
5332     m_commitAckMarkerHash.release(commitAckMarker);
5333     regTcPtr->commitAckMarker = RNIL;
5334     regApiPtr->commitAckMarker = RNIL;
5335   }
5336 }
5337 
markOperationAborted(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)5338 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
5339 				TcConnectRecord * const regTcPtr)
5340 {
5341   /*------------------------------------------------------------------------
5342    * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
5343    * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
5344    * ALREADY COMPLETED.
5345    *------------------------------------------------------------------------*/
5346   regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
5347   regTcPtr->tcConnectstate = OS_ABORTING;
5348   clearCommitAckMarker(regApiPtr, regTcPtr);
5349 }
5350 
5351 /*--------------------------------------*/
5352 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ  */
5353 /* OR TCROLLBACKREQ FROM THE USER TO    */
5354 /* CONTINUE THE TRANSACTION             */
5355 /*--------------------------------------*/
execTC_COMMITREQ(Signal * signal)5356 void Dbtc::execTC_COMMITREQ(Signal* signal)
5357 {
5358   UintR compare_transid1, compare_transid2;
5359 
5360   jamEntry();
5361   apiConnectptr.i = signal->theData[0];
5362   if (apiConnectptr.i < capiConnectFilesize) {
5363     ptrAss(apiConnectptr, apiConnectRecord);
5364     compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
5365     compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
5366     compare_transid1 = compare_transid1 | compare_transid2;
5367     if (compare_transid1 != 0) {
5368       jam();
5369       return;
5370     }//if
5371 
5372     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5373 
5374     const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
5375     const Uint32 apiBlockRef   = regApiPtr->ndbapiBlockref;
5376     const Uint32 transId1      = regApiPtr->transid[0];
5377     const Uint32 transId2      = regApiPtr->transid[1];
5378     Uint32 errorCode           = 0;
5379 
5380     regApiPtr->m_exec_flag = 1;
5381     switch (regApiPtr->apiConnectstate) {
5382     case CS_STARTED:
5383       tcConnectptr.i = regApiPtr->firstTcConnect;
5384       if (tcConnectptr.i != RNIL) {
5385         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
5386         if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
5387           jam();
5388           /*******************************************************************/
5389           // The proper case where the application is waiting for commit or
5390           // abort order.
5391           // Start the commit order.
5392           /*******************************************************************/
5393           regApiPtr->returnsignal = RS_TC_COMMITCONF;
5394           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5395           diverify010Lab(signal);
5396           return;
5397         } else {
5398           jam();
5399           /*******************************************************************/
5400           // The transaction is started but not all operations are completed.
5401           // It is not possible to commit the transaction in this state.
5402           // We will abort it instead.
5403           /*******************************************************************/
5404           regApiPtr->returnsignal = RS_NO_RETURN;
5405           errorCode = ZTRANS_STATUS_ERROR;
5406           abort010Lab(signal);
5407         }//if
5408       } else {
5409         jam();
5410         /**
5411          * No operations, accept commit
5412          */
5413         TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
5414         commitConf->apiConnectPtr = apiConnectPtr;
5415         commitConf->transId1 = transId1;
5416         commitConf->transId2 = transId2;
5417         commitConf->gci = 0;
5418         sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
5419 		   TcCommitConf::SignalLength, JBB);
5420 
5421         regApiPtr->returnsignal = RS_NO_RETURN;
5422         releaseAbortResources(signal);
5423         return;
5424       }//if
5425       break;
5426     case CS_RECEIVING:
5427       jam();
5428       /***********************************************************************/
5429       // A transaction is still receiving data. We cannot commit an unfinished
5430       // transaction. We will abort it instead.
5431       /***********************************************************************/
5432       regApiPtr->returnsignal = RS_NO_RETURN;
5433       errorCode = ZPREPAREINPROGRESS;
5434       abort010Lab(signal);
5435       break;
5436 
5437     case CS_START_COMMITTING:
5438     case CS_COMMITTING:
5439     case CS_COMMIT_SENT:
5440     case CS_COMPLETING:
5441     case CS_COMPLETE_SENT:
5442     case CS_REC_COMMITTING:
5443     case CS_PREPARE_TO_COMMIT:
5444       jam();
5445       /***********************************************************************/
5446       // The transaction is already performing a commit but it is not concluded
5447       // yet.
5448       /***********************************************************************/
5449       errorCode = ZCOMMITINPROGRESS;
5450       break;
5451     case CS_ABORTING:
5452       jam();
5453       errorCode = regApiPtr->returncode ?
5454 	regApiPtr->returncode : ZABORTINPROGRESS;
5455       break;
5456     case CS_START_SCAN:
5457       jam();
5458       /***********************************************************************/
5459       // The transaction is a scan. Scans cannot commit
5460       /***********************************************************************/
5461       errorCode = ZSCANINPROGRESS;
5462       break;
5463     case CS_PREPARED:
5464       jam();
5465       return;
5466     case CS_START_PREPARING:
5467       jam();
5468       return;
5469     case CS_REC_PREPARING:
5470       jam();
5471       return;
5472       break;
5473     default:
5474       warningHandlerLab(signal, __LINE__);
5475       return;
5476     }//switch
5477     TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
5478     commitRef->apiConnectPtr = apiConnectPtr;
5479     commitRef->transId1 = transId1;
5480     commitRef->transId2 = transId2;
5481     commitRef->errorCode = errorCode;
5482     sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
5483 	       TcCommitRef::SignalLength, JBB);
5484     return;
5485   } else /** apiConnectptr.i < capiConnectFilesize */ {
5486     jam();
5487     warningHandlerLab(signal, __LINE__);
5488     return;
5489   }
5490 }//Dbtc::execTC_COMMITREQ()
5491 
5492 /**
5493  * TCROLLBACKREQ
5494  *
5495  * Format is:
5496  *
5497  * thedata[0] = apiconnectptr
5498  * thedata[1] = transid[0]
5499  * thedata[2] = transid[1]
5500  * OPTIONAL thedata[3] = flags
5501  *
5502  * Flags:
5503  *    0x1  =  potentiallyBad data from API (try not to assert)
5504  */
execTCROLLBACKREQ(Signal * signal)5505 void Dbtc::execTCROLLBACKREQ(Signal* signal)
5506 {
5507   bool potentiallyBad= false;
5508   UintR compare_transid1, compare_transid2;
5509 
5510   jamEntry();
5511 
5512   if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
5513   {
5514     ndbout_c("Trying to roll back potentially bad txn\n");
5515     potentiallyBad= true;
5516   }
5517 
5518   apiConnectptr.i = signal->theData[0];
5519   if (apiConnectptr.i >= capiConnectFilesize) {
5520     goto TC_ROLL_warning;
5521   }//if
5522   ptrAss(apiConnectptr, apiConnectRecord);
5523   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
5524   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
5525   compare_transid1 = compare_transid1 | compare_transid2;
5526   if (compare_transid1 != 0) {
5527     jam();
5528     return;
5529   }//if
5530 
5531   apiConnectptr.p->m_exec_flag = 1;
5532   switch (apiConnectptr.p->apiConnectstate) {
5533   case CS_STARTED:
5534   case CS_RECEIVING:
5535     jam();
5536     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
5537     abort010Lab(signal);
5538     return;
5539   case CS_CONNECTED:
5540     jam();
5541     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
5542     signal->theData[1] = apiConnectptr.p->transid[0];
5543     signal->theData[2] = apiConnectptr.p->transid[1];
5544     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
5545 	       signal, 3, JBB);
5546     break;
5547   case CS_START_SCAN:
5548   case CS_PREPARE_TO_COMMIT:
5549   case CS_COMMITTING:
5550   case CS_COMMIT_SENT:
5551   case CS_COMPLETING:
5552   case CS_COMPLETE_SENT:
5553   case CS_WAIT_COMMIT_CONF:
5554   case CS_WAIT_COMPLETE_CONF:
5555   case CS_RESTART:
5556   case CS_DISCONNECTED:
5557   case CS_START_COMMITTING:
5558   case CS_REC_COMMITTING:
5559     jam();
5560     /* ***************< */
5561     /* TC_ROLLBACKREF < */
5562     /* ***************< */
5563     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
5564     signal->theData[1] = apiConnectptr.p->transid[0];
5565     signal->theData[2] = apiConnectptr.p->transid[1];
5566     signal->theData[3] = ZROLLBACKNOTALLOWED;
5567     signal->theData[4] = apiConnectptr.p->apiConnectstate;
5568     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
5569 	       signal, 5, JBB);
5570     break;
5571                                                  /* SEND A REFUSAL SIGNAL*/
5572   case CS_ABORTING:
5573     jam();
5574     if (apiConnectptr.p->abortState == AS_IDLE) {
5575       jam();
5576       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
5577       signal->theData[1] = apiConnectptr.p->transid[0];
5578       signal->theData[2] = apiConnectptr.p->transid[1];
5579       sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
5580 		 signal, 3, JBB);
5581     } else {
5582       jam();
5583       apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
5584     }//if
5585     break;
5586   case CS_WAIT_ABORT_CONF:
5587     jam();
5588     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
5589     break;
5590   case CS_START_PREPARING:
5591     jam();
5592   case CS_PREPARED:
5593     jam();
5594   case CS_REC_PREPARING:
5595     jam();
5596   default:
5597     goto TC_ROLL_system_error;
5598     break;
5599   }//switch
5600   return;
5601 
5602 TC_ROLL_warning:
5603   jam();
5604   if(likely(potentiallyBad==false))
5605     warningHandlerLab(signal, __LINE__);
5606   return;
5607 
5608 TC_ROLL_system_error:
5609   jam();
5610   if(likely(potentiallyBad==false))
5611     systemErrorLab(signal, __LINE__);
5612   return;
5613 }//Dbtc::execTCROLLBACKREQ()
5614 
execTC_HBREP(Signal * signal)5615 void Dbtc::execTC_HBREP(Signal* signal)
5616 {
5617   const TcHbRep * const tcHbRep =
5618     (TcHbRep *)signal->getDataPtr();
5619 
5620   jamEntry();
5621   apiConnectptr.i = tcHbRep->apiConnectPtr;
5622   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
5623 
5624   if (apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
5625       apiConnectptr.p->transid[1] == tcHbRep->transId2){
5626 
5627     if (getApiConTimer(apiConnectptr.i) != 0){
5628       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5629     } else {
5630       DEBUG("TCHBREP received when timer was off apiConnectptr.i="
5631 	    << apiConnectptr.i);
5632     }
5633   }
5634 }//Dbtc::execTCHBREP()
5635 
5636 /*
5637 4.3.15 ABORT
5638 -----------
5639 */
5640 /*****************************************************************************/
5641 /*                                  A B O R T                                */
5642 /*                                                                           */
5643 /*****************************************************************************/
warningReport(Signal * signal,int place)5644 void Dbtc::warningReport(Signal* signal, int place)
5645 {
5646   switch (place) {
5647   case 0:
5648     jam();
5649 #ifdef ABORT_TRACE
5650     ndbout << "ABORTED to not active TC record" << endl;
5651 #endif
5652     break;
5653   case 1:
5654     jam();
5655 #ifdef ABORT_TRACE
5656     ndbout << "ABORTED to TC record active with new transaction" << endl;
5657 #endif
5658     break;
5659   case 2:
5660     jam();
5661 #ifdef ABORT_TRACE
5662     ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
5663 #endif
5664     break;
5665   case 3:
5666     jam();
5667 #ifdef ABORT_TRACE
5668     ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
5669     ndbout << "This is ok when aborting in node failure situations" << endl;
5670 #endif
5671     break;
5672   case 4:
5673     jam();
5674 #ifdef ABORT_TRACE
5675     ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
5676 #endif
5677     break;
5678   case 5:
5679     jam();
5680 #ifdef ABORT_TRACE
5681     ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
5682 #endif
5683     break;
5684   case 6:
5685     jam();
5686 #ifdef ABORT_TRACE
5687     ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
5688 #endif
5689     break;
5690   case 7:
5691     jam();
5692 #ifdef ABORT_TRACE
5693     ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
5694 #endif
5695     break;
5696   case 8:
5697     jam();
5698 #ifdef ABORT_TRACE
5699     ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
5700 #endif
5701     break;
5702   case 9:
5703     jam();
5704 #ifdef ABORT_TRACE
5705     ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
5706 #endif
5707     break;
5708   case 10:
5709     jam();
5710 #ifdef ABORT_TRACE
5711     ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
5712 #endif
5713     break;
5714   case 11:
5715     jam();
5716 #ifdef ABORT_TRACE
5717     ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
5718 #endif
5719     break;
5720   case 12:
5721     jam();
5722 #ifdef ABORT_TRACE
5723     ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
5724 #endif
5725     break;
5726   case 13:
5727     jam();
5728 #ifdef ABORT_TRACE
5729     ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
5730 #endif
5731     break;
5732   case 14:
5733     jam();
5734 #ifdef ABORT_TRACE
5735     ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
5736 #endif
5737     break;
5738   case 15:
5739     jam();
5740 #ifdef ABORT_TRACE
5741     ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
5742 #endif
5743     break;
5744   case 16:
5745     jam();
5746 #ifdef ABORT_TRACE
5747     ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
5748 #endif
5749     break;
5750   case 17:
5751     jam();
5752 #ifdef ABORT_TRACE
5753     ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
5754 #endif
5755     break;
5756   case 18:
5757     jam();
5758 #ifdef ABORT_TRACE
5759     ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
5760 #endif
5761     break;
5762   case 19:
5763     jam();
5764 #ifdef ABORT_TRACE
5765     ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
5766 #endif
5767     break;
5768   case 20:
5769     jam();
5770 #ifdef ABORT_TRACE
5771     ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
5772 #endif
5773     break;
5774   case 21:
5775     jam();
5776 #ifdef ABORT_TRACE
5777     ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
5778 #endif
5779     break;
5780   case 22:
5781     jam();
5782 #ifdef ABORT_TRACE
5783     ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
5784 #endif
5785     break;
5786   case 23:
5787     jam();
5788 #ifdef ABORT_TRACE
5789     ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
5790 #endif
5791     break;
5792   case 24:
5793     jam();
5794 #ifdef ABORT_TRACE
5795     ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
5796 #endif
5797     break;
5798   case 25:
5799     jam();
5800 #ifdef ABORT_TRACE
5801     ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
5802 #endif
5803     break;
5804   case 26:
5805     jam();
5806 #ifdef ABORT_TRACE
5807     ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
5808 #endif
5809     break;
5810   case 27:
5811     jam();
5812     // printState(signal, 27);
5813 #ifdef ABORT_TRACE
5814     ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
5815 #endif
5816     break;
5817   default:
5818     jam();
5819     break;
5820   }//switch
5821   return;
5822 }//Dbtc::warningReport()
5823 
errorReport(Signal * signal,int place)5824 void Dbtc::errorReport(Signal* signal, int place)
5825 {
5826   switch (place) {
5827   case 0:
5828     jam();
5829     break;
5830   case 1:
5831     jam();
5832     break;
5833   case 2:
5834     jam();
5835     break;
5836   case 3:
5837     jam();
5838     break;
5839   case 4:
5840     jam();
5841     break;
5842   case 5:
5843     jam();
5844     break;
5845   case 6:
5846     jam();
5847     break;
5848   default:
5849     jam();
5850     break;
5851   }//switch
5852   systemErrorLab(signal, __LINE__);
5853   return;
5854 }//Dbtc::errorReport()
5855 
5856 /* ------------------------------------------------------------------------- */
5857 /* -------                       ENTER ABORTED                       ------- */
5858 /*                                                                           */
5859 /*-------------------------------------------------------------------------- */
execABORTED(Signal * signal)5860 void Dbtc::execABORTED(Signal* signal)
5861 {
5862   UintR compare_transid1, compare_transid2;
5863 
5864   jamEntry();
5865   tcConnectptr.i = signal->theData[0];
5866   UintR Tnodeid = signal->theData[3];
5867   UintR TlastLqhInd = signal->theData[4];
5868 
5869   if (ERROR_INSERTED(8040)) {
5870     CLEAR_ERROR_INSERT_VALUE;
5871     sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
5872     return;
5873   }//if
5874   /*------------------------------------------------------------------------
5875    *    ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
5876    *------------------------------------------------------------------------*/
5877   if (tcConnectptr.i >= ctcConnectFilesize) {
5878     errorReport(signal, 0);
5879     return;
5880   }//if
5881   /*-------------------------------------------------------------------------
5882    *     WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
5883    *     TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
5884    *     IN TC WAITING FOR ABORTED.
5885    *-------------------------------------------------------------------------*/
5886   ptrAss(tcConnectptr, tcConnectRecord);
5887   if (tcConnectptr.p->tcConnectstate != OS_ABORT_SENT) {
5888     warningReport(signal, 2);
5889     return;
5890     /*-----------------------------------------------------------------------*/
5891     // ABORTED reported on an operation not expecting ABORT.
5892     /*-----------------------------------------------------------------------*/
5893   }//if
5894   apiConnectptr.i = tcConnectptr.p->apiConnect;
5895   if (apiConnectptr.i >= capiConnectFilesize) {
5896     warningReport(signal, 0);
5897     return;
5898   }//if
5899   ptrAss(apiConnectptr, apiConnectRecord);
5900   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
5901   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
5902   compare_transid1 = compare_transid1 | compare_transid2;
5903   if (compare_transid1 != 0) {
5904     warningReport(signal, 1);
5905     return;
5906   }//if
5907   if (ERROR_INSERTED(8024)) {
5908     jam();
5909     systemErrorLab(signal, __LINE__);
5910   }//if
5911 
5912   /**
5913    * Release marker
5914    */
5915   clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
5916 
5917   Uint32 i;
5918   Uint32 Tfound = 0;
5919   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
5920     jam();
5921     if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
5922       /*---------------------------------------------------------------------
5923        * We have received ABORTED from one of the participants in this
5924        * operation in this aborted transaction.
5925        * Record all nodes that have completed abort.
5926        * If last indicator is set it means that no more replica has
5927        * heard of the operation and are thus also aborted.
5928        *---------------------------------------------------------------------*/
5929       jam();
5930       Tfound = 1;
5931       clearTcNodeData(signal, TlastLqhInd, i);
5932     }//if
5933   }//for
5934   if (Tfound == 0) {
5935     warningReport(signal, 3);
5936     return;
5937   }
5938   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
5939     if (tcConnectptr.p->tcNodedata[i] != 0) {
5940       /*--------------------------------------------------------------------
5941        * There are still outstanding ABORTED's to wait for.
5942        *--------------------------------------------------------------------*/
5943       jam();
5944       return;
5945     }//if
5946   }//for
5947   tcConnectptr.p->noOfNodes = 0;
5948   tcConnectptr.p->tcConnectstate = OS_ABORTING;
5949   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
5950   apiConnectptr.p->counter--;
5951   if (apiConnectptr.p->counter > 0) {
5952     jam();
5953     /*----------------------------------------------------------------------
5954      *       WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
5955      *----------------------------------------------------------------------*/
5956     return;
5957   }//if
5958   /*------------------------------------------------------------------------*/
5959   /*                                                                        */
5960   /*     WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED  */
5961   /*     FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL   */
5962   /*     RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
5963   /*------------------------------------------------------------------------*/
5964   releaseAbortResources(signal);
5965 }//Dbtc::execABORTED()
5966 
clearTcNodeData(Signal * signal,UintR TLastLqhIndicator,UintR Tstart)5967 void Dbtc::clearTcNodeData(Signal* signal,
5968                            UintR TLastLqhIndicator,
5969                            UintR Tstart)
5970 {
5971   UintR Ti;
5972   if (TLastLqhIndicator == ZTRUE) {
5973     for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
5974       jam();
5975       tcConnectptr.p->tcNodedata[Ti] = 0;
5976     }//for
5977   } else {
5978     jam();
5979     tcConnectptr.p->tcNodedata[Tstart] = 0;
5980   }//for
5981 }//clearTcNodeData()
5982 
abortErrorLab(Signal * signal)5983 void Dbtc::abortErrorLab(Signal* signal)
5984 {
5985   ptrGuard(apiConnectptr);
5986   ApiConnectRecord * transP = apiConnectptr.p;
5987   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
5988     jam();
5989     return;
5990   }
5991   transP->returnsignal = RS_TCROLLBACKREP;
5992   if(transP->returncode == 0){
5993     jam();
5994     transP->returncode = terrorCode;
5995   }
5996   abort010Lab(signal);
5997 }//Dbtc::abortErrorLab()
5998 
abort010Lab(Signal * signal)5999 void Dbtc::abort010Lab(Signal* signal)
6000 {
6001   ApiConnectRecord * transP = apiConnectptr.p;
6002   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
6003     jam();
6004     return;
6005   }
6006   transP->apiConnectstate = CS_ABORTING;
6007   /*------------------------------------------------------------------------*/
6008   /*     AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
6009   /*     ALL PARTICIPANTS IN THE TRANSACTION.                               */
6010   /*------------------------------------------------------------------------*/
6011   transP->abortState = AS_ACTIVE;
6012   transP->counter = 0;
6013 
6014   if (transP->firstTcConnect == RNIL) {
6015     jam();
6016     /*--------------------------------------------------------------------*/
6017     /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION.                        */
6018     /*--------------------------------------------------------------------*/
6019     releaseAbortResources(signal);
6020     return;
6021   }//if
6022   tcConnectptr.i = transP->firstTcConnect;
6023   abort015Lab(signal);
6024 }//Dbtc::abort010Lab()
6025 
6026 /*--------------------------------------------------------------------------*/
6027 /*                                                                          */
6028 /*       WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP    */
6029 /*       ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE.        */
6030 /*       EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE   */
6031 /*       MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES    */
6032 /*       NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
6033 /*       WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
6034 /*--------------------------------------------------------------------------*/
abort015Lab(Signal * signal)6035 void Dbtc::abort015Lab(Signal* signal)
6036 {
6037   Uint32 TloopCount = 0;
6038 ABORT020:
6039   jam();
6040   TloopCount++;
6041   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6042   switch (tcConnectptr.p->tcConnectstate) {
6043   case OS_WAIT_DIH:
6044   case OS_WAIT_KEYINFO:
6045   case OS_WAIT_ATTR:
6046     jam();
6047     /*----------------------------------------------------------------------*/
6048     /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
6049     /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING.              */
6050     /*----------------------------------------------------------------------*/
6051     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
6052     tcConnectptr.p->tcConnectstate = OS_ABORTING;
6053     break;
6054   case OS_CONNECTED:
6055     jam();
6056     /*-----------------------------------------------------------------------
6057      *   WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
6058      *   NEED NOT BOTHER ABOUT ANY LQH ABORTS.
6059      *-----------------------------------------------------------------------*/
6060     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
6061     tcConnectptr.p->tcConnectstate = OS_ABORTING;
6062     break;
6063   case OS_PREPARED:
6064     jam();
6065   case OS_OPERATING:
6066     jam();
6067     /*----------------------------------------------------------------------
6068      * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
6069      * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
6070      * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
6071      *----------------------------------------------------------------------*/
6072     releaseAndAbort(signal);
6073     tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
6074     TloopCount += 127;
6075     break;
6076   case OS_ABORTING:
6077     jam();
6078     break;
6079   case OS_ABORT_SENT:
6080     jam();
6081     DEBUG("ABORT_SENT state in abort015Lab(), not expected");
6082     systemErrorLab(signal, __LINE__);
6083     return;
6084   default:
6085     jam();
6086     DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
6087     systemErrorLab(signal, __LINE__);
6088     return;
6089   }//switch
6090 
6091   if (tcConnectptr.p->nextTcConnect != RNIL) {
6092     jam();
6093     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
6094     if (TloopCount < 1024) {
6095       goto ABORT020;
6096     } else {
6097       jam();
6098       /*---------------------------------------------------------------------
6099        * Reset timer to avoid time-out in real-time break.
6100        * Increase counter to ensure that we don't think that all ABORTED have
6101        * been received before all have been sent.
6102        *---------------------------------------------------------------------*/
6103       apiConnectptr.p->counter++;
6104       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6105       signal->theData[0] = TcContinueB::ZABORT_BREAK;
6106       signal->theData[1] = tcConnectptr.i;
6107       signal->theData[2] = apiConnectptr.i;
6108       sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
6109       return;
6110     }//if
6111   }//if
6112   if (apiConnectptr.p->counter > 0) {
6113     jam();
6114     setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6115     return;
6116   }//if
6117   /*-----------------------------------------------------------------------
6118    *    WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
6119    *    FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
6120    *    RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
6121    *------------------------------------------------------------------------*/
6122   releaseAbortResources(signal);
6123 }//Dbtc::abort015Lab()
6124 
6125 /*--------------------------------------------------------------------------*/
6126 /*       RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK.  */
6127 /*--------------------------------------------------------------------------*/
releaseAndAbort(Signal * signal)6128 int Dbtc::releaseAndAbort(Signal* signal)
6129 {
6130   HostRecordPtr localHostptr;
6131   UintR TnoLoops = tcConnectptr.p->noOfNodes;
6132 
6133   apiConnectptr.p->counter++;
6134   bool prevAlive = false;
6135   for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
6136     localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
6137     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
6138     if (localHostptr.p->hostStatus == HS_ALIVE) {
6139       jam();
6140       if (prevAlive) {
6141         // if previous is alive, its LQH forwards abort to this node
6142         jam();
6143         continue;
6144       }
6145       /* ************< */
6146       /*    ABORT    < */
6147       /* ************< */
6148       tblockref = calcLqhBlockRef(localHostptr.i);
6149       signal->theData[0] = tcConnectptr.i;
6150       signal->theData[1] = cownref;
6151       signal->theData[2] = apiConnectptr.p->transid[0];
6152       signal->theData[3] = apiConnectptr.p->transid[1];
6153       sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
6154       prevAlive = true;
6155     } else {
6156       jam();
6157       signal->theData[0] = tcConnectptr.i;
6158       signal->theData[1] = apiConnectptr.p->transid[0];
6159       signal->theData[2] = apiConnectptr.p->transid[1];
6160       signal->theData[3] = localHostptr.i;
6161       signal->theData[4] = ZFALSE;
6162       sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
6163       prevAlive = false;
6164     }//if
6165   }//for
6166   return 1;
6167 }//Dbtc::releaseAndAbort()
6168 
6169 /* ------------------------------------------------------------------------- */
6170 /* -------                       ENTER TIME_SIGNAL                   ------- */
6171 /*                                                                           */
6172 /* ------------------------------------------------------------------------- */
execTIME_SIGNAL(Signal * signal)6173 void Dbtc::execTIME_SIGNAL(Signal* signal)
6174 {
6175 
6176   jamEntry();
6177   ctcTimer++;
6178   if (csystemStart != SSS_TRUE) {
6179     jam();
6180     return;
6181   }//if
6182   checkStartTimeout(signal);
6183   checkStartFragTimeout(signal);
6184 }//Dbtc::execTIME_SIGNAL()
6185 
6186 /*------------------------------------------------*/
6187 /* Start timeout handling if not already going on */
6188 /*------------------------------------------------*/
checkStartTimeout(Signal * signal)6189 void Dbtc::checkStartTimeout(Signal* signal)
6190 {
6191   ctimeOutCheckCounter++;
6192   if (ctimeOutCheckActive == TOCS_TRUE) {
6193     jam();
6194     // Check heartbeat of timeout loop
6195     if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
6196       jam();
6197       ctimeOutMissedHeartbeats = 0;
6198     }else{
6199       jam();
6200       ctimeOutMissedHeartbeats++;
6201       if (ctimeOutMissedHeartbeats > 100){
6202 	jam();
6203 	systemErrorLab(signal, __LINE__);
6204       }
6205     }
6206     ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
6207     return;
6208   }//if
6209   if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
6210     jam();
6211     /*------------------------------------------------------------------*/
6212     /*                                                                  */
6213     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
6214     /*------------------------------------------------------------------*/
6215     return;
6216   }//if
6217   ctimeOutCheckActive = TOCS_TRUE;
6218   ctimeOutCheckCounter = 0;
6219   timeOutLoopStartLab(signal, 0); // 0 is first api connect record
6220   return;
6221 }//Dbtc::execTIME_SIGNAL()
6222 
6223 /*----------------------------------------------------------------*/
6224 /* Start fragment (scan) timeout handling if not already going on */
6225 /*----------------------------------------------------------------*/
checkStartFragTimeout(Signal * signal)6226 void Dbtc::checkStartFragTimeout(Signal* signal)
6227 {
6228   ctimeOutCheckFragCounter++;
6229   if (ctimeOutCheckFragActive == TOCS_TRUE) {
6230     jam();
6231     return;
6232   }//if
6233   if (ctimeOutCheckFragCounter < ctimeOutCheckDelay) {
6234     jam();
6235     /*------------------------------------------------------------------*/
6236     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
6237     /*------------------------------------------------------------------*/
6238     return;
6239   }//if
6240 
6241   // Go through the fragment records and look for timeout in a scan.
6242   ctimeOutCheckFragActive = TOCS_TRUE;
6243   ctimeOutCheckFragCounter = 0;
6244   timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
6245 }//checkStartFragTimeout()
6246 
6247 /*------------------------------------------------------------------*/
6248 /*       IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE      */
6249 /*       BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM     */
6250 /*       SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM  */
6251 /*       THE WAITING PART OF A PROTOCOL.                            */
6252 /*
6253 The algorithm used here is to check 1024 transactions at a time before
6254 doing a real-time break.
6255 To avoid aborting both transactions in a deadlock detected by time-out
6256 we insert a random extra time-out of upto 630 ms by using the lowest
6257 six bits of the api connect reference.
6258 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
6259 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
6260 and otherwise we spread it out 310 ms.
6261 */
6262 /*------------------------------------------------------------------*/
timeOutLoopStartLab(Signal * signal,Uint32 api_con_ptr)6263 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_ptr)
6264 {
6265   Uint32 end_ptr, time_passed, time_out_value, mask_value;
6266   Uint32 old_mask_value= 0;
6267   const Uint32 api_con_sz= capiConnectFilesize;
6268   const Uint32 tc_timer= ctcTimer;
6269   const Uint32 time_out_param= ctimeOutValue;
6270   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
6271 
6272   ctimeOutCheckHeartbeat = tc_timer;
6273 
6274   if (api_con_ptr + 1024 < api_con_sz) {
6275     jam();
6276     end_ptr= api_con_ptr + 1024;
6277   } else {
6278     jam();
6279     end_ptr= api_con_sz;
6280   }
6281   if (time_out_param > 300) {
6282     jam();
6283     mask_value= 63;
6284   } else if (time_out_param < 30) {
6285     jam();
6286     mask_value= 7;
6287   } else {
6288     jam();
6289     mask_value= 31;
6290   }
6291   if (time_out_param != old_time_out_param &&
6292       getNodeState().getSingleUserMode())
6293   {
6294     // abort during single user mode, use old_mask_value as flag
6295     // and calculate value to be used for connections with allowed api
6296     if (old_time_out_param > 300) {
6297       jam();
6298       old_mask_value= 63;
6299     } else if (old_time_out_param < 30) {
6300       jam();
6301       old_mask_value= 7;
6302     } else {
6303       jam();
6304       old_mask_value= 31;
6305     }
6306   }
6307   for ( ; api_con_ptr < end_ptr; api_con_ptr++) {
6308     Uint32 api_timer= getApiConTimer(api_con_ptr);
6309     jam();
6310     if (api_timer != 0) {
6311       Uint32 error= ZTIME_OUT_ERROR;
6312       time_out_value= time_out_param + (ndb_rand() & mask_value);
6313       if (unlikely(old_mask_value)) // abort during single user mode
6314       {
6315         apiConnectptr.i = api_con_ptr;
6316         ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6317         if ((getNodeState().getSingleUserApi() ==
6318              refToNode(apiConnectptr.p->ndbapiBlockref)) ||
6319             !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
6320         {
6321           // api allowed during single user, use original timeout
6322           time_out_value=
6323             old_time_out_param + (api_con_ptr & old_mask_value);
6324         }
6325         else
6326         {
6327           error= ZCLUSTER_IN_SINGLEUSER_MODE;
6328         }
6329       }
6330       time_passed= tc_timer - api_timer;
6331       if (time_passed > time_out_value)
6332       {
6333         jam();
6334         timeOutFoundLab(signal, api_con_ptr, error);
6335 	api_con_ptr++;
6336 	break;
6337       }
6338     }
6339   }
6340   if (api_con_ptr == api_con_sz) {
6341     jam();
6342     /*------------------------------------------------------------------*/
6343     /*                                                                  */
6344     /*       WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
6345     /*       STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW    */
6346     /*       READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK.            */
6347     /*------------------------------------------------------------------*/
6348     ctimeOutCheckActive = TOCS_FALSE;
6349   } else {
6350     jam();
6351     sendContinueTimeOutControl(signal, api_con_ptr);
6352   }
6353   return;
6354 }//Dbtc::timeOutLoopStartLab()
6355 
timeOutFoundLab(Signal * signal,Uint32 TapiConPtr,Uint32 errCode)6356 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
6357 {
6358   apiConnectptr.i = TapiConPtr;
6359   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6360   /*------------------------------------------------------------------*/
6361   /*                                                                  */
6362   /*       THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
6363   /*       FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
6364   /*------------------------------------------------------------------*/
6365   DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
6366 	<< " H'" << apiConnectptr.p->transid[1] << "] " << dec
6367 	<< "Time-out in state = " << apiConnectptr.p->apiConnectstate
6368 	<< " apiConnectptr.i = " << apiConnectptr.i
6369 	<< " - exec: " << apiConnectptr.p->m_exec_flag
6370 	<< " - place: " << c_apiConTimer_line[apiConnectptr.i]
6371 	<< " code: " << errCode);
6372   switch (apiConnectptr.p->apiConnectstate) {
6373   case CS_STARTED:
6374     if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
6375        errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
6376       jam();
6377       /*
6378       We are waiting for application to continue the transaction. In this
6379       particular state we will use the application timeout parameter rather
6380       than the shorter Deadlock detection timeout.
6381       */
6382       if (c_appl_timeout_value == 0 ||
6383           (ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
6384         jam();
6385         return;
6386       }//if
6387     }
6388     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
6389     apiConnectptr.p->returncode = errCode;
6390     abort010Lab(signal);
6391     return;
6392   case CS_RECEIVING:
6393   case CS_REC_COMMITTING:
6394   case CS_START_COMMITTING:
6395     jam();
6396     /*------------------------------------------------------------------*/
6397     /*       WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS  */
6398     /*       NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO     */
6399     /*       START ABORTING THE TRANSACTION. ALSO START CHECKING THE    */
6400     /*       REMAINING TRANSACTIONS.                                    */
6401     /*------------------------------------------------------------------*/
6402     terrorCode = errCode;
6403     abortErrorLab(signal);
6404     return;
6405   case CS_COMMITTING:
6406     jam();
6407     /*------------------------------------------------------------------*/
6408     // We are simply waiting for a signal in the job buffer. Only extreme
6409     // conditions should get us here. We ignore it.
6410     /*------------------------------------------------------------------*/
6411   case CS_COMPLETING:
6412     jam();
6413     /*------------------------------------------------------------------*/
6414     // We are simply waiting for a signal in the job buffer. Only extreme
6415     // conditions should get us here. We ignore it.
6416     /*------------------------------------------------------------------*/
6417   case CS_PREPARE_TO_COMMIT:
6418   {
6419     jam();
6420     /*------------------------------------------------------------------*/
6421     /*       WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
6422     /*       KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO.  */
6423     /*       IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE.  */
6424     // To ensure against strange bugs we crash the system if we have passed
6425     // time-out period by a factor of 10 and it is also at least 5 seconds.
6426     /*------------------------------------------------------------------*/
6427     Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr.i);
6428     if (time_passed > 500 &&
6429         time_passed > (5 * cDbHbInterval) &&
6430         time_passed > (10 * ctimeOutValue))
6431     {
6432       jam();
6433       systemErrorLab(signal, __LINE__);
6434     }//if
6435     break;
6436   }
6437   case CS_COMMIT_SENT:
6438     jam();
6439     /*------------------------------------------------------------------*/
6440     /*       WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
6441     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE   */
6442     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL  */
6443     /*       TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO   */
6444     /*       A NODE FAILURE.                                            */
6445     /*------------------------------------------------------------------*/
6446     tabortInd = ZCOMMIT_SETUP;
6447     setupFailData(signal);
6448     toCommitHandlingLab(signal);
6449     return;
6450   case CS_COMPLETE_SENT:
6451     jam();
6452     /*--------------------------------------------------------------------*/
6453     /*       WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
6454     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE     */
6455     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL  */
6456     /*       TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO   */
6457     /*       A NODE FAILURE.                                              */
6458     /*--------------------------------------------------------------------*/
6459     tabortInd = ZCOMMIT_SETUP;
6460     setupFailData(signal);
6461     toCompleteHandlingLab(signal);
6462     return;
6463   case CS_ABORTING:
6464     jam();
6465     /*------------------------------------------------------------------*/
6466     /*       TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL     */
6467     /*       NODES THAT HAVE FAILED BEFORE SENDING ABORTED.             */
6468     /*------------------------------------------------------------------*/
6469     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
6470     sendAbortedAfterTimeout(signal, 0);
6471     break;
6472   case CS_START_SCAN:{
6473     jam();
6474 
6475     /*
6476       We are waiting for application to continue the transaction. In this
6477       particular state we will use the application timeout parameter rather
6478       than the shorter Deadlock detection timeout.
6479     */
6480     if (c_appl_timeout_value == 0 ||
6481 	(ctcTimer - getApiConTimer(apiConnectptr.i)) <= c_appl_timeout_value) {
6482       jam();
6483       return;
6484     }//if
6485 
6486     ScanRecordPtr scanPtr;
6487     scanPtr.i = apiConnectptr.p->apiScanRec;
6488     ptrCheckGuard(scanPtr, cscanrecFileSize, scanRecord);
6489     scanError(signal, scanPtr, ZSCANTIME_OUT_ERROR);
6490     break;
6491   }
6492   case CS_WAIT_ABORT_CONF:
6493     jam();
6494     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
6495     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6496     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
6497     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
6498     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6499     if (hostptr.p->hostStatus == HS_ALIVE) {
6500       /*------------------------------------------------------------------*/
6501       // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
6502       // case.
6503       /*------------------------------------------------------------------*/
6504       warningReport(signal, 20);
6505       apiConnectptr.p->timeOutCounter++;
6506       if (apiConnectptr.p->timeOutCounter > 3) {
6507 	/*------------------------------------------------------------------*/
6508 	// 100 time-outs are not acceptable. We will shoot down the node
6509 	// not responding.
6510 	/*------------------------------------------------------------------*/
6511         reportNodeFailed(signal, hostptr.i);
6512       }//if
6513       apiConnectptr.p->currentReplicaNo++;
6514     }//if
6515     tcurrentReplicaNo = (Uint8)Z8NIL;
6516     toAbortHandlingLab(signal);
6517     return;
6518   case CS_WAIT_COMMIT_CONF:
6519     jam();
6520     CRASH_INSERTION(8053);
6521     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
6522     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6523     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
6524     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
6525     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6526     if (hostptr.p->hostStatus == HS_ALIVE) {
6527       /*------------------------------------------------------------------*/
6528       // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
6529       // case.
6530       /*------------------------------------------------------------------*/
6531       warningReport(signal, 21);
6532       apiConnectptr.p->timeOutCounter++;
6533       if (apiConnectptr.p->timeOutCounter > 3) {
6534 	/*------------------------------------------------------------------*/
6535 	// 100 time-outs are not acceptable. We will shoot down the node
6536 	// not responding.
6537 	/*------------------------------------------------------------------*/
6538         reportNodeFailed(signal, hostptr.i);
6539       }//if
6540       apiConnectptr.p->currentReplicaNo++;
6541     }//if
6542     tcurrentReplicaNo = (Uint8)Z8NIL;
6543     toCommitHandlingLab(signal);
6544     return;
6545   case CS_WAIT_COMPLETE_CONF:
6546     jam();
6547     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
6548     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6549     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
6550     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
6551     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6552     if (hostptr.p->hostStatus == HS_ALIVE) {
6553       /*------------------------------------------------------------------*/
6554       // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
6555       // just in case.
6556       /*------------------------------------------------------------------*/
6557       warningReport(signal, 22);
6558       apiConnectptr.p->timeOutCounter++;
6559       if (apiConnectptr.p->timeOutCounter > 100) {
6560 	/*------------------------------------------------------------------*/
6561 	// 100 time-outs are not acceptable. We will shoot down the node
6562 	// not responding.
6563 	/*------------------------------------------------------------------*/
6564         reportNodeFailed(signal, hostptr.i);
6565       }//if
6566       apiConnectptr.p->currentReplicaNo++;
6567     }//if
6568     tcurrentReplicaNo = (Uint8)Z8NIL;
6569     toCompleteHandlingLab(signal);
6570     return;
6571   case CS_FAIL_PREPARED:
6572     jam();
6573   case CS_FAIL_COMMITTING:
6574     jam();
6575   case CS_FAIL_COMMITTED:
6576     jam();
6577   case CS_REC_PREPARING:
6578     jam();
6579   case CS_START_PREPARING:
6580     jam();
6581   case CS_PREPARED:
6582     jam();
6583   case CS_RESTART:
6584     jam();
6585   case CS_FAIL_ABORTED:
6586     jam();
6587   case CS_DISCONNECTED:
6588     jam();
6589   default:
6590     jam();
6591     /*------------------------------------------------------------------*/
6592     /*       AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM.              */
6593     /*------------------------------------------------------------------*/
6594     DEBUG("State = " << apiConnectptr.p->apiConnectstate);
6595     systemErrorLab(signal, __LINE__);
6596     return;
6597   }//switch
6598   return;
6599 }//Dbtc::timeOutFoundLab()
6600 
sendAbortedAfterTimeout(Signal * signal,int Tcheck)6601 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck)
6602 {
6603   ApiConnectRecord * transP = apiConnectptr.p;
6604   if(transP->abortState == AS_IDLE){
6605     jam();
6606     warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
6607 		 __LINE__,
6608 		 apiConnectptr.i,
6609 		 transP->apiConnectstate,
6610 		 c_apiConTimer_line[apiConnectptr.i],
6611 		 transP->firstTcConnect,
6612 		 c_apiConTimer[apiConnectptr.i]
6613 		 );
6614     ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
6615 	     __LINE__,
6616 	     apiConnectptr.i,
6617 	     transP->apiConnectstate,
6618 	     c_apiConTimer_line[apiConnectptr.i],
6619 	     transP->firstTcConnect,
6620 	     c_apiConTimer[apiConnectptr.i]
6621 	     );
6622     ndbrequire(false);
6623     setApiConTimer(apiConnectptr.i, 0, __LINE__);
6624     return;
6625   }
6626 
6627   bool found = false;
6628   OperationState tmp[16];
6629 
6630   Uint32 TloopCount = 0;
6631   do {
6632     jam();
6633     if (tcConnectptr.i == RNIL) {
6634       jam();
6635 
6636 #ifdef VM_TRACE
6637       ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
6638 	       found, Tcheck, apiConnectptr.p->counter);
6639 #endif
6640       if (found || apiConnectptr.p->counter)
6641       {
6642 	jam();
6643 	/**
6644 	 * We sent atleast one ABORT/ABORTED
6645 	 *   or ZABORT_TIMEOUT_BREAK is in job buffer
6646 	 *   wait for reception...
6647 	 */
6648 	return;
6649       }
6650 
6651       if (Tcheck == 1)
6652       {
6653 	jam();
6654 	releaseAbortResources(signal);
6655 	return;
6656       }
6657 
6658       if (Tcheck == 0)
6659       {
6660         jam();
6661 	/*------------------------------------------------------------------
6662 	 * All nodes had already reported ABORTED for all tcConnect records.
6663 	 * Crash since it is an error situation that we then received a
6664 	 * time-out.
6665 	 *------------------------------------------------------------------*/
6666 	char buf[96]; buf[0] = 0;
6667 	char buf2[96];
6668 	BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
6669 			     __LINE__, apiConnectptr.i,
6670 			     apiConnectptr.p->counter);
6671 	for(Uint32 i = 0; i<TloopCount; i++)
6672 	{
6673 	  BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
6674 	  BaseString::snprintf(buf, sizeof(buf), buf2);
6675 	}
6676 	warningEvent(buf);
6677 	ndbout_c(buf);
6678 	ndbrequire(false);
6679 	releaseAbortResources(signal);
6680 	return;
6681       }
6682 
6683       return;
6684     }//if
6685     TloopCount++;
6686     if (TloopCount >= 1024) {
6687       jam();
6688       /*------------------------------------------------------------------*/
6689       // Insert a real-time break for large transactions to avoid blowing
6690       // away the job buffer.
6691       /*------------------------------------------------------------------*/
6692       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6693       apiConnectptr.p->counter++;
6694       signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
6695       signal->theData[1] = tcConnectptr.i;
6696       signal->theData[2] = apiConnectptr.i;
6697       if (ERROR_INSERTED(8050))
6698       {
6699 	ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
6700 		 Tcheck, apiConnectptr.p->counter);
6701 	sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
6702       }
6703       else
6704       {
6705 	sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
6706       }
6707       return;
6708     }//if
6709     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
6710     if(TloopCount < 16){
6711       jam();
6712       tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
6713     }
6714 
6715     if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
6716       jam();
6717       /*------------------------------------------------------------------*/
6718       // We have sent an ABORT signal to this node but not yet received any
6719       // reply. We have to send an ABORTED signal on our own in some cases.
6720       // If the node is declared as up and running and still do not respond
6721       // in time to the ABORT signal we will declare it as dead.
6722       /*------------------------------------------------------------------*/
6723       UintR Ti = 0;
6724       arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
6725       for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
6726         jam();
6727         if (tcConnectptr.p->tcNodedata[Ti] != 0) {
6728           TloopCount += 31;
6729 	  found = true;
6730           hostptr.i = tcConnectptr.p->tcNodedata[Ti];
6731           ptrCheckGuard(hostptr, chostFilesize, hostRecord);
6732           if (hostptr.p->hostStatus == HS_ALIVE) {
6733             jam();
6734 	    /*---------------------------------------------------------------
6735 	     * A backup replica has not sent ABORTED.
6736 	     * Could be that a node before him has crashed.
6737 	     * Send an ABORT signal specifically to this node.
6738 	     * We will not send to any more nodes after this
6739 	     * to avoid race problems.
6740 	     * To also ensure that we use this message also as a heartbeat
6741 	     * we will move this node to the primary replica seat.
6742 	     * The primary replica and any failed node after it will
6743 	     * be removed from the node list. Update also number of nodes.
6744 	     * Finally break the loop to ensure we don't mess
6745 	     * things up by executing another loop.
6746 	     * We also update the timer to ensure we don't get time-out
6747 	     * too early.
6748 	     *--------------------------------------------------------------*/
6749             BlockReference TBRef = calcLqhBlockRef(hostptr.i);
6750             signal->theData[0] = tcConnectptr.i;
6751             signal->theData[1] = cownref;
6752             signal->theData[2] = apiConnectptr.p->transid[0];
6753             signal->theData[3] = apiConnectptr.p->transid[1];
6754             sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
6755             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6756             break;
6757           } else {
6758             jam();
6759 	    /*--------------------------------------------------------------
6760 	     * The node we are waiting for is dead. We will send ABORTED to
6761 	     * ourselves vicarious for the failed node.
6762 	     *--------------------------------------------------------------*/
6763             setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
6764             signal->theData[0] = tcConnectptr.i;
6765             signal->theData[1] = apiConnectptr.p->transid[0];
6766             signal->theData[2] = apiConnectptr.p->transid[1];
6767             signal->theData[3] = hostptr.i;
6768             signal->theData[4] = ZFALSE;
6769             sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
6770           }//if
6771         }//if
6772       }//for
6773     }//if
6774     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
6775   } while (1);
6776 }//Dbtc::sendAbortedAfterTimeout()
6777 
reportNodeFailed(Signal * signal,Uint32 nodeId)6778 void Dbtc::reportNodeFailed(Signal* signal, Uint32 nodeId)
6779 {
6780   DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
6781   rep->nodeId = nodeId;
6782   rep->err = DisconnectRep::TcReportNodeFailed;
6783   sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
6784 	     DisconnectRep::SignalLength, JBB);
6785 }//Dbtc::reportNodeFailed()
6786 
6787 /*-------------------------------------------------*/
6788 /*      Timeout-loop for scanned fragments.        */
6789 /*-------------------------------------------------*/
timeOutLoopStartFragLab(Signal * signal,Uint32 TscanConPtr)6790 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
6791 {
6792   ScanFragRecPtr timeOutPtr[8];
6793   UintR tfragTimer[8];
6794   UintR texpiredTime[8];
6795   UintR TloopCount = 0;
6796   Uint32 TtcTimer = ctcTimer;
6797 
6798   while ((TscanConPtr + 8) < cscanFragrecFileSize) {
6799     jam();
6800     timeOutPtr[0].i  = TscanConPtr + 0;
6801     timeOutPtr[1].i  = TscanConPtr + 1;
6802     timeOutPtr[2].i  = TscanConPtr + 2;
6803     timeOutPtr[3].i  = TscanConPtr + 3;
6804     timeOutPtr[4].i  = TscanConPtr + 4;
6805     timeOutPtr[5].i  = TscanConPtr + 5;
6806     timeOutPtr[6].i  = TscanConPtr + 6;
6807     timeOutPtr[7].i  = TscanConPtr + 7;
6808 
6809     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
6810     c_scan_frag_pool.getPtrForce(timeOutPtr[1]);
6811     c_scan_frag_pool.getPtrForce(timeOutPtr[2]);
6812     c_scan_frag_pool.getPtrForce(timeOutPtr[3]);
6813     c_scan_frag_pool.getPtrForce(timeOutPtr[4]);
6814     c_scan_frag_pool.getPtrForce(timeOutPtr[5]);
6815     c_scan_frag_pool.getPtrForce(timeOutPtr[6]);
6816     c_scan_frag_pool.getPtrForce(timeOutPtr[7]);
6817 
6818     tfragTimer[0] = timeOutPtr[0].p->scanFragTimer;
6819     tfragTimer[1] = timeOutPtr[1].p->scanFragTimer;
6820     tfragTimer[2] = timeOutPtr[2].p->scanFragTimer;
6821     tfragTimer[3] = timeOutPtr[3].p->scanFragTimer;
6822     tfragTimer[4] = timeOutPtr[4].p->scanFragTimer;
6823     tfragTimer[5] = timeOutPtr[5].p->scanFragTimer;
6824     tfragTimer[6] = timeOutPtr[6].p->scanFragTimer;
6825     tfragTimer[7] = timeOutPtr[7].p->scanFragTimer;
6826 
6827     texpiredTime[0] = TtcTimer - tfragTimer[0];
6828     texpiredTime[1] = TtcTimer - tfragTimer[1];
6829     texpiredTime[2] = TtcTimer - tfragTimer[2];
6830     texpiredTime[3] = TtcTimer - tfragTimer[3];
6831     texpiredTime[4] = TtcTimer - tfragTimer[4];
6832     texpiredTime[5] = TtcTimer - tfragTimer[5];
6833     texpiredTime[6] = TtcTimer - tfragTimer[6];
6834     texpiredTime[7] = TtcTimer - tfragTimer[7];
6835 
6836     for (Uint32 Ti = 0; Ti < 8; Ti++) {
6837       jam();
6838       if (tfragTimer[Ti] != 0) {
6839 
6840         if (texpiredTime[Ti] > ctimeOutValue) {
6841 	  jam();
6842 	  DEBUG("Fragment timeout found:"<<
6843 		" ctimeOutValue=" <<ctimeOutValue
6844 		<<", texpiredTime="<<texpiredTime[Ti]<<endl
6845 		<<"      tfragTimer="<<tfragTimer[Ti]
6846 		<<", ctcTimer="<<ctcTimer);
6847           timeOutFoundFragLab(signal, TscanConPtr + Ti);
6848           return;
6849         }//if
6850       }//if
6851     }//for
6852     TscanConPtr += 8;
6853     /*----------------------------------------------------------------*/
6854     /* We split the process up checking 1024 fragmentrecords at a time*/
6855     /* to maintain real time behaviour.                               */
6856     /*----------------------------------------------------------------*/
6857     if (TloopCount++ > 128 ) {
6858       jam();
6859       signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
6860       signal->theData[1] = TscanConPtr;
6861       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
6862       return;
6863     }//if
6864   }//while
6865   for ( ; TscanConPtr < cscanFragrecFileSize; TscanConPtr++){
6866     jam();
6867     timeOutPtr[0].i = TscanConPtr;
6868     c_scan_frag_pool.getPtrForce(timeOutPtr[0]);
6869     if (timeOutPtr[0].p->scanFragTimer != 0) {
6870       texpiredTime[0] = ctcTimer - timeOutPtr[0].p->scanFragTimer;
6871       if (texpiredTime[0] > ctimeOutValue) {
6872         jam();
6873 	DEBUG("Fragment timeout found:"<<
6874 	      " ctimeOutValue=" <<ctimeOutValue
6875 	      <<", texpiredTime="<<texpiredTime[0]<<endl
6876 		<<"      tfragTimer="<<tfragTimer[0]
6877 		<<", ctcTimer="<<ctcTimer);
6878         timeOutFoundFragLab(signal, TscanConPtr);
6879         return;
6880       }//if
6881     }//if
6882   }//for
6883   ctimeOutCheckFragActive = TOCS_FALSE;
6884 
6885   return;
6886 }//timeOutLoopStartFragLab()
6887 
6888 /*--------------------------------------------------------------------------*/
6889 /*Handle the heartbeat signal from LQH in a scan process                    */
6890 // (Set timer on fragrec.)
6891 /*--------------------------------------------------------------------------*/
execSCAN_HBREP(Signal * signal)6892 void Dbtc::execSCAN_HBREP(Signal* signal)
6893 {
6894   jamEntry();
6895 
6896   scanFragptr.i = signal->theData[0];
6897   c_scan_frag_pool.getPtr(scanFragptr);
6898   switch (scanFragptr.p->scanFragState){
6899   case ScanFragRec::LQH_ACTIVE:
6900     break;
6901   default:
6902     DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
6903     systemErrorLab(signal, __LINE__);
6904     break;
6905   }
6906 
6907   ScanRecordPtr scanptr;
6908   scanptr.i = scanFragptr.p->scanRec;
6909   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
6910 
6911   apiConnectptr.i = scanptr.p->scanApiRec;
6912   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
6913 
6914   if (!(apiConnectptr.p->transid[0] == signal->theData[1] &&
6915 	apiConnectptr.p->transid[1] == signal->theData[2])){
6916     jam();
6917     /**
6918      * Send signal back to sender so that the crash occurs there
6919      */
6920     // Save original transid
6921     signal->theData[3] = signal->theData[0];
6922     signal->theData[4] = signal->theData[1];
6923     // Set transid to illegal values
6924     signal->theData[1] = RNIL;
6925     signal->theData[2] = RNIL;
6926 
6927     sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
6928     DEBUG("SCAN_HBREP with wrong transid("
6929 	  <<signal->theData[3]<<", "<<signal->theData[4]<<")");
6930     return;
6931   }//if
6932 
6933   // Update timer on ScanFragRec
6934   if (scanFragptr.p->scanFragTimer != 0){
6935     updateBuddyTimer(apiConnectptr);
6936     scanFragptr.p->startFragTimer(ctcTimer);
6937   } else {
6938     ndbassert(false);
6939     DEBUG("SCAN_HBREP when scanFragTimer was turned off");
6940   }
6941 }//execSCAN_HBREP()
6942 
6943 /*--------------------------------------------------------------------------*/
6944 /*      Timeout has occured on a fragment which means a scan has timed out. */
6945 /*      If this is true we have an error in LQH/ACC.                        */
6946 /*--------------------------------------------------------------------------*/
timeOutFoundFragLab(Signal * signal,UintR TscanConPtr)6947 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
6948 {
6949   ScanFragRecPtr ptr;
6950   c_scan_frag_pool.getPtr(ptr, TscanConPtr);
6951   DEBUG(TscanConPtr << " timeOutFoundFragLab: scanFragState = "<< ptr.p->scanFragState);
6952 
6953   const Uint32 time_out_param= ctimeOutValue;
6954   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
6955 
6956   if (unlikely(time_out_param != old_time_out_param &&
6957 	       getNodeState().getSingleUserMode()))
6958   {
6959     jam();
6960     ScanRecordPtr scanptr;
6961     scanptr.i = ptr.p->scanRec;
6962     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
6963     ApiConnectRecordPtr TlocalApiConnectptr;
6964     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
6965     ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
6966 
6967     if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
6968 	getNodeState().getSingleUserApi())
6969     {
6970       jam();
6971       Uint32 val = ctcTimer - ptr.p->scanFragTimer;
6972       if (val <= old_time_out_param)
6973       {
6974 	jam();
6975 	goto next;
6976       }
6977     }
6978   }
6979 
6980   /*-------------------------------------------------------------------------*/
6981   // The scan fragment has expired its timeout. Check its state to decide
6982   // what to do.
6983   /*-------------------------------------------------------------------------*/
6984   switch (ptr.p->scanFragState) {
6985   case ScanFragRec::WAIT_GET_PRIMCONF:
6986     jam();
6987     ndbrequire(false);
6988     break;
6989   case ScanFragRec::LQH_ACTIVE:{
6990     jam();
6991 
6992     /**
6993      * The LQH expired it's timeout, try to close it
6994      */
6995     Uint32 nodeId = refToNode(ptr.p->lqhBlockref);
6996     Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
6997     ScanRecordPtr scanptr;
6998     scanptr.i = ptr.p->scanRec;
6999     ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
7000 
7001     if(connectCount != ptr.p->m_connectCount){
7002       jam();
7003       /**
7004        * The node has died
7005        */
7006       ptr.p->scanFragState = ScanFragRec::COMPLETED;
7007       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
7008 
7009       run.release(ptr);
7010       ptr.p->stopFragTimer();
7011     }
7012 
7013     scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
7014     break;
7015   }
7016   case ScanFragRec::DELIVERED:
7017     jam();
7018   case ScanFragRec::IDLE:
7019     jam();
7020   case ScanFragRec::QUEUED_FOR_DELIVERY:
7021     jam();
7022     /*-----------------------------------------------------------------------
7023      * Should never occur. We will simply report set the timer to zero and
7024      * continue. In a debug version we should crash here but not in a release
7025      * version. In a release version we will simply set the time-out to zero.
7026      *-----------------------------------------------------------------------*/
7027 #ifdef VM_TRACE
7028     systemErrorLab(signal, __LINE__);
7029 #endif
7030     scanFragptr.p->stopFragTimer();
7031     break;
7032   default:
7033     jam();
7034     /*-----------------------------------------------------------------------
7035      * Non-existent state. Crash.
7036      *-----------------------------------------------------------------------*/
7037     systemErrorLab(signal, __LINE__);
7038     break;
7039   }//switch
7040 
7041 next:
7042   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
7043   signal->theData[1] = TscanConPtr + 1;
7044   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
7045   return;
7046 }//timeOutFoundFragLab()
7047 
7048 
7049 /*
7050   4.3.16 GCP_NOMORETRANS
7051   ----------------------
7052 */
7053 /*****************************************************************************
7054  *                         G C P _ N O M O R E T R A N S
7055  *
7056  *  WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
7057  *  THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
7058  *  SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
7059  *  CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
7060  *  FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
7061  *  COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
7062  *  THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
7063  *  THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
7064  *  TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
7065  *****************************************************************************/
execGCP_NOMORETRANS(Signal * signal)7066 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
7067 {
7068   jamEntry();
7069   c_gcp_ref = signal->theData[0];
7070   tcheckGcpId = signal->theData[1];
7071   if (cfirstgcp != RNIL) {
7072     jam();
7073                                       /* A GLOBAL CHECKPOINT IS GOING ON */
7074     gcpPtr.i = cfirstgcp;             /* SET POINTER TO FIRST GCP IN QUEUE*/
7075     ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
7076     if (gcpPtr.p->gcpId == tcheckGcpId) {
7077       jam();
7078       if (gcpPtr.p->firstApiConnect != RNIL) {
7079         jam();
7080         gcpPtr.p->gcpNomoretransRec = ZTRUE;
7081       } else {
7082         jam();
7083         gcpTcfinished(signal);
7084         unlinkGcp(signal);
7085       }//if
7086     } else {
7087       jam();
7088       /*------------------------------------------------------------*/
7089       /*       IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO       */
7090       /*       RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE  */
7091       /*       THE GLOBAL CHECKPOINTS IN ORDER.                     */
7092       /*------------------------------------------------------------*/
7093       gcpTcfinished(signal);
7094     }//if
7095   } else {
7096     jam();
7097     gcpTcfinished(signal);
7098   }//if
7099   return;
7100 }//Dbtc::execGCP_NOMORETRANS()
7101 
7102 /*****************************************************************************/
7103 /*                                                                           */
7104 /*                            TAKE OVER MODULE                               */
7105 /*                                                                           */
7106 /*****************************************************************************/
7107 /*                                                                           */
7108 /*    THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE  */
7109 /*    NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT   */
7110 /*    ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE   */
7111 /*    FAILED.                                                                */
7112 /*                                                                           */
7113 /*    AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
7114 /*    CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
7115 /*    COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED.    */
7116 /*    IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO  */
7117 /*    WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT.            */
7118 /*****************************************************************************/
execNODE_FAILREP(Signal * signal)7119 void Dbtc::execNODE_FAILREP(Signal* signal)
7120 {
7121   jamEntry();
7122 
7123   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
7124 
7125   cfailure_nr = nodeFail->failNo;
7126   const Uint32 tnoOfNodes  = nodeFail->noOfNodes;
7127   const Uint32 tnewMasterId = nodeFail->masterNodeId;
7128 
7129   arrGuard(tnoOfNodes, MAX_NDB_NODES);
7130   Uint32 i;
7131   int index = 0;
7132   for (i = 1; i< MAX_NDB_NODES; i++)
7133   {
7134     if(NodeBitmask::get(nodeFail->theNodes, i))
7135     {
7136       cdata[index] = i;
7137       index++;
7138     }//if
7139   }//for
7140 
7141   cmasterNodeId = tnewMasterId;
7142 
7143   tcNodeFailptr.i = 0;
7144   ptrAss(tcNodeFailptr, tcFailRecord);
7145   for (i = 0; i < tnoOfNodes; i++)
7146   {
7147     jam();
7148     hostptr.i = cdata[i];
7149     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7150 
7151     /*------------------------------------------------------------*/
7152     /*       SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS   */
7153     /*       FAILED.                                              */
7154     /*------------------------------------------------------------*/
7155     hostptr.p->hostStatus = HS_DEAD;
7156     hostptr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
7157     c_alive_nodes.clear(hostptr.i);
7158 
7159     if (tcNodeFailptr.p->failStatus == FS_LISTENING)
7160     {
7161       jam();
7162       /*------------------------------------------------------------*/
7163       /*       THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE   */
7164       /*       FAILURE.                                             */
7165       /*------------------------------------------------------------*/
7166       if (hostptr.p->lqhTransStatus == LTS_ACTIVE)
7167       {
7168 	jam();
7169 	/*------------------------------------------------------------*/
7170 	/*       WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
7171 	/*       PROTOCOL FOR TC.                                     */
7172 	/*------------------------------------------------------------*/
7173 	signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
7174 	signal->theData[1] = hostptr.i;
7175 	sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
7176       }//if
7177     }//if
7178 
7179     if (getOwnNodeId() != tnewMasterId)
7180     {
7181       jam();
7182       /**
7183        * Only master does takeover currently
7184        */
7185       hostptr.p->m_nf_bits &= ~HostRecord::NF_TAKEOVER;
7186     }
7187     else
7188     {
7189       jam();
7190       signal->theData[0] = hostptr.i;
7191       sendSignal(cownref, GSN_TAKE_OVERTCREQ, signal, 1, JBB);
7192     }
7193 
7194     checkScanActiveInFailedLqh(signal, 0, hostptr.i);
7195     checkWaitDropTabFailedLqh(signal, hostptr.i, 0); // nodeid, tableid
7196     nodeFailCheckTransactions(signal, 0, hostptr.i);
7197   }
7198 }//Dbtc::execNODE_FAILREP()
7199 
7200 void
checkNodeFailComplete(Signal * signal,Uint32 failedNodeId,Uint32 bit)7201 Dbtc::checkNodeFailComplete(Signal* signal,
7202 			    Uint32 failedNodeId,
7203 			    Uint32 bit)
7204 {
7205   hostptr.i = failedNodeId;
7206   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7207   hostptr.p->m_nf_bits &= ~bit;
7208   if (hostptr.p->m_nf_bits == 0)
7209   {
7210     NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
7211     nfRep->blockNo      = DBTC;
7212     nfRep->nodeId       = cownNodeid;
7213     nfRep->failedNodeId = hostptr.i;
7214     sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
7215 	       NFCompleteRep::SignalLength, JBB);
7216   }
7217 }
7218 
checkScanActiveInFailedLqh(Signal * signal,Uint32 scanPtrI,Uint32 failedNodeId)7219 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
7220 				      Uint32 scanPtrI,
7221 				      Uint32 failedNodeId){
7222 
7223   ScanRecordPtr scanptr;
7224   for (scanptr.i = scanPtrI; scanptr.i < cscanrecFileSize; scanptr.i++) {
7225     jam();
7226     ptrAss(scanptr, scanRecord);
7227     bool found = false;
7228     if (scanptr.p->scanState != ScanRecord::IDLE){
7229       jam();
7230       ScanFragRecPtr ptr;
7231       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
7232 
7233       for(run.first(ptr); !ptr.isNull(); ){
7234 	jam();
7235 	ScanFragRecPtr curr = ptr;
7236 	run.next(ptr);
7237 	if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
7238 	    refToNode(curr.p->lqhBlockref) == failedNodeId){
7239 	  jam();
7240 
7241 	  run.release(curr);
7242 	  curr.p->scanFragState = ScanFragRec::COMPLETED;
7243 	  curr.p->stopFragTimer();
7244 	  found = true;
7245 	}
7246       }
7247 
7248       ScanFragList deliv(c_scan_frag_pool, scanptr.p->m_delivered_scan_frags);
7249       for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
7250       {
7251 	jam();
7252 	if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
7253 	{
7254 	  jam();
7255 	  found = true;
7256 	  break;
7257 	}
7258       }
7259     }
7260     if(found){
7261       jam();
7262       scanError(signal, scanptr, ZSCAN_LQH_ERROR);
7263     }
7264 
7265     // Send CONTINUEB to continue later
7266     signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
7267     signal->theData[1] = scanptr.i + 1; // Check next scanptr
7268     signal->theData[2] = failedNodeId;
7269     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7270     return;
7271   }//for
7272 
7273   checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
7274 }
7275 
7276 void
nodeFailCheckTransactions(Signal * signal,Uint32 transPtrI,Uint32 failedNodeId)7277 Dbtc::nodeFailCheckTransactions(Signal* signal,
7278 				Uint32 transPtrI,
7279 				Uint32 failedNodeId)
7280 {
7281   jam();
7282   Ptr<ApiConnectRecord> transPtr;
7283   Uint32 TtcTimer = ctcTimer;
7284   Uint32 TapplTimeout = c_appl_timeout_value;
7285   for (transPtr.i = transPtrI; transPtr.i < capiConnectFilesize; transPtr.i++)
7286   {
7287     ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
7288     if (transPtr.p->m_transaction_nodes.get(failedNodeId))
7289     {
7290       jam();
7291 
7292       // Force timeout regardless of state
7293       c_appl_timeout_value = 1;
7294       setApiConTimer(transPtr.i, TtcTimer - 2, __LINE__);
7295       timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
7296       c_appl_timeout_value = TapplTimeout;
7297     }
7298 
7299     // Send CONTINUEB to continue later
7300     signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
7301     signal->theData[1] = transPtr.i + 1; // Check next
7302     signal->theData[2] = failedNodeId;
7303     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7304     return;
7305   }
7306 
7307   checkNodeFailComplete(signal, failedNodeId,
7308 			HostRecord::NF_CHECK_TRANSACTION);
7309 }
7310 
7311 
7312 void
checkScanFragList(Signal * signal,Uint32 failedNodeId,ScanRecord * scanP,ScanFragList::Head & head)7313 Dbtc::checkScanFragList(Signal* signal,
7314 			Uint32 failedNodeId,
7315 			ScanRecord * scanP,
7316 			ScanFragList::Head & head){
7317 
7318   DEBUG("checkScanActiveInFailedLqh: scanFragError");
7319 }
7320 
execTAKE_OVERTCCONF(Signal * signal)7321 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
7322 {
7323   jamEntry();
7324   tfailedNodeId = signal->theData[0];
7325   hostptr.i = tfailedNodeId;
7326   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7327 
7328   if (signal->getSendersBlockRef() != reference())
7329   {
7330     jam();
7331     return;
7332   }
7333 
7334   checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
7335 }//Dbtc::execTAKE_OVERTCCONF()
7336 
execTAKE_OVERTCREQ(Signal * signal)7337 void Dbtc::execTAKE_OVERTCREQ(Signal* signal)
7338 {
7339   jamEntry();
7340   tfailedNodeId = signal->theData[0];
7341   tcNodeFailptr.i = 0;
7342   ptrAss(tcNodeFailptr, tcFailRecord);
7343   if (tcNodeFailptr.p->failStatus != FS_IDLE) {
7344     jam();
7345     /*------------------------------------------------------------*/
7346     /*       WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
7347     /*------------------------------------------------------------*/
7348     /*       IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL      */
7349     /*       QUEUE THE TAKE OVER AND START IT AS SOON AS THE      */
7350     /*       PREVIOUS ARE COMPLETED.                              */
7351     /*------------------------------------------------------------*/
7352     arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
7353     tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = tfailedNodeId;
7354     tcNodeFailptr.p->queueIndex = tcNodeFailptr.p->queueIndex + 1;
7355     return;
7356   }//if
7357   startTakeOverLab(signal);
7358 }//Dbtc::execTAKE_OVERTCREQ()
7359 
7360 /*------------------------------------------------------------*/
7361 /*       INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS  */
7362 /*       AND OPERATIONS DURING TC TAKE OVER.                  */
7363 /*------------------------------------------------------------*/
startTakeOverLab(Signal * signal)7364 void Dbtc::startTakeOverLab(Signal* signal)
7365 {
7366   for (tindex = 0; tindex <= 511; tindex++) {
7367     ctransidFailHash[tindex] = RNIL;
7368   }//for
7369   for (tindex = 0; tindex <= 1023; tindex++) {
7370     ctcConnectFailHash[tindex] = RNIL;
7371   }//for
7372   tcNodeFailptr.p->failStatus = FS_LISTENING;
7373   tcNodeFailptr.p->takeOverNode = tfailedNodeId;
7374   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
7375     jam();
7376     ptrAss(hostptr, hostRecord);
7377     if (hostptr.p->hostStatus == HS_ALIVE) {
7378       jam();
7379       tblockref = calcLqhBlockRef(hostptr.i);
7380       hostptr.p->lqhTransStatus = LTS_ACTIVE;
7381       signal->theData[0] = tcNodeFailptr.i;
7382       signal->theData[1] = cownref;
7383       signal->theData[2] = tfailedNodeId;
7384       sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, 3, JBB);
7385     }//if
7386   }//for
7387 }//Dbtc::startTakeOverLab()
7388 
7389 /*------------------------------------------------------------*/
7390 /*       A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
7391 /*------------------------------------------------------------*/
execLQH_TRANSCONF(Signal * signal)7392 void Dbtc::execLQH_TRANSCONF(Signal* signal)
7393 {
7394   jamEntry();
7395   LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
7396 
7397   tcNodeFailptr.i = lqhTransConf->tcRef;
7398   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
7399   tnodeid = lqhTransConf->lqhNodeId;
7400   ttransStatus = (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
7401   ttransid1    = lqhTransConf->transId1;
7402   ttransid2    = lqhTransConf->transId2;
7403   ttcOprec     = lqhTransConf->oldTcOpRec;
7404   treqinfo     = lqhTransConf->requestInfo;
7405   tgci         = lqhTransConf->gci;
7406   cnodes[0]    = lqhTransConf->nextNodeId1;
7407   cnodes[1]    = lqhTransConf->nextNodeId2;
7408   cnodes[2]    = lqhTransConf->nextNodeId3;
7409   const Uint32 ref = tapplRef = lqhTransConf->apiRef;
7410   tapplOprec   = lqhTransConf->apiOpRec;
7411   const Uint32 tableId = lqhTransConf->tableId;
7412 
7413   if (ttransStatus == LqhTransConf::LastTransConf){
7414     jam();
7415     /*------------------------------------------------------------*/
7416     /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
7417     /*------------------------------------------------------------*/
7418     nodeTakeOverCompletedLab(signal);
7419     return;
7420   }//if
7421   if (ttransStatus == LqhTransConf::Marker){
7422     jam();
7423     treqinfo = 0;
7424     LqhTransConf::setMarkerFlag(treqinfo, 1);
7425   } else {
7426     TableRecordPtr tabPtr;
7427     tabPtr.i = tableId;
7428     ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
7429     switch((DictTabInfo::TableType)tabPtr.p->tableType){
7430     case DictTabInfo::SystemTable:
7431     case DictTabInfo::UserTable:
7432       break;
7433     default:
7434       tapplRef = 0;
7435       tapplOprec = 0;
7436     }
7437   }
7438 
7439   findApiConnectFail(signal);
7440 
7441   if(apiConnectptr.p->ndbapiBlockref == 0 && tapplRef != 0){
7442     apiConnectptr.p->ndbapiBlockref = ref;
7443     apiConnectptr.p->ndbapiConnect = tapplOprec;
7444   }
7445 
7446   if (ttransStatus != LqhTransConf::Marker){
7447     jam();
7448     findTcConnectFail(signal);
7449   }
7450 }//Dbtc::execLQH_TRANSCONF()
7451 
7452 /*------------------------------------------------------------*/
7453 /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
7454 /*------------------------------------------------------------*/
nodeTakeOverCompletedLab(Signal * signal)7455 void Dbtc::nodeTakeOverCompletedLab(Signal* signal)
7456 {
7457   Uint32 guard0;
7458 
7459   hostptr.i = tnodeid;
7460   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7461   hostptr.p->lqhTransStatus = LTS_IDLE;
7462   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
7463     jam();
7464     ptrAss(hostptr, hostRecord);
7465     if (hostptr.p->hostStatus == HS_ALIVE) {
7466       if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
7467         jam();
7468 	/*------------------------------------------------------------*/
7469 	/*       NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE    */
7470 	/*       TAKE OVER.                                           */
7471 	/*------------------------------------------------------------*/
7472         return;
7473       }//if
7474     }//if
7475   }//for
7476   /*------------------------------------------------------------*/
7477   /*       ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
7478   /*       OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE  */
7479   /*       ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE       */
7480   /*       TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN     */
7481   /*       UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
7482   /*       TO THE APPLICATION IF THAT IS STILL ALIVE.           */
7483   /*------------------------------------------------------------*/
7484   tcNodeFailptr.p->currentHashIndexTakeOver = 0;
7485   tcNodeFailptr.p->completedTakeOver = 0;
7486   tcNodeFailptr.p->failStatus = FS_COMPLETING;
7487   guard0 = cnoParallelTakeOver - 1;
7488   /*------------------------------------------------------------*/
7489   /*       WE WILL COMPLETE THE TRANSACTIONS BY STARTING A      */
7490   /*       NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL    */
7491   /*       COMPLETE ONE TRANSACTION AT A TIME AND IN THAT       */
7492   /*       TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
7493   /*       WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
7494   /*       IS COMPLETED.                                        */
7495   /*------------------------------------------------------------*/
7496   arrGuard(guard0, MAX_NDB_NODES);
7497   for (tindex = 0; tindex <= guard0; tindex++) {
7498     jam();
7499     tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
7500     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7501     signal->theData[1] = tcNodeFailptr.i;
7502     signal->theData[2] = tindex;
7503     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7504   }//for
7505 }//Dbtc::nodeTakeOverCompletedLab()
7506 
7507 /*------------------------------------------------------------*/
7508 /*       COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF    */
7509 /*       TRANSACTIONS TO COMPLETE.                            */
7510 /*------------------------------------------------------------*/
completeTransAtTakeOverLab(Signal * signal,UintR TtakeOverInd)7511 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
7512 {
7513   jam();
7514   while (tcNodeFailptr.p->currentHashIndexTakeOver < 512){
7515     jam();
7516     apiConnectptr.i =
7517         ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
7518     if (apiConnectptr.i != RNIL) {
7519       jam();
7520       /*------------------------------------------------------------*/
7521       /*       WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE         */
7522       /*       COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT   */
7523       /*       NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS     */
7524       /*       TRANSACTION.                                         */
7525       /*------------------------------------------------------------*/
7526       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7527       ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
7528         apiConnectptr.p->nextApiConnect;
7529 
7530       completeTransAtTakeOverDoOne(signal, TtakeOverInd);
7531       // One transaction taken care of, return from this function
7532       // and wait for the next CONTINUEB to continue processing
7533       break;
7534 
7535     } else {
7536       if (tcNodeFailptr.p->currentHashIndexTakeOver < 511){
7537         jam();
7538         tcNodeFailptr.p->currentHashIndexTakeOver++;
7539       } else {
7540         jam();
7541         completeTransAtTakeOverDoLast(signal, TtakeOverInd);
7542         tcNodeFailptr.p->currentHashIndexTakeOver++;
7543       }//if
7544     }//if
7545   }//while
7546 }//Dbtc::completeTransAtTakeOverLab()
7547 
7548 
7549 
7550 
completeTransAtTakeOverDoLast(Signal * signal,UintR TtakeOverInd)7551 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
7552 {
7553   Uint32 guard0;
7554   /*------------------------------------------------------------*/
7555   /*       THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS     */
7556   /*       ACTIVITY IS COMPLETED.                               */
7557   /*------------------------------------------------------------*/
7558   arrGuard(TtakeOverInd, MAX_NDB_NODES);
7559   if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
7560     jam();
7561     systemErrorLab(signal, __LINE__);
7562     return;
7563   }//if
7564   tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
7565   tcNodeFailptr.p->completedTakeOver++;
7566 
7567   if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
7568     jam();
7569     /*------------------------------------------------------------*/
7570     /*       WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
7571     /*       TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL     */
7572     /*       NODES THAT ARE ALIVE.                                */
7573     /*------------------------------------------------------------*/
7574     NodeReceiverGroup rg(DBTC, c_alive_nodes);
7575     signal->theData[0] = tcNodeFailptr.p->takeOverNode;
7576     sendSignal(rg, GSN_TAKE_OVERTCCONF, signal, 1, JBB);
7577 
7578     if (tcNodeFailptr.p->queueIndex > 0) {
7579       jam();
7580       /*------------------------------------------------------------*/
7581       /*       THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START  */
7582       /*       THE TAKE OVER.                                       */
7583       /*------------------------------------------------------------*/
7584       tfailedNodeId = tcNodeFailptr.p->queueList[0];
7585       guard0 = tcNodeFailptr.p->queueIndex - 1;
7586       arrGuard(guard0 + 1, MAX_NDB_NODES);
7587       for (tindex = 0; tindex <= guard0; tindex++) {
7588         jam();
7589         tcNodeFailptr.p->queueList[tindex] =
7590           tcNodeFailptr.p->queueList[tindex + 1];
7591       }//for
7592       tcNodeFailptr.p->queueIndex--;
7593       startTakeOverLab(signal);
7594       return;
7595     } else {
7596       jam();
7597       tcNodeFailptr.p->failStatus = FS_IDLE;
7598     }//if
7599   }//if
7600   return;
7601 }//Dbtc::completeTransAtTakeOverDoLast()
7602 
completeTransAtTakeOverDoOne(Signal * signal,UintR TtakeOverInd)7603 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd)
7604 {
7605   apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
7606   apiConnectptr.p->takeOverInd = TtakeOverInd;
7607 
7608   switch (apiConnectptr.p->apiConnectstate) {
7609   case CS_FAIL_COMMITTED:
7610     jam();
7611     /*------------------------------------------------------------*/
7612     /*       ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
7613     /*       HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT  */
7614     /*       COMMITTED TO THE APPLICATION AND CONTINUE WITH THE   */
7615     /*       COMPLETE PHASE.                                      */
7616     /*------------------------------------------------------------*/
7617     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
7618     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7619     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7620     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7621     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7622     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7623     toCompleteHandlingLab(signal);
7624     return;
7625   case CS_FAIL_COMMITTING:
7626     jam();
7627     /*------------------------------------------------------------*/
7628     /*       AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
7629     /*       PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
7630     /*       THEN CONTINUE AS AFTER COMMITTED.                    */
7631     /*------------------------------------------------------------*/
7632     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7633     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7634     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7635     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7636     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7637     toCommitHandlingLab(signal);
7638     return;
7639   case CS_FAIL_ABORTING:
7640   case CS_FAIL_PREPARED:
7641     jam();
7642     /*------------------------------------------------------------*/
7643     /*       WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
7644     /*       STATE IN THIS VERSION. IN LATER VERSIONS WE WILL     */
7645     /*       HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT  */
7646     /*       TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
7647     /*       HAVE HEARD FROM THE TRANSACTION COORDINATOR.         */
7648     /*                                                            */
7649     /*       IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE       */
7650     /*       PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL  */
7651     /*       LATER VERSIONS.                                      */
7652     /*------------------------------------------------------------*/
7653     tcConnectptr.i = apiConnectptr.p->firstTcConnect;
7654     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7655     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7656     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7657     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7658     toAbortHandlingLab(signal);
7659     return;
7660   case CS_FAIL_ABORTED:
7661     jam();
7662     sendTCKEY_FAILREF(signal, apiConnectptr.p);
7663 
7664     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7665     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
7666     signal->theData[2] = apiConnectptr.p->takeOverInd;
7667     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7668     releaseTakeOver(signal);
7669     break;
7670   case CS_FAIL_COMPLETED:
7671     jam();
7672     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
7673 
7674     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7675     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
7676     signal->theData[2] = apiConnectptr.p->takeOverInd;
7677     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7678     releaseApiConnectFail(signal);
7679     break;
7680   default:
7681     jam();
7682     systemErrorLab(signal, __LINE__);
7683     return;
7684   }//switch
7685 }//Dbtc::completeTransAtTakeOverDoOne()
7686 
7687 void
sendTCKEY_FAILREF(Signal * signal,const ApiConnectRecord * regApiPtr)7688 Dbtc::sendTCKEY_FAILREF(Signal* signal, const ApiConnectRecord * regApiPtr){
7689   jam();
7690 
7691   const Uint32 ref = regApiPtr->ndbapiBlockref;
7692   if(ref != 0){
7693     signal->theData[0] = regApiPtr->ndbapiConnect;
7694     signal->theData[1] = regApiPtr->transid[0];
7695     signal->theData[2] = regApiPtr->transid[1];
7696 
7697     sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
7698   }
7699 }
7700 
7701 void
sendTCKEY_FAILCONF(Signal * signal,ApiConnectRecord * regApiPtr)7702 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
7703   jam();
7704   TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
7705 
7706   const Uint32 ref = regApiPtr->ndbapiBlockref;
7707   const Uint32 marker = regApiPtr->commitAckMarker;
7708   if(ref != 0){
7709     failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
7710     failConf->transId1 = regApiPtr->transid[0];
7711     failConf->transId2 = regApiPtr->transid[1];
7712 
7713     sendSignal(regApiPtr->ndbapiBlockref,
7714 	       GSN_TCKEY_FAILCONF, signal, TcKeyFailConf::SignalLength, JBB);
7715   }
7716   regApiPtr->commitAckMarker = RNIL;
7717 }
7718 
7719 /*------------------------------------------------------------*/
7720 /*       THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A   */
7721 /*       NODE FAILURE BEFORE THE COMMIT DECISION.             */
7722 /*------------------------------------------------------------*/
7723 /*       ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID      */
7724 /*------------------------------------------------------------*/
execABORTCONF(Signal * signal)7725 void Dbtc::execABORTCONF(Signal* signal)
7726 {
7727   UintR compare_transid1, compare_transid2;
7728 
7729   jamEntry();
7730   tcConnectptr.i = signal->theData[0];
7731   tnodeid = signal->theData[2];
7732   if (ERROR_INSERTED(8045)) {
7733     CLEAR_ERROR_INSERT_VALUE;
7734     sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
7735     return;
7736   }//if
7737   if (tcConnectptr.i >= ctcConnectFilesize) {
7738     errorReport(signal, 5);
7739     return;
7740   }//if
7741   ptrAss(tcConnectptr, tcConnectRecord);
7742   if (tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF) {
7743     warningReport(signal, 16);
7744     return;
7745   }//if
7746   apiConnectptr.i = tcConnectptr.p->apiConnect;
7747   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7748   if (apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF) {
7749     warningReport(signal, 17);
7750     return;
7751   }//if
7752   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
7753   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
7754   compare_transid1 = compare_transid1 | compare_transid2;
7755   if (compare_transid1 != 0) {
7756     warningReport(signal, 18);
7757     return;
7758   }//if
7759   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7760   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
7761       tnodeid) {
7762     warningReport(signal, 19);
7763     return;
7764   }//if
7765   tcurrentReplicaNo = (Uint8)Z8NIL;
7766   tcConnectptr.p->tcConnectstate = OS_ABORTING;
7767   toAbortHandlingLab(signal);
7768 }//Dbtc::execABORTCONF()
7769 
toAbortHandlingLab(Signal * signal)7770 void Dbtc::toAbortHandlingLab(Signal* signal)
7771 {
7772   do {
7773     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
7774       jam();
7775       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
7776       const LqhTransConf::OperationStatus stat =
7777 	(LqhTransConf::OperationStatus)
7778 	tcConnectptr.p->failData[tcurrentReplicaNo];
7779       switch(stat){
7780       case LqhTransConf::InvalidStatus:
7781       case LqhTransConf::Aborted:
7782         jam();
7783         /*empty*/;
7784         break;
7785       case LqhTransConf::Prepared:
7786         jam();
7787         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
7788         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7789         if (hostptr.p->hostStatus == HS_ALIVE) {
7790           jam();
7791           tblockref = calcLqhBlockRef(hostptr.i);
7792           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7793           tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
7794           apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
7795           apiConnectptr.p->timeOutCounter = 0;
7796           signal->theData[0] = tcConnectptr.i;
7797           signal->theData[1] = cownref;
7798           signal->theData[2] = apiConnectptr.p->transid[0];
7799           signal->theData[3] = apiConnectptr.p->transid[1];
7800           signal->theData[4] = apiConnectptr.p->tcBlockref;
7801           signal->theData[5] = tcConnectptr.p->tcOprec;
7802           sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
7803           return;
7804         }//if
7805         break;
7806       default:
7807         jam();
7808         systemErrorLab(signal, __LINE__);
7809         return;
7810       }//switch
7811     }//if
7812     if (apiConnectptr.p->currentReplicaNo > 0) {
7813       jam();
7814       /*------------------------------------------------------------*/
7815       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
7816       /*       ABORTED.                                             */
7817       /*------------------------------------------------------------*/
7818       apiConnectptr.p->currentReplicaNo--;
7819       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
7820     } else {
7821       /*------------------------------------------------------------*/
7822       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
7823       /*------------------------------------------------------------*/
7824       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7825       if (tcConnectptr.i == RNIL) {
7826 	/*------------------------------------------------------------*/
7827 	/*       WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
7828 	/*       THE ABORT STATUS TO THE APPLICATION AND CONTINUE     */
7829 	/*       WITH THE NEXT TRANSACTION.                           */
7830 	/*------------------------------------------------------------*/
7831         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
7832           jam();
7833 	  sendTCKEY_FAILREF(signal, apiConnectptr.p);
7834 	  const Uint32 marker = apiConnectptr.p->commitAckMarker;
7835           if(marker != RNIL){
7836 	    jam();
7837 
7838             CommitAckMarkerPtr tmp;
7839             tmp.i = marker;
7840             tmp.p = m_commitAckMarkerHash.getPtr(tmp.i);
7841 
7842             m_commitAckMarkerHash.release(tmp);
7843             apiConnectptr.p->commitAckMarker = RNIL;
7844           }
7845 
7846 	  /*------------------------------------------------------------*/
7847 	  /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
7848 	  /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
7849 	  /*------------------------------------------------------------*/
7850           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
7851           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
7852           signal->theData[2] = apiConnectptr.p->takeOverInd;
7853           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7854           releaseTakeOver(signal);
7855         } else {
7856           jam();
7857           releaseAbortResources(signal);
7858         }//if
7859         return;
7860       }//if
7861       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
7862       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
7863       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
7864       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
7865     }//if
7866   } while (1);
7867 }//Dbtc::toAbortHandlingLab()
7868 
7869 /*------------------------------------------------------------*/
7870 /*       THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A  */
7871 /*       NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE.      */
7872 /*------------------------------------------------------------*/
7873 /*       COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID     */
7874 /*------------------------------------------------------------*/
execCOMMITCONF(Signal * signal)7875 void Dbtc::execCOMMITCONF(Signal* signal)
7876 {
7877   UintR compare_transid1, compare_transid2;
7878 
7879   jamEntry();
7880   tcConnectptr.i = signal->theData[0];
7881   tnodeid = signal->theData[1];
7882   if (ERROR_INSERTED(8046)) {
7883     CLEAR_ERROR_INSERT_VALUE;
7884     sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
7885     return;
7886   }//if
7887   if (tcConnectptr.i >= ctcConnectFilesize) {
7888     errorReport(signal, 4);
7889     return;
7890   }//if
7891   ptrAss(tcConnectptr, tcConnectRecord);
7892   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF) {
7893     warningReport(signal, 8);
7894     return;
7895   }//if
7896   apiConnectptr.i = tcConnectptr.p->apiConnect;
7897   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
7898   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF) {
7899     warningReport(signal, 9);
7900     return;
7901   }//if
7902   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
7903   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
7904   compare_transid1 = compare_transid1 | compare_transid2;
7905   if (compare_transid1 != 0) {
7906     warningReport(signal, 10);
7907     return;
7908   }//if
7909   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
7910   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
7911       tnodeid) {
7912     warningReport(signal, 11);
7913     return;
7914   }//if
7915   if (ERROR_INSERTED(8026)) {
7916     jam();
7917     systemErrorLab(signal, __LINE__);
7918   }//if
7919   tcurrentReplicaNo = (Uint8)Z8NIL;
7920   tcConnectptr.p->tcConnectstate = OS_COMMITTED;
7921   toCommitHandlingLab(signal);
7922 }//Dbtc::execCOMMITCONF()
7923 
toCommitHandlingLab(Signal * signal)7924 void Dbtc::toCommitHandlingLab(Signal* signal)
7925 {
7926   do {
7927     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
7928       jam();
7929       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
7930       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
7931       case LqhTransConf::InvalidStatus:
7932         jam();
7933         /*empty*/;
7934         break;
7935       case LqhTransConf::Committed:
7936         jam();
7937         /*empty*/;
7938         break;
7939       case LqhTransConf::Prepared:
7940         jam();
7941         /*------------------------------------------------------------*/
7942         /*       THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR    */
7943         /*       COMMIT REQUEST FROM TC.                              */
7944         /*------------------------------------------------------------*/
7945         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
7946         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
7947         if (hostptr.p->hostStatus == HS_ALIVE) {
7948           jam();
7949           tblockref = calcLqhBlockRef(hostptr.i);
7950           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
7951           apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
7952           apiConnectptr.p->timeOutCounter = 0;
7953           tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
7954           signal->theData[0] = tcConnectptr.i;
7955           signal->theData[1] = cownref;
7956           signal->theData[2] = apiConnectptr.p->globalcheckpointid;
7957           signal->theData[3] = apiConnectptr.p->transid[0];
7958           signal->theData[4] = apiConnectptr.p->transid[1];
7959           signal->theData[5] = apiConnectptr.p->tcBlockref;
7960           signal->theData[6] = tcConnectptr.p->tcOprec;
7961           sendSignal(tblockref, GSN_COMMITREQ, signal, 7, JBB);
7962           return;
7963         }//if
7964         break;
7965       default:
7966         jam();
7967         systemErrorLab(signal, __LINE__);
7968         return;
7969         break;
7970       }//switch
7971     }//if
7972     if (apiConnectptr.p->currentReplicaNo > 0) {
7973       jam();
7974       /*------------------------------------------------------------*/
7975       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
7976       /*       COMMITTED.                                           */
7977       /*------------------------------------------------------------*/
7978       apiConnectptr.p->currentReplicaNo--;
7979       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
7980     } else {
7981       /*------------------------------------------------------------*/
7982       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
7983       /*------------------------------------------------------------*/
7984       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
7985       if (tcConnectptr.i == RNIL) {
7986 	/*------------------------------------------------------------*/
7987 	/*       WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
7988 	/*       THE COMMIT STATUS TO THE APPLICATION AND CONTINUE    */
7989 	/*       WITH THE COMPLETE PHASE.                             */
7990 	/*------------------------------------------------------------*/
7991         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
7992           jam();
7993 	  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
7994 	} else {
7995           jam();
7996           sendApiCommit(signal);
7997         }//if
7998         apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
7999         tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8000         ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8001         tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8002         apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
8003         toCompleteHandlingLab(signal);
8004         return;
8005       }//if
8006       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
8007       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8008       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
8009       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8010     }//if
8011   } while (1);
8012 }//Dbtc::toCommitHandlingLab()
8013 
8014 /*------------------------------------------------------------*/
8015 /*       COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE   */
8016 /*       HAVE FAILED.                                         */
8017 /*------------------------------------------------------------*/
8018 /*       THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION   */
8019 /*------------------------------------------------------------*/
execCOMPLETECONF(Signal * signal)8020 void Dbtc::execCOMPLETECONF(Signal* signal)
8021 {
8022   UintR compare_transid1, compare_transid2;
8023 
8024   jamEntry();
8025   tcConnectptr.i = signal->theData[0];
8026   tnodeid = signal->theData[1];
8027   if (ERROR_INSERTED(8047)) {
8028     CLEAR_ERROR_INSERT_VALUE;
8029     sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
8030     return;
8031   }//if
8032   if (tcConnectptr.i >= ctcConnectFilesize) {
8033     errorReport(signal, 3);
8034     return;
8035   }//if
8036   ptrAss(tcConnectptr, tcConnectRecord);
8037   if (tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF) {
8038     warningReport(signal, 12);
8039     return;
8040   }//if
8041   apiConnectptr.i = tcConnectptr.p->apiConnect;
8042   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8043   if (apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF) {
8044     warningReport(signal, 13);
8045     return;
8046   }//if
8047   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
8048   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
8049   compare_transid1 = compare_transid1 | compare_transid2;
8050   if (compare_transid1 != 0) {
8051     warningReport(signal, 14);
8052     return;
8053   }//if
8054   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
8055   if (tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
8056       tnodeid) {
8057     warningReport(signal, 15);
8058     return;
8059   }//if
8060   if (ERROR_INSERTED(8028)) {
8061     jam();
8062     systemErrorLab(signal, __LINE__);
8063   }//if
8064   tcConnectptr.p->tcConnectstate = OS_COMPLETED;
8065   tcurrentReplicaNo = (Uint8)Z8NIL;
8066   toCompleteHandlingLab(signal);
8067 }//Dbtc::execCOMPLETECONF()
8068 
toCompleteHandlingLab(Signal * signal)8069 void Dbtc::toCompleteHandlingLab(Signal* signal)
8070 {
8071   do {
8072     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
8073       jam();
8074       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
8075       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
8076       case LqhTransConf::InvalidStatus:
8077         jam();
8078         /*empty*/;
8079         break;
8080       default:
8081         jam();
8082         /*------------------------------------------------------------*/
8083         /*       THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
8084         /*       IT MUST HAVE FAILED.                                 */
8085         /*------------------------------------------------------------*/
8086         /*------------------------------------------------------------*/
8087         /*       SEND COMPLETEREQ TO THE NEXT REPLICA.                */
8088         /*------------------------------------------------------------*/
8089         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
8090         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8091         if (hostptr.p->hostStatus == HS_ALIVE) {
8092           jam();
8093           tblockref = calcLqhBlockRef(hostptr.i);
8094           setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8095           tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
8096           apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
8097           apiConnectptr.p->timeOutCounter = 0;
8098           tcConnectptr.p->apiConnect = apiConnectptr.i;
8099           signal->theData[0] = tcConnectptr.i;
8100           signal->theData[1] = cownref;
8101           signal->theData[2] = apiConnectptr.p->transid[0];
8102           signal->theData[3] = apiConnectptr.p->transid[1];
8103           signal->theData[4] = apiConnectptr.p->tcBlockref;
8104           signal->theData[5] = tcConnectptr.p->tcOprec;
8105           sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
8106           return;
8107         }//if
8108         break;
8109       }//switch
8110     }//if
8111     if (apiConnectptr.p->currentReplicaNo != 0) {
8112       jam();
8113       /*------------------------------------------------------------*/
8114       /*       THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE  */
8115       /*       NEED TO CONTINUE WITH THOSE REPLICAS.                */
8116       /*------------------------------------------------------------*/
8117       apiConnectptr.p->currentReplicaNo--;
8118       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
8119     } else {
8120       tcConnectptr.i = tcConnectptr.p->nextTcConnect;
8121       if (tcConnectptr.i == RNIL) {
8122         /*------------------------------------------------------------*/
8123         /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
8124         /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
8125         /*------------------------------------------------------------*/
8126         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
8127           jam();
8128           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
8129           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
8130           signal->theData[2] = apiConnectptr.p->takeOverInd;
8131           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
8132           releaseTakeOver(signal);
8133         } else {
8134           jam();
8135           releaseTransResources(signal);
8136         }//if
8137         return;
8138       }//if
8139       /*------------------------------------------------------------*/
8140       /*       WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
8141       /*       COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
8142       /*       FIRST REPLICA SINCE IT IS THE COMPLETE PHASE.        */
8143       /*------------------------------------------------------------*/
8144       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
8145       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8146       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8147       apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
8148     }//if
8149   } while (1);
8150 }//Dbtc::toCompleteHandlingLab()
8151 
8152 /*------------------------------------------------------------*/
8153 /*                                                            */
8154 /*       FIND THE API CONNECT RECORD FOR THIS TRANSACTION     */
8155 /*       DURING TAKE OVER FROM A FAILED TC. IF NONE EXISTS    */
8156 /*       YET THEN SEIZE A NEW API CONNECT RECORD AND LINK IT  */
8157 /*       INTO THE HASH TABLE.                                 */
8158 /*------------------------------------------------------------*/
findApiConnectFail(Signal * signal)8159 void Dbtc::findApiConnectFail(Signal* signal)
8160 {
8161   ApiConnectRecordPtr fafPrevApiConnectptr;
8162   ApiConnectRecordPtr fafNextApiConnectptr;
8163   UintR tfafHashNumber;
8164 
8165   tfafHashNumber = ttransid1 & 511;
8166   fafPrevApiConnectptr.i = RNIL;
8167   ptrNull(fafPrevApiConnectptr);
8168   arrGuard(tfafHashNumber, 512);
8169   fafNextApiConnectptr.i = ctransidFailHash[tfafHashNumber];
8170   ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
8171 FAF_LOOP:
8172   jam();
8173   if (fafNextApiConnectptr.i == RNIL) {
8174     jam();
8175     if (cfirstfreeApiConnectFail == RNIL) {
8176       jam();
8177       systemErrorLab(signal, __LINE__);
8178       return;
8179     }//if
8180     seizeApiConnectFail(signal);
8181     if (fafPrevApiConnectptr.i == RNIL) {
8182       jam();
8183       ctransidFailHash[tfafHashNumber] = apiConnectptr.i;
8184     } else {
8185       jam();
8186       ptrGuard(fafPrevApiConnectptr);
8187       fafPrevApiConnectptr.p->nextApiConnect = apiConnectptr.i;
8188     }//if
8189     apiConnectptr.p->nextApiConnect = RNIL;
8190     initApiConnectFail(signal);
8191   } else {
8192     jam();
8193     fafPrevApiConnectptr.i = fafNextApiConnectptr.i;
8194     fafPrevApiConnectptr.p = fafNextApiConnectptr.p;
8195     apiConnectptr.i = fafNextApiConnectptr.i;
8196     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
8197     fafNextApiConnectptr.i = apiConnectptr.p->nextApiConnect;
8198     ptrCheck(fafNextApiConnectptr, capiConnectFilesize, apiConnectRecord);
8199     if ((apiConnectptr.p->transid[1] != ttransid2) ||
8200         (apiConnectptr.p->transid[0] != ttransid1)) {
8201       goto FAF_LOOP;
8202     }//if
8203     updateApiStateFail(signal);
8204   }//if
8205 }//Dbtc::findApiConnectFail()
8206 
8207 /*----------------------------------------------------------*/
8208 /*       FIND THE TC CONNECT AND IF NOT FOUND ALLOCATE A NEW  */
8209 /*----------------------------------------------------------*/
findTcConnectFail(Signal * signal)8210 void Dbtc::findTcConnectFail(Signal* signal)
8211 {
8212   UintR tftfHashNumber;
8213 
8214   tftfHashNumber = (ttransid1 ^ ttcOprec) & 1023;
8215   tcConnectptr.i = ctcConnectFailHash[tftfHashNumber];
8216   do {
8217     if (tcConnectptr.i == RNIL) {
8218       jam();
8219       if (cfirstfreeTcConnectFail == RNIL) {
8220         jam();
8221         systemErrorLab(signal, __LINE__);
8222         return;
8223       }//if
8224       seizeTcConnectFail(signal);
8225       linkTcInConnectionlist(signal);
8226       tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[tftfHashNumber];
8227       ctcConnectFailHash[tftfHashNumber] = tcConnectptr.i;
8228       initTcConnectFail(signal);
8229       return;
8230     } else {
8231       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8232       if (tcConnectptr.p->tcOprec != ttcOprec) {
8233         jam();  /* FRAGMENTID = TC_OPREC HERE, LOOP ANOTHER TURN */
8234         tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
8235       } else {
8236         updateTcStateFail(signal);
8237         return;
8238       }//if
8239     }//if
8240   } while (1);
8241 }//Dbtc::findTcConnectFail()
8242 
8243 /*----------------------------------------------------------*/
8244 /*       INITIALISE AN API CONNECT FAIL RECORD              */
8245 /*----------------------------------------------------------*/
initApiConnectFail(Signal * signal)8246 void Dbtc::initApiConnectFail(Signal* signal)
8247 {
8248   apiConnectptr.p->transid[0] = ttransid1;
8249   apiConnectptr.p->transid[1] = ttransid2;
8250   apiConnectptr.p->firstTcConnect = RNIL;
8251   apiConnectptr.p->currSavePointId = 0;
8252   apiConnectptr.p->lastTcConnect = RNIL;
8253   tblockref = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
8254 
8255   apiConnectptr.p->tcBlockref = tblockref;
8256   apiConnectptr.p->ndbapiBlockref = 0;
8257   apiConnectptr.p->ndbapiConnect = 0;
8258   apiConnectptr.p->buddyPtr = RNIL;
8259   apiConnectptr.p->m_transaction_nodes.clear();
8260   apiConnectptr.p->singleUserMode = 0;
8261   setApiConTimer(apiConnectptr.i, 0, __LINE__);
8262   switch(ttransStatus){
8263   case LqhTransConf::Committed:
8264     jam();
8265     apiConnectptr.p->globalcheckpointid = tgci;
8266     apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
8267     break;
8268   case LqhTransConf::Prepared:
8269     jam();
8270     apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
8271     break;
8272   case LqhTransConf::Aborted:
8273     jam();
8274     apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
8275     break;
8276   case LqhTransConf::Marker:
8277     jam();
8278     apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
8279     break;
8280   default:
8281     jam();
8282     systemErrorLab(signal, __LINE__);
8283   }//if
8284   apiConnectptr.p->commitAckMarker = RNIL;
8285   if(LqhTransConf::getMarkerFlag(treqinfo)){
8286     jam();
8287     CommitAckMarkerPtr tmp;
8288     m_commitAckMarkerHash.seize(tmp);
8289 
8290     ndbrequire(tmp.i != RNIL);
8291 
8292     apiConnectptr.p->commitAckMarker = tmp.i;
8293     tmp.p->transid1      = ttransid1;
8294     tmp.p->transid2      = ttransid2;
8295     tmp.p->apiNodeId     = refToNode(tapplRef);
8296     tmp.p->noOfLqhs      = 1;
8297     tmp.p->lqhNodeId[0]  = tnodeid;
8298     tmp.p->apiConnectPtr = apiConnectptr.i;
8299 
8300 #if defined VM_TRACE || defined ERROR_INSERT
8301     {
8302       CommitAckMarkerPtr check;
8303       ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
8304     }
8305 #endif
8306     m_commitAckMarkerHash.add(tmp);
8307   }
8308 }//Dbtc::initApiConnectFail()
8309 
8310 /*------------------------------------------------------------*/
8311 /*       INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
8312 /*       THE TC CONNECT RECORD.                               */
8313 /*------------------------------------------------------------*/
initTcConnectFail(Signal * signal)8314 void Dbtc::initTcConnectFail(Signal* signal)
8315 {
8316   tcConnectptr.p->apiConnect = apiConnectptr.i;
8317   tcConnectptr.p->tcOprec = ttcOprec;
8318   Uint32 treplicaNo = LqhTransConf::getReplicaNo(treqinfo);
8319   for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
8320     tcConnectptr.p->failData[i] = LqhTransConf::InvalidStatus;
8321   }//for
8322   tcConnectptr.p->tcNodedata[treplicaNo] = tnodeid;
8323   tcConnectptr.p->failData[treplicaNo] = ttransStatus;
8324   tcConnectptr.p->lastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
8325   tcConnectptr.p->dirtyOp = LqhTransConf::getDirtyFlag(treqinfo);
8326 
8327 }//Dbtc::initTcConnectFail()
8328 
8329 /*----------------------------------------------------------*/
8330 /*       INITIALISE TC NODE FAIL RECORD.                    */
8331 /*----------------------------------------------------------*/
initTcFail(Signal * signal)8332 void Dbtc::initTcFail(Signal* signal)
8333 {
8334   tcNodeFailptr.i = 0;
8335   ptrAss(tcNodeFailptr, tcFailRecord);
8336   tcNodeFailptr.p->queueIndex = 0;
8337   tcNodeFailptr.p->failStatus = FS_IDLE;
8338 }//Dbtc::initTcFail()
8339 
8340 /*----------------------------------------------------------*/
8341 /*               RELEASE_TAKE_OVER                          */
8342 /*----------------------------------------------------------*/
releaseTakeOver(Signal * signal)8343 void Dbtc::releaseTakeOver(Signal* signal)
8344 {
8345   TcConnectRecordPtr rtoNextTcConnectptr;
8346 
8347   rtoNextTcConnectptr.i = apiConnectptr.p->firstTcConnect;
8348   do {
8349     jam();
8350     tcConnectptr.i = rtoNextTcConnectptr.i;
8351     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8352     rtoNextTcConnectptr.i = tcConnectptr.p->nextTcConnect;
8353     releaseTcConnectFail(signal);
8354   } while (rtoNextTcConnectptr.i != RNIL);
8355   releaseApiConnectFail(signal);
8356 }//Dbtc::releaseTakeOver()
8357 
8358 /*---------------------------------------------------------------------------*/
8359 /*                               SETUP_FAIL_DATA                             */
8360 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE      */
8361 /* FAILURE SITUATIONS.                                                       */
8362 /*---------------------------------------------------------------------------*/
setupFailData(Signal * signal)8363 void Dbtc::setupFailData(Signal* signal)
8364 {
8365   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8366   do {
8367     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8368     switch (tcConnectptr.p->tcConnectstate) {
8369     case OS_PREPARED:
8370     case OS_COMMITTING:
8371       jam();
8372       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
8373       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
8374 	jam();
8375 	/*-------------------------------------------------------------------
8376 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
8377 	 * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
8378 	 * COMMIT/ABORT DECISION.
8379 	 *------------------------------------------------------------------*/
8380 	tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
8381       }//for
8382       break;
8383     case OS_COMMITTED:
8384     case OS_COMPLETING:
8385       jam();
8386       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
8387       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
8388 	jam();
8389 	/*-------------------------------------------------------------------
8390 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
8391 	 * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
8392 	 * COMPLETE MESSAGE.
8393 	 *------------------------------------------------------------------*/
8394 	tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
8395       }//for
8396       break;
8397     case OS_COMPLETED:
8398       jam();
8399       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
8400       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
8401 	jam();
8402 	/*-------------------------------------------------------------------
8403 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
8404 	 * IN THIS CASE ALL LQH'S ARE COMPLETED.
8405 	 *-------------------------------------------------------------------*/
8406 	tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
8407       }//for
8408       break;
8409     default:
8410       jam();
8411       sendSystemError(signal, __LINE__);
8412       break;
8413     }//switch
8414     if (tabortInd != ZCOMMIT_SETUP) {
8415       jam();
8416       for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
8417         hostptr.i = tcConnectptr.p->tcNodedata[Ti];
8418         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
8419         if (hostptr.p->hostStatus != HS_ALIVE) {
8420           jam();
8421 	  /*-----------------------------------------------------------------
8422 	   * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
8423 	   *-----------------------------------------------------------------*/
8424           tabortInd = ZTRUE;
8425         }//if
8426       }//for
8427     }//if
8428     tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
8429     tcConnectptr.p->tcOprec = tcConnectptr.i;
8430     tcConnectptr.i = tcConnectptr.p->nextTcConnect;
8431   } while (tcConnectptr.i != RNIL);
8432   apiConnectptr.p->tcBlockref = cownref;
8433   apiConnectptr.p->currentTcConnect = apiConnectptr.p->firstTcConnect;
8434   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
8435   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
8436   apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
8437   tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
8438 }//Dbtc::setupFailData()
8439 
8440 /*----------------------------------------------------------*/
8441 /*       UPDATE THE STATE OF THE API CONNECT FOR THIS PART.   */
8442 /*----------------------------------------------------------*/
updateApiStateFail(Signal * signal)8443 void Dbtc::updateApiStateFail(Signal* signal)
8444 {
8445   if(LqhTransConf::getMarkerFlag(treqinfo)){
8446     jam();
8447     const Uint32 marker = apiConnectptr.p->commitAckMarker;
8448     if(marker == RNIL){
8449       jam();
8450 
8451       CommitAckMarkerPtr tmp;
8452       m_commitAckMarkerHash.seize(tmp);
8453       ndbrequire(tmp.i != RNIL);
8454 
8455       apiConnectptr.p->commitAckMarker = tmp.i;
8456       tmp.p->transid1      = ttransid1;
8457       tmp.p->transid2      = ttransid2;
8458       tmp.p->apiNodeId     = refToNode(tapplRef);
8459       tmp.p->noOfLqhs      = 1;
8460       tmp.p->lqhNodeId[0]  = tnodeid;
8461       tmp.p->apiConnectPtr = apiConnectptr.i;
8462 #if defined VM_TRACE || defined ERROR_INSERT
8463       {
8464 	CommitAckMarkerPtr check;
8465 	ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
8466       }
8467 #endif
8468       m_commitAckMarkerHash.add(tmp);
8469     } else {
8470       jam();
8471 
8472       CommitAckMarkerPtr tmp;
8473       tmp.i = marker;
8474       tmp.p = m_commitAckMarkerHash.getPtr(marker);
8475 
8476       const Uint32 noOfLqhs = tmp.p->noOfLqhs;
8477       ndbrequire(noOfLqhs < MAX_REPLICAS);
8478       tmp.p->lqhNodeId[noOfLqhs] = tnodeid;
8479       tmp.p->noOfLqhs = (noOfLqhs + 1);
8480     }
8481   }
8482 
8483   switch (ttransStatus) {
8484   case LqhTransConf::Committed:
8485     jam();
8486     switch (apiConnectptr.p->apiConnectstate) {
8487     case CS_FAIL_COMMITTING:
8488     case CS_FAIL_COMMITTED:
8489       jam();
8490       ndbrequire(tgci == apiConnectptr.p->globalcheckpointid);
8491       break;
8492     case CS_FAIL_PREPARED:
8493       jam();
8494       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
8495       apiConnectptr.p->globalcheckpointid = tgci;
8496       break;
8497     case CS_FAIL_COMPLETED:
8498       jam();
8499       apiConnectptr.p->globalcheckpointid = tgci;
8500       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
8501       break;
8502     default:
8503       jam();
8504       systemErrorLab(signal, __LINE__);
8505       break;
8506     }//switch
8507     break;
8508   case LqhTransConf::Prepared:
8509     jam();
8510     switch (apiConnectptr.p->apiConnectstate) {
8511     case CS_FAIL_COMMITTED:
8512       jam();
8513       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
8514       break;
8515     case CS_FAIL_ABORTED:
8516       jam();
8517       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
8518       break;
8519     case CS_FAIL_COMMITTING:
8520     case CS_FAIL_PREPARED:
8521     case CS_FAIL_ABORTING:
8522       jam();
8523       /*empty*/;
8524       break;
8525     default:
8526       jam();
8527       systemErrorLab(signal, __LINE__);
8528       break;
8529     }//switch
8530     break;
8531   case LqhTransConf::Aborted:
8532     jam();
8533     switch (apiConnectptr.p->apiConnectstate) {
8534     case CS_FAIL_COMMITTING:
8535     case CS_FAIL_COMMITTED:
8536       jam();
8537       systemErrorLab(signal, __LINE__);
8538       break;
8539     case CS_FAIL_PREPARED:
8540       jam();
8541       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
8542       break;
8543     case CS_FAIL_ABORTING:
8544     case CS_FAIL_ABORTED:
8545       jam();
8546       /*empty*/;
8547       break;
8548     default:
8549       jam();
8550       systemErrorLab(signal, __LINE__);
8551       break;
8552     }//switch
8553     break;
8554   case LqhTransConf::Marker:
8555     jam();
8556     break;
8557   default:
8558     jam();
8559     systemErrorLab(signal, __LINE__);
8560     break;
8561   }//switch
8562 }//Dbtc::updateApiStateFail()
8563 
8564 /*------------------------------------------------------------*/
8565 /*               UPDATE_TC_STATE_FAIL                         */
8566 /*                                                            */
8567 /*       WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
8568 /*       WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY      */
8569 /*       BETWEEN THE DIFFERENT REPLICAS.                      */
8570 /*------------------------------------------------------------*/
updateTcStateFail(Signal * signal)8571 void Dbtc::updateTcStateFail(Signal* signal)
8572 {
8573   const Uint8 treplicaNo     = LqhTransConf::getReplicaNo(treqinfo);
8574   const Uint8 tlastReplicaNo = LqhTransConf::getLastReplicaNo(treqinfo);
8575   const Uint8 tdirtyOp       = LqhTransConf::getDirtyFlag(treqinfo);
8576 
8577   TcConnectRecord * regTcPtr = tcConnectptr.p;
8578 
8579   ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
8580   ndbrequire(regTcPtr->failData[treplicaNo] == LqhTransConf::InvalidStatus);
8581   ndbrequire(regTcPtr->lastReplicaNo == tlastReplicaNo);
8582   ndbrequire(regTcPtr->dirtyOp == tdirtyOp);
8583 
8584   regTcPtr->tcNodedata[treplicaNo] = tnodeid;
8585   regTcPtr->failData[treplicaNo] = ttransStatus;
8586 }//Dbtc::updateTcStateFail()
8587 
execTCGETOPSIZEREQ(Signal * signal)8588 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
8589 {
8590   jamEntry();
8591   CRASH_INSERTION(8000);
8592 
8593   UintR Tuserpointer = signal->theData[0];         /* DBDIH POINTER         */
8594   BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
8595   signal->theData[0] = Tuserpointer;
8596   signal->theData[1] = coperationsize;
8597   sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
8598 }//Dbtc::execTCGETOPSIZEREQ()
8599 
execTC_CLOPSIZEREQ(Signal * signal)8600 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
8601 {
8602   jamEntry();
8603   CRASH_INSERTION(8001);
8604 
8605   tuserpointer = signal->theData[0];
8606   tusersblkref = signal->theData[1];
8607                                             /* DBDIH BLOCK REFERENCE         */
8608   coperationsize = 0;
8609   signal->theData[0] = tuserpointer;
8610   sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
8611 }//Dbtc::execTC_CLOPSIZEREQ()
8612 
8613 /* ######################################################################### */
8614 /* #######                        ERROR MODULE                       ####### */
8615 /* ######################################################################### */
tabStateErrorLab(Signal * signal)8616 void Dbtc::tabStateErrorLab(Signal* signal)
8617 {
8618   terrorCode = ZSTATE_ERROR;
8619   releaseAtErrorLab(signal);
8620 }//Dbtc::tabStateErrorLab()
8621 
wrongSchemaVersionErrorLab(Signal * signal)8622 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal)
8623 {
8624   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
8625 
8626   TableRecordPtr tabPtr;
8627   tabPtr.i = tcKeyReq->tableId;
8628   const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
8629   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
8630 
8631   terrorCode = tabPtr.p->getErrorCode(schemVer);
8632 
8633   abortErrorLab(signal);
8634 }//Dbtc::wrongSchemaVersionErrorLab()
8635 
noFreeConnectionErrorLab(Signal * signal)8636 void Dbtc::noFreeConnectionErrorLab(Signal* signal)
8637 {
8638   terrorCode = ZNO_FREE_TC_CONNECTION;
8639   abortErrorLab(signal);        /* RECORD. OTHERWISE GOTO ERRORHANDLING  */
8640 }//Dbtc::noFreeConnectionErrorLab()
8641 
aiErrorLab(Signal * signal)8642 void Dbtc::aiErrorLab(Signal* signal)
8643 {
8644   terrorCode = ZLENGTH_ERROR;
8645   abortErrorLab(signal);
8646 }//Dbtc::aiErrorLab()
8647 
seizeAttrbuferrorLab(Signal * signal)8648 void Dbtc::seizeAttrbuferrorLab(Signal* signal)
8649 {
8650   terrorCode = ZGET_ATTRBUF_ERROR;
8651   abortErrorLab(signal);
8652 }//Dbtc::seizeAttrbuferrorLab()
8653 
seizeDatabuferrorLab(Signal * signal)8654 void Dbtc::seizeDatabuferrorLab(Signal* signal)
8655 {
8656   terrorCode = ZGET_DATAREC_ERROR;
8657   releaseAtErrorLab(signal);
8658 }//Dbtc::seizeDatabuferrorLab()
8659 
releaseAtErrorLab(Signal * signal)8660 void Dbtc::releaseAtErrorLab(Signal* signal)
8661 {
8662   ptrGuard(tcConnectptr);
8663   tcConnectptr.p->tcConnectstate = OS_ABORTING;
8664   /*-------------------------------------------------------------------------*
8665    * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
8666    * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
8667    * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
8668    * TO HANDLE THIS PROBLEM.
8669    * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
8670    * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
8671    * ANY SIGNALS.
8672    *-------------------------------------------------------------------------*/
8673   tcConnectptr.p->noOfNodes = 0;
8674   abortErrorLab(signal);
8675 }//Dbtc::releaseAtErrorLab()
8676 
warningHandlerLab(Signal * signal,int line)8677 void Dbtc::warningHandlerLab(Signal* signal, int line)
8678 {
8679   ndbassert(false);
8680 }//Dbtc::warningHandlerLab()
8681 
systemErrorLab(Signal * signal,int line)8682 void Dbtc::systemErrorLab(Signal* signal, int line)
8683 {
8684   progError(line, NDBD_EXIT_NDBREQUIRE);
8685 }//Dbtc::systemErrorLab()
8686 
8687 
8688 /* ######################################################################### *
8689  * #######                        SCAN MODULE                        ####### *
8690  * ######################################################################### *
8691 
8692   The application orders a scan of a table.  We divide the scan into a scan on
8693   each fragment.  The scan uses the primary replicas since the scan might be
8694   used for an update in a separate transaction.
8695 
8696   Scans are always done as a separate transaction.  Locks from the scan
8697   can be overtaken by another transaction.  Scans can never lock the entire
8698   table.  Locks are released immediately after the read has been verified
8699   by the application. There is not even an option to leave the locks.
8700   The reason is that this would hurt real-time behaviour too much.
8701 
8702   -#  The first step in handling a scan of a table is to receive all signals
8703       defining the scan. If failures occur during this step we release all
8704       resource and reply with SCAN_TABREF providing the error code.
8705       If system load is too high, the request will not be allowed.
8706 
8707   -#  The second step retrieves the number of fragments that exist in the
8708       table. It also ensures that the table actually exist.  After this,
8709       the scan is ready to be parallelised.  The idea is that the receiving
8710       process (hereafter called delivery process) will start up a number
8711       of scan processes.  Each of these scan processes will
8712       independently scan one fragment at a time.  The delivery
8713       process object is the scan record and the scan process object is
8714       the scan fragment record plus the scan operation record.
8715 
8716   -#  The third step is thus performed in parallel. In the third step each
8717       scan process retrieves the primary replica of the fragment it will
8718       scan.  Then it starts the scan as soon as the load on that node permits.
8719 
8720   The LQH returns either when it retrieved the maximum number of tuples or
8721   when it has retrived at least one tuple and is hindered by a lock to
8722   retrieve the next tuple.  This is to ensure that a scan process never
8723   can be involved in a deadlock situation.
8724 
8725   When the scan process receives a number of tuples to report to the
8726   application it checks the state of the delivery process. Only one delivery
8727   at a time is handled by the application. Thus if the delivery process
8728   has already sent a number of tuples to the application this set of tuples
8729   are queued.
8730 
8731   When the application requests the next set of tuples it is immediately
8732   delivered if any are queued, otherwise it waits for the next scan
8733   process that is ready to deliver.
8734 
8735 
8736   ERROR HANDLING
8737 
8738   As already mentioned it is rather easy to handle errors before the scan
8739   processes have started.  In this case it is enough to release the resources
8740   and send SCAN_TAB_REF.
8741 
8742   If an error occurs in any of the scan processes then we have to stop all
8743   scan processes. We do however only stop the delivery process and ask
8744   the api to order us to close the scan.  The reason is that we can easily
8745   enter into difficult timing problems since the application and this
8746   block is out of synch we will thus always start by report the error to
8747   the application and wait for a close request. This error report uses the
8748   SCAN_TABREF signal with a special error code that the api must check for.
8749 
8750 
8751   CLOSING AN ACTIVE SCAN
8752 
8753   The application can close a scan for several reasons before it is completed.
8754   One reason was mentioned above where an error in a scan process led to a
8755   request to close the scan. Another reason could simply be that the
8756   application found what it looked for and is thus not interested in the
8757   rest of the scan.
8758 
8759   IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
8760 
8761   When a close scan request is received, all scan processes are stopped and all
8762   resources belonging to those scan processes are released. Stopping the scan
8763   processes most often includes communication with an LQH where the local scan
8764   is controlled. Finally all resources belonging to the scan is released and
8765   the SCAN_TABCONF is sent with an indication of that the scan is closed.
8766 
8767 
8768   CLOSING A COMPLETED SCAN
8769 
8770   When all scan processes are completed then a report is sent to the
8771   application which indicates that no more tuples can be fetched.
8772   The application will send a close scan and the same action as when
8773   closing an active scan is performed.
8774   In this case it will of course not find any active scan processes.
8775   It will even find all scan processes already released.
8776 
8777   The reason for requiring the api to close the scan is the same as above.
8778   It is to avoid any timing problems due to that the api and this block
8779   is out of synch.
8780 
8781   * ######################################################################## */
execSCAN_TABREQ(Signal * signal)8782 void Dbtc::execSCAN_TABREQ(Signal* signal)
8783 {
8784   const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
8785   const Uint32 ri = scanTabReq->requestInfo;
8786   const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
8787   const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
8788   const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
8789   const Uint32 transid1 = scanTabReq->transId1;
8790   const Uint32 transid2 = scanTabReq->transId2;
8791   const Uint32 tmpXX = scanTabReq->buddyConPtr;
8792   const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
8793   Uint32 currSavePointId = 0;
8794 
8795   Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
8796   Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
8797   Uint32 scanParallel = scanConcurrency;
8798   Uint32 errCode;
8799   ScanRecordPtr scanptr;
8800 
8801   jamEntry();
8802 
8803   SegmentedSectionPtr api_op_ptr;
8804   signal->getSection(api_op_ptr, 0);
8805   copy(&cdata[0], api_op_ptr);
8806   releaseSections(signal);
8807 
8808   apiConnectptr.i = scanTabReq->apiConnectPtr;
8809   tabptr.i = scanTabReq->tableId;
8810 
8811   if (apiConnectptr.i >= capiConnectFilesize)
8812   {
8813     jam();
8814     warningHandlerLab(signal, __LINE__);
8815     return;
8816   }//if
8817 
8818   ptrAss(apiConnectptr, apiConnectRecord);
8819   ApiConnectRecord * transP = apiConnectptr.p;
8820 
8821   if (transP->apiConnectstate != CS_CONNECTED) {
8822     jam();
8823     // could be left over from TCKEYREQ rollback
8824     if (transP->apiConnectstate == CS_ABORTING &&
8825 	transP->abortState == AS_IDLE) {
8826       jam();
8827     } else if(transP->apiConnectstate == CS_STARTED &&
8828 	      transP->firstTcConnect == RNIL){
8829       jam();
8830       // left over from simple/dirty read
8831     } else {
8832       jam();
8833       jamLine(transP->apiConnectstate);
8834       errCode = ZSTATE_ERROR;
8835       goto SCAN_TAB_error_no_state_change;
8836     }
8837   }
8838 
8839   if(tabptr.i >= ctabrecFilesize)
8840   {
8841     errCode = ZUNKNOWN_TABLE_ERROR;
8842     goto SCAN_TAB_error;
8843   }
8844 
8845   ptrAss(tabptr, tableRecord);
8846   if ((aiLength == 0) ||
8847       (!tabptr.p->checkTable(schemaVersion)) ||
8848       (scanConcurrency == 0) ||
8849       (cfirstfreeTcConnect == RNIL) ||
8850       (cfirstfreeScanrec == RNIL)) {
8851     goto SCAN_error_check;
8852   }
8853   if (buddyPtr != RNIL) {
8854     jam();
8855     ApiConnectRecordPtr buddyApiPtr;
8856     buddyApiPtr.i = buddyPtr;
8857     ptrCheckGuard(buddyApiPtr, capiConnectFilesize, apiConnectRecord);
8858     if ((transid1 == buddyApiPtr.p->transid[0]) &&
8859 	(transid2 == buddyApiPtr.p->transid[1])) {
8860       jam();
8861 
8862       if (buddyApiPtr.p->apiConnectstate == CS_ABORTING) {
8863 	// transaction has been aborted
8864 	jam();
8865 	errCode = buddyApiPtr.p->returncode;
8866 	goto SCAN_TAB_error;
8867       }//if
8868       currSavePointId = buddyApiPtr.p->currSavePointId;
8869       buddyApiPtr.p->currSavePointId++;
8870     }
8871   }
8872 
8873   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
8874       getNodeState().getSingleUserApi() !=
8875       refToNode(apiConnectptr.p->ndbapiBlockref))
8876   {
8877     errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
8878     goto SCAN_TAB_error;
8879   }
8880 
8881   seizeTcConnect(signal);
8882   tcConnectptr.p->apiConnect = apiConnectptr.i;
8883   tcConnectptr.p->tcConnectstate = OS_WAIT_SCAN;
8884   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
8885 
8886   seizeCacheRecord(signal);
8887   cachePtr.p->keylen = keyLen;
8888   cachePtr.p->save1 = 0;
8889   cachePtr.p->distributionKey = scanTabReq->distributionKey;
8890   cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
8891   scanptr = seizeScanrec(signal);
8892 
8893   ndbrequire(transP->apiScanRec == RNIL);
8894   ndbrequire(scanptr.p->scanApiRec == RNIL);
8895 
8896   initScanrec(scanptr, scanTabReq, scanParallel, noOprecPerFrag);
8897 
8898   transP->apiScanRec = scanptr.i;
8899   transP->returncode = 0;
8900   transP->transid[0] = transid1;
8901   transP->transid[1] = transid2;
8902   transP->buddyPtr   = buddyPtr;
8903 
8904   // The scan is started
8905   transP->apiConnectstate = CS_START_SCAN;
8906   transP->currSavePointId = currSavePointId;
8907 
8908   /**********************************************************
8909   * We start the timer on scanRec to be able to discover a
8910   * timeout in the API the API now is in charge!
8911   ***********************************************************/
8912   setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
8913   updateBuddyTimer(apiConnectptr);
8914 
8915   /***********************************************************
8916    * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
8917    * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
8918    * IF ANY TO RECEIVE.
8919    **********************************************************/
8920   scanptr.p->scanState = ScanRecord::WAIT_AI;
8921 
8922   if (ERROR_INSERTED(8038))
8923   {
8924     /**
8925      * Force API_FAILREQ
8926      */
8927     DisconnectRep * const  rep = (DisconnectRep *)signal->getDataPtrSend();
8928     rep->nodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
8929     rep->err = 8038;
8930 
8931     EXECUTE_DIRECT(CMVMI, GSN_DISCONNECT_REP, signal, 2);
8932     CLEAR_ERROR_INSERT_VALUE;
8933   }
8934 
8935   return;
8936 
8937  SCAN_error_check:
8938   if (aiLength == 0) {
8939     jam()
8940     errCode = ZSCAN_AI_LEN_ERROR;
8941     goto SCAN_TAB_error;
8942   }//if
8943   if (!tabptr.p->checkTable(schemaVersion)){
8944     jam();
8945     errCode = tabptr.p->getErrorCode(schemaVersion);
8946     goto SCAN_TAB_error;
8947   }//if
8948   if (scanConcurrency == 0) {
8949     jam();
8950     errCode = ZNO_CONCURRENCY_ERROR;
8951     goto SCAN_TAB_error;
8952   }//if
8953   if (cfirstfreeTcConnect == RNIL) {
8954     jam();
8955     errCode = ZNO_FREE_TC_CONNECTION;
8956     goto SCAN_TAB_error;
8957   }//if
8958   ndbrequire(cfirstfreeScanrec == RNIL);
8959   jam();
8960   errCode = ZNO_SCANREC_ERROR;
8961   goto SCAN_TAB_error;
8962 
8963 SCAN_TAB_error:
8964   jam();
8965   /**
8966    * Prepare for up coming ATTRINFO/KEYINFO
8967    */
8968   transP->apiConnectstate = CS_ABORTING;
8969   transP->abortState = AS_IDLE;
8970   transP->transid[0] = transid1;
8971   transP->transid[1] = transid2;
8972 
8973 SCAN_TAB_error_no_state_change:
8974 
8975   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
8976   ref->apiConnectPtr = transP->ndbapiConnect;
8977   ref->transId1 = transid1;
8978   ref->transId2 = transid2;
8979   ref->errorCode  = errCode;
8980   ref->closeNeeded = 0;
8981   sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
8982 	     signal, ScanTabRef::SignalLength, JBB);
8983   return;
8984 }//Dbtc::execSCAN_TABREQ()
8985 
initScanrec(ScanRecordPtr scanptr,const ScanTabReq * scanTabReq,UintR scanParallel,UintR noOprecPerFrag)8986 void Dbtc::initScanrec(ScanRecordPtr scanptr,
8987 		       const ScanTabReq * scanTabReq,
8988 		       UintR scanParallel,
8989 		       UintR noOprecPerFrag)
8990 {
8991   const UintR ri = scanTabReq->requestInfo;
8992   scanptr.p->scanTcrec = tcConnectptr.i;
8993   scanptr.p->scanApiRec = apiConnectptr.i;
8994   scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
8995   scanptr.p->scanKeyLen = scanTabReq->attrLenKeyLen >> 16;
8996   scanptr.p->scanTableref = tabptr.i;
8997   scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
8998   scanptr.p->scanParallel = scanParallel;
8999   scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
9000   scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
9001   scanptr.p->batch_size_rows = noOprecPerFrag;
9002 
9003   Uint32 tmp = 0;
9004   ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
9005   ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
9006   ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
9007   ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
9008   ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
9009   ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
9010   ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
9011   ScanFragReq::setAttrLen(tmp, scanTabReq->attrLenKeyLen & 0xFFFF);
9012   ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
9013 
9014   scanptr.p->scanRequestInfo = tmp;
9015   scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
9016   scanptr.p->scanState = ScanRecord::RUNNING;
9017   scanptr.p->m_queued_count = 0;
9018 
9019   ScanFragList list(c_scan_frag_pool,
9020 		    scanptr.p->m_running_scan_frags);
9021   for (Uint32 i = 0; i < scanParallel; i++) {
9022     jam();
9023     ScanFragRecPtr ptr;
9024     ndbrequire(list.seize(ptr));
9025     ptr.p->scanFragState = ScanFragRec::IDLE;
9026     ptr.p->scanRec = scanptr.i;
9027     ptr.p->scanFragId = 0;
9028     ptr.p->m_apiPtr = cdata[i];
9029   }//for
9030 
9031   (* (ScanTabReq::getRangeScanFlag(ri) ?
9032       &c_counters.c_range_scan_count :
9033       &c_counters.c_scan_count))++;
9034 }//Dbtc::initScanrec()
9035 
scanTabRefLab(Signal * signal,Uint32 errCode)9036 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode)
9037 {
9038   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
9039   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9040   ref->transId1 = apiConnectptr.p->transid[0];
9041   ref->transId2 = apiConnectptr.p->transid[1];
9042   ref->errorCode  = errCode;
9043   ref->closeNeeded = 0;
9044   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
9045 	     signal, ScanTabRef::SignalLength, JBB);
9046 }//Dbtc::scanTabRefLab()
9047 
9048 /*---------------------------------------------------------------------------*/
9049 /*                                                                           */
9050 /*       RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST.                       */
9051 /*---------------------------------------------------------------------------*/
scanAttrinfoLab(Signal * signal,UintR Tlen)9052 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen)
9053 {
9054   ScanRecordPtr scanptr;
9055   scanptr.i = apiConnectptr.p->apiScanRec;
9056   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9057   tcConnectptr.i = scanptr.p->scanTcrec;
9058   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9059   cachePtr.i = apiConnectptr.p->cachePtr;
9060   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
9061   CacheRecord * const regCachePtr = cachePtr.p;
9062   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
9063 
9064   regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
9065   if (regCachePtr->currReclenAi < scanptr.p->scanAiLength) {
9066     if (cfirstfreeAttrbuf == RNIL) {
9067       goto scanAttrinfo_attrbuf_error;
9068     }//if
9069     saveAttrbuf(signal);
9070   } else {
9071     if (regCachePtr->currReclenAi > scanptr.p->scanAiLength) {
9072       goto scanAttrinfo_len_error;
9073     } else {
9074       /* CURR_RECLEN_AI = SCAN_AI_LENGTH */
9075       if (cfirstfreeAttrbuf == RNIL) {
9076         goto scanAttrinfo_attrbuf2_error;
9077       }//if
9078       saveAttrbuf(signal);
9079       /**************************************************
9080        * WE HAVE NOW RECEIVED ALL INFORMATION CONCERNING
9081        * THIS SCAN. WE ARE READY TO START THE ACTUAL
9082        * EXECUTION OF THE SCAN QUERY
9083        **************************************************/
9084       diFcountReqLab(signal, scanptr);
9085       return;
9086     }//if
9087   }//if
9088   return;
9089 
9090 scanAttrinfo_attrbuf_error:
9091   jam();
9092   abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
9093   return;
9094 
9095 scanAttrinfo_attrbuf2_error:
9096   jam();
9097   abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true);
9098   return;
9099 
9100 scanAttrinfo_len_error:
9101   jam();
9102   abortScanLab(signal, scanptr, ZLENGTH_ERROR, true);
9103   return;
9104 }//Dbtc::scanAttrinfoLab()
9105 
diFcountReqLab(Signal * signal,ScanRecordPtr scanptr)9106 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
9107 {
9108   /**
9109    * Check so that the table is not being dropped
9110    */
9111   TableRecordPtr tabPtr;
9112   tabPtr.i = scanptr.p->scanTableref;
9113   tabPtr.p = &tableRecord[tabPtr.i];
9114   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
9115     ;
9116   } else {
9117     abortScanLab(signal, scanptr,
9118 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
9119 		 true);
9120     return;
9121   }
9122 
9123   scanptr.p->scanNextFragId = 0;
9124   scanptr.p->m_booked_fragments_count= 0;
9125   scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
9126 
9127   if(!cachePtr.p->distributionKeyIndicator)
9128   {
9129     jam();
9130     /*************************************************
9131      * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
9132      * WE MUST FIRST GET THE NUMBER OF  FRAGMENTS IN THE TABLE.
9133      ***************************************************/
9134     DihFragCountReq * const req = (DihFragCountReq*)signal->getDataPtrSend();
9135     req->m_connectionData = tcConnectptr.p->dihConnectptr;
9136     req->m_tableRef = scanptr.p->scanTableref;
9137     sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal,
9138                DihFragCountReq::SignalLength, JBB);
9139   }
9140   else
9141   {
9142     signal->theData[0] = tcConnectptr.p->dihConnectptr;
9143     signal->theData[1] = tabPtr.i;
9144     signal->theData[2] = cachePtr.p->distributionKey;
9145     EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
9146     UintR TerrorIndicator = signal->theData[0];
9147     jamEntry();
9148     if (TerrorIndicator != 0) {
9149       DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
9150       ref->m_connectionData = tcConnectptr.i;
9151       ref->m_error = signal->theData[1];
9152       execDI_FCOUNTREF(signal);
9153       return;
9154     }
9155 
9156     UintR Tdata1 = signal->theData[1];
9157     scanptr.p->scanNextFragId = Tdata1;
9158     DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
9159     conf->m_connectionData = tcConnectptr.i;
9160     conf->m_fragmentCount = 1; // Frag count
9161     execDI_FCOUNTCONF(signal);
9162   }
9163   return;
9164 }//Dbtc::diFcountReqLab()
9165 
9166 /********************************************************************
9167  * execDI_FCOUNTCONF
9168  *
9169  * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
9170  * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
9171  * THESE WILL SCAN ONE FRAGMENT AT A TIME. THEY WILL CONTINUE THIS
9172  * UNTIL THERE ARE NO MORE FRAGMENTS TO SCAN OR UNTIL THE APPLICATION
9173  * CLOSES THE SCAN.
9174  ********************************************************************/
execDI_FCOUNTCONF(Signal * signal)9175 void Dbtc::execDI_FCOUNTCONF(Signal* signal)
9176 {
9177   jamEntry();
9178   DihFragCountConf * const conf = (DihFragCountConf*)signal->getDataPtr();
9179   tcConnectptr.i = conf->m_connectionData;
9180   Uint32 tfragCount = conf->m_fragmentCount;
9181   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9182   apiConnectptr.i = tcConnectptr.p->apiConnect;
9183   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9184   ScanRecordPtr scanptr;
9185   scanptr.i = apiConnectptr.p->apiScanRec;
9186   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9187   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
9188   if (apiConnectptr.p->apiFailState == ZTRUE) {
9189     jam();
9190     releaseScanResources(scanptr, true);
9191     handleApiFailState(signal, apiConnectptr.i);
9192     return;
9193   }//if
9194   if (tfragCount == 0) {
9195     jam();
9196     abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true);
9197     return;
9198   }//if
9199 
9200   /**
9201    * Check so that the table is not being dropped
9202    */
9203   TableRecordPtr tabPtr;
9204   tabPtr.i = scanptr.p->scanTableref;
9205   tabPtr.p = &tableRecord[tabPtr.i];
9206   if (tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)){
9207     ;
9208   } else {
9209     abortScanLab(signal, scanptr,
9210 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
9211 		 true);
9212     return;
9213   }
9214 
9215   scanptr.p->scanParallel = tfragCount;
9216   scanptr.p->scanNoFrag = tfragCount;
9217   scanptr.p->scanState = ScanRecord::RUNNING;
9218 
9219   setApiConTimer(apiConnectptr.i, 0, __LINE__);
9220   updateBuddyTimer(apiConnectptr);
9221 
9222   ScanFragRecPtr ptr;
9223   ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9224   for (list.first(ptr); !ptr.isNull() && tfragCount;
9225        list.next(ptr), tfragCount--){
9226     jam();
9227 
9228     ptr.p->lqhBlockref = 0;
9229     ptr.p->startFragTimer(ctcTimer);
9230     ptr.p->scanFragId = scanptr.p->scanNextFragId++;
9231     ptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
9232     ptr.p->startFragTimer(ctcTimer);
9233 
9234     signal->theData[0] = tcConnectptr.p->dihConnectptr;
9235     signal->theData[1] = ptr.i;
9236     signal->theData[2] = scanptr.p->scanTableref;
9237     signal->theData[3] = ptr.p->scanFragId;
9238     sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
9239   }//for
9240 
9241   ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
9242   for (; !ptr.isNull();)
9243   {
9244     ptr.p->m_ops = 0;
9245     ptr.p->m_totalLen = 0;
9246     ptr.p->m_scan_frag_conf_status = 1;
9247     ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
9248     ptr.p->stopFragTimer();
9249 
9250     ScanFragRecPtr tmp = ptr;
9251     list.next(ptr);
9252     list.remove(tmp);
9253     queued.add(tmp);
9254     scanptr.p->m_queued_count++;
9255   }
9256 }//Dbtc::execDI_FCOUNTCONF()
9257 
9258 /******************************************************
9259  * execDI_FCOUNTREF
9260  ******************************************************/
execDI_FCOUNTREF(Signal * signal)9261 void Dbtc::execDI_FCOUNTREF(Signal* signal)
9262 {
9263   jamEntry();
9264   DihFragCountRef * const ref = (DihFragCountRef*)signal->getDataPtr();
9265   tcConnectptr.i = ref->m_connectionData;
9266   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9267   const Uint32 errCode = ref->m_error;
9268   apiConnectptr.i = tcConnectptr.p->apiConnect;
9269   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9270   ScanRecordPtr scanptr;
9271   scanptr.i = apiConnectptr.p->apiScanRec;
9272   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9273   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_FRAGMENT_COUNT);
9274   if (apiConnectptr.p->apiFailState == ZTRUE) {
9275     jam();
9276     releaseScanResources(scanptr, true);
9277     handleApiFailState(signal, apiConnectptr.i);
9278     return;
9279   }//if
9280   abortScanLab(signal, scanptr, errCode, true);
9281 }//Dbtc::execDI_FCOUNTREF()
9282 
abortScanLab(Signal * signal,ScanRecordPtr scanptr,Uint32 errCode,bool not_started)9283 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
9284 			bool not_started)
9285 {
9286   scanTabRefLab(signal, errCode);
9287   releaseScanResources(scanptr, not_started);
9288 }//Dbtc::abortScanLab()
9289 
releaseScanResources(ScanRecordPtr scanPtr,bool not_started)9290 void Dbtc::releaseScanResources(ScanRecordPtr scanPtr,
9291 				bool not_started)
9292 {
9293   if (apiConnectptr.p->cachePtr != RNIL) {
9294     cachePtr.i = apiConnectptr.p->cachePtr;
9295     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
9296     releaseKeys();
9297     releaseAttrinfo();
9298   }//if
9299   tcConnectptr.i = scanPtr.p->scanTcrec;
9300   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9301   releaseTcCon();
9302 
9303   if (not_started)
9304   {
9305     jam();
9306     ScanFragList run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
9307     ScanFragList queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
9308     run.release();
9309     queue.release();
9310   }
9311 
9312   ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
9313   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
9314   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
9315 
9316   ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
9317   ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
9318 
9319   // link into free list
9320   scanPtr.p->nextScan = cfirstfreeScanrec;
9321   scanPtr.p->scanState = ScanRecord::IDLE;
9322   scanPtr.p->scanTcrec = RNIL;
9323   scanPtr.p->scanApiRec = RNIL;
9324   cfirstfreeScanrec = scanPtr.i;
9325 
9326   apiConnectptr.p->apiScanRec = RNIL;
9327   apiConnectptr.p->apiConnectstate = CS_CONNECTED;
9328   setApiConTimer(apiConnectptr.i, 0, __LINE__);
9329 }//Dbtc::releaseScanResources()
9330 
9331 
9332 /****************************************************************
9333  * execDIGETPRIMCONF
9334  *
9335  * WE HAVE RECEIVED THE PRIMARY NODE OF THIS FRAGMENT.
9336  * WE ARE NOW READY TO ASK  FOR PERMISSION TO LOAD THIS
9337  * SPECIFIC NODE WITH A SCAN OPERATION.
9338  ****************************************************************/
execDIGETPRIMCONF(Signal * signal)9339 void Dbtc::execDIGETPRIMCONF(Signal* signal)
9340 {
9341   jamEntry();
9342   //  tcConnectptr.i in theData[0] is not used
9343   scanFragptr.i = signal->theData[1];
9344   c_scan_frag_pool.getPtr(scanFragptr);
9345 
9346   tnodeid = signal->theData[2];
9347   arrGuard(tnodeid, MAX_NDB_NODES);
9348 
9349   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
9350   scanFragptr.p->stopFragTimer();
9351 
9352   ScanRecordPtr scanptr;
9353   scanptr.i = scanFragptr.p->scanRec;
9354   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9355 
9356   /**
9357    * This must be false as select count(*) otherwise
9358    *   can "pass" committing on backup fragments and
9359    *   get incorrect row count
9360    */
9361   if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
9362   {
9363     jam();
9364     Uint32 max = 3+signal->theData[6];
9365     Uint32 nodeid = getOwnNodeId();
9366     for(Uint32 i = 3; i<max; i++)
9367       if(signal->theData[i] ==  nodeid)
9368       {
9369 	jam();
9370 	tnodeid = nodeid;
9371 	break;
9372       }
9373   }
9374 
9375   {
9376     /**
9377      * Check table
9378      */
9379     TableRecordPtr tabPtr;
9380     tabPtr.i = scanptr.p->scanTableref;
9381     ptrAss(tabPtr, tableRecord);
9382     Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
9383     if(tabPtr.p->checkTable(schemaVersion) == false){
9384       jam();
9385       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9386 
9387       run.release(scanFragptr);
9388       scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
9389       return;
9390     }
9391   }
9392 
9393   tcConnectptr.i = scanptr.p->scanTcrec;
9394   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9395   apiConnectptr.i = scanptr.p->scanApiRec;
9396   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9397   cachePtr.i = apiConnectptr.p->cachePtr;
9398   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
9399   switch (scanptr.p->scanState) {
9400   case ScanRecord::CLOSING_SCAN:
9401     jam();
9402     updateBuddyTimer(apiConnectptr);
9403     {
9404       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9405 
9406       run.release(scanFragptr);
9407     }
9408     close_scan_req_send_conf(signal, scanptr);
9409     return;
9410   default:
9411     jam();
9412     /*empty*/;
9413     break;
9414   }//switch
9415   Uint32 ref = calcLqhBlockRef(tnodeid);
9416   scanFragptr.p->lqhBlockref = ref;
9417   scanFragptr.p->m_connectCount = getNodeInfo(tnodeid).m_connectCount;
9418   sendScanFragReq(signal, scanptr.p, scanFragptr.p);
9419   if(ERROR_INSERTED(8035))
9420     globalTransporterRegistry.performSend();
9421   attrbufptr.i = cachePtr.p->firstAttrbuf;
9422   while (attrbufptr.i != RNIL) {
9423     jam();
9424     ptrCheckGuard(attrbufptr, cattrbufFilesize, attrbufRecord);
9425     sendAttrinfo(signal,
9426                  scanFragptr.i,
9427                  attrbufptr.p,
9428                  ref);
9429     attrbufptr.i = attrbufptr.p->attrbuf[ZINBUF_NEXT];
9430     if(ERROR_INSERTED(8035))
9431       globalTransporterRegistry.performSend();
9432   }//while
9433   scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9434   scanFragptr.p->startFragTimer(ctcTimer);
9435   updateBuddyTimer(apiConnectptr);
9436   /*********************************************
9437    * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
9438    * WAIT FOR THE FIRST SCANNED RECORDS
9439    *********************************************/
9440 }//Dbtc::execDIGETPRIMCONF
9441 
9442 /***************************************************
9443  * execDIGETPRIMREF
9444  *
9445  * WE ARE NOW FORCED TO STOP THE SCAN. THIS ERROR
9446  * IS NOT RECOVERABLE SINCE THERE IS A PROBLEM WITH
9447  * FINDING A PRIMARY REPLICA OF A CERTAIN FRAGMENT.
9448  ***************************************************/
execDIGETPRIMREF(Signal * signal)9449 void Dbtc::execDIGETPRIMREF(Signal* signal)
9450 {
9451   jamEntry();
9452   // tcConnectptr.i in theData[0] is not used.
9453   scanFragptr.i = signal->theData[1];
9454   const Uint32 errCode = signal->theData[2];
9455   c_scan_frag_pool.getPtr(scanFragptr);
9456   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::WAIT_GET_PRIMCONF);
9457 
9458   ScanRecordPtr scanptr;
9459   scanptr.i = scanFragptr.p->scanRec;
9460   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9461 
9462   ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9463 
9464   run.release(scanFragptr);
9465 
9466   scanError(signal, scanptr, errCode);
9467 }//Dbtc::execDIGETPRIMREF()
9468 
9469 /**
9470  * Dbtc::execSCAN_FRAGREF
9471  *  Our attempt to scan a fragment was refused
9472  *  set error code and close all other fragment
9473  *  scan's belonging to this scan
9474  */
execSCAN_FRAGREF(Signal * signal)9475 void Dbtc::execSCAN_FRAGREF(Signal* signal)
9476 {
9477   const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
9478 
9479   jamEntry();
9480   const Uint32 errCode = ref->errorCode;
9481 
9482   scanFragptr.i = ref->senderData;
9483   c_scan_frag_pool.getPtr(scanFragptr);
9484 
9485   ScanRecordPtr scanptr;
9486   scanptr.i = scanFragptr.p->scanRec;
9487   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9488 
9489   apiConnectptr.i = scanptr.p->scanApiRec;
9490   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9491 
9492   Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
9493   Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
9494   transid1 = transid1 | transid2;
9495   if (transid1 != 0) {
9496     jam();
9497     systemErrorLab(signal, __LINE__);
9498   }//if
9499 
9500   /**
9501    * Set errorcode, close connection to this lqh fragment,
9502    * stop fragment timer and call scanFragError to start
9503    * close of the other fragment scans
9504    */
9505   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
9506   {
9507     scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
9508     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9509 
9510     run.release(scanFragptr);
9511     scanFragptr.p->stopFragTimer();
9512   }
9513   scanError(signal, scanptr, errCode);
9514 }//Dbtc::execSCAN_FRAGREF()
9515 
9516 /**
9517  * Dbtc::scanError
9518  *
9519  * Called when an error occurs during
9520  */
scanError(Signal * signal,ScanRecordPtr scanptr,Uint32 errorCode)9521 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
9522 {
9523   jam();
9524   ScanRecord* scanP = scanptr.p;
9525 
9526   DEBUG("scanError, errorCode = "<< errorCode <<
9527 	", scanState = " << scanptr.p->scanState);
9528 
9529   apiConnectptr.i = scanP->scanApiRec;
9530   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9531   ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
9532 
9533   if(scanP->scanState == ScanRecord::CLOSING_SCAN){
9534     jam();
9535     close_scan_req_send_conf(signal, scanptr);
9536     return;
9537   }
9538 
9539   ndbrequire(scanP->scanState == ScanRecord::RUNNING);
9540 
9541   /**
9542    * Close scan wo/ having received an order to do so
9543    */
9544   close_scan_req(signal, scanptr, false);
9545 
9546   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
9547   if(apiFail){
9548     jam();
9549     return;
9550   }
9551 
9552   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
9553   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9554   ref->transId1 = apiConnectptr.p->transid[0];
9555   ref->transId2 = apiConnectptr.p->transid[1];
9556   ref->errorCode  = errorCode;
9557   ref->closeNeeded = 1;
9558   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
9559 	     signal, ScanTabRef::SignalLength, JBB);
9560 }//Dbtc::scanError()
9561 
9562 /************************************************************
9563  * execSCAN_FRAGCONF
9564  *
9565  * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
9566  * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
9567  ************************************************************/
execSCAN_FRAGCONF(Signal * signal)9568 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
9569 {
9570   Uint32 transid1, transid2, total_len;
9571   jamEntry();
9572 
9573   const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
9574   const Uint32 noCompletedOps = conf->completedOps;
9575   const Uint32 status = conf->fragmentCompleted;
9576 
9577   scanFragptr.i = conf->senderData;
9578   c_scan_frag_pool.getPtr(scanFragptr);
9579 
9580   ScanRecordPtr scanptr;
9581   scanptr.i = scanFragptr.p->scanRec;
9582   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9583 
9584   apiConnectptr.i = scanptr.p->scanApiRec;
9585   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
9586 
9587   transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
9588   transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
9589   total_len= conf->total_len;
9590   transid1 = transid1 | transid2;
9591   if (transid1 != 0) {
9592     jam();
9593     systemErrorLab(signal, __LINE__);
9594   }//if
9595 
9596   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
9597 
9598   if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
9599     jam();
9600     if(status == 0){
9601       /**
9602        * We have started closing = we sent a close -> ignore this
9603        */
9604       return;
9605     } else {
9606       jam();
9607       ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9608 
9609       run.release(scanFragptr);
9610       scanFragptr.p->stopFragTimer();
9611       scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
9612     }
9613     close_scan_req_send_conf(signal, scanptr);
9614     return;
9615   }
9616 
9617   if(noCompletedOps == 0 && status != 0 &&
9618      scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count < scanptr.p->scanNoFrag){
9619     /**
9620      * Start on next fragment
9621      */
9622     scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
9623     scanFragptr.p->startFragTimer(ctcTimer);
9624 
9625     tcConnectptr.i = scanptr.p->scanTcrec;
9626     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9627     scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
9628     signal->theData[0] = tcConnectptr.p->dihConnectptr;
9629     signal->theData[1] = scanFragptr.i;
9630     signal->theData[2] = scanptr.p->scanTableref;
9631     signal->theData[3] = scanFragptr.p->scanFragId;
9632     sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
9633     return;
9634   }
9635  /*
9636   Uint32 totalLen = 0;
9637   for(Uint32 i = 0; i<noCompletedOps; i++){
9638     Uint32 tmp = conf->opReturnDataLen[i];
9639     totalLen += tmp;
9640   }
9641  */
9642   {
9643     ScanFragList run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
9644     ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
9645 
9646     run.remove(scanFragptr);
9647     queued.add(scanFragptr);
9648     scanptr.p->m_queued_count++;
9649   }
9650 
9651   scanFragptr.p->m_scan_frag_conf_status = status;
9652   scanFragptr.p->m_ops = noCompletedOps;
9653   scanFragptr.p->m_totalLen = total_len;
9654   scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
9655   scanFragptr.p->stopFragTimer();
9656 
9657   if(scanptr.p->m_queued_count > /** Min */ 0){
9658     jam();
9659     sendScanTabConf(signal, scanptr);
9660   }
9661 }//Dbtc::execSCAN_FRAGCONF()
9662 
9663 /****************************************************************************
9664  * execSCAN_NEXTREQ
9665  *
9666  * THE APPLICATION HAVE PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
9667  * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
9668  ****************************************************************************/
execSCAN_NEXTREQ(Signal * signal)9669 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
9670 {
9671   const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
9672   const UintR transid1 = req->transId1;
9673   const UintR transid2 = req->transId2;
9674   const UintR stopScan = req->stopScan;
9675 
9676   jamEntry();
9677 
9678   apiConnectptr.i = req->apiConnectPtr;
9679   if (apiConnectptr.i >= capiConnectFilesize) {
9680     jam();
9681     warningHandlerLab(signal, __LINE__);
9682     return;
9683   }//if
9684   ptrAss(apiConnectptr, apiConnectRecord);
9685 
9686   /**
9687    * Check transid
9688    */
9689   const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
9690   const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
9691   if ((ctransid1 | ctransid2) != 0){
9692     ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
9693     ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9694     ref->transId1 = transid1;
9695     ref->transId2 = transid2;
9696     ref->errorCode  = ZSTATE_ERROR;
9697     ref->closeNeeded = 0;
9698     sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
9699 	       signal, ScanTabRef::SignalLength, JBB);
9700     DEBUG("Wrong transid");
9701     return;
9702   }
9703 
9704   /**
9705    * Check state of API connection
9706    */
9707   if (apiConnectptr.p->apiConnectstate != CS_START_SCAN) {
9708     jam();
9709     if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
9710       jam();
9711       /*********************************************************************
9712        * The application sends a SCAN_NEXTREQ after experiencing a time-out.
9713        *  We will send a SCAN_TABREF to indicate a time-out occurred.
9714        *********************************************************************/
9715       DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
9716       ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
9717       ndbrequire(false); //B2 indication of strange things going on
9718       scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2);
9719       return;
9720     }
9721     DEBUG("scanTabRefLab: ZSTATE_ERROR");
9722     DEBUG("  apiConnectstate="<<apiConnectptr.p->apiConnectstate);
9723     ndbrequire(false); //B2 indication of strange things going on
9724     scanTabRefLab(signal, ZSTATE_ERROR);
9725     return;
9726   }//if
9727 
9728   /*******************************************************
9729    * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
9730    ********************************************************/
9731   // Stop the timer that is used to check for timeout in the API
9732   setApiConTimer(apiConnectptr.i, 0, __LINE__);
9733   ScanRecordPtr scanptr;
9734   scanptr.i = apiConnectptr.p->apiScanRec;
9735   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
9736   ScanRecord* scanP = scanptr.p;
9737 
9738   const Uint32 len = signal->getLength() - 4;
9739 
9740   if (stopScan == ZTRUE) {
9741     jam();
9742     /*********************************************************************
9743      * APPLICATION IS CLOSING THE SCAN.
9744      **********************************************************************/
9745     close_scan_req(signal, scanptr, true);
9746     return;
9747   }//if
9748 
9749   if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
9750     jam();
9751     /**
9752      * The scan is closing (typically due to error)
9753      *   but the API hasn't understood it yet
9754      *
9755      * Wait for API close request
9756      */
9757     return;
9758   }
9759 
9760   // Copy op ptrs so I dont overwrite them when sending...
9761   memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len);
9762 
9763   ScanFragNextReq tmp;
9764   tmp.closeFlag = ZFALSE;
9765   tmp.transId1 = apiConnectptr.p->transid[0];
9766   tmp.transId2 = apiConnectptr.p->transid[1];
9767   tmp.batch_size_rows = scanP->batch_size_rows;
9768   tmp.batch_size_bytes = scanP->batch_byte_size;
9769 
9770   ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
9771   ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
9772   for(Uint32 i = 0 ; i<len; i++){
9773     jam();
9774     scanFragptr.i = signal->theData[i+25];
9775     c_scan_frag_pool.getPtr(scanFragptr);
9776     ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
9777 
9778     scanFragptr.p->startFragTimer(ctcTimer);
9779     scanFragptr.p->m_ops = 0;
9780 
9781     if(scanFragptr.p->m_scan_frag_conf_status)
9782     {
9783       /**
9784        * last scan was complete
9785        */
9786       jam();
9787       ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
9788       jam();
9789       ndbassert(scanptr.p->m_booked_fragments_count);
9790       scanptr.p->m_booked_fragments_count--;
9791       scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
9792 
9793       tcConnectptr.i = scanptr.p->scanTcrec;
9794       ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
9795       scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
9796       signal->theData[0] = tcConnectptr.p->dihConnectptr;
9797       signal->theData[1] = scanFragptr.i;
9798       signal->theData[2] = scanptr.p->scanTableref;
9799       signal->theData[3] = scanFragptr.p->scanFragId;
9800       sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
9801     }
9802     else
9803     {
9804       jam();
9805       scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9806       ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
9807       * req = tmp;
9808       req->senderData = scanFragptr.i;
9809       sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9810 		 ScanFragNextReq::SignalLength, JBB);
9811     }
9812     delivered.remove(scanFragptr);
9813     running.add(scanFragptr);
9814   }//for
9815 
9816 }//Dbtc::execSCAN_NEXTREQ()
9817 
9818 void
close_scan_req(Signal * signal,ScanRecordPtr scanPtr,bool req_received)9819 Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
9820 
9821   ScanRecord* scanP = scanPtr.p;
9822   ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
9823   ScanRecord::ScanState old = scanPtr.p->scanState;
9824   scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
9825   scanPtr.p->m_close_scan_req = req_received;
9826 
9827   if (old == ScanRecord::WAIT_FRAGMENT_COUNT)
9828   {
9829     jam();
9830     scanPtr.p->scanState = old;
9831     return; // Will continue on execDI_FCOUNTCONF
9832   }
9833 
9834   /**
9835    * Queue         : Action
9836    * ============= : =================
9837    * completed     : -
9838    * running       : close -> LQH
9839    * delivered w/  : close -> LQH
9840    * delivered wo/ : move to completed
9841    * queued w/     : close -> LQH
9842    * queued wo/    : move to completed
9843    */
9844 
9845   ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
9846   nextReq->closeFlag = ZTRUE;
9847   nextReq->transId1 = apiConnectptr.p->transid[0];
9848   nextReq->transId2 = apiConnectptr.p->transid[1];
9849 
9850   {
9851     ScanFragRecPtr ptr;
9852     ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
9853     ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
9854     ScanFragList queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
9855 
9856     // Close running
9857     for(running.first(ptr); !ptr.isNull(); ){
9858       ScanFragRecPtr curr = ptr; // Remove while iterating...
9859       running.next(ptr);
9860 
9861       switch(curr.p->scanFragState){
9862       case ScanFragRec::IDLE:
9863 	jam(); // real early abort
9864 	ndbrequire(old == ScanRecord::WAIT_AI);
9865 	running.release(curr);
9866 	continue;
9867       case ScanFragRec::WAIT_GET_PRIMCONF:
9868 	jam();
9869 	continue;
9870       case ScanFragRec::LQH_ACTIVE:
9871 	jam();
9872 	break;
9873       default:
9874 	jamLine(curr.p->scanFragState);
9875 	ndbrequire(false);
9876       }
9877 
9878       curr.p->startFragTimer(ctcTimer);
9879       curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9880       nextReq->senderData = curr.i;
9881       sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9882 		 ScanFragNextReq::SignalLength, JBB);
9883     }
9884 
9885     // Close delivered
9886     for(delivered.first(ptr); !ptr.isNull(); ){
9887       jam();
9888       ScanFragRecPtr curr = ptr; // Remove while iterating...
9889       delivered.next(ptr);
9890 
9891       ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
9892       delivered.remove(curr);
9893 
9894       if(curr.p->m_ops > 0 && curr.p->m_scan_frag_conf_status == 0){
9895 	jam();
9896 	running.add(curr);
9897 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9898 	curr.p->startFragTimer(ctcTimer);
9899 	nextReq->senderData = curr.i;
9900 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9901 		   ScanFragNextReq::SignalLength, JBB);
9902 
9903       } else {
9904 	jam();
9905 	c_scan_frag_pool.release(curr);
9906 	curr.p->scanFragState = ScanFragRec::COMPLETED;
9907 	curr.p->stopFragTimer();
9908       }
9909     }//for
9910 
9911     /**
9912      * All queued with data should be closed
9913      */
9914     for(queued.first(ptr); !ptr.isNull(); ){
9915       jam();
9916       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
9917       ScanFragRecPtr curr = ptr; // Remove while iterating...
9918       queued.next(ptr);
9919 
9920       queued.remove(curr);
9921       scanP->m_queued_count--;
9922 
9923       if(curr.p->m_ops > 0){
9924 	jam();
9925 	running.add(curr);
9926 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
9927 	curr.p->startFragTimer(ctcTimer);
9928 	nextReq->senderData = curr.i;
9929 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
9930 		   ScanFragNextReq::SignalLength, JBB);
9931       } else {
9932 	jam();
9933 	c_scan_frag_pool.release(curr);
9934 	curr.p->scanFragState = ScanFragRec::COMPLETED;
9935 	curr.p->stopFragTimer();
9936       }
9937     }
9938   }
9939   close_scan_req_send_conf(signal, scanPtr);
9940 }
9941 
9942 void
close_scan_req_send_conf(Signal * signal,ScanRecordPtr scanPtr)9943 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr){
9944 
9945   jam();
9946 
9947   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
9948   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
9949   //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
9950 
9951 #if 0
9952   {
9953     ScanFragList comp(c_scan_frag_pool, scanPtr.p->m_completed_scan_frags);
9954     ScanFragRecPtr ptr;
9955     for(comp.first(ptr); !ptr.isNull(); comp.next(ptr)){
9956       ndbrequire(ptr.p->scanFragTimer == 0);
9957       ndbrequire(ptr.p->scanFragState == ScanFragRec::COMPLETED);
9958     }
9959   }
9960 #endif
9961 
9962   if(!scanPtr.p->m_running_scan_frags.isEmpty()){
9963     jam();
9964     return;
9965   }
9966 
9967   const bool apiFail = (apiConnectptr.p->apiFailState == ZTRUE);
9968 
9969   if(!scanPtr.p->m_close_scan_req){
9970     jam();
9971     /**
9972      * The API hasn't order closing yet
9973      */
9974     return;
9975   }
9976 
9977   Uint32 ref = apiConnectptr.p->ndbapiBlockref;
9978   if(!apiFail && ref){
9979     jam();
9980     ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
9981     conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
9982     conf->requestInfo = ScanTabConf::EndOfData;
9983     conf->transId1 = apiConnectptr.p->transid[0];
9984     conf->transId2 = apiConnectptr.p->transid[1];
9985     sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
9986   }
9987 
9988   releaseScanResources(scanPtr);
9989 
9990   if(apiFail){
9991     jam();
9992     /**
9993      * API has failed
9994      */
9995     handleApiFailState(signal, apiConnectptr.i);
9996   }
9997 }
9998 
9999 Dbtc::ScanRecordPtr
seizeScanrec(Signal * signal)10000 Dbtc::seizeScanrec(Signal* signal) {
10001   ScanRecordPtr scanptr;
10002   scanptr.i = cfirstfreeScanrec;
10003   ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
10004   cfirstfreeScanrec = scanptr.p->nextScan;
10005   scanptr.p->nextScan = RNIL;
10006   ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
10007   return scanptr;
10008 }//Dbtc::seizeScanrec()
10009 
sendScanFragReq(Signal * signal,ScanRecord * scanP,ScanFragRec * scanFragP)10010 void Dbtc::sendScanFragReq(Signal* signal,
10011 			   ScanRecord* scanP,
10012 			   ScanFragRec* scanFragP)
10013 {
10014   ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
10015   Uint32 requestInfo = scanP->scanRequestInfo;
10016   ScanFragReq::setScanPrio(requestInfo, 1);
10017   apiConnectptr.i = scanP->scanApiRec;
10018   req->tableId = scanP->scanTableref;
10019   req->schemaVersion = scanP->scanSchemaVersion;
10020   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10021   req->senderData = scanFragptr.i;
10022   req->requestInfo = requestInfo;
10023   req->fragmentNoKeyLen = scanFragP->scanFragId | (scanP->scanKeyLen << 16);
10024   req->resultRef = apiConnectptr.p->ndbapiBlockref;
10025   req->savePointId = apiConnectptr.p->currSavePointId;
10026   req->transId1 = apiConnectptr.p->transid[0];
10027   req->transId2 = apiConnectptr.p->transid[1];
10028   req->clientOpPtr = scanFragP->m_apiPtr;
10029   req->batch_size_rows= scanP->batch_size_rows;
10030   req->batch_size_bytes= scanP->batch_byte_size;
10031   sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
10032              ScanFragReq::SignalLength, JBB);
10033   if(scanP->scanKeyLen > 0)
10034   {
10035     tcConnectptr.i = scanFragptr.i;
10036     packKeyData000Lab(signal, scanFragP->lqhBlockref, scanP->scanKeyLen);
10037   }
10038   updateBuddyTimer(apiConnectptr);
10039   scanFragP->startFragTimer(ctcTimer);
10040 }//Dbtc::sendScanFragReq()
10041 
10042 
sendScanTabConf(Signal * signal,ScanRecordPtr scanPtr)10043 void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
10044   jam();
10045   Uint32* ops = signal->getDataPtrSend()+4;
10046   Uint32 op_count = scanPtr.p->m_queued_count;
10047   if(4 + 3 * op_count > 25){
10048     jam();
10049     ops += 21;
10050   }
10051 
10052   int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
10053   Uint32 booked = scanPtr.p->m_booked_fragments_count;
10054 
10055   ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
10056   conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
10057   conf->requestInfo = op_count;
10058   conf->transId1 = apiConnectptr.p->transid[0];
10059   conf->transId2 = apiConnectptr.p->transid[1];
10060   ScanFragRecPtr ptr;
10061   {
10062     ScanFragList queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
10063     ScanFragList delivered(c_scan_frag_pool,scanPtr.p->m_delivered_scan_frags);
10064     for(queued.first(ptr); !ptr.isNull(); ){
10065       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
10066       ScanFragRecPtr curr = ptr; // Remove while iterating...
10067       queued.next(ptr);
10068 
10069       bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
10070       if(curr.p->m_scan_frag_conf_status)
10071 	booked++;
10072 
10073       * ops++ = curr.p->m_apiPtr;
10074       * ops++ = done ? RNIL : curr.i;
10075       * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
10076 
10077       queued.remove(curr);
10078       if(!done){
10079 	delivered.add(curr);
10080 	curr.p->scanFragState = ScanFragRec::DELIVERED;
10081 	curr.p->stopFragTimer();
10082       } else {
10083 	c_scan_frag_pool.release(curr);
10084 	curr.p->scanFragState = ScanFragRec::COMPLETED;
10085 	curr.p->stopFragTimer();
10086       }
10087     }
10088   }
10089 
10090   scanPtr.p->m_booked_fragments_count = booked;
10091   if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
10092      scanPtr.p->m_running_scan_frags.isEmpty())
10093   {
10094     conf->requestInfo = op_count | ScanTabConf::EndOfData;
10095     releaseScanResources(scanPtr);
10096   }
10097   else
10098   {
10099     if (scanPtr.p->m_running_scan_frags.isEmpty())
10100     {
10101       jam();
10102       /**
10103        * All scan frags delivered...waiting for API
10104        */
10105       setApiConTimer(apiConnectptr.i, ctcTimer, __LINE__);
10106     }
10107   }
10108 
10109   if(4 + 3 * op_count > 25){
10110     jam();
10111     LinearSectionPtr ptr[3];
10112     ptr[0].p = signal->getDataPtrSend()+25;
10113     ptr[0].sz = 3 * op_count;
10114     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
10115 	       ScanTabConf::SignalLength, JBB, ptr, 1);
10116   } else {
10117     jam();
10118     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABCONF, signal,
10119 	       ScanTabConf::SignalLength + 3 * op_count, JBB);
10120   }
10121   scanPtr.p->m_queued_count = 0;
10122 }//Dbtc::sendScanTabConf()
10123 
10124 
gcpTcfinished(Signal * signal)10125 void Dbtc::gcpTcfinished(Signal* signal)
10126 {
10127   signal->theData[0] = c_gcp_ref;
10128   signal->theData[1] = tcheckGcpId;
10129   sendSignal(cdihblockref, GSN_GCP_TCFINISHED, signal, 2, JBB);
10130 }//Dbtc::gcpTcfinished()
10131 
initApiConnect(Signal * signal)10132 void Dbtc::initApiConnect(Signal* signal)
10133 {
10134   Uint32 tiacTmp;
10135   Uint32 guard4;
10136 
10137   tiacTmp = capiConnectFilesize / 3;
10138   ndbrequire(tiacTmp > 0);
10139   guard4 = tiacTmp + 1;
10140   for (cachePtr.i = 0; cachePtr.i < guard4; cachePtr.i++) {
10141     refresh_watch_dog();
10142     ptrAss(cachePtr, cacheRecord);
10143     cachePtr.p->firstAttrbuf = RNIL;
10144     cachePtr.p->lastAttrbuf = RNIL;
10145     cachePtr.p->firstKeybuf = RNIL;
10146     cachePtr.p->lastKeybuf = RNIL;
10147     cachePtr.p->nextCacheRec = cachePtr.i + 1;
10148   }//for
10149   cachePtr.i = tiacTmp;
10150   ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10151   cachePtr.p->nextCacheRec = RNIL;
10152   cfirstfreeCacheRec = 0;
10153 
10154   guard4 = tiacTmp - 1;
10155   for (apiConnectptr.i = 0; apiConnectptr.i <= guard4; apiConnectptr.i++) {
10156     refresh_watch_dog();
10157     jam();
10158     ptrAss(apiConnectptr, apiConnectRecord);
10159     apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
10160     apiConnectptr.p->apiFailState = ZFALSE;
10161     setApiConTimer(apiConnectptr.i, 0, __LINE__);
10162     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10163     apiConnectptr.p->cachePtr = RNIL;
10164     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
10165     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
10166     apiConnectptr.p->commitAckMarker = RNIL;
10167     apiConnectptr.p->firstTcConnect = RNIL;
10168     apiConnectptr.p->lastTcConnect = RNIL;
10169     apiConnectptr.p->triggerPending = false;
10170     apiConnectptr.p->isIndexOp = false;
10171     apiConnectptr.p->accumulatingIndexOp = RNIL;
10172     apiConnectptr.p->executingIndexOp = RNIL;
10173     apiConnectptr.p->buddyPtr = RNIL;
10174     apiConnectptr.p->currSavePointId = 0;
10175     apiConnectptr.p->m_transaction_nodes.clear();
10176     apiConnectptr.p->singleUserMode = 0;
10177   }//for
10178   apiConnectptr.i = tiacTmp - 1;
10179   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10180   apiConnectptr.p->nextApiConnect = RNIL;
10181   cfirstfreeApiConnect = 0;
10182   guard4 = (2 * tiacTmp) - 1;
10183   for (apiConnectptr.i = tiacTmp; apiConnectptr.i <= guard4; apiConnectptr.i++)
10184     {
10185       refresh_watch_dog();
10186       jam();
10187       ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10188       apiConnectptr.p->apiConnectstate = CS_RESTART;
10189       apiConnectptr.p->apiFailState = ZFALSE;
10190       setApiConTimer(apiConnectptr.i, 0, __LINE__);
10191       apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10192       apiConnectptr.p->cachePtr = RNIL;
10193       apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
10194       apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
10195       apiConnectptr.p->commitAckMarker = RNIL;
10196       apiConnectptr.p->firstTcConnect = RNIL;
10197       apiConnectptr.p->lastTcConnect = RNIL;
10198       apiConnectptr.p->triggerPending = false;
10199       apiConnectptr.p->isIndexOp = false;
10200       apiConnectptr.p->accumulatingIndexOp = RNIL;
10201       apiConnectptr.p->executingIndexOp = RNIL;
10202       apiConnectptr.p->buddyPtr = RNIL;
10203       apiConnectptr.p->currSavePointId = 0;
10204       apiConnectptr.p->m_transaction_nodes.clear();
10205       apiConnectptr.p->singleUserMode = 0;
10206     }//for
10207   apiConnectptr.i = (2 * tiacTmp) - 1;
10208   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10209   apiConnectptr.p->nextApiConnect = RNIL;
10210   cfirstfreeApiConnectCopy = tiacTmp;
10211   guard4 = (3 * tiacTmp) - 1;
10212   for (apiConnectptr.i = 2 * tiacTmp; apiConnectptr.i <= guard4;
10213        apiConnectptr.i++) {
10214     refresh_watch_dog();
10215     jam();
10216     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10217     setApiConTimer(apiConnectptr.i, 0, __LINE__);
10218     apiConnectptr.p->apiFailState = ZFALSE;
10219     apiConnectptr.p->apiConnectstate = CS_RESTART;
10220     apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10221     apiConnectptr.p->cachePtr = RNIL;
10222     apiConnectptr.p->nextApiConnect = apiConnectptr.i + 1;
10223     apiConnectptr.p->ndbapiBlockref = 0xFFFFFFFF; // Invalid ref
10224     apiConnectptr.p->commitAckMarker = RNIL;
10225     apiConnectptr.p->firstTcConnect = RNIL;
10226     apiConnectptr.p->lastTcConnect = RNIL;
10227     apiConnectptr.p->triggerPending = false;
10228     apiConnectptr.p->isIndexOp = false;
10229     apiConnectptr.p->accumulatingIndexOp = RNIL;
10230     apiConnectptr.p->executingIndexOp = RNIL;
10231     apiConnectptr.p->buddyPtr = RNIL;
10232     apiConnectptr.p->currSavePointId = 0;
10233     apiConnectptr.p->m_transaction_nodes.clear();
10234     apiConnectptr.p->singleUserMode = 0;
10235   }//for
10236   apiConnectptr.i = (3 * tiacTmp) - 1;
10237   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10238   apiConnectptr.p->nextApiConnect = RNIL;
10239   cfirstfreeApiConnectFail = 2 * tiacTmp;
10240 }//Dbtc::initApiConnect()
10241 
initattrbuf(Signal * signal)10242 void Dbtc::initattrbuf(Signal* signal)
10243 {
10244   ndbrequire(cattrbufFilesize > 0);
10245   for (attrbufptr.i = 0; attrbufptr.i < cattrbufFilesize; attrbufptr.i++) {
10246     refresh_watch_dog();
10247     jam();
10248     ptrAss(attrbufptr, attrbufRecord);
10249     attrbufptr.p->attrbuf[ZINBUF_NEXT] = attrbufptr.i + 1;  /* NEXT ATTRBUF */
10250   }//for
10251   attrbufptr.i = cattrbufFilesize - 1;
10252   ptrAss(attrbufptr, attrbufRecord);
10253   attrbufptr.p->attrbuf[ZINBUF_NEXT] = RNIL;    /* NEXT ATTRBUF */
10254   cfirstfreeAttrbuf = 0;
10255 }//Dbtc::initattrbuf()
10256 
initdatabuf(Signal * signal)10257 void Dbtc::initdatabuf(Signal* signal)
10258 {
10259   ndbrequire(cdatabufFilesize > 0);
10260   for (databufptr.i = 0; databufptr.i < cdatabufFilesize; databufptr.i++) {
10261     refresh_watch_dog();
10262     ptrAss(databufptr, databufRecord);
10263     databufptr.p->nextDatabuf = databufptr.i + 1;
10264   }//for
10265   databufptr.i = cdatabufFilesize - 1;
10266   ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
10267   databufptr.p->nextDatabuf = RNIL;
10268   cfirstfreeDatabuf = 0;
10269 }//Dbtc::initdatabuf()
10270 
initgcp(Signal * signal)10271 void Dbtc::initgcp(Signal* signal)
10272 {
10273   ndbrequire(cgcpFilesize > 0);
10274   for (gcpPtr.i = 0; gcpPtr.i < cgcpFilesize; gcpPtr.i++) {
10275     ptrAss(gcpPtr, gcpRecord);
10276     gcpPtr.p->nextGcp = gcpPtr.i + 1;
10277   }//for
10278   gcpPtr.i = cgcpFilesize - 1;
10279   ptrCheckGuard(gcpPtr, cgcpFilesize, gcpRecord);
10280   gcpPtr.p->nextGcp = RNIL;
10281   cfirstfreeGcp = 0;
10282   cfirstgcp = RNIL;
10283   clastgcp = RNIL;
10284 }//Dbtc::initgcp()
10285 
inithost(Signal * signal)10286 void Dbtc::inithost(Signal* signal)
10287 {
10288   cpackedListIndex = 0;
10289   ndbrequire(chostFilesize > 0);
10290   for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
10291     jam();
10292     ptrAss(hostptr, hostRecord);
10293     hostptr.p->hostStatus = HS_DEAD;
10294     hostptr.p->inPackedList = false;
10295     hostptr.p->lqhTransStatus = LTS_IDLE;
10296     hostptr.p->noOfWordsTCKEYCONF = 0;
10297     hostptr.p->noOfWordsTCINDXCONF = 0;
10298     hostptr.p->noOfPackedWordsLqh = 0;
10299     hostptr.p->hostLqhBlockRef = calcLqhBlockRef(hostptr.i);
10300     hostptr.p->m_nf_bits = 0;
10301   }//for
10302   c_alive_nodes.clear();
10303 }//Dbtc::inithost()
10304 
initialiseRecordsLab(Signal * signal,UintR Tdata0,Uint32 retRef,Uint32 retData)10305 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
10306 				Uint32 retRef, Uint32 retData)
10307 {
10308   switch (Tdata0) {
10309   case 0:
10310     jam();
10311     initApiConnect(signal);
10312     break;
10313   case 1:
10314     jam();
10315     initattrbuf(signal);
10316     break;
10317   case 2:
10318     jam();
10319     initdatabuf(signal);
10320     break;
10321   case 3:
10322     jam();
10323     initgcp(signal);
10324     break;
10325   case 4:
10326     jam();
10327     inithost(signal);
10328     break;
10329   case 5:
10330     jam();
10331     // UNUSED Free to initialise something
10332     break;
10333   case 6:
10334     jam();
10335     initTable(signal);
10336     break;
10337   case 7:
10338     jam();
10339     initialiseScanrec(signal);
10340     break;
10341   case 8:
10342     jam();
10343     initialiseScanOprec(signal);
10344     break;
10345   case 9:
10346     jam();
10347     initialiseScanFragrec(signal);
10348     break;
10349   case 10:
10350     jam();
10351     initialiseTcConnect(signal);
10352     break;
10353   case 11:
10354     jam();
10355     initTcFail(signal);
10356 
10357     {
10358       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
10359       conf->senderRef = reference();
10360       conf->senderData = retData;
10361       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
10362 		 ReadConfigConf::SignalLength, JBB);
10363     }
10364     return;
10365     break;
10366   default:
10367     jam();
10368     systemErrorLab(signal, __LINE__);
10369     return;
10370     break;
10371   }//switch
10372 
10373   signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
10374   signal->theData[1] = Tdata0 + 1;
10375   signal->theData[2] = 0;
10376   signal->theData[3] = retRef;
10377   signal->theData[4] = retData;
10378   sendSignal(DBTC_REF, GSN_CONTINUEB, signal, 5, JBB);
10379 }
10380 
10381 /* ========================================================================= */
10382 /* =======                       INITIALISE_SCANREC                  ======= */
10383 /*                                                                           */
10384 /* ========================================================================= */
initialiseScanrec(Signal * signal)10385 void Dbtc::initialiseScanrec(Signal* signal)
10386 {
10387   ScanRecordPtr scanptr;
10388   ndbrequire(cscanrecFileSize > 0);
10389   for (scanptr.i = 0; scanptr.i < cscanrecFileSize; scanptr.i++) {
10390     refresh_watch_dog();
10391     jam();
10392     ptrAss(scanptr, scanRecord);
10393     new (scanptr.p) ScanRecord();
10394     scanptr.p->scanState = ScanRecord::IDLE;
10395     scanptr.p->scanApiRec = RNIL;
10396     scanptr.p->nextScan = scanptr.i + 1;
10397   }//for
10398   scanptr.i = cscanrecFileSize - 1;
10399   ptrAss(scanptr, scanRecord);
10400   scanptr.p->nextScan = RNIL;
10401   cfirstfreeScanrec = 0;
10402 }//Dbtc::initialiseScanrec()
10403 
initialiseScanFragrec(Signal * signal)10404 void Dbtc::initialiseScanFragrec(Signal* signal)
10405 {
10406 }//Dbtc::initialiseScanFragrec()
10407 
initialiseScanOprec(Signal * signal)10408 void Dbtc::initialiseScanOprec(Signal* signal)
10409 {
10410 }//Dbtc::initialiseScanOprec()
10411 
initTable(Signal * signal)10412 void Dbtc::initTable(Signal* signal)
10413 {
10414 
10415   ndbrequire(ctabrecFilesize > 0);
10416   for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
10417     refresh_watch_dog();
10418     ptrAss(tabptr, tableRecord);
10419     tabptr.p->currentSchemaVersion = 0;
10420     tabptr.p->m_flags = 0;
10421     tabptr.p->set_storedTable(true);
10422     tabptr.p->tableType = 0;
10423     tabptr.p->set_enabled(false);
10424     tabptr.p->set_dropping(false);
10425     tabptr.p->noOfKeyAttr = 0;
10426     tabptr.p->hasCharAttr = 0;
10427     tabptr.p->noOfDistrKeys = 0;
10428     tabptr.p->hasVarKeys = 0;
10429   }//for
10430 }//Dbtc::initTable()
10431 
initialiseTcConnect(Signal * signal)10432 void Dbtc::initialiseTcConnect(Signal* signal)
10433 {
10434   ndbrequire(ctcConnectFilesize >= 2);
10435 
10436   // Place half of tcConnectptr's in cfirstfreeTcConnectFail list
10437   Uint32 titcTmp = ctcConnectFilesize / 2;
10438   for (tcConnectptr.i = 0; tcConnectptr.i < titcTmp; tcConnectptr.i++) {
10439     refresh_watch_dog();
10440     jam();
10441     ptrAss(tcConnectptr, tcConnectRecord);
10442     tcConnectptr.p->tcConnectstate = OS_RESTART;
10443     tcConnectptr.p->apiConnect = RNIL;
10444     tcConnectptr.p->noOfNodes = 0;
10445     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
10446   }//for
10447   tcConnectptr.i = titcTmp - 1;
10448   ptrAss(tcConnectptr, tcConnectRecord);
10449   tcConnectptr.p->nextTcConnect = RNIL;
10450   cfirstfreeTcConnectFail = 0;
10451 
10452   // Place other half in cfirstfreeTcConnect list
10453   for (tcConnectptr.i = titcTmp; tcConnectptr.i < ctcConnectFilesize;
10454        tcConnectptr.i++) {
10455     refresh_watch_dog();
10456     jam();
10457     ptrAss(tcConnectptr, tcConnectRecord);
10458     tcConnectptr.p->tcConnectstate = OS_RESTART;
10459     tcConnectptr.p->apiConnect = RNIL;
10460     tcConnectptr.p->noOfNodes = 0;
10461     tcConnectptr.p->nextTcConnect = tcConnectptr.i + 1;
10462   }//for
10463   tcConnectptr.i = ctcConnectFilesize - 1;
10464   ptrAss(tcConnectptr, tcConnectRecord);
10465   tcConnectptr.p->nextTcConnect = RNIL;
10466   cfirstfreeTcConnect = titcTmp;
10467   c_counters.cconcurrentOp = 0;
10468 }//Dbtc::initialiseTcConnect()
10469 
10470 /* ------------------------------------------------------------------------- */
10471 /* ----     LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS  */
10472 /*          WAITING FOR COMPLETION.                                          */
10473 /* ------------------------------------------------------------------------- */
linkGciInGcilist(Signal * signal)10474 void Dbtc::linkGciInGcilist(Signal* signal)
10475 {
10476   GcpRecordPtr tmpGcpPointer;
10477   if (cfirstgcp == RNIL) {
10478     jam();
10479     cfirstgcp = gcpPtr.i;
10480   } else {
10481     jam();
10482     tmpGcpPointer.i = clastgcp;
10483     ptrCheckGuard(tmpGcpPointer, cgcpFilesize, gcpRecord);
10484     tmpGcpPointer.p->nextGcp = gcpPtr.i;
10485   }//if
10486   clastgcp = gcpPtr.i;
10487 }//Dbtc::linkGciInGcilist()
10488 
10489 /* ------------------------------------------------------------------------- */
10490 /* -------        LINK SECONDARY KEY BUFFER IN OPERATION RECORD      ------- */
10491 /* ------------------------------------------------------------------------- */
linkKeybuf(Signal * signal)10492 void Dbtc::linkKeybuf(Signal* signal)
10493 {
10494   seizeDatabuf(signal);
10495   tmpDatabufptr.i = cachePtr.p->lastKeybuf;
10496   cachePtr.p->lastKeybuf = databufptr.i;
10497   if (tmpDatabufptr.i == RNIL) {
10498     jam();
10499     cachePtr.p->firstKeybuf = databufptr.i;
10500   } else {
10501     jam();
10502     ptrCheckGuard(tmpDatabufptr, cdatabufFilesize, databufRecord);
10503     tmpDatabufptr.p->nextDatabuf = databufptr.i;
10504   }//if
10505 }//Dbtc::linkKeybuf()
10506 
10507 /* ------------------------------------------------------------------------- */
10508 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS  --- */
10509 /* ------------------------------------------------------------------------- */
linkTcInConnectionlist(Signal * signal)10510 void Dbtc::linkTcInConnectionlist(Signal* signal)
10511 {
10512   /* POINTER FOR THE CONNECT_RECORD */
10513   TcConnectRecordPtr ltcTcConnectptr;
10514 
10515   tcConnectptr.p->nextTcConnect = RNIL;
10516   ltcTcConnectptr.i = apiConnectptr.p->lastTcConnect;
10517   ptrCheck(ltcTcConnectptr, ctcConnectFilesize, tcConnectRecord);
10518   apiConnectptr.p->lastTcConnect = tcConnectptr.i;
10519   if (ltcTcConnectptr.i == RNIL) {
10520     jam();
10521     apiConnectptr.p->firstTcConnect = tcConnectptr.i;
10522   } else {
10523     jam();
10524     ptrGuard(ltcTcConnectptr);
10525     ltcTcConnectptr.p->nextTcConnect = tcConnectptr.i;
10526   }//if
10527 }//Dbtc::linkTcInConnectionlist()
10528 
10529 /*---------------------------------------------------------------------------*/
10530 /*                    RELEASE_ABORT_RESOURCES                                */
10531 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
10532 /* SENDS THE ABORT DECISION TO THE APPLICATION.                              */
10533 /*---------------------------------------------------------------------------*/
releaseAbortResources(Signal * signal)10534 void Dbtc::releaseAbortResources(Signal* signal)
10535 {
10536   TcConnectRecordPtr rarTcConnectptr;
10537 
10538   c_counters.cabortCount++;
10539   if (apiConnectptr.p->cachePtr != RNIL) {
10540     cachePtr.i = apiConnectptr.p->cachePtr;
10541     ptrCheckGuard(cachePtr, ccacheFilesize, cacheRecord);
10542     releaseAttrinfo();
10543     releaseKeys();
10544   }//if
10545   tcConnectptr.i = apiConnectptr.p->firstTcConnect;
10546   while (tcConnectptr.i != RNIL) {
10547     jam();
10548     ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10549     // Clear any markers that were set in CS_RECEIVING state
10550     clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
10551     rarTcConnectptr.i = tcConnectptr.p->nextTcConnect;
10552     releaseTcCon();
10553     tcConnectptr.i = rarTcConnectptr.i;
10554   }//while
10555   apiConnectptr.p->firstTcConnect = RNIL;
10556   apiConnectptr.p->lastTcConnect = RNIL;
10557   apiConnectptr.p->m_transaction_nodes.clear();
10558   apiConnectptr.p->singleUserMode = 0;
10559 
10560   // MASV let state be CS_ABORTING until all
10561   // signals in the "air" have been received. Reset to CS_CONNECTED
10562   // will be done when a TCKEYREQ with start flag is recieved
10563   // or releaseApiCon is called
10564   // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
10565   apiConnectptr.p->apiConnectstate = CS_ABORTING;
10566   apiConnectptr.p->abortState = AS_IDLE;
10567   releaseAllSeizedIndexOperations(apiConnectptr.p);
10568   if(apiConnectptr.p->m_exec_flag || apiConnectptr.p->apiFailState == ZTRUE){
10569     jam();
10570     bool ok = false;
10571     Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
10572     ReturnSignal ret = apiConnectptr.p->returnsignal;
10573     apiConnectptr.p->returnsignal = RS_NO_RETURN;
10574     apiConnectptr.p->m_exec_flag = 0;
10575     switch(ret){
10576     case RS_TCROLLBACKCONF:
10577       jam();
10578       ok = true;
10579       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
10580       signal->theData[1] = apiConnectptr.p->transid[0];
10581       signal->theData[2] = apiConnectptr.p->transid[1];
10582       sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
10583       break;
10584     case RS_TCROLLBACKREP:{
10585       jam();
10586       ok = true;
10587       TcRollbackRep * const tcRollbackRep =
10588 	(TcRollbackRep *) signal->getDataPtr();
10589 
10590       tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
10591       tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
10592       tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
10593       tcRollbackRep->returnCode = apiConnectptr.p->returncode;
10594       tcRollbackRep->errorData = apiConnectptr.p->errorData;
10595       sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
10596 		 TcRollbackRep::SignalLength, JBB);
10597     }
10598       break;
10599     case RS_NO_RETURN:
10600       jam();
10601       ok = true;
10602       break;
10603     case RS_TCKEYCONF:
10604     case RS_TC_COMMITCONF:
10605       break;
10606     }
10607     if(!ok){
10608       jam();
10609       ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
10610       sendSystemError(signal, __LINE__);
10611     }//if
10612 
10613   }
10614   setApiConTimer(apiConnectptr.i, 0,
10615 		 100000+c_apiConTimer_line[apiConnectptr.i]);
10616   if (apiConnectptr.p->apiFailState == ZTRUE) {
10617     jam();
10618     handleApiFailState(signal, apiConnectptr.i);
10619     return;
10620   }//if
10621 }//Dbtc::releaseAbortResources()
10622 
releaseApiCon(Signal * signal,UintR TapiConnectPtr)10623 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
10624 {
10625   ApiConnectRecordPtr TlocalApiConnectptr;
10626 
10627   TlocalApiConnectptr.i = TapiConnectPtr;
10628   ptrCheckGuard(TlocalApiConnectptr, capiConnectFilesize, apiConnectRecord);
10629   TlocalApiConnectptr.p->nextApiConnect = cfirstfreeApiConnect;
10630   cfirstfreeApiConnect = TlocalApiConnectptr.i;
10631   setApiConTimer(TlocalApiConnectptr.i, 0, __LINE__);
10632   TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
10633   ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
10634   ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
10635   TlocalApiConnectptr.p->ndbapiBlockref = 0;
10636 }//Dbtc::releaseApiCon()
10637 
releaseApiConnectFail(Signal * signal)10638 void Dbtc::releaseApiConnectFail(Signal* signal)
10639 {
10640   apiConnectptr.p->apiConnectstate = CS_RESTART;
10641   apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
10642   setApiConTimer(apiConnectptr.i, 0, __LINE__);
10643   apiConnectptr.p->nextApiConnect = cfirstfreeApiConnectFail;
10644   cfirstfreeApiConnectFail = apiConnectptr.i;
10645 }//Dbtc::releaseApiConnectFail()
10646 
releaseGcp(Signal * signal)10647 void Dbtc::releaseGcp(Signal* signal)
10648 {
10649   ptrGuard(gcpPtr);
10650   gcpPtr.p->nextGcp = cfirstfreeGcp;
10651   cfirstfreeGcp = gcpPtr.i;
10652 }//Dbtc::releaseGcp()
10653 
releaseKeys()10654 void Dbtc::releaseKeys()
10655 {
10656   UintR Tmp;
10657   databufptr.i = cachePtr.p->firstKeybuf;
10658   while (databufptr.i != RNIL) {
10659     jam();
10660     ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
10661     Tmp = databufptr.p->nextDatabuf;
10662     databufptr.p->nextDatabuf = cfirstfreeDatabuf;
10663     cfirstfreeDatabuf = databufptr.i;
10664     databufptr.i = Tmp;
10665   }//while
10666   cachePtr.p->firstKeybuf = RNIL;
10667   cachePtr.p->lastKeybuf = RNIL;
10668 }//Dbtc::releaseKeys()
10669 
releaseTcConnectFail(Signal * signal)10670 void Dbtc::releaseTcConnectFail(Signal* signal)
10671 {
10672   ptrGuard(tcConnectptr);
10673   tcConnectptr.p->nextTcConnect = cfirstfreeTcConnectFail;
10674   cfirstfreeTcConnectFail = tcConnectptr.i;
10675 }//Dbtc::releaseTcConnectFail()
10676 
seizeApiConnect(Signal * signal)10677 void Dbtc::seizeApiConnect(Signal* signal)
10678 {
10679   if (cfirstfreeApiConnect != RNIL) {
10680     jam();
10681     terrorCode = ZOK;
10682     apiConnectptr.i = cfirstfreeApiConnect;     /* ASSIGN A FREE RECORD FROM */
10683     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10684     cfirstfreeApiConnect = apiConnectptr.p->nextApiConnect;
10685     apiConnectptr.p->nextApiConnect = RNIL;
10686     setApiConTimer(apiConnectptr.i, 0, __LINE__);
10687     apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
10688     apiConnectptr.p->triggerPending = false;
10689     apiConnectptr.p->isIndexOp = false;
10690   } else {
10691     jam();
10692     terrorCode = ZNO_FREE_API_CONNECTION;
10693   }//if
10694 }//Dbtc::seizeApiConnect()
10695 
seizeApiConnectFail(Signal * signal)10696 void Dbtc::seizeApiConnectFail(Signal* signal)
10697 {
10698   apiConnectptr.i = cfirstfreeApiConnectFail;
10699   ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
10700   cfirstfreeApiConnectFail = apiConnectptr.p->nextApiConnect;
10701 }//Dbtc::seizeApiConnectFail()
10702 
seizeDatabuf(Signal * signal)10703 void Dbtc::seizeDatabuf(Signal* signal)
10704 {
10705   databufptr.i = cfirstfreeDatabuf;
10706   ptrCheckGuard(databufptr, cdatabufFilesize, databufRecord);
10707   cfirstfreeDatabuf = databufptr.p->nextDatabuf;
10708   databufptr.p->nextDatabuf = RNIL;
10709 }//Dbtc::seizeDatabuf()
10710 
seizeTcConnect(Signal * signal)10711 void Dbtc::seizeTcConnect(Signal* signal)
10712 {
10713   tcConnectptr.i = cfirstfreeTcConnect;
10714   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10715   cfirstfreeTcConnect = tcConnectptr.p->nextTcConnect;
10716   c_counters.cconcurrentOp++;
10717   tcConnectptr.p->isIndexOp = false;
10718 }//Dbtc::seizeTcConnect()
10719 
seizeTcConnectFail(Signal * signal)10720 void Dbtc::seizeTcConnectFail(Signal* signal)
10721 {
10722   tcConnectptr.i = cfirstfreeTcConnectFail;
10723   ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
10724   cfirstfreeTcConnectFail = tcConnectptr.p->nextTcConnect;
10725 }//Dbtc::seizeTcConnectFail()
10726 
sendAttrinfo(Signal * signal,UintR TattrinfoPtr,AttrbufRecord * const regAttrPtr,UintR TBref)10727 void Dbtc::sendAttrinfo(Signal* signal,
10728                         UintR TattrinfoPtr,
10729                         AttrbufRecord * const regAttrPtr,
10730                         UintR TBref)
10731 {
10732   UintR TdataPos;
10733   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6, sig7;
10734   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
10735   TdataPos = regAttrPtr->attrbuf[ZINBUF_DATA_LEN];
10736   sig0 = TattrinfoPtr;
10737   sig1 = regApiPtr->transid[0];
10738   sig2 = regApiPtr->transid[1];
10739 
10740   signal->theData[0] = sig0;
10741   signal->theData[1] = sig1;
10742   signal->theData[2] = sig2;
10743 
10744   sig0 = regAttrPtr->attrbuf[0];
10745   sig1 = regAttrPtr->attrbuf[1];
10746   sig2 = regAttrPtr->attrbuf[2];
10747   sig3 = regAttrPtr->attrbuf[3];
10748   sig4 = regAttrPtr->attrbuf[4];
10749   sig5 = regAttrPtr->attrbuf[5];
10750   sig6 = regAttrPtr->attrbuf[6];
10751   sig7 = regAttrPtr->attrbuf[7];
10752 
10753   signal->theData[3] = sig0;
10754   signal->theData[4] = sig1;
10755   signal->theData[5] = sig2;
10756   signal->theData[6] = sig3;
10757   signal->theData[7] = sig4;
10758   signal->theData[8] = sig5;
10759   signal->theData[9] = sig6;
10760   signal->theData[10] = sig7;
10761 
10762   if (TdataPos > 8) {
10763     sig0 = regAttrPtr->attrbuf[8];
10764     sig1 = regAttrPtr->attrbuf[9];
10765     sig2 = regAttrPtr->attrbuf[10];
10766     sig3 = regAttrPtr->attrbuf[11];
10767     sig4 = regAttrPtr->attrbuf[12];
10768     sig5 = regAttrPtr->attrbuf[13];
10769     sig6 = regAttrPtr->attrbuf[14];
10770 
10771     jam();
10772     signal->theData[11] = sig0;
10773     signal->theData[12] = sig1;
10774     signal->theData[13] = sig2;
10775     signal->theData[14] = sig3;
10776     signal->theData[15] = sig4;
10777     signal->theData[16] = sig5;
10778     signal->theData[17] = sig6;
10779 
10780     if (TdataPos > 15) {
10781 
10782       sig0 = regAttrPtr->attrbuf[15];
10783       sig1 = regAttrPtr->attrbuf[16];
10784       sig2 = regAttrPtr->attrbuf[17];
10785       sig3 = regAttrPtr->attrbuf[18];
10786       sig4 = regAttrPtr->attrbuf[19];
10787       sig5 = regAttrPtr->attrbuf[20];
10788       sig6 = regAttrPtr->attrbuf[21];
10789 
10790       jam();
10791       signal->theData[18] = sig0;
10792       signal->theData[19] = sig1;
10793       signal->theData[20] = sig2;
10794       signal->theData[21] = sig3;
10795       signal->theData[22] = sig4;
10796       signal->theData[23] = sig5;
10797       signal->theData[24] = sig6;
10798     }//if
10799   }//if
10800   sendSignal(TBref, GSN_ATTRINFO, signal, TdataPos + 3, JBB);
10801 }//Dbtc::sendAttrinfo()
10802 
sendContinueTimeOutControl(Signal * signal,Uint32 TapiConPtr)10803 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
10804 {
10805   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
10806   signal->theData[1] = TapiConPtr;
10807   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
10808 }//Dbtc::sendContinueTimeOutControl()
10809 
sendKeyinfo(Signal * signal,BlockReference TBRef,Uint32 len)10810 void Dbtc::sendKeyinfo(Signal* signal, BlockReference TBRef, Uint32 len)
10811 {
10812   signal->theData[0] = tcConnectptr.i;
10813   signal->theData[1] = apiConnectptr.p->transid[0];
10814   signal->theData[2] = apiConnectptr.p->transid[1];
10815   signal->theData[3] = cdata[0];
10816   signal->theData[4] = cdata[1];
10817   signal->theData[5] = cdata[2];
10818   signal->theData[6] = cdata[3];
10819   signal->theData[7] = cdata[4];
10820   signal->theData[8] = cdata[5];
10821   signal->theData[9] = cdata[6];
10822   signal->theData[10] = cdata[7];
10823   signal->theData[11] = cdata[8];
10824   signal->theData[12] = cdata[9];
10825   signal->theData[13] = cdata[10];
10826   signal->theData[14] = cdata[11];
10827   signal->theData[15] = cdata[12];
10828   signal->theData[16] = cdata[13];
10829   signal->theData[17] = cdata[14];
10830   signal->theData[18] = cdata[15];
10831   signal->theData[19] = cdata[16];
10832   signal->theData[20] = cdata[17];
10833   signal->theData[21] = cdata[18];
10834   signal->theData[22] = cdata[19];
10835   sendSignal(TBRef, GSN_KEYINFO, signal, 3 + len, JBB);
10836 }//Dbtc::sendKeyinfo()
10837 
sendSystemError(Signal * signal,int line)10838 void Dbtc::sendSystemError(Signal* signal, int line)
10839 {
10840   progError(line, NDBD_EXIT_NDBREQUIRE);
10841 }//Dbtc::sendSystemError()
10842 
10843 /* ========================================================================= */
10844 /* -------             LINK ACTUAL GCP OUT OF LIST                   ------- */
10845 /* ------------------------------------------------------------------------- */
unlinkGcp(Signal * signal)10846 void Dbtc::unlinkGcp(Signal* signal)
10847 {
10848   if (cfirstgcp == gcpPtr.i) {
10849     jam();
10850     cfirstgcp = gcpPtr.p->nextGcp;
10851     if (gcpPtr.i == clastgcp) {
10852       jam();
10853       clastgcp = RNIL;
10854     }//if
10855   } else {
10856     jam();
10857     /* --------------------------------------------------------------------
10858      * WE ARE TRYING TO REMOVE A GLOBAL CHECKPOINT WHICH WAS NOT THE OLDEST.
10859      * THIS IS A SYSTEM ERROR.
10860      * ------------------------------------------------------------------- */
10861     sendSystemError(signal, __LINE__);
10862   }//if
10863   gcpPtr.p->nextGcp = cfirstfreeGcp;
10864   cfirstfreeGcp = gcpPtr.i;
10865 }//Dbtc::unlinkGcp()
10866 
10867 void
execDUMP_STATE_ORD(Signal * signal)10868 Dbtc::execDUMP_STATE_ORD(Signal* signal)
10869 {
10870   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
10871   if(signal->theData[0] == DumpStateOrd::CommitAckMarkersSize){
10872     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
10873               m_commitAckMarkerPool.getNoOfFree(),
10874               m_commitAckMarkerPool.getSize());
10875   }
10876   if(signal->theData[0] == DumpStateOrd::CommitAckMarkersDump){
10877     infoEvent("TC: m_commitAckMarkerPool: %d free size: %d",
10878               m_commitAckMarkerPool.getNoOfFree(),
10879               m_commitAckMarkerPool.getSize());
10880 
10881     CommitAckMarkerIterator iter;
10882     for(m_commitAckMarkerHash.first(iter); iter.curr.i != RNIL;
10883         m_commitAckMarkerHash.next(iter)){
10884       infoEvent("CommitAckMarker: i = %d (0x%x, 0x%x)"
10885                 " Api: %d Lghs(%d): %d %d %d %d bucket = %d",
10886                 iter.curr.i,
10887                 iter.curr.p->transid1,
10888                 iter.curr.p->transid2,
10889                 iter.curr.p->apiNodeId,
10890                 iter.curr.p->noOfLqhs,
10891                 iter.curr.p->lqhNodeId[0],
10892                 iter.curr.p->lqhNodeId[1],
10893                 iter.curr.p->lqhNodeId[2],
10894                 iter.curr.p->lqhNodeId[3],
10895                 iter.bucket);
10896     }
10897   }
10898   // Dump all ScanFragRecs
10899   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanFragRec){
10900     Uint32 recordNo = 0;
10901     if (signal->getLength() == 1)
10902       infoEvent("TC: Dump all ScanFragRec - size: %d",
10903 		cscanFragrecFileSize);
10904     else if (signal->getLength() == 2)
10905       recordNo = dumpState->args[1];
10906     else
10907       return;
10908 
10909     dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
10910     dumpState->args[1] = recordNo;
10911     execDUMP_STATE_ORD(signal);
10912 
10913     if (recordNo < cscanFragrecFileSize-1){
10914       dumpState->args[0] = DumpStateOrd::TcDumpAllScanFragRec;
10915       dumpState->args[1] = recordNo+1;
10916       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
10917     }
10918   }
10919 
10920   // Dump one ScanFragRec
10921   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
10922     Uint32 recordNo = RNIL;
10923     if (signal->getLength() == 2)
10924       recordNo = dumpState->args[1];
10925     else
10926       return;
10927 
10928     if (recordNo >= cscanFragrecFileSize)
10929       return;
10930 
10931     ScanFragRecPtr sfp;
10932     sfp.i = recordNo;
10933     c_scan_frag_pool.getPtr(sfp);
10934     infoEvent("Dbtc::ScanFragRec[%d]: state=%d fragid=%d",
10935 	      sfp.i,
10936 	      sfp.p->scanFragState,
10937 	      sfp.p->scanFragId);
10938     infoEvent(" nodeid=%d, timer=%d",
10939 	      refToNode(sfp.p->lqhBlockref),
10940 	      sfp.p->scanFragTimer);
10941   }
10942 
10943   // Dump all ScanRecords
10944   if (dumpState->args[0] == DumpStateOrd::TcDumpAllScanRec){
10945     Uint32 recordNo = 0;
10946     if (signal->getLength() == 1)
10947       infoEvent("TC: Dump all ScanRecord - size: %d",
10948 		cscanrecFileSize);
10949     else if (signal->getLength() == 2)
10950       recordNo = dumpState->args[1];
10951     else
10952       return;
10953 
10954     dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
10955     dumpState->args[1] = recordNo;
10956     execDUMP_STATE_ORD(signal);
10957 
10958     if (recordNo < cscanrecFileSize-1){
10959       dumpState->args[0] = DumpStateOrd::TcDumpAllScanRec;
10960       dumpState->args[1] = recordNo+1;
10961       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
10962     }
10963   }
10964 
10965   // Dump all active ScanRecords
10966   if (dumpState->args[0] == DumpStateOrd::TcDumpAllActiveScanRec){
10967     Uint32 recordNo = 0;
10968     if (signal->getLength() == 1)
10969       infoEvent("TC: Dump active ScanRecord - size: %d",
10970 		cscanrecFileSize);
10971     else if (signal->getLength() == 2)
10972       recordNo = dumpState->args[1];
10973     else
10974       return;
10975 
10976     ScanRecordPtr sp;
10977     sp.i = recordNo;
10978     ptrAss(sp, scanRecord);
10979     if (sp.p->scanState != ScanRecord::IDLE){
10980       dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
10981       dumpState->args[1] = recordNo;
10982       execDUMP_STATE_ORD(signal);
10983     }
10984 
10985     if (recordNo < cscanrecFileSize-1){
10986       dumpState->args[0] = DumpStateOrd::TcDumpAllActiveScanRec;
10987       dumpState->args[1] = recordNo+1;
10988       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
10989     }
10990   }
10991 
10992   // Dump one ScanRecord
10993   // and associated ScanFragRec and ApiConnectRecord
10994   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
10995     Uint32 recordNo = RNIL;
10996     if (signal->getLength() == 2)
10997       recordNo = dumpState->args[1];
10998     else
10999       return;
11000 
11001     if (recordNo >= cscanrecFileSize)
11002       return;
11003 
11004     ScanRecordPtr sp;
11005     sp.i = recordNo;
11006     ptrAss(sp, scanRecord);
11007     infoEvent("Dbtc::ScanRecord[%d]: state=%d"
11008 	      "nextfrag=%d, nofrag=%d",
11009 	      sp.i,
11010 	      sp.p->scanState,
11011 	      sp.p->scanNextFragId,
11012 	      sp.p->scanNoFrag);
11013     infoEvent(" ailen=%d, para=%d, receivedop=%d, noOprePperFrag=%d",
11014 	      sp.p->scanAiLength,
11015 	      sp.p->scanParallel,
11016 	      sp.p->scanReceivedOperations,
11017 	      sp.p->batch_size_rows);
11018     infoEvent(" schv=%d, tab=%d, sproc=%d",
11019 	      sp.p->scanSchemaVersion,
11020 	      sp.p->scanTableref,
11021 	      sp.p->scanStoredProcId);
11022     infoEvent(" apiRec=%d, next=%d",
11023 	      sp.p->scanApiRec, sp.p->nextScan);
11024 
11025     if (sp.p->scanState != ScanRecord::IDLE){
11026       // Request dump of ScanFragRec
11027       ScanFragRecPtr sfptr;
11028 #define DUMP_SFR(x){\
11029       ScanFragList list(c_scan_frag_pool, x);\
11030       for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
11031 	dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
11032 	dumpState->args[1] = sfptr.i;\
11033 	execDUMP_STATE_ORD(signal);\
11034       }}
11035 
11036       DUMP_SFR(sp.p->m_running_scan_frags);
11037       DUMP_SFR(sp.p->m_queued_scan_frags);
11038       DUMP_SFR(sp.p->m_delivered_scan_frags);
11039 
11040       // Request dump of ApiConnectRecord
11041       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
11042       dumpState->args[1] = sp.p->scanApiRec;
11043       execDUMP_STATE_ORD(signal);
11044     }
11045 
11046   }
11047 
11048   // Dump all ApiConnectRecord(s)
11049   if (dumpState->args[0] == DumpStateOrd::TcDumpAllApiConnectRec){
11050     Uint32 recordNo = 0;
11051     if (signal->getLength() == 1)
11052       infoEvent("TC: Dump all ApiConnectRecord - size: %d",
11053 		capiConnectFilesize);
11054     else if (signal->getLength() == 2)
11055       recordNo = dumpState->args[1];
11056     else
11057       return;
11058 
11059     dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
11060     dumpState->args[1] = recordNo;
11061     execDUMP_STATE_ORD(signal);
11062 
11063     if (recordNo < capiConnectFilesize-1){
11064       dumpState->args[0] = DumpStateOrd::TcDumpAllApiConnectRec;
11065       dumpState->args[1] = recordNo+1;
11066       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 2, JBB);
11067     }
11068   }
11069 
11070   // Dump one ApiConnectRecord
11071   if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
11072     Uint32 recordNo = RNIL;
11073     if (signal->getLength() == 2)
11074       recordNo = dumpState->args[1];
11075     else
11076       return;
11077 
11078     if (recordNo >= capiConnectFilesize)
11079       return;
11080 
11081     ApiConnectRecordPtr ap;
11082     ap.i = recordNo;
11083     ptrAss(ap, apiConnectRecord);
11084     infoEvent("Dbtc::ApiConnectRecord[%d]: state=%d, abortState=%d, "
11085 	      "apiFailState=%d",
11086 	      ap.i,
11087 	      ap.p->apiConnectstate,
11088 	      ap.p->abortState,
11089 	      ap.p->apiFailState);
11090     infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
11091 	      ap.p->transid[0],
11092 	      ap.p->transid[1],
11093 	      ap.p->ndbapiBlockref,
11094 	      ap.p->apiScanRec);
11095     infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
11096 	      "retsig=%d",
11097 	      ctcTimer, getApiConTimer(ap.i),
11098 	      ap.p->counter,
11099 	      ap.p->returncode,
11100 	      ap.p->returnsignal);
11101     infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
11102 	      "tckeyrec=%d",
11103 	      ap.p->lqhkeyconfrec,
11104 	      ap.p->lqhkeyreqrec,
11105 	      ap.p->tckeyrec);
11106     infoEvent(" next=%d ",
11107 	      ap.p->nextApiConnect);
11108   }
11109 
11110   if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
11111     jam();
11112     if(signal->getLength() > 1){
11113       set_timeout_value(signal->theData[1]);
11114     }
11115   }
11116 
11117   if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
11118     jam();
11119     if(signal->getLength() > 1){
11120       set_appl_timeout_value(signal->theData[1]);
11121     }
11122   }
11123 
11124   if (dumpState->args[0] == DumpStateOrd::StartTcTimer){
11125     c_counters.c_trans_status = TransCounters::Started;
11126     c_counters.reset();
11127   }
11128 
11129   if (dumpState->args[0] == DumpStateOrd::StopTcTimer){
11130     c_counters.c_trans_status = TransCounters::Off;
11131     Uint32 len = c_counters.report(signal);
11132     sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
11133     c_counters.reset();
11134   }
11135 
11136   if (dumpState->args[0] == DumpStateOrd::StartPeriodicTcTimer){
11137     c_counters.c_trans_status = TransCounters::Timer;
11138     c_counters.reset();
11139     signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
11140     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
11141   }
11142 
11143   if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
11144   {
11145     static int frequency = 1;
11146     if (signal->getLength() > 1)
11147       frequency = signal->theData[1];
11148     else
11149       if (refToBlock(signal->getSendersBlockRef()) != DBTC)
11150 	frequency = 1;
11151 
11152     if (frequency)
11153     {
11154       dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
11155       execDUMP_STATE_ORD(signal);
11156       dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
11157 
11158       Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
11159       sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
11160     }
11161   }
11162 
11163   if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
11164   {
11165     infoEvent("IndexOpCount: pool: %d free: %d",
11166 	      c_theIndexOperationPool.getSize(),
11167 	      c_theIndexOperationPool.getNoOfFree());
11168   }
11169 
11170   if (dumpState->args[0] == 2514)
11171   {
11172     if (signal->getLength() == 2)
11173     {
11174       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
11175       execDUMP_STATE_ORD(signal);
11176     }
11177 
11178     NodeReceiverGroup rg(CMVMI, c_alive_nodes);
11179     dumpState->args[0] = 15;
11180     sendSignal(rg, GSN_DUMP_STATE_ORD, signal, 1, JBB);
11181 
11182     signal->theData[0] = 2515;
11183     sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, 1000, 1);
11184     return;
11185   }
11186 
11187   if (dumpState->args[0] == 2515)
11188   {
11189     NdbNodeBitmask mask = c_alive_nodes;
11190     mask.clear(getOwnNodeId());
11191     NodeReceiverGroup rg(NDBCNTR, mask);
11192 
11193     sendSignal(rg, GSN_SYSTEM_ERROR, signal, 1, JBB);
11194     sendSignalWithDelay(cownref, GSN_SYSTEM_ERROR, signal, 300, 1);
11195     return;
11196   }
11197 }//Dbtc::execDUMP_STATE_ORD()
11198 
execABORT_ALL_REQ(Signal * signal)11199 void Dbtc::execABORT_ALL_REQ(Signal* signal)
11200 {
11201   jamEntry();
11202   AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
11203   AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
11204 
11205   const Uint32 senderData = req->senderData;
11206   const BlockReference senderRef = req->senderRef;
11207 
11208   if(getAllowStartTransaction(refToNode(senderRef), 0) == true && !getNodeState().getSingleUserMode()){
11209     jam();
11210 
11211     ref->senderData = senderData;
11212     ref->errorCode = AbortAllRef::InvalidState;
11213     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
11214 	       AbortAllRef::SignalLength, JBB);
11215     return;
11216   }
11217 
11218   if(c_abortRec.clientRef != 0){
11219     jam();
11220 
11221     ref->senderData = senderData;
11222     ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
11223     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
11224 	       AbortAllRef::SignalLength, JBB);
11225     return;
11226   }
11227 
11228   if(refToNode(senderRef) != getOwnNodeId()){
11229     jam();
11230 
11231     ref->senderData = senderData;
11232     ref->errorCode = AbortAllRef::FunctionNotImplemented;
11233     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
11234 	       AbortAllRef::SignalLength, JBB);
11235     return;
11236   }
11237 
11238   c_abortRec.clientRef = senderRef;
11239   c_abortRec.clientData = senderData;
11240   c_abortRec.oldTimeOutValue = ctimeOutValue;
11241 
11242   ctimeOutValue = 0;
11243   const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
11244 
11245   checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
11246 }
11247 
checkAbortAllTimeout(Signal * signal,Uint32 sleepTime)11248 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
11249 {
11250 
11251   ndbrequire(c_abortRec.clientRef != 0);
11252 
11253   if(sleepTime > 0){
11254     jam();
11255 
11256     sleepTime -= 1;
11257     signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
11258     signal->theData[1] = sleepTime;
11259     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
11260     return;
11261   }
11262 
11263   AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
11264   conf->senderData = c_abortRec.clientData;
11265   sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
11266 	     AbortAllConf::SignalLength, JBB);
11267 
11268   ctimeOutValue = c_abortRec.oldTimeOutValue;
11269   c_abortRec.clientRef = 0;
11270 }
11271 
11272 /* **************************************************************** */
11273 /* ---------------------------------------------------------------- */
11274 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
11275 /* ---------------------------------------------------------------- */
11276 /* **************************************************************** */
11277 
execCREATE_TRIG_REQ(Signal * signal)11278 void Dbtc::execCREATE_TRIG_REQ(Signal* signal)
11279 {
11280   jamEntry();
11281   CreateTrigReq * const createTrigReq =
11282     (CreateTrigReq *)&signal->theData[0];
11283   TcDefinedTriggerData* triggerData;
11284   DefinedTriggerPtr triggerPtr;
11285   BlockReference sender = signal->senderBlockRef();
11286 
11287   releaseSections(signal);
11288 
11289   triggerPtr.i = createTrigReq->getTriggerId();
11290   if (ERROR_INSERTED(8033) ||
11291       !c_theDefinedTriggers.seizeId(triggerPtr,
11292 				    createTrigReq->getTriggerId())) {
11293     jam();
11294     CLEAR_ERROR_INSERT_VALUE;
11295     // Failed to allocate trigger record
11296     CreateTrigRef * const createTrigRef =
11297       (CreateTrigRef *)&signal->theData[0];
11298 
11299     createTrigRef->setConnectionPtr(createTrigReq->getConnectionPtr());
11300     createTrigRef->setErrorCode(CreateTrigRef::TooManyTriggers);
11301     sendSignal(sender, GSN_CREATE_TRIG_REF,
11302                signal, CreateTrigRef::SignalLength, JBB);
11303     return;
11304   }
11305 
11306   triggerData = triggerPtr.p;
11307   triggerData->triggerId = createTrigReq->getTriggerId();
11308   triggerData->triggerType = createTrigReq->getTriggerType();
11309   triggerData->triggerEvent = createTrigReq->getTriggerEvent();
11310   triggerData->attributeMask = createTrigReq->getAttributeMask();
11311   if (triggerData->triggerType == TriggerType::SECONDARY_INDEX)
11312     triggerData->indexId = createTrigReq->getIndexId();
11313   CreateTrigConf * const createTrigConf =
11314     (CreateTrigConf *)&signal->theData[0];
11315 
11316   createTrigConf->setConnectionPtr(createTrigReq->getConnectionPtr());
11317   sendSignal(sender, GSN_CREATE_TRIG_CONF,
11318              signal, CreateTrigConf::SignalLength, JBB);
11319 }
11320 
11321 
execDROP_TRIG_REQ(Signal * signal)11322 void Dbtc::execDROP_TRIG_REQ(Signal* signal)
11323 {
11324   jamEntry();
11325   DropTrigReq * const dropTrigReq =  (DropTrigReq *)&signal->theData[0];
11326   BlockReference sender = signal->senderBlockRef();
11327 
11328   if (ERROR_INSERTED(8035) ||
11329       (c_theDefinedTriggers.getPtr(dropTrigReq->getTriggerId())) == NULL) {
11330     jam();
11331     CLEAR_ERROR_INSERT_VALUE;
11332     // Failed to find find trigger record
11333     DropTrigRef * const dropTrigRef =  (DropTrigRef *)&signal->theData[0];
11334 
11335     dropTrigRef->setConnectionPtr(dropTrigReq->getConnectionPtr());
11336     dropTrigRef->setErrorCode(DropTrigRef::TriggerNotFound);
11337     sendSignal(sender, GSN_DROP_TRIG_REF,
11338                signal, DropTrigRef::SignalLength, JBB);
11339     return;
11340   }
11341 
11342   // Release trigger record
11343   c_theDefinedTriggers.release(dropTrigReq->getTriggerId());
11344 
11345   DropTrigConf * const dropTrigConf =  (DropTrigConf *)&signal->theData[0];
11346 
11347   dropTrigConf->setConnectionPtr(dropTrigReq->getConnectionPtr());
11348   sendSignal(sender, GSN_DROP_TRIG_CONF,
11349              signal, DropTrigConf::SignalLength, JBB);
11350 }
11351 
execCREATE_INDX_REQ(Signal * signal)11352 void Dbtc::execCREATE_INDX_REQ(Signal* signal)
11353 {
11354   jamEntry();
11355   CreateIndxReq * const createIndxReq =
11356     (CreateIndxReq *)signal->getDataPtr();
11357   TcIndexData* indexData;
11358   TcIndexDataPtr indexPtr;
11359   BlockReference sender = signal->senderBlockRef();
11360 
11361   if (ERROR_INSERTED(8034) ||
11362       !c_theIndexes.seizeId(indexPtr, createIndxReq->getIndexId())) {
11363     jam();
11364     CLEAR_ERROR_INSERT_VALUE;
11365     // Failed to allocate index record
11366      CreateIndxRef * const createIndxRef =
11367        (CreateIndxRef *)&signal->theData[0];
11368 
11369      createIndxRef->setConnectionPtr(createIndxReq->getConnectionPtr());
11370      createIndxRef->setErrorCode(CreateIndxRef::TooManyIndexes);
11371      releaseSections(signal);
11372      sendSignal(sender, GSN_CREATE_INDX_REF,
11373                 signal, CreateIndxRef::SignalLength, JBB);
11374      return;
11375   }
11376   indexData = indexPtr.p;
11377   // Indexes always start in state IS_BUILDING
11378   // Will become IS_ONLINE in execALTER_INDX_REQ
11379   indexData->indexState = IS_BUILDING;
11380   indexData->indexId = indexPtr.i;
11381   indexData->primaryTableId = createIndxReq->getTableId();
11382 
11383   // So far need only attribute count
11384   SegmentedSectionPtr ssPtr;
11385   signal->getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
11386   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
11387   r0.reset(); // undo implicit first()
11388   if (!r0.getWord(&indexData->attributeList.sz) ||
11389       !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
11390     ndbrequire(false);
11391   }
11392   indexData->primaryKeyPos = indexData->attributeList.sz;
11393 
11394   releaseSections(signal);
11395 
11396   CreateIndxConf * const createIndxConf =
11397     (CreateIndxConf *)&signal->theData[0];
11398 
11399   createIndxConf->setConnectionPtr(createIndxReq->getConnectionPtr());
11400   createIndxConf->setTableId(createIndxReq->getTableId());
11401   createIndxConf->setIndexId(createIndxReq->getIndexId());
11402   sendSignal(sender, GSN_CREATE_INDX_CONF,
11403              signal, CreateIndxConf::SignalLength, JBB);
11404 }
11405 
execALTER_INDX_REQ(Signal * signal)11406 void Dbtc::execALTER_INDX_REQ(Signal* signal)
11407 {
11408   jamEntry();
11409   AlterIndxReq * const alterIndxReq =  (AlterIndxReq *)signal->getDataPtr();
11410   TcIndexData* indexData;
11411   //BlockReference sender = signal->senderBlockRef();
11412   BlockReference sender = (BlockReference) alterIndxReq->getUserRef();
11413   Uint32 connectionPtr = alterIndxReq->getConnectionPtr();
11414   AlterIndxReq::RequestType requestType = alterIndxReq->getRequestType();
11415   Uint32 tableId = alterIndxReq->getTableId();
11416   Uint32 indexId = alterIndxReq->getIndexId();
11417   bool online = (alterIndxReq->getOnline() == 1) ? true : false;
11418 
11419   if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
11420     jam();
11421     // Failed to find index record
11422     AlterIndxRef * const alterIndxRef =
11423       (AlterIndxRef *)signal->getDataPtrSend();
11424 
11425     alterIndxRef->setUserRef(reference());
11426     alterIndxRef->setConnectionPtr(connectionPtr);
11427     alterIndxRef->setRequestType(requestType);
11428     alterIndxRef->setTableId(tableId);
11429     alterIndxRef->setIndexId(indexId);
11430     alterIndxRef->setErrorCode(AlterIndxRef::IndexNotFound);
11431     alterIndxRef->setErrorLine(__LINE__);
11432     alterIndxRef->setErrorNode(getOwnNodeId());
11433     sendSignal(sender, GSN_ALTER_INDX_REF,
11434 	       signal, AlterIndxRef::SignalLength, JBB);
11435     return;
11436   }
11437   // Found index record, alter it's state
11438   if (online) {
11439     jam();
11440     indexData->indexState = IS_ONLINE;
11441   } else {
11442     jam();
11443     indexData->indexState = IS_BUILDING;
11444   }//if
11445   AlterIndxConf * const alterIndxConf =
11446     (AlterIndxConf *)signal->getDataPtrSend();
11447 
11448   alterIndxConf->setUserRef(reference());
11449   alterIndxConf->setConnectionPtr(connectionPtr);
11450   alterIndxConf->setRequestType(requestType);
11451   alterIndxConf->setTableId(tableId);
11452   alterIndxConf->setIndexId(indexId);
11453   sendSignal(sender, GSN_ALTER_INDX_CONF,
11454 	     signal, AlterIndxConf::SignalLength, JBB);
11455 }
11456 
execFIRE_TRIG_ORD(Signal * signal)11457 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
11458 {
11459   jamEntry();
11460   FireTrigOrd * const fireOrd =  (FireTrigOrd *)signal->getDataPtr();
11461   ApiConnectRecord *localApiConnectRecord = apiConnectRecord;
11462   ApiConnectRecordPtr transPtr;
11463   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
11464   TcConnectRecordPtr opPtr;
11465   /**
11466    * TODO
11467    * Check transid,
11468    * Fix overload i.e invalid word count
11469    */
11470   TcFiredTriggerData key;
11471   key.fireingOperation = fireOrd->getConnectionPtr();
11472   key.nodeId = refToNode(signal->getSendersBlockRef());
11473   FiredTriggerPtr trigPtr;
11474   if(c_firedTriggerHash.find(trigPtr, key)){
11475 
11476     c_firedTriggerHash.remove(trigPtr);
11477 
11478     trigPtr.p->fragId= fireOrd->fragId;
11479     bool ok = trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
11480     ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
11481     ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
11482     if(ok){
11483       opPtr.i = key.fireingOperation;
11484       ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
11485       transPtr.i = opPtr.p->apiConnect;
11486       transPtr.p = &localApiConnectRecord[transPtr.i];
11487 
11488       opPtr.p->noReceivedTriggers++;
11489       opPtr.p->triggerExecutionCount++;
11490 
11491       // Insert fired trigger in execution queue
11492       transPtr.p->theFiredTriggers.add(trigPtr);
11493       if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
11494 	executeTriggers(signal, &transPtr);
11495       }
11496       return;
11497     }
11498     jam();
11499     c_theFiredTriggerPool.release(trigPtr);
11500   }
11501   jam();
11502   /**
11503    * Failed to find record or invalid word counts
11504    */
11505   ndbrequire(false);
11506 }
11507 
execTRIG_ATTRINFO(Signal * signal)11508 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
11509 {
11510   jamEntry();
11511   TrigAttrInfo * const trigAttrInfo =  (TrigAttrInfo *)signal->getDataPtr();
11512   Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
11513   const Uint32 *src = trigAttrInfo->getData();
11514   FiredTriggerPtr firedTrigPtr;
11515 
11516   TcFiredTriggerData key;
11517   key.fireingOperation = trigAttrInfo->getConnectionPtr();
11518   key.nodeId = refToNode(signal->getSendersBlockRef());
11519   if(!c_firedTriggerHash.find(firedTrigPtr, key)){
11520     jam();
11521     if(!c_firedTriggerHash.seize(firedTrigPtr)){
11522       jam();
11523       /**
11524        * Will be handled when FIRE_TRIG_ORD arrives
11525        */
11526       ndbout_c("op: %d node: %d failed to seize",
11527 	       key.fireingOperation, key.nodeId);
11528       return;
11529     }
11530     ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
11531 	       firedTrigPtr.p->beforeValues.getSize() == 0 &&
11532 	       firedTrigPtr.p->afterValues.getSize() == 0);
11533 
11534     firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
11535     firedTrigPtr.p->fireingOperation = key.fireingOperation;
11536     firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
11537     c_firedTriggerHash.add(firedTrigPtr);
11538   }
11539 
11540   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
11541   switch (trigAttrInfo->getAttrInfoType()) {
11542   case(TrigAttrInfo::PRIMARY_KEY):
11543     jam();
11544     {
11545       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->keyValues);
11546       buf.append(src, attrInfoLength);
11547     }
11548     break;
11549   case(TrigAttrInfo::BEFORE_VALUES):
11550     jam();
11551     {
11552       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->beforeValues);
11553       buf.append(src, attrInfoLength);
11554     }
11555     break;
11556   case(TrigAttrInfo::AFTER_VALUES):
11557     jam();
11558     {
11559       LocalDataBuffer<11> buf(pool, firedTrigPtr.p->afterValues);
11560       buf.append(src, attrInfoLength);
11561     }
11562     break;
11563   default:
11564     ndbrequire(false);
11565   }
11566 }
11567 
execDROP_INDX_REQ(Signal * signal)11568 void Dbtc::execDROP_INDX_REQ(Signal* signal)
11569 {
11570   jamEntry();
11571   DropIndxReq * const dropIndxReq =  (DropIndxReq *)signal->getDataPtr();
11572   TcIndexData* indexData;
11573   BlockReference sender = signal->senderBlockRef();
11574 
11575   if (ERROR_INSERTED(8036) ||
11576       (indexData = c_theIndexes.getPtr(dropIndxReq->getIndexId())) == NULL) {
11577     jam();
11578     CLEAR_ERROR_INSERT_VALUE;
11579     // Failed to find index record
11580     DropIndxRef * const dropIndxRef =
11581       (DropIndxRef *)signal->getDataPtrSend();
11582 
11583     dropIndxRef->setConnectionPtr(dropIndxReq->getConnectionPtr());
11584     dropIndxRef->setErrorCode(DropIndxRef::IndexNotFound);
11585     sendSignal(sender, GSN_DROP_INDX_REF,
11586                signal, DropIndxRef::SignalLength, JBB);
11587     return;
11588   }
11589   // Release index record
11590   c_theIndexes.release(dropIndxReq->getIndexId());
11591 
11592   DropIndxConf * const dropIndxConf =
11593     (DropIndxConf *)signal->getDataPtrSend();
11594 
11595   dropIndxConf->setConnectionPtr(dropIndxReq->getConnectionPtr());
11596   sendSignal(sender, GSN_DROP_INDX_CONF,
11597              signal, DropIndxConf::SignalLength, JBB);
11598 }
11599 
execTCINDXREQ(Signal * signal)11600 void Dbtc::execTCINDXREQ(Signal* signal)
11601 {
11602   jamEntry();
11603 
11604   TcKeyReq * const tcIndxReq =  (TcKeyReq *)signal->getDataPtr();
11605   const UintR TapiIndex = tcIndxReq->apiConnectPtr;
11606   Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
11607   Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
11608   Uint32 * dataPtr = &tcIndxReq->scanInfo;
11609   Uint32 indexBufSize = 8; // Maximum for index in TCINDXREQ
11610   Uint32 attrBufSize = 5;  // Maximum for attrInfo in TCINDXREQ
11611   ApiConnectRecordPtr transPtr;
11612   transPtr.i = TapiIndex;
11613   if (transPtr.i >= capiConnectFilesize) {
11614     jam();
11615     warningHandlerLab(signal, __LINE__);
11616     return;
11617   }//if
11618   ptrAss(transPtr, apiConnectRecord);
11619   ApiConnectRecord * const regApiPtr = transPtr.p;
11620   // Seize index operation
11621   TcIndexOperationPtr indexOpPtr;
11622   if ((startFlag == 1) &&
11623       (regApiPtr->apiConnectstate == CS_CONNECTED ||
11624        (regApiPtr->apiConnectstate == CS_STARTED &&
11625 	regApiPtr->firstTcConnect == RNIL)) ||
11626       (regApiPtr->apiConnectstate == CS_ABORTING &&
11627        regApiPtr->abortState == AS_IDLE)) {
11628     jam();
11629     // This is a newly started transaction, clean-up
11630     releaseAllSeizedIndexOperations(regApiPtr);
11631 
11632     regApiPtr->apiConnectstate = CS_STARTED;
11633     regApiPtr->transid[0] = tcIndxReq->transId1;
11634     regApiPtr->transid[1] = tcIndxReq->transId2;
11635   }//if
11636 
11637   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
11638       getNodeState().getSingleUserApi() !=
11639       refToNode(regApiPtr->ndbapiBlockref))
11640   {
11641     terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
11642     regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
11643     apiConnectptr = transPtr;
11644     abortErrorLab(signal);
11645     return;
11646   }
11647 
11648   if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
11649     jam();
11650     // Failed to allocate index operation
11651     terrorCode = 288;
11652     regApiPtr->m_exec_flag |= TcKeyReq::getExecuteFlag(tcIndxRequestInfo);
11653     apiConnectptr = transPtr;
11654     abortErrorLab(signal);
11655     return;
11656   }
11657   TcIndexOperation* indexOp = indexOpPtr.p;
11658   indexOp->indexOpId = indexOpPtr.i;
11659 
11660   // Save original signal
11661   indexOp->tcIndxReq = *tcIndxReq;
11662   indexOp->connectionIndex = TapiIndex;
11663   regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
11664 
11665   // If operation is readTupleExclusive or updateTuple then read index
11666   // table with exclusive lock
11667   Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
11668   Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
11669   indexOp->expectedKeyInfo = indexLength;
11670   Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
11671   indexOp->expectedAttrInfo = attrLength;
11672   Uint32 includedAttrLength = MIN(attrLength, attrBufSize);
11673 
11674   int ret;
11675   if ((ret = saveINDXKEYINFO(signal,
11676                              indexOp,
11677                              dataPtr,
11678                              includedIndexLength)) == 0)
11679   {
11680     jam();
11681     // We have received all we need
11682     readIndexTable(signal, regApiPtr, indexOp);
11683     return;
11684   }
11685   else if (ret == -1)
11686   {
11687     jam();
11688     return;
11689   }
11690 
11691   dataPtr += includedIndexLength;
11692   if (saveINDXATTRINFO(signal,
11693                        indexOp,
11694                        dataPtr,
11695                        includedAttrLength) == 0) {
11696     jam();
11697     // We have received all we need
11698     readIndexTable(signal, regApiPtr, indexOp);
11699     return;
11700   }
11701 }
11702 
11703 
sendTcIndxConf(Signal * signal,UintR TcommitFlag)11704 void Dbtc::sendTcIndxConf(Signal* signal, UintR TcommitFlag)
11705 {
11706   HostRecordPtr localHostptr;
11707   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
11708   const UintR TopWords = (UintR)regApiPtr->tcindxrec;
11709   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
11710   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
11711   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
11712   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
11713   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL ? 0 : 1);
11714   ptrAss(localHostptr, hostRecord);
11715   UintR TcurrLen = localHostptr.p->noOfWordsTCINDXCONF;
11716   UintR confInfo = 0;
11717   TcIndxConf::setNoOfOperations(confInfo, (TopWords >> 1));
11718   TcIndxConf::setCommitFlag(confInfo, TcommitFlag == 1);
11719   TcIndxConf::setMarkerFlag(confInfo, Tmarker);
11720   const UintR TpacketLen = 6 + TopWords;
11721   regApiPtr->tcindxrec = 0;
11722 
11723   if(TcommitFlag || (regApiPtr->lqhkeyreqrec == regApiPtr->lqhkeyconfrec)){
11724     jam();
11725     regApiPtr->m_exec_flag = 0;
11726   }
11727 
11728   if ((TpacketLen > 25) || !is_api){
11729     TcIndxConf * const tcIndxConf = (TcIndxConf *)signal->getDataPtrSend();
11730 
11731     jam();
11732     tcIndxConf->apiConnectPtr = regApiPtr->ndbapiConnect;
11733     tcIndxConf->gci = regApiPtr->globalcheckpointid;;
11734     tcIndxConf->confInfo = confInfo;
11735     tcIndxConf->transId1 = regApiPtr->transid[0];
11736     tcIndxConf->transId2 = regApiPtr->transid[1];
11737     copyFromToLen(&regApiPtr->tcIndxSendArray[0],
11738                   (UintR*)&tcIndxConf->operations,
11739                   (UintR)ZTCOPCONF_SIZE);
11740     sendSignal(regApiPtr->ndbapiBlockref,
11741                GSN_TCINDXCONF, signal, (TpacketLen - 1), JBB);
11742     return;
11743   } else if (((TcurrLen + TpacketLen) > 25) && (TcurrLen > 0)) {
11744     jam();
11745     sendPackedTCINDXCONF(signal, localHostptr.p, localHostptr.i);
11746     TcurrLen = 0;
11747   } else {
11748     jam();
11749     updatePackedList(signal, localHostptr.p, localHostptr.i);
11750   }//if
11751 // -------------------------------------------------------------------------
11752 // The header contains the block reference of receiver plus the real signal
11753 // length - 3, since we have the real signal length plus one additional word
11754 // for the header we have to do - 4.
11755 // -------------------------------------------------------------------------
11756   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4);
11757   UintR Tpack1 = regApiPtr->ndbapiConnect;
11758   UintR Tpack2 = regApiPtr->globalcheckpointid;
11759   UintR Tpack3 = confInfo;
11760   UintR Tpack4 = regApiPtr->transid[0];
11761   UintR Tpack5 = regApiPtr->transid[1];
11762 
11763   localHostptr.p->noOfWordsTCINDXCONF = TcurrLen + TpacketLen;
11764 
11765   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 0] = Tpack0;
11766   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 1] = Tpack1;
11767   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 2] = Tpack2;
11768   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 3] = Tpack3;
11769   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 4] = Tpack4;
11770   localHostptr.p->packedWordsTCINDXCONF[TcurrLen + 5] = Tpack5;
11771 
11772   UintR Ti;
11773   for (Ti = 6; Ti < TpacketLen; Ti++) {
11774     localHostptr.p->packedWordsTCINDXCONF[TcurrLen + Ti] =
11775           regApiPtr->tcIndxSendArray[Ti - 6];
11776   }//for
11777 }//Dbtc::sendTcIndxConf()
11778 
execINDXKEYINFO(Signal * signal)11779 void Dbtc::execINDXKEYINFO(Signal* signal)
11780 {
11781   jamEntry();
11782   Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
11783   IndxKeyInfo * const indxKeyInfo =  (IndxKeyInfo *)signal->getDataPtr();
11784   const Uint32 *src = indxKeyInfo->getData();
11785   const UintR TconnectIndex = indxKeyInfo->connectPtr;
11786   ApiConnectRecordPtr transPtr;
11787   transPtr.i = TconnectIndex;
11788   if (transPtr.i >= capiConnectFilesize) {
11789     jam();
11790     warningHandlerLab(signal, __LINE__);
11791     return;
11792   }//if
11793   ptrAss(transPtr, apiConnectRecord);
11794   ApiConnectRecord * const regApiPtr = transPtr.p;
11795   TcIndexOperationPtr indexOpPtr;
11796   TcIndexOperation* indexOp;
11797 
11798   if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
11799   {
11800     TCKEY_abort(signal, 19);
11801     return;
11802   }
11803 
11804   if (regApiPtr->apiConnectstate == CS_ABORTING)
11805   {
11806     jam();
11807     return;
11808   }
11809 
11810   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
11811   {
11812     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
11813     if (saveINDXKEYINFO(signal,
11814 			indexOp,
11815 			src,
11816 			keyInfoLength) == 0) {
11817       jam();
11818       // We have received all we need
11819       readIndexTable(signal, regApiPtr, indexOp);
11820     }
11821   }
11822 }
11823 
execINDXATTRINFO(Signal * signal)11824 void Dbtc::execINDXATTRINFO(Signal* signal)
11825 {
11826   jamEntry();
11827   Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
11828   IndxAttrInfo * const indxAttrInfo =  (IndxAttrInfo *)signal->getDataPtr();
11829   const Uint32 *src = indxAttrInfo->getData();
11830   const UintR TconnectIndex = indxAttrInfo->connectPtr;
11831   ApiConnectRecordPtr transPtr;
11832   transPtr.i = TconnectIndex;
11833   if (transPtr.i >= capiConnectFilesize) {
11834     jam();
11835     warningHandlerLab(signal, __LINE__);
11836     return;
11837   }//if
11838   ptrAss(transPtr, apiConnectRecord);
11839   ApiConnectRecord * const regApiPtr = transPtr.p;
11840   TcIndexOperationPtr indexOpPtr;
11841   TcIndexOperation* indexOp;
11842 
11843   if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
11844   {
11845     TCKEY_abort(signal, 19);
11846     return;
11847   }
11848 
11849   if (regApiPtr->apiConnectstate == CS_ABORTING)
11850   {
11851     jam();
11852     return;
11853   }
11854 
11855   if((indexOpPtr.i = regApiPtr->accumulatingIndexOp) != RNIL)
11856   {
11857     indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
11858     if (saveINDXATTRINFO(signal,
11859 			 indexOp,
11860 			 src,
11861 			 attrInfoLength) == 0) {
11862       jam();
11863       // We have received all we need
11864       readIndexTable(signal, regApiPtr, indexOp);
11865       return;
11866     }
11867     return;
11868   }
11869 }
11870 
11871 /**
11872  * Save signal INDXKEYINFO
11873  * Return true if we have received all needed data
11874  */
11875 int
saveINDXKEYINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)11876 Dbtc::saveINDXKEYINFO(Signal* signal,
11877                       TcIndexOperation* indexOp,
11878                       const Uint32 *src,
11879                       Uint32 len)
11880 {
11881   if (ERROR_INSERTED(8052) || !indexOp->keyInfo.append(src, len)) {
11882     jam();
11883     // Failed to seize keyInfo, abort transaction
11884 #ifdef VM_TRACE
11885     ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize keyinfo\n");
11886 #endif
11887     // Abort transaction
11888     apiConnectptr.i = indexOp->connectionIndex;
11889     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11890     releaseIndexOperation(apiConnectptr.p, indexOp);
11891     terrorCode = 289;
11892     if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
11893       apiConnectptr.p->m_exec_flag= 1;
11894     abortErrorLab(signal);
11895     return -1;
11896   }
11897   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
11898     jam();
11899     return 0;
11900   }
11901   return 1;
11902 }
11903 
receivedAllINDXKEYINFO(TcIndexOperation * indexOp)11904 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
11905 {
11906   return (indexOp->keyInfo.getSize() == indexOp->expectedKeyInfo);
11907 }
11908 
11909 /**
11910  * Save signal INDXATTRINFO
11911  * Return true if we have received all needed data
11912  */
11913 int
saveINDXATTRINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)11914 Dbtc::saveINDXATTRINFO(Signal* signal,
11915                        TcIndexOperation* indexOp,
11916                        const Uint32 *src,
11917                        Uint32 len)
11918 {
11919   if (ERROR_INSERTED(8051) || !indexOp->attrInfo.append(src, len)) {
11920     jam();
11921 #ifdef VM_TRACE
11922     ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize attrInfo\n");
11923 #endif
11924     apiConnectptr.i = indexOp->connectionIndex;
11925     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11926     releaseIndexOperation(apiConnectptr.p, indexOp);
11927     terrorCode = 289;
11928     if(TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
11929       apiConnectptr.p->m_exec_flag= 1;
11930     abortErrorLab(signal);
11931     return -1;
11932   }
11933   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp)) {
11934     jam();
11935     return 0;
11936   }
11937   return 1;
11938 }
11939 
receivedAllINDXATTRINFO(TcIndexOperation * indexOp)11940 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
11941 {
11942   return (indexOp->attrInfo.getSize() == indexOp->expectedAttrInfo);
11943 }
11944 
saveTRANSID_AI(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)11945 bool  Dbtc::saveTRANSID_AI(Signal* signal,
11946 			   TcIndexOperation* indexOp,
11947                            const Uint32 *src,
11948                            Uint32 len)
11949 {
11950   Uint32 currentTransIdAILength = indexOp->transIdAI.getSize();
11951 
11952   if (currentTransIdAILength == 0) {
11953     jam();
11954     // Read first AttributeHeader to get expected size
11955     // of the single key attribute expected
11956     AttributeHeader* head = (AttributeHeader *) src;
11957     indexOp->expectedTransIdAI = head->getHeaderSize() + head->getDataSize();
11958   }
11959   if (!indexOp->transIdAI.append(src, len)) {
11960     jam();
11961 #ifdef VM_TRACE
11962     ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize transIdAI\n");
11963 #endif
11964     apiConnectptr.i = indexOp->connectionIndex;
11965     ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
11966     releaseIndexOperation(apiConnectptr.p, indexOp);
11967     terrorCode = 4000;
11968     abortErrorLab(signal);
11969     return false;
11970   }
11971   return true;
11972 }
11973 
receivedAllTRANSID_AI(TcIndexOperation * indexOp)11974 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
11975 {
11976   return (indexOp->transIdAI.getSize() == indexOp->expectedTransIdAI);
11977 }
11978 
11979 /**
11980  * Receive signal TCINDXCONF
11981  * This can be either the return of reading an index table
11982  * or performing an index operation
11983  */
execTCKEYCONF(Signal * signal)11984 void Dbtc::execTCKEYCONF(Signal* signal)
11985 {
11986   TcKeyConf * const tcKeyConf =  (TcKeyConf *)signal->getDataPtr();
11987   TcIndexOperationPtr indexOpPtr;
11988 
11989   jamEntry();
11990   indexOpPtr.i = tcKeyConf->apiConnectPtr;
11991   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
11992   Uint32 confInfo = tcKeyConf->confInfo;
11993 
11994   /**
11995    * Check on TCKEYCONF wheater the the transaction was committed
11996    */
11997   Uint32 Tcommit = TcKeyConf::getCommitFlag(confInfo);
11998 
11999   indexOpPtr.p = indexOp;
12000   if (!indexOp) {
12001     jam();
12002     // Missing index operation
12003     return;
12004   }
12005   const UintR TconnectIndex = indexOp->connectionIndex;
12006   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
12007   apiConnectptr.p = regApiPtr;
12008   apiConnectptr.i = TconnectIndex;
12009   switch(indexOp->indexOpState) {
12010   case(IOS_NOOP): {
12011     jam();
12012     // Should never happen, abort
12013     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12014 
12015     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12016     tcIndxRef->transId[0] = regApiPtr->transid[0];
12017     tcIndxRef->transId[1] = regApiPtr->transid[1];
12018     tcIndxRef->errorCode = 4349;
12019     tcIndxRef->errorData = 0;
12020     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12021 	       TcKeyRef::SignalLength, JBB);
12022     return;
12023   }
12024   case(IOS_INDEX_ACCESS): {
12025     jam();
12026     // Wait for TRANSID_AI
12027     indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
12028     break;
12029   }
12030   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
12031     jam();
12032     // Double TCKEYCONF, should never happen, abort
12033     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12034 
12035     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12036     tcIndxRef->transId[0] = regApiPtr->transid[0];
12037     tcIndxRef->transId[1] = regApiPtr->transid[1];
12038     tcIndxRef->errorCode = 4349;
12039     tcIndxRef->errorData = 0;
12040     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12041 	       TcKeyRef::SignalLength, JBB);
12042     return;
12043   }
12044   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
12045     jam();
12046     // Continue with index operation
12047     executeIndexOperation(signal, regApiPtr, indexOp);
12048     break;
12049   }
12050   case(IOS_INDEX_OPERATION): {
12051     // We are done, send TCINDXCONF
12052     jam();
12053     Uint32 Ttcindxrec = regApiPtr->tcindxrec;
12054     // Copy reply from TcKeyConf
12055 
12056     ndbassert(regApiPtr->noIndexOp);
12057     regApiPtr->noIndexOp--; // Decrease count
12058     regApiPtr->tcIndxSendArray[Ttcindxrec] = indexOp->tcIndxReq.senderData;
12059     regApiPtr->tcIndxSendArray[Ttcindxrec + 1] =
12060       tcKeyConf->operations[0].attrInfoLen;
12061     regApiPtr->tcindxrec = Ttcindxrec + 2;
12062     if (regApiPtr->noIndexOp == 0) {
12063       jam();
12064       sendTcIndxConf(signal, Tcommit);
12065     } else if (regApiPtr->tcindxrec == ZTCOPCONF_SIZE) {
12066       jam();
12067       sendTcIndxConf(signal, 0);
12068     }
12069     releaseIndexOperation(regApiPtr, indexOp);
12070     break;
12071   }
12072   }
12073 }
12074 
execTCKEYREF(Signal * signal)12075 void Dbtc::execTCKEYREF(Signal* signal)
12076 {
12077   TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
12078   TcIndexOperationPtr indexOpPtr;
12079 
12080   jamEntry();
12081   indexOpPtr.i = tcKeyRef->connectPtr;
12082   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
12083   indexOpPtr.p = indexOp;
12084   if (!indexOp) {
12085     jam();
12086     // Missing index operation
12087     return;
12088   }
12089   const UintR TconnectIndex = indexOp->connectionIndex;
12090   ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
12091 
12092   switch(indexOp->indexOpState) {
12093   case(IOS_NOOP): {
12094     jam();
12095     // Should never happen, abort
12096     break;
12097   }
12098   case(IOS_INDEX_ACCESS):
12099   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
12100   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
12101     jam();
12102     /**
12103      * Increase count as it will be decreased below...
12104      *   (and the code is written to handle failing lookup on "real" table
12105      *    not lookup on index table)
12106      */
12107     regApiPtr->noIndexOp++;
12108     // else continue
12109   }
12110   case(IOS_INDEX_OPERATION): {
12111     // Send TCINDXREF
12112 
12113     jam();
12114     TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
12115     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12116 
12117     ndbassert(regApiPtr->noIndexOp);
12118     regApiPtr->noIndexOp--; // Decrease count
12119     tcIndxRef->connectPtr = tcIndxReq->senderData;
12120     tcIndxRef->transId[0] = tcKeyRef->transId[0];
12121     tcIndxRef->transId[1] = tcKeyRef->transId[1];
12122     tcIndxRef->errorCode = tcKeyRef->errorCode;
12123     tcIndxRef->errorData = 0;
12124 
12125     releaseIndexOperation(regApiPtr, indexOp);
12126 
12127     sendSignal(regApiPtr->ndbapiBlockref,
12128                GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
12129     return;
12130   }
12131   }
12132 }
12133 
execTRANSID_AI_R(Signal * signal)12134 void Dbtc::execTRANSID_AI_R(Signal* signal){
12135   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
12136   Uint32 sigLen = signal->length();
12137   Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
12138   Uint32 recBlockref = transIdAI->attrData[dataLen];
12139 
12140   jamEntry();
12141 
12142   /**
12143    * Forward signal to final destination
12144    * Truncate last word since that was used to hold the final dest.
12145    */
12146   sendSignal(recBlockref, GSN_TRANSID_AI,
12147 	     signal, sigLen - 1, JBB);
12148 }
12149 
execKEYINFO20_R(Signal * signal)12150 void Dbtc::execKEYINFO20_R(Signal* signal){
12151   KeyInfo20 * const keyInfo =  (KeyInfo20 *)signal->getDataPtr();
12152   Uint32 sigLen = signal->length();
12153   Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
12154   Uint32 recBlockref = keyInfo->keyData[dataLen];
12155 
12156   jamEntry();
12157 
12158   /**
12159    * Forward signal to final destination
12160    * Truncate last word since that was used to hold the final dest.
12161    */
12162   sendSignal(recBlockref, GSN_KEYINFO20,
12163 	     signal, sigLen - 1, JBB);
12164 }
12165 
12166 
execTRANSID_AI(Signal * signal)12167 void Dbtc::execTRANSID_AI(Signal* signal)
12168 {
12169   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
12170 
12171   jamEntry();
12172   TcIndexOperationPtr indexOpPtr;
12173   indexOpPtr.i = transIdAI->connectPtr;
12174   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
12175   indexOpPtr.p = indexOp;
12176   if (!indexOp) {
12177     jam();
12178     // Missing index operation
12179   }
12180   const UintR TconnectIndex = indexOp->connectionIndex;
12181   //  ApiConnectRecord * const regApiPtr = &apiConnectRecord[TconnectIndex];
12182   ApiConnectRecordPtr transPtr;
12183 
12184   transPtr.i = TconnectIndex;
12185   ptrCheckGuard(transPtr, capiConnectFilesize, apiConnectRecord);
12186   ApiConnectRecord * const regApiPtr = transPtr.p;
12187 
12188   // Acccumulate attribute data
12189   if (!saveTRANSID_AI(signal,
12190 		      indexOp,
12191                       transIdAI->getData(),
12192                       signal->getLength() - TransIdAI::HeaderLength)) {
12193     jam();
12194     // Failed to allocate space for TransIdAI
12195     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12196 
12197     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12198     tcIndxRef->transId[0] = regApiPtr->transid[0];
12199     tcIndxRef->transId[1] = regApiPtr->transid[1];
12200     tcIndxRef->errorCode = 4000;
12201     tcIndxRef->errorData = 0;
12202     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12203 	       TcKeyRef::SignalLength, JBB);
12204     return;
12205   }
12206 
12207   switch(indexOp->indexOpState) {
12208   case(IOS_NOOP): {
12209     jam();
12210     // Should never happen, abort
12211     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12212 
12213     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12214     tcIndxRef->transId[0] = regApiPtr->transid[0];
12215     tcIndxRef->transId[1] = regApiPtr->transid[1];
12216     tcIndxRef->errorCode = 4349;
12217     tcIndxRef->errorData = 0;
12218     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12219 	       TcKeyRef::SignalLength, JBB);
12220     return;
12221     break;
12222   }
12223   case(IOS_INDEX_ACCESS): {
12224     jam();
12225     // Check if all TRANSID_AI have been received
12226     if (receivedAllTRANSID_AI(indexOp)) {
12227       jam();
12228       // Wait for TRANSID_AI
12229       indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
12230     }
12231     break;
12232     }
12233   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
12234     jam();
12235 #ifdef VM_TRACE
12236     ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
12237 #endif
12238     /*
12239     // Too many TRANSID_AI
12240     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12241 
12242     tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
12243     tcIndxRef->transId[0] = regApiPtr->transid[0];
12244     tcIndxRef->transId[1] = regApiPtr->transid[1];
12245     tcIndxRef->errorCode = 4349;
12246     tcIndxRef->errorData = 0;
12247     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12248                TcKeyRef::SignalLength, JBB);
12249     */
12250     break;
12251   }
12252   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
12253     jam();
12254     // Check if all TRANSID_AI have been received
12255     if (receivedAllTRANSID_AI(indexOp)) {
12256       jam();
12257       // Continue with index operation
12258       executeIndexOperation(signal, regApiPtr, indexOp);
12259     }
12260     // else continue waiting for more TRANSID_AI
12261     break;
12262   }
12263   case(IOS_INDEX_OPERATION): {
12264     // Should never receive TRANSID_AI in this state!!
12265     jam();
12266     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12267 
12268     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12269     tcIndxRef->transId[0] = regApiPtr->transid[0];
12270     tcIndxRef->transId[1] = regApiPtr->transid[1];
12271     tcIndxRef->errorCode = 4349;
12272     tcIndxRef->errorData = regApiPtr->errorData;
12273     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12274 	       TcKeyRef::SignalLength, JBB);
12275     return;
12276   }
12277   }
12278 }
12279 
execTCROLLBACKREP(Signal * signal)12280 void Dbtc::execTCROLLBACKREP(Signal* signal)
12281 {
12282   TcRollbackRep* tcRollbackRep =  (TcRollbackRep *)signal->getDataPtr();
12283   jamEntry();
12284   TcIndexOperationPtr indexOpPtr;
12285   indexOpPtr.i = tcRollbackRep->connectPtr;
12286   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
12287   indexOpPtr.p = indexOp;
12288   tcRollbackRep =  (TcRollbackRep *)signal->getDataPtrSend();
12289   tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
12290   sendSignal(apiConnectptr.p->ndbapiBlockref,
12291 	     GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
12292 }
12293 
12294 /**
12295  * Read index table with the index attributes as PK
12296  */
readIndexTable(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)12297 void Dbtc::readIndexTable(Signal* signal,
12298 			  ApiConnectRecord* regApiPtr,
12299 			  TcIndexOperation* indexOp)
12300 {
12301   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
12302   Uint32 dataPos = 0;
12303   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
12304   Uint32 * dataPtr = &tcKeyReq->scanInfo;
12305   Uint32 tcKeyLength = TcKeyReq::StaticLength;
12306   Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
12307   AttributeBuffer::DataBufferIterator keyIter;
12308   Uint32 keyLength = TcKeyReq::getKeyLength(tcKeyRequestInfo);
12309   TcIndexData* indexData;
12310   Uint32 transId1 = indexOp->tcIndxReq.transId1;
12311   Uint32 transId2 = indexOp->tcIndxReq.transId2;
12312 
12313   const Operation_t opType =
12314     (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
12315 
12316   // Find index table
12317   if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
12318     jam();
12319     // Failed to find index record
12320     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12321 
12322     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12323     tcIndxRef->transId[0] = regApiPtr->transid[0];
12324     tcIndxRef->transId[1] = regApiPtr->transid[1];
12325     tcIndxRef->errorCode = 4000;
12326     // tcIndxRef->errorData = ??; Where to find indexId
12327     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12328 	       TcKeyRef::SignalLength, JBB);
12329     return;
12330   }
12331   tcKeyReq->transId1 = transId1;
12332   tcKeyReq->transId2 = transId2;
12333   tcKeyReq->tableId = indexData->indexId;
12334   tcKeyLength += MIN(keyLength, keyBufSize);
12335   tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
12336   TcKeyReq::setOperationType(tcKeyRequestInfo,
12337 			     opType == ZREAD ? ZREAD : ZREAD_EX);
12338   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
12339   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
12340   tcKeyReq->senderData = indexOp->indexOpId;
12341   indexOp->indexOpState = IOS_INDEX_ACCESS;
12342   regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
12343   regApiPtr->accumulatingIndexOp = RNIL;
12344   regApiPtr->isIndexOp = 2;
12345 
12346   if (ERROR_INSERTED(8037))
12347   {
12348     ndbout_c("shifting index version");
12349     tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
12350   }
12351 
12352   Uint32 remainingKey = indexOp->keyInfo.getSize();
12353   bool moreKeyData = indexOp->keyInfo.first(keyIter);
12354   // *********** KEYINFO in TCKEYREQ ***********
12355   while((dataPos < keyBufSize) &&
12356         (remainingKey-- != 0)) {
12357     *dataPtr++ = *keyIter.data;
12358     dataPos++;
12359     moreKeyData = indexOp->keyInfo.next(keyIter);
12360   }
12361   // *********** ATTRINFO in TCKEYREQ ***********
12362   tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
12363   AttributeHeader::init(dataPtr, indexData->primaryKeyPos, 0);
12364   tcKeyLength++;
12365   tcKeyReq->requestInfo = tcKeyRequestInfo;
12366 
12367   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
12368   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
12369   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
12370   jamEntry();
12371 
12372   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12373   {
12374     goto err;
12375   }
12376 
12377   // *********** KEYINFO ***********
12378   if (moreKeyData) {
12379     jam();
12380     // Send KEYINFO sequence
12381     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
12382 
12383     keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
12384     keyInfo->transId[0] = transId1;
12385     keyInfo->transId[1] = transId2;
12386     dataPtr = (Uint32 *) &keyInfo->keyData;
12387     dataPos = 0;
12388     while(remainingKey-- != 0) {// If we have not read complete key
12389       *dataPtr++ = *keyIter.data;
12390       dataPos++;
12391       if (dataPos == KeyInfo::DataLength) {
12392 	// Flush KEYINFO
12393 	EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12394 		       KeyInfo::HeaderLength + KeyInfo::DataLength);
12395         jamEntry();
12396 	if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12397 	{
12398 	  goto err;
12399 	}
12400 	dataPos = 0;
12401 	dataPtr = (Uint32 *) &keyInfo->keyData;
12402       }
12403       moreKeyData = indexOp->keyInfo.next(keyIter);
12404     }
12405     if (dataPos != 0) {
12406       // Flush last KEYINFO
12407       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12408 		     KeyInfo::HeaderLength + dataPos);
12409       jamEntry();
12410       if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12411       {
12412 	goto err;
12413       }
12414     }
12415   }
12416 
12417   /**
12418    * "Fool" TC not to start commiting transaction since it always will
12419    *   have one outstanding lqhkeyreq
12420    * This is later decreased when the index read is complete
12421    */
12422   regApiPtr->lqhkeyreqrec++;
12423 
12424   /**
12425    * Remember ptr to index read operation
12426    *   (used to set correct save point id on index operation later)
12427    */
12428   indexOp->indexReadTcConnect = regApiPtr->lastTcConnect;
12429 
12430 done:
12431   return;
12432 
12433 err:
12434   jam();
12435   goto done;
12436 }
12437 
12438 /**
12439  * Execute the index operation with the result from
12440  * the index table read as PK
12441  */
executeIndexOperation(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)12442 void Dbtc::executeIndexOperation(Signal* signal,
12443 				 ApiConnectRecord* regApiPtr,
12444 				 TcIndexOperation* indexOp) {
12445 
12446   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
12447   Uint32 attrBufSize = 5;
12448   Uint32 dataPos = 0;
12449   TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
12450   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
12451   /*
12452     Data points to distrGroupHashValue since scanInfo is used to send
12453     fragment id of receiving fragment
12454   */
12455   Uint32 * dataPtr = &tcKeyReq->distrGroupHashValue;
12456   Uint32 tcKeyLength = TcKeyReq::StaticLength;
12457   Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
12458   TcIndexData* indexData;
12459   AttributeBuffer::DataBufferIterator attrIter;
12460   AttributeBuffer::DataBufferIterator aiIter;
12461   bool moreKeyData = indexOp->transIdAI.first(aiIter);
12462 
12463   // Find index table
12464   if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
12465     jam();
12466     // Failed to find index record
12467     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
12468 
12469     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
12470     tcIndxRef->transId[0] = regApiPtr->transid[0];
12471     tcIndxRef->transId[1] = regApiPtr->transid[1];
12472     tcIndxRef->errorCode = 4349;
12473     tcIndxRef->errorData = 0;
12474     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
12475 	       TcKeyRef::SignalLength, JBB);
12476     return;
12477   }
12478   // Find schema version of primary table
12479   TableRecordPtr tabPtr;
12480   tabPtr.i = indexData->primaryTableId;
12481   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
12482 
12483   tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
12484   tcKeyReq->attrLen = tcIndxReq->attrLen;
12485   tcKeyReq->tableId = indexData->primaryTableId;
12486   tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
12487   tcKeyReq->transId1 = regApiPtr->transid[0];
12488   tcKeyReq->transId2 = regApiPtr->transid[1];
12489   tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
12490   indexOp->indexOpState = IOS_INDEX_OPERATION;
12491   regApiPtr->isIndexOp = 1;
12492   regApiPtr->executingIndexOp = indexOp->indexOpId;;
12493   regApiPtr->noIndexOp++; // Increase count
12494 
12495   /*
12496     Filter out AttributeHeader:s since this should not be in key.
12497     Also filter out fragment id from primary key and handle that
12498     separately by setting it as Distribution Key and set indicator.
12499   */
12500 
12501   AttributeHeader* attrHeader = (AttributeHeader *) aiIter.data;
12502 
12503   Uint32 headerSize = attrHeader->getHeaderSize();
12504   Uint32 keySize = attrHeader->getDataSize() - 1;
12505   TcKeyReq::setKeyLength(tcKeyRequestInfo, keySize);
12506   // Skip header
12507   if (headerSize == 1) {
12508     jam();
12509     moreKeyData = indexOp->transIdAI.next(aiIter);
12510   } else {
12511     jam();
12512     moreKeyData = indexOp->transIdAI.next(aiIter, headerSize - 1);
12513   }//if
12514   tcKeyReq->scanInfo = *aiIter.data; //Fragment Id
12515   moreKeyData = indexOp->transIdAI.next(aiIter);
12516   TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
12517   while(// If we have not read complete key
12518 	(keySize != 0) &&
12519 	(dataPos < keyBufSize)) {
12520     *dataPtr++ = *aiIter.data;
12521     dataPos++;
12522     keySize--;
12523     moreKeyData = indexOp->transIdAI.next(aiIter);
12524   }
12525   tcKeyLength += dataPos;
12526 
12527   Uint32 attributesLength = indexOp->attrInfo.getSize();
12528   if (attributesLength <= attrBufSize) {
12529     jam();
12530     // ATTRINFO fits in TCKEYREQ
12531     // Pack ATTRINFO IN TCKEYREQ
12532     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, indexOp->attrInfo.getSize());
12533     // Insert IndxAttrInfo
12534     for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
12535         moreAttrData;
12536         moreAttrData = indexOp->attrInfo.next(attrIter)) {
12537       *dataPtr++ = *attrIter.data;
12538     }
12539     tcKeyLength += attributesLength;
12540   } else {
12541     jam();
12542     // No ATTRINFO in TCKEYREQ
12543     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
12544   }
12545 
12546   TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
12547   TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
12548   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, 0);
12549   tcKeyReq->requestInfo = tcKeyRequestInfo;
12550 
12551   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
12552   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
12553 
12554   /**
12555    * Decrease lqhkeyreqrec to compensate for addition
12556    *   during read of index table
12557    * I.e. let TC start committing when other operations has completed
12558    */
12559   regApiPtr->lqhkeyreqrec--;
12560 
12561   /**
12562    * Fix savepoint id -
12563    *   fix so that index operation has the same savepoint id
12564    *   as the read of the index table (TCINDXREQ)
12565    */
12566   TcConnectRecordPtr tmp;
12567   tmp.i = indexOp->indexReadTcConnect;
12568   ptrCheckGuard(tmp, ctcConnectFilesize, tcConnectRecord);
12569   const Uint32 currSavePointId = regApiPtr->currSavePointId;
12570   regApiPtr->currSavePointId = tmp.p->savePointId;
12571   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
12572   jamEntry();
12573 
12574   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12575   {
12576     jam();
12577     return;
12578   }
12579 
12580   regApiPtr->currSavePointId = currSavePointId;
12581 
12582   // *********** KEYINFO ***********
12583   if (moreKeyData) {
12584     jam();
12585     // Send KEYINFO sequence
12586     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
12587 
12588     keyInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
12589     keyInfo->transId[0] = regApiPtr->transid[0];
12590     keyInfo->transId[1] = regApiPtr->transid[1];
12591     dataPtr = (Uint32 *) &keyInfo->keyData;
12592     dataPos = 0;
12593     // Pack any part of a key attribute that did no fit TCKEYREQ
12594     while(keySize-- != 0) {// If we have not read complete key
12595       *dataPtr++ = *aiIter.data;
12596       dataPos++;
12597       if (dataPos == KeyInfo::DataLength) {
12598 	// Flush KEYINFO
12599 	EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12600 		       KeyInfo::HeaderLength + KeyInfo::DataLength);
12601         jamEntry();
12602 
12603 	if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12604 	{
12605 	  jam();
12606 	  return;
12607 	}
12608 
12609 	dataPos = 0;
12610 	dataPtr = (Uint32 *) &keyInfo->keyData;
12611       }
12612       moreKeyData = indexOp->transIdAI.next(aiIter);
12613     }
12614     if (dataPos != 0) {
12615       // Flush last KEYINFO
12616       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
12617 		     KeyInfo::HeaderLength + dataPos);
12618       jamEntry();
12619 
12620       if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12621       {
12622 	jam();
12623 	return;
12624       }
12625     }
12626   }
12627 
12628   // *********** ATTRINFO ***********
12629   if (attributesLength > attrBufSize) {
12630     jam();
12631     // No ATTRINFO in TcKeyReq
12632     TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
12633     // Send ATTRINFO sequence
12634     AttrInfo * const attrInfo =  (AttrInfo *)signal->getDataPtrSend();
12635     Uint32 attrInfoPos = 0;
12636 
12637     attrInfo->connectPtr = indexOp->tcIndxReq.apiConnectPtr;
12638     attrInfo->transId[0] = regApiPtr->transid[0];
12639     attrInfo->transId[1] = regApiPtr->transid[1];
12640     dataPtr = (Uint32 *) &attrInfo->attrData;
12641 
12642 
12643     // Insert attribute values (insert key values of primary table)
12644     for(bool moreAttrData = indexOp->attrInfo.first(attrIter);
12645         moreAttrData;
12646         moreAttrData = indexOp->attrInfo.next(attrIter)) {
12647       *dataPtr++ = *attrIter.data;
12648       attrInfoPos++;
12649       if (attrInfoPos == AttrInfo::DataLength) {
12650         // Flush ATTRINFO
12651         EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
12652 		       AttrInfo::HeaderLength + AttrInfo::DataLength);
12653         jamEntry();
12654 
12655 	if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
12656 	{
12657 	  jam();
12658 	  return;
12659 	}
12660 
12661         attrInfoPos = 0;
12662 	dataPtr = (Uint32 *) &attrInfo->attrData;
12663       }
12664     }
12665     if (attrInfoPos != 0) {
12666       // Send last ATTRINFO
12667       EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
12668 		     AttrInfo::HeaderLength + attrInfoPos);
12669       jamEntry();
12670     }
12671   }
12672 }
12673 
seizeIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperationPtr & indexOpPtr)12674 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
12675 			       TcIndexOperationPtr& indexOpPtr)
12676 {
12677   if (regApiPtr->theSeizedIndexOperations.seize(indexOpPtr))
12678   {
12679     ndbassert(indexOpPtr.p->expectedKeyInfo == 0);
12680     ndbassert(indexOpPtr.p->keyInfo.getSize() == 0);
12681     ndbassert(indexOpPtr.p->expectedAttrInfo == 0);
12682     ndbassert(indexOpPtr.p->attrInfo.getSize() == 0);
12683     ndbassert(indexOpPtr.p->expectedTransIdAI == 0);
12684     ndbassert(indexOpPtr.p->transIdAI.getSize() == 0);
12685     return true;
12686   }
12687 
12688   return false;
12689 }
12690 
releaseIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)12691 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
12692 				 TcIndexOperation* indexOp)
12693 {
12694   indexOp->indexOpState = IOS_NOOP;
12695   indexOp->expectedKeyInfo = 0;
12696   indexOp->keyInfo.release();
12697   indexOp->expectedAttrInfo = 0;
12698   indexOp->attrInfo.release();
12699   indexOp->expectedTransIdAI = 0;
12700   indexOp->transIdAI.release();
12701   regApiPtr->theSeizedIndexOperations.release(indexOp->indexOpId);
12702 }
12703 
releaseAllSeizedIndexOperations(ApiConnectRecord * regApiPtr)12704 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
12705 {
12706   TcIndexOperationPtr seizedIndexOpPtr;
12707 
12708   regApiPtr->theSeizedIndexOperations.first(seizedIndexOpPtr);
12709   while(seizedIndexOpPtr.i != RNIL) {
12710     jam();
12711     TcIndexOperation* indexOp = seizedIndexOpPtr.p;
12712 
12713     indexOp->indexOpState = IOS_NOOP;
12714     indexOp->expectedKeyInfo = 0;
12715     indexOp->keyInfo.release();
12716     indexOp->expectedAttrInfo = 0;
12717     indexOp->attrInfo.release();
12718     indexOp->expectedTransIdAI = 0;
12719     indexOp->transIdAI.release();
12720     regApiPtr->theSeizedIndexOperations.next(seizedIndexOpPtr);
12721   }
12722   regApiPtr->theSeizedIndexOperations.release();
12723 }
12724 
saveTriggeringOpState(Signal * signal,TcConnectRecord * trigOp)12725 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
12726 {
12727   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
12728   copyFromToLen((UintR*)lqhKeyConf,
12729 		&trigOp->savedState[0],
12730                 LqhKeyConf::SignalLength);
12731 }
12732 
continueTriggeringOp(Signal * signal,TcConnectRecord * trigOp)12733 void Dbtc::continueTriggeringOp(Signal* signal, TcConnectRecord* trigOp)
12734 {
12735   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
12736   copyFromToLen(&trigOp->savedState[0],
12737                 (UintR*)lqhKeyConf,
12738 		LqhKeyConf::SignalLength);
12739 
12740   lqhKeyConf->noFiredTriggers = 0;
12741   trigOp->noReceivedTriggers = 0;
12742 
12743   // All triggers executed successfully, continue operation
12744   execLQHKEYCONF(signal);
12745 }
12746 
scheduleFiredTrigger(ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)12747 void Dbtc::scheduleFiredTrigger(ApiConnectRecordPtr* transPtr,
12748                                 TcConnectRecordPtr* opPtr)
12749 {
12750   // Set initial values for trigger fireing operation
12751   opPtr->p->triggerExecutionCount++;
12752 
12753   // Insert fired trigger in execution queue
12754   transPtr->p->theFiredTriggers.add(opPtr->p->accumulatingTriggerData);
12755   opPtr->p->accumulatingTriggerData.i = RNIL;
12756   opPtr->p->accumulatingTriggerData.p = NULL;
12757 }
12758 
executeTriggers(Signal * signal,ApiConnectRecordPtr * transPtr)12759 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr* transPtr)
12760 {
12761   ApiConnectRecord* regApiPtr = transPtr->p;
12762   TcConnectRecord *localTcConnectRecord = tcConnectRecord;
12763   TcConnectRecordPtr opPtr;
12764   FiredTriggerPtr trigPtr;
12765 
12766   if (!regApiPtr->theFiredTriggers.isEmpty()) {
12767     jam();
12768     if ((regApiPtr->apiConnectstate == CS_STARTED) ||
12769         (regApiPtr->apiConnectstate == CS_START_COMMITTING)) {
12770       jam();
12771       regApiPtr->theFiredTriggers.first(trigPtr);
12772       while (trigPtr.i != RNIL) {
12773         jam();
12774         // Execute all ready triggers in parallel
12775         opPtr.i = trigPtr.p->fireingOperation;
12776         ptrCheckGuard(opPtr, ctcConnectFilesize, localTcConnectRecord);
12777 	FiredTriggerPtr nextTrigPtr = trigPtr;
12778 	regApiPtr->theFiredTriggers.next(nextTrigPtr);
12779         if (opPtr.p->noReceivedTriggers == opPtr.p->noFiredTriggers) {
12780           jam();
12781           // Fireing operation is ready to have a trigger executing
12782           executeTrigger(signal, trigPtr.p, transPtr, &opPtr);
12783           // Should allow for interleaving here by sending a CONTINUEB and
12784 	  // return
12785           // Release trigger records
12786 	  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
12787 	  LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
12788 	  tmp1.release();
12789 	  LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
12790 	  tmp2.release();
12791 	  LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
12792 	  tmp3.release();
12793           regApiPtr->theFiredTriggers.release(trigPtr);
12794         }
12795 	trigPtr = nextTrigPtr;
12796       }
12797       return;
12798     // No more triggers, continue transaction after last executed trigger has
12799     // reurned (in execLQHKEYCONF or execLQHKEYREF)
12800     } else {
12801       // Wait until transaction is ready to execute a trigger
12802       jam();
12803       if (!regApiPtr->triggerPending) {
12804         jam();
12805         regApiPtr->triggerPending = true;
12806         signal->theData[0] = TcContinueB::TRIGGER_PENDING;
12807         signal->theData[1] = transPtr->i;
12808         sendSignal(reference(), GSN_CONTINUEB, signal, 3, JBB);
12809       }
12810       // else
12811       // We are already waiting for a pending trigger (CONTINUEB)
12812     }
12813   }
12814 }
12815 
executeTrigger(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)12816 void Dbtc::executeTrigger(Signal* signal,
12817                           TcFiredTriggerData* firedTriggerData,
12818                           ApiConnectRecordPtr* transPtr,
12819                           TcConnectRecordPtr* opPtr)
12820 {
12821   TcDefinedTriggerData* definedTriggerData;
12822 
12823   if ((definedTriggerData =
12824        c_theDefinedTriggers.getPtr(firedTriggerData->triggerId))
12825       != NULL) {
12826     switch(definedTriggerData->triggerType) {
12827     case(TriggerType::SECONDARY_INDEX):
12828       jam();
12829       executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
12830                           transPtr, opPtr);
12831       break;
12832     default:
12833       ndbrequire(false);
12834     }
12835   }
12836 }
12837 
executeIndexTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr)12838 void Dbtc::executeIndexTrigger(Signal* signal,
12839                                TcDefinedTriggerData* definedTriggerData,
12840                                TcFiredTriggerData* firedTriggerData,
12841                                ApiConnectRecordPtr* transPtr,
12842                                TcConnectRecordPtr* opPtr)
12843 {
12844   TcIndexData* indexData;
12845 
12846   indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
12847   ndbassert(indexData != NULL);
12848 
12849   switch (definedTriggerData->triggerEvent) {
12850   case(TriggerEvent::TE_INSERT): {
12851     jam();
12852     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
12853     break;
12854   }
12855   case(TriggerEvent::TE_DELETE): {
12856     jam();
12857     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
12858     break;
12859   }
12860   case(TriggerEvent::TE_UPDATE): {
12861     jam();
12862     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr,
12863 			 indexData, true); // Hold the triggering operation
12864     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
12865     break;
12866   }
12867   default:
12868     ndbrequire(false);
12869   }
12870 }
12871 
releaseFiredTriggerData(DLFifoList<TcFiredTriggerData> * triggers)12872 void Dbtc::releaseFiredTriggerData(DLFifoList<TcFiredTriggerData>* triggers)
12873 {
12874   FiredTriggerPtr trigPtr;
12875 
12876   triggers->first(trigPtr);
12877   while (trigPtr.i != RNIL) {
12878     jam();
12879     // Release trigger records
12880 
12881     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
12882     LocalDataBuffer<11> tmp1(pool, trigPtr.p->keyValues);
12883     tmp1.release();
12884     LocalDataBuffer<11> tmp2(pool, trigPtr.p->beforeValues);
12885     tmp2.release();
12886     LocalDataBuffer<11> tmp3(pool, trigPtr.p->afterValues);
12887     tmp3.release();
12888 
12889     triggers->next(trigPtr);
12890   }
12891   triggers->release();
12892 }
12893 
insertIntoIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData,bool holdOperation)12894 void Dbtc::insertIntoIndexTable(Signal* signal,
12895                                 TcFiredTriggerData* firedTriggerData,
12896                                 ApiConnectRecordPtr* transPtr,
12897                                 TcConnectRecordPtr* opPtr,
12898                                 TcIndexData* indexData,
12899                                 bool holdOperation)
12900 {
12901   ApiConnectRecord* regApiPtr = transPtr->p;
12902   TcConnectRecord* opRecord = opPtr->p;
12903   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
12904   Uint32 tcKeyRequestInfo = 0;
12905   Uint32 tcKeyLength = TcKeyReq::StaticLength;
12906   TableRecordPtr indexTabPtr;
12907   AttributeBuffer::DataBufferIterator iter;
12908   Uint32 attrId = 0;
12909   Uint32 keyLength = 0;
12910   Uint32 totalPrimaryKeyLength = 1; // fragment length
12911   Uint32 hops;
12912 
12913   indexTabPtr.i = indexData->indexId;
12914   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
12915   tcKeyReq->apiConnectPtr = transPtr->i;
12916   tcKeyReq->senderData = opPtr->i;
12917   if (holdOperation) {
12918     jam();
12919     opRecord->triggerExecutionCount++;
12920   }//if
12921   // Calculate key length and renumber attribute id:s
12922   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
12923   LocalDataBuffer<11> afterValues(pool, firedTriggerData->afterValues);
12924   bool skipNull = false;
12925   for(bool moreKeyAttrs = afterValues.first(iter); moreKeyAttrs; attrId++) {
12926     jam();
12927     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
12928 
12929     // Filter out NULL valued attributes
12930     if (attrHeader->isNULL()) {
12931       skipNull = true;
12932       break;
12933     }
12934     attrHeader->setAttributeId(attrId);
12935     keyLength += attrHeader->getDataSize();
12936     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
12937     moreKeyAttrs = afterValues.next(iter, hops);
12938   }
12939   if (skipNull) {
12940     jam();
12941     opRecord->triggerExecutionCount--;
12942     if (opRecord->triggerExecutionCount == 0) {
12943       /*
12944 	We have completed current trigger execution
12945 	Continue triggering operation
12946       */
12947       jam();
12948       continueTriggeringOp(signal, opRecord);
12949     }//if
12950     return;
12951   }//if
12952 
12953   // Calculate total length of primary key to be stored in index table
12954   LocalDataBuffer<11> keyValues(pool, firedTriggerData->keyValues);
12955   for(bool moreAttrData = keyValues.first(iter); moreAttrData; ) {
12956     jam();
12957     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
12958 
12959     totalPrimaryKeyLength += attrHeader->getDataSize();
12960     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
12961     moreAttrData = keyValues.next(iter, hops);
12962   }
12963   AttributeHeader pkAttrHeader(attrId, totalPrimaryKeyLength << 2);
12964   Uint32 attributesLength = afterValues.getSize() +
12965     pkAttrHeader.getHeaderSize() + pkAttrHeader.getDataSize();
12966 
12967   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
12968   tcKeyReq->attrLen = attributesLength;
12969   tcKeyReq->tableId = indexData->indexId;
12970   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
12971   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
12972   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
12973   tcKeyReq->transId1 = regApiPtr->transid[0];
12974   tcKeyReq->transId2 = regApiPtr->transid[1];
12975   Uint32 * dataPtr = &tcKeyReq->scanInfo;
12976   // Write first part of key in TCKEYREQ
12977   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
12978   Uint32 attrBufSize = 5; // Maximum for key in TCKEYREQ
12979   Uint32 dataPos = 0;
12980   // Filter out AttributeHeader:s since this should no be in key
12981   bool moreKeyData = afterValues.first(iter);
12982   Uint32 headerSize = 0, keyAttrSize = 0, dataSize = 0, headAndData = 0;
12983 
12984   while (moreKeyData && (dataPos < keyBufSize)) {
12985     /*
12986      * If we have not read complete key
12987      * and it fits in the signal
12988      */
12989     jam();
12990     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
12991 
12992     headerSize = attrHeader->getHeaderSize();
12993     keyAttrSize = attrHeader->getDataSize();
12994     headAndData = headerSize + attrHeader->getDataSize();
12995     // Skip header
12996     if (headerSize == 1) {
12997       jam();
12998       moreKeyData = afterValues.next(iter);
12999     } else {
13000       jam();
13001       moreKeyData = afterValues.next(iter, headerSize - 1);
13002     }//if
13003     while((keyAttrSize != 0) && (dataPos < keyBufSize)) {
13004       // If we have not read complete key
13005       jam();
13006       *dataPtr++ = *iter.data;
13007       dataPos++;
13008       keyAttrSize--;
13009       moreKeyData = afterValues.next(iter);
13010     }
13011     if (keyAttrSize != 0) {
13012       jam();
13013       break;
13014     }//if
13015   }
13016 
13017   tcKeyLength += dataPos;
13018   /*
13019     Size of attrinfo is unique index attributes one by one, header for each
13020     of them (all contained in the afterValues data structure), plus a header,
13021     the primary key (compacted) and the fragment id before the primary key
13022   */
13023   if (attributesLength <= attrBufSize) {
13024     jam();
13025     // ATTRINFO fits in TCKEYREQ
13026     // Pack ATTRINFO IN TCKEYREQ as one attribute
13027     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, attributesLength);
13028     bool moreAttrData;
13029     // Insert primary key attributes (insert after values of primary table)
13030     for(moreAttrData = afterValues.first(iter);
13031 	moreAttrData;
13032 	moreAttrData = afterValues.next(iter)) {
13033       *dataPtr++ = *iter.data;
13034     }
13035     // Insert attribute values (insert key values of primary table)
13036     // as one attribute
13037     pkAttrHeader.insertHeader(dataPtr);
13038     dataPtr += pkAttrHeader.getHeaderSize();
13039     /*
13040       Insert fragment id before primary key as part of reference to tuple
13041     */
13042     *dataPtr++ = firedTriggerData->fragId;
13043     moreAttrData = keyValues.first(iter);
13044     while(moreAttrData) {
13045       jam();
13046       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13047 
13048       headerSize = attrHeader->getHeaderSize();
13049       dataSize = attrHeader->getDataSize();
13050       // Skip header
13051       if (headerSize == 1) {
13052         jam();
13053         moreAttrData = keyValues.next(iter);
13054       } else {
13055         jam();
13056         moreAttrData = keyValues.next(iter, headerSize - 1);
13057       }//if
13058       // Copy attribute data
13059       while(dataSize-- != 0) {
13060 	*dataPtr++ = *iter.data;
13061 	moreAttrData = keyValues.next(iter);
13062       }
13063     }
13064     tcKeyLength += attributesLength;
13065   } else {
13066     jam();
13067     // No ATTRINFO in TCKEYREQ
13068     TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
13069   }
13070   tcKeyReq->requestInfo = tcKeyRequestInfo;
13071 
13072   /**
13073    * Fix savepoint id -
13074    *   fix so that insert has same savepoint id as triggering operation
13075    */
13076   const Uint32 currSavePointId = regApiPtr->currSavePointId;
13077   regApiPtr->currSavePointId = opRecord->savePointId;
13078   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
13079   jamEntry();
13080 
13081   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13082   {
13083     jam();
13084     return;
13085   }
13086 
13087   regApiPtr->currSavePointId = currSavePointId;
13088   tcConnectptr.p->currentIndexId = indexData->indexId;
13089 
13090   // *********** KEYINFO ***********
13091   if (moreKeyData) {
13092     jam();
13093     // Send KEYINFO sequence
13094     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
13095 
13096     keyInfo->connectPtr = transPtr->i;
13097     keyInfo->transId[0] = regApiPtr->transid[0];
13098     keyInfo->transId[1] = regApiPtr->transid[1];
13099     dataPtr = (Uint32 *) &keyInfo->keyData;
13100     dataPos = 0;
13101     // Pack any part of a key attribute that did no fit TCKEYREQ
13102     while((keyAttrSize != 0) && (dataPos < KeyInfo::DataLength)) {
13103       // If we have not read complete key
13104       *dataPtr++ = *iter.data;
13105       dataPos++;
13106       keyAttrSize--;
13107       if (dataPos == KeyInfo::DataLength) {
13108         jam();
13109 	// Flush KEYINFO
13110 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13111 	sendSignal(reference(), GSN_KEYINFO, signal,
13112 		   KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13113 #else
13114 	EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13115 		       KeyInfo::HeaderLength + KeyInfo::DataLength);
13116         jamEntry();
13117 #endif
13118 	if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13119 	{
13120 	  jam();
13121 	  return;
13122 	}
13123 
13124 	dataPtr = (Uint32 *) &keyInfo->keyData;
13125 	dataPos = 0;
13126       }
13127       moreKeyData = afterValues.next(iter);
13128     }
13129 
13130     while(moreKeyData) {
13131       jam();
13132       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13133 
13134       headerSize = attrHeader->getHeaderSize();
13135       keyAttrSize = attrHeader->getDataSize();
13136       headAndData = headerSize + attrHeader->getDataSize();
13137       // Skip header
13138       if (headerSize == 1) {
13139         jam();
13140         moreKeyData = afterValues.next(iter);
13141       } else {
13142         jam();
13143         moreKeyData = afterValues.next(iter, headerSize - 1);
13144       }//if
13145       while (keyAttrSize-- != 0) {
13146         *dataPtr++ = *iter.data;
13147         dataPos++;
13148         if (dataPos == KeyInfo::DataLength) {
13149           jam();
13150           // Flush KEYINFO
13151 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13152 	  sendSignal(reference(), GSN_KEYINFO, signal,
13153 		     KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13154 #else
13155           EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13156 			 KeyInfo::HeaderLength + KeyInfo::DataLength);
13157           jamEntry();
13158 #endif
13159 
13160 	  if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13161 	  {
13162 	    jam();
13163 	    return;
13164 	  }
13165 
13166 	  dataPtr = (Uint32 *) &keyInfo->keyData;
13167           dataPos = 0;
13168         }
13169         moreKeyData = afterValues.next(iter);
13170       }
13171     }
13172     if (dataPos != 0) {
13173       jam();
13174       // Flush last KEYINFO
13175 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13176       sendSignal(reference(), GSN_KEYINFO, signal,
13177 		 KeyInfo::HeaderLength + dataPos, JBA);
13178 #else
13179       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13180 		     KeyInfo::HeaderLength + dataPos);
13181       jamEntry();
13182 #endif
13183       if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13184       {
13185 	jam();
13186 	return;
13187       }
13188     }
13189   }
13190 
13191   // *********** ATTRINFO ***********
13192   if (attributesLength > attrBufSize) {
13193     jam();
13194     // No ATTRINFO in TcKeyReq
13195     TcKeyReq::setAIInTcKeyReq(tcKeyReq->requestInfo, 0);
13196     // Send ATTRINFO sequence
13197     AttrInfo * const attrInfo =  (AttrInfo *)signal->getDataPtrSend();
13198     Uint32 attrInfoPos = 0;
13199 
13200     attrInfo->connectPtr = transPtr->i;
13201     attrInfo->transId[0] = regApiPtr->transid[0];
13202     attrInfo->transId[1] = regApiPtr->transid[1];
13203     dataPtr = (Uint32 *) &attrInfo->attrData;
13204 
13205     bool moreAttrData;
13206     // Insert primary key attributes (insert after values of primary table)
13207     for(moreAttrData = afterValues.first(iter);
13208 	moreAttrData;
13209 	moreAttrData = afterValues.next(iter)) {
13210       *dataPtr++ = *iter.data;
13211       attrInfoPos++;
13212       if (attrInfoPos == AttrInfo::DataLength) {
13213         jam();
13214 	// Flush ATTRINFO
13215 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13216 	sendSignal(reference(), GSN_ATTRINFO, signal,
13217 		   AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
13218 #else
13219 	EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13220 		       AttrInfo::HeaderLength + AttrInfo::DataLength);
13221         jamEntry();
13222 #endif
13223 	if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13224 	{
13225 	  jam();
13226 	  return;
13227 	}
13228 
13229 	dataPtr = (Uint32 *) &attrInfo->attrData;
13230 	attrInfoPos = 0;
13231       }
13232     }
13233     // Insert attribute values (insert key values of primary table)
13234     // as one attribute
13235     pkAttrHeader.insertHeader(dataPtr);
13236     dataPtr += pkAttrHeader.getHeaderSize();
13237     attrInfoPos += pkAttrHeader.getHeaderSize();
13238     /*
13239       Add fragment id before primary key
13240       TODO: This code really needs to be made into a long signal
13241       to remove this messy code.
13242     */
13243     if (attrInfoPos == AttrInfo::DataLength)
13244     {
13245       jam();
13246       // Flush ATTRINFO
13247 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13248       sendSignal(reference(), GSN_ATTRINFO, signal,
13249                  AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
13250 #else
13251       EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13252                      AttrInfo::HeaderLength + AttrInfo::DataLength);
13253       jamEntry();
13254 #endif
13255       dataPtr = (Uint32 *) &attrInfo->attrData;
13256       attrInfoPos = 0;
13257     }
13258     attrInfoPos++;
13259     *dataPtr++ = firedTriggerData->fragId;
13260 
13261     moreAttrData = keyValues.first(iter);
13262     while(moreAttrData) {
13263       jam();
13264       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13265 
13266       headerSize = attrHeader->getHeaderSize();
13267       dataSize = attrHeader->getDataSize();
13268       // Skip header
13269       if (headerSize == 1) {
13270         jam();
13271         moreAttrData = keyValues.next(iter);
13272       } else {
13273         jam();
13274         moreAttrData = keyValues.next(iter, headerSize - 1);
13275       }//if
13276       while(dataSize-- != 0) { // If we have not read complete key
13277         if (attrInfoPos == AttrInfo::DataLength) {
13278           jam();
13279           // Flush ATTRINFO
13280 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13281 	  sendSignal(reference(), GSN_ATTRINFO, signal,
13282 		     AttrInfo::HeaderLength + AttrInfo::DataLength, JBA);
13283 #else
13284 	  EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13285 			 AttrInfo::HeaderLength + AttrInfo::DataLength);
13286           jamEntry();
13287 #endif
13288 	  if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13289 	  {
13290 	    jam();
13291 	    return;
13292 	  }
13293 
13294 	  dataPtr = (Uint32 *) &attrInfo->attrData;
13295           attrInfoPos = 0;
13296         }
13297         *dataPtr++ = *iter.data;
13298         attrInfoPos++;
13299         moreAttrData = keyValues.next(iter);
13300       }
13301     }
13302     if (attrInfoPos != 0) {
13303       jam();
13304       // Flush last ATTRINFO
13305 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13306       sendSignal(reference(), GSN_ATTRINFO, signal,
13307 		 AttrInfo::HeaderLength + attrInfoPos, JBA);
13308 #else
13309       EXECUTE_DIRECT(DBTC, GSN_ATTRINFO, signal,
13310 		     AttrInfo::HeaderLength + attrInfoPos);
13311       jamEntry();
13312 #endif
13313     }
13314   }
13315 }
13316 
deleteFromIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData,bool holdOperation)13317 void Dbtc::deleteFromIndexTable(Signal* signal,
13318                                 TcFiredTriggerData* firedTriggerData,
13319                                 ApiConnectRecordPtr* transPtr,
13320                                 TcConnectRecordPtr* opPtr,
13321                                 TcIndexData* indexData,
13322                                 bool holdOperation)
13323 {
13324   ApiConnectRecord* regApiPtr = transPtr->p;
13325   TcConnectRecord* opRecord = opPtr->p;
13326   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
13327   Uint32 tcKeyRequestInfo = 0;
13328   Uint32 tcKeyLength = 12; // Static length
13329   TableRecordPtr indexTabPtr;
13330   AttributeBuffer::DataBufferIterator iter;
13331   Uint32 attrId = 0;
13332   Uint32 keyLength = 0;
13333   Uint32 hops;
13334 
13335   indexTabPtr.i = indexData->indexId;
13336   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
13337   tcKeyReq->apiConnectPtr = transPtr->i;
13338   tcKeyReq->senderData = opPtr->i;
13339   if (holdOperation) {
13340     jam();
13341     opRecord->triggerExecutionCount++;
13342   }//if
13343   // Calculate key length and renumber attribute id:s
13344   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
13345   LocalDataBuffer<11> beforeValues(pool, firedTriggerData->beforeValues);
13346   bool skipNull = false;
13347   for(bool moreKeyAttrs = beforeValues.first(iter);
13348       (moreKeyAttrs);
13349       attrId++) {
13350     jam();
13351     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13352 
13353     // Filter out NULL valued attributes
13354     if (attrHeader->isNULL()) {
13355       skipNull = true;
13356       break;
13357     }
13358     attrHeader->setAttributeId(attrId);
13359     keyLength += attrHeader->getDataSize();
13360     hops = attrHeader->getHeaderSize() + attrHeader->getDataSize();
13361     moreKeyAttrs = beforeValues.next(iter, hops);
13362   }
13363 
13364   if (skipNull) {
13365     jam();
13366     opRecord->triggerExecutionCount--;
13367     if (opRecord->triggerExecutionCount == 0) {
13368       /*
13369         We have completed current trigger execution
13370 	Continue triggering operation
13371       */
13372       jam();
13373       continueTriggeringOp(signal, opRecord);
13374     }//if
13375     return;
13376   }//if
13377 
13378   TcKeyReq::setKeyLength(tcKeyRequestInfo, keyLength);
13379   tcKeyReq->attrLen = 0;
13380   tcKeyReq->tableId = indexData->indexId;
13381   TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
13382   TcKeyReq::setExecutingTrigger(tcKeyRequestInfo, true);
13383   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
13384   tcKeyReq->transId1 = regApiPtr->transid[0];
13385   tcKeyReq->transId2 = regApiPtr->transid[1];
13386   Uint32 * dataPtr = &tcKeyReq->scanInfo;
13387   // Write first part of key in TCKEYREQ
13388   Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
13389   Uint32 dataPos = 0;
13390   // Filter out AttributeHeader:s since this should no be in key
13391   bool moreKeyData = beforeValues.first(iter);
13392   Uint32 headerSize = 0, keyAttrSize = 0, headAndData = 0;
13393 
13394   while (moreKeyData &&
13395          (dataPos < keyBufSize)) {
13396     /*
13397     If we have not read complete key
13398     and it fits in the signal
13399     */
13400     jam();
13401     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13402 
13403     headerSize = attrHeader->getHeaderSize();
13404     keyAttrSize = attrHeader->getDataSize();
13405     headAndData = headerSize + attrHeader->getDataSize();
13406     // Skip header
13407     if (headerSize == 1) {
13408       jam();
13409       moreKeyData = beforeValues.next(iter);
13410     } else {
13411       jam();
13412       moreKeyData = beforeValues.next(iter, headerSize - 1);
13413     }//if
13414     while((keyAttrSize != 0) &&
13415           (dataPos < keyBufSize)) {
13416       // If we have not read complete key
13417       jam();
13418       *dataPtr++ = *iter.data;
13419       dataPos++;
13420       keyAttrSize--;
13421       moreKeyData = beforeValues.next(iter);
13422     }
13423     if (keyAttrSize != 0) {
13424       jam();
13425       break;
13426     }//if
13427   }
13428 
13429   tcKeyLength += dataPos;
13430   tcKeyReq->requestInfo = tcKeyRequestInfo;
13431 
13432   /**
13433    * Fix savepoint id -
13434    *   fix so that delete has same savepoint id as triggering operation
13435    */
13436   const Uint32 currSavePointId = regApiPtr->currSavePointId;
13437   regApiPtr->currSavePointId = opRecord->savePointId;
13438   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, tcKeyLength);
13439   jamEntry();
13440 
13441   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13442   {
13443     jam();
13444     return;
13445   }
13446 
13447   regApiPtr->currSavePointId = currSavePointId;
13448   tcConnectptr.p->currentIndexId = indexData->indexId;
13449 
13450   // *********** KEYINFO ***********
13451   if (moreKeyData) {
13452     jam();
13453     // Send KEYINFO sequence
13454     KeyInfo * const keyInfo =  (KeyInfo *)signal->getDataPtrSend();
13455 
13456     keyInfo->connectPtr = transPtr->i;
13457     keyInfo->transId[0] = regApiPtr->transid[0];
13458     keyInfo->transId[1] = regApiPtr->transid[1];
13459     dataPtr = (Uint32 *) &keyInfo->keyData;
13460     dataPos = 0;
13461     // Pack any part of a key attribute that did no fit TCKEYREQ
13462     while((keyAttrSize != 0) &&
13463 	  (dataPos < KeyInfo::DataLength)) {
13464       // If we have not read complete key
13465       *dataPtr++ = *iter.data;
13466       dataPos++;
13467       keyAttrSize--;
13468       if (dataPos == KeyInfo::DataLength) {
13469         jam();
13470 	// Flush KEYINFO
13471 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13472 	sendSignal(reference(), GSN_KEYINFO, signal,
13473 		   KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13474 #else
13475 	EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13476 		       KeyInfo::HeaderLength + KeyInfo::DataLength);
13477         jamEntry();
13478 #endif
13479 	if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13480 	{
13481 	  jam();
13482 	  return;
13483 	}
13484 
13485 	dataPtr = (Uint32 *) &keyInfo->keyData;
13486 	dataPos = 0;
13487       }
13488       moreKeyData = beforeValues.next(iter);
13489     }
13490 
13491     while(moreKeyData) {
13492       jam();
13493       AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
13494 
13495       headerSize = attrHeader->getHeaderSize();
13496       keyAttrSize = attrHeader->getDataSize();
13497       headAndData = headerSize + attrHeader->getDataSize();
13498       // Skip header
13499       if (headerSize == 1) {
13500         jam();
13501         moreKeyData = beforeValues.next(iter);
13502       } else {
13503         jam();
13504         moreKeyData = beforeValues.next(iter,
13505 							  headerSize - 1);
13506       }//if
13507       while (keyAttrSize-- != 0) {
13508         *dataPtr++ = *iter.data;
13509         dataPos++;
13510         if (dataPos == KeyInfo::DataLength) {
13511           jam();
13512           // Flush KEYINFO
13513 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13514 	  sendSignal(reference(), GSN_KEYINFO, signal,
13515 		     KeyInfo::HeaderLength + KeyInfo::DataLength, JBA);
13516 #else
13517           EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13518 			 KeyInfo::HeaderLength + KeyInfo::DataLength);
13519           jamEntry();
13520 #endif
13521 	  if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
13522 	  {
13523 	    jam();
13524 	    return;
13525 	  }
13526 
13527 	  dataPtr = (Uint32 *) &keyInfo->keyData;
13528           dataPos = 0;
13529         }
13530         moreKeyData = beforeValues.next(iter);
13531       }
13532     }
13533     if (dataPos != 0) {
13534       jam();
13535       // Flush last KEYINFO
13536 #if INTERNAL_TRIGGER_TCKEYREQ_JBA
13537       sendSignal(reference(), GSN_KEYINFO, signal,
13538 		 KeyInfo::HeaderLength + dataPos, JBA);
13539 #else
13540       EXECUTE_DIRECT(DBTC, GSN_KEYINFO, signal,
13541 		     KeyInfo::HeaderLength + dataPos);
13542       jamEntry();
13543 #endif
13544     }
13545   }
13546 }
13547 
13548 Uint32
getErrorCode(Uint32 schemaVersion) const13549 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
13550   if(!get_enabled())
13551     return ZNO_SUCH_TABLE;
13552   if(get_dropping())
13553     return ZDROP_TABLE_IN_PROGRESS;
13554   if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
13555     return ZWRONG_SCHEMA_VERSION_ERROR;
13556   ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
13557 			      __FILE__, __LINE__);
13558   return 0;
13559 }
13560 
13561 void
execROUTE_ORD(Signal * signal)13562 Dbtc::execROUTE_ORD(Signal* signal)
13563 {
13564   jamEntry();
13565   if(!assembleFragments(signal)){
13566     jam();
13567     return;
13568   }
13569 
13570   RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
13571   Uint32 dstRef = ord->dstRef;
13572   Uint32 srcRef = ord->srcRef;
13573   Uint32 gsn = ord->gsn;
13574 
13575   if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
13576   {
13577     jam();
13578     Uint32 secCount = signal->getNoOfSections();
13579     SegmentedSectionPtr ptr[3];
13580     ndbrequire(secCount >= 1 && secCount <= 3);
13581 
13582     jamLine(secCount);
13583     for (Uint32 i = 0; i<secCount; i++)
13584       signal->getSection(ptr[i], i);
13585 
13586     /**
13587      * Put section 0 in signal->theData
13588      */
13589     ndbrequire(ptr[0].sz <= 25);
13590     copy(signal->theData, ptr[0]);
13591 
13592     signal->header.m_noOfSections = 0;
13593 
13594     /**
13595      * Shift rest of sections
13596      */
13597     for(Uint32 i = 1; i<secCount; i++)
13598     {
13599       signal->setSection(ptr[i], i - 1);
13600     }
13601 
13602     sendSignal(dstRef, gsn, signal, ptr[0].sz, JBB);
13603 
13604     signal->header.m_noOfSections = 0;
13605     signal->setSection(ptr[0], 0);
13606     releaseSections(signal);
13607     return ;
13608   }
13609 
13610   warningEvent("Unable to route GSN: %d from %x to %x",
13611 	       gsn, srcRef, dstRef);
13612 }
13613