1 /*
2    Copyright (c) 2003, 2020, Oracle and/or its affiliates. All rights reserved.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License, version 2.0,
6    as published by the Free Software Foundation.
7 
8    This program is also distributed with certain software (including
9    but not limited to OpenSSL) that is licensed under separate terms,
10    as designated in a particular file or component or in included license
11    documentation.  The authors of MySQL hereby grant you an additional
12    permission to link the program and your derivative works with the
13    separately licensed software that they have included with MySQL.
14 
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License, version 2.0, for more details.
19 
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
23 */
24 
25 //#define DBTC_MAIN
26 #define DBTC_C
27 
28 #include "Dbtc.hpp"
29 #include "md5_hash.hpp"
30 #include <RefConvert.hpp>
31 #include <ndb_limits.h>
32 #include <ndb_rand.h>
33 
34 #include <signaldata/DiGetNodes.hpp>
35 #include <signaldata/EventReport.hpp>
36 #include <signaldata/TcKeyReq.hpp>
37 #include <signaldata/TcKeyConf.hpp>
38 #include <signaldata/TcKeyRef.hpp>
39 #include <signaldata/KeyInfo.hpp>
40 #include <signaldata/AttrInfo.hpp>
41 #include <signaldata/TransIdAI.hpp>
42 #include <signaldata/TcRollbackRep.hpp>
43 #include <signaldata/NodeFailRep.hpp>
44 #include <signaldata/ReadNodesConf.hpp>
45 #include <signaldata/NFCompleteRep.hpp>
46 #include <signaldata/LqhKey.hpp>
47 #include <signaldata/TcCommit.hpp>
48 #include <signaldata/TcContinueB.hpp>
49 #include <signaldata/TcKeyFailConf.hpp>
50 #include <signaldata/AbortAll.hpp>
51 #include <signaldata/DihScanTab.hpp>
52 #include <signaldata/ScanFrag.hpp>
53 #include <signaldata/ScanTab.hpp>
54 #include <signaldata/PrepDropTab.hpp>
55 #include <signaldata/DropTab.hpp>
56 #include <signaldata/AlterTab.hpp>
57 #include <signaldata/AlterTable.hpp>
58 #include <signaldata/CreateTrig.hpp>
59 #include <signaldata/CreateTrigImpl.hpp>
60 #include <signaldata/DropTrig.hpp>
61 #include <signaldata/DropTrigImpl.hpp>
62 #include <signaldata/FireTrigOrd.hpp>
63 #include <signaldata/TrigAttrInfo.hpp>
64 #include <signaldata/CreateIndx.hpp>
65 #include <signaldata/CreateIndxImpl.hpp>
66 #include <signaldata/DropIndx.hpp>
67 #include <signaldata/DropIndxImpl.hpp>
68 #include <signaldata/AlterIndx.hpp>
69 #include <signaldata/AlterIndxImpl.hpp>
70 #include <signaldata/ScanTab.hpp>
71 #include <signaldata/SystemError.hpp>
72 #include <signaldata/DumpStateOrd.hpp>
73 #include <signaldata/DisconnectRep.hpp>
74 #include <signaldata/TcHbRep.hpp>
75 
76 #include <signaldata/PrepDropTab.hpp>
77 #include <signaldata/DropTab.hpp>
78 #include <signaldata/TcIndx.hpp>
79 #include <signaldata/IndxKeyInfo.hpp>
80 #include <signaldata/IndxAttrInfo.hpp>
81 #include <signaldata/PackedSignal.hpp>
82 #include <signaldata/SignalDroppedRep.hpp>
83 #include <signaldata/LqhTransReq.hpp>
84 #include <signaldata/TakeOverTcConf.hpp>
85 #include <AttributeHeader.hpp>
86 #include <signaldata/DictTabInfo.hpp>
87 #include <AttributeDescriptor.hpp>
88 #include <SectionReader.hpp>
89 #include <KeyDescriptor.hpp>
90 
91 #include <NdbOut.hpp>
92 #include <DebuggerNames.hpp>
93 #include <signaldata/CheckNodeGroups.hpp>
94 
95 #include <signaldata/RouteOrd.hpp>
96 #include <signaldata/GCP.hpp>
97 
98 #include <signaldata/DbinfoScan.hpp>
99 #include <signaldata/TransIdAI.hpp>
100 #include <signaldata/CreateTab.hpp>
101 
102 #include <TransporterRegistry.hpp> // error 8035
103 #include <EventLogger.hpp>
104 
105 #include <signaldata/CreateFKImpl.hpp>
106 #include <signaldata/DropFKImpl.hpp>
107 #include <kernel/Interpreter.hpp>
108 #include <signaldata/TuxBound.hpp>
109 
110 #define JAM_FILE_ID 353
111 
112 //#define DO_TRANSIENT_POOL_STAT
113 
114 //#define ABORT_TRACE 1
115 #define TC_TIME_SIGNAL_DELAY 50
116 
117 extern EventLogger * g_eventLogger;
118 
119 // Use DEBUG to print messages that should be
120 // seen only when we debug the product
121 //#define USE_TC_DEBUG
122 #ifdef USE_TC_DEBUG
123 #define DEBUG(x) ndbout << "DBTC: "<< x << endl;
124 #else
125 #define DEBUG(x)
126 #endif
127 
128 #if (defined(VM_TRACE) || defined(ERROR_INSERT))
129 //#define DEBUG_NODE_FAILURE 1
130 #endif
131 
132 #ifdef DEBUG_NODE_FAILURE
133 #define DEB_NODE_FAILURE(arglist) do { g_eventLogger->info arglist ; } while (0)
134 #else
135 #define DEB_NODE_FAILURE(arglist) do { } while (0)
136 #endif
137 
138 #ifdef VM_TRACE
139 NdbOut &
operator <<(NdbOut & out,Dbtc::ConnectionState state)140 operator<<(NdbOut& out, Dbtc::ConnectionState state){
141   switch(state){
142   case Dbtc::CS_CONNECTED: out << "CS_CONNECTED"; break;
143   case Dbtc::CS_DISCONNECTED: out << "CS_DISCONNECTED"; break;
144   case Dbtc::CS_STARTED: out << "CS_STARTED"; break;
145   case Dbtc::CS_RECEIVING: out << "CS_RECEIVING"; break;
146   case Dbtc::CS_RESTART: out << "CS_RESTART"; break;
147   case Dbtc::CS_ABORTING: out << "CS_ABORTING"; break;
148   case Dbtc::CS_COMPLETING: out << "CS_COMPLETING"; break;
149   case Dbtc::CS_COMPLETE_SENT: out << "CS_COMPLETE_SENT"; break;
150   case Dbtc::CS_PREPARE_TO_COMMIT: out << "CS_PREPARE_TO_COMMIT"; break;
151   case Dbtc::CS_COMMIT_SENT: out << "CS_COMMIT_SENT"; break;
152   case Dbtc::CS_START_COMMITTING: out << "CS_START_COMMITTING"; break;
153   case Dbtc::CS_COMMITTING: out << "CS_COMMITTING"; break;
154   case Dbtc::CS_REC_COMMITTING: out << "CS_REC_COMMITTING"; break;
155   case Dbtc::CS_WAIT_ABORT_CONF: out << "CS_WAIT_ABORT_CONF"; break;
156   case Dbtc::CS_WAIT_COMPLETE_CONF: out << "CS_WAIT_COMPLETE_CONF"; break;
157   case Dbtc::CS_WAIT_COMMIT_CONF: out << "CS_WAIT_COMMIT_CONF"; break;
158   case Dbtc::CS_FAIL_ABORTING: out << "CS_FAIL_ABORTING"; break;
159   case Dbtc::CS_FAIL_ABORTED: out << "CS_FAIL_ABORTED"; break;
160   case Dbtc::CS_FAIL_PREPARED: out << "CS_FAIL_PREPARED"; break;
161   case Dbtc::CS_FAIL_COMMITTING: out << "CS_FAIL_COMMITTING"; break;
162   case Dbtc::CS_FAIL_COMMITTED: out << "CS_FAIL_COMMITTED"; break;
163   case Dbtc::CS_FAIL_COMPLETED: out << "CS_FAIL_COMPLETED"; break;
164   case Dbtc::CS_START_SCAN: out << "CS_START_SCAN"; break;
165   case Dbtc::CS_SEND_FIRE_TRIG_REQ: out << "CS_SEND_FIRE_TRIG_REQ"; break;
166   case Dbtc::CS_WAIT_FIRE_TRIG_REQ: out << "CS_WAIT_FIRE_TRIG_REQ"; break;
167 
168   default:
169     out << "Unknown: " << (int)state; break;
170   }
171   return out;
172 }
173 NdbOut &
operator <<(NdbOut & out,Dbtc::OperationState state)174 operator<<(NdbOut& out, Dbtc::OperationState state){
175   out << (int)state;
176   return out;
177 }
178 NdbOut &
operator <<(NdbOut & out,Dbtc::AbortState state)179 operator<<(NdbOut& out, Dbtc::AbortState state){
180   out << (int)state;
181   return out;
182 }
183 NdbOut &
operator <<(NdbOut & out,Dbtc::ReturnSignal state)184 operator<<(NdbOut& out, Dbtc::ReturnSignal state){
185   out << (int)state;
186   return out;
187 }
188 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanRecord::ScanState state)189 operator<<(NdbOut& out, Dbtc::ScanRecord::ScanState state){
190   out << (int)state;
191   return out;
192 }
193 NdbOut &
operator <<(NdbOut & out,Dbtc::ScanFragRec::ScanFragState state)194 operator<<(NdbOut& out, Dbtc::ScanFragRec::ScanFragState state){
195   out << (int)state;
196   return out;
197 }
198 #endif
199 
200 extern Uint32 ErrorSignalReceive;
201 extern Uint32 ErrorMaxSegmentsToSeize;
202 
203 void
updateBuddyTimer(ApiConnectRecordPtr apiPtr)204 Dbtc::updateBuddyTimer(ApiConnectRecordPtr apiPtr)
205 {
206   jam();
207   ApiConnectRecordPtr buddyApiPtr;
208   buddyApiPtr.i = apiPtr.p->buddyPtr;
209 
210   if (unlikely(buddyApiPtr.i == RNIL))
211   {
212     jam();
213     return;
214   }
215   if (unlikely(!c_apiConnectRecordPool.getValidPtr(buddyApiPtr)))
216   {
217     jam();
218     apiPtr.p->buddyPtr = RNIL;
219     return;
220   }
221   if (unlikely(getApiConTimer(buddyApiPtr) == 0))
222   {
223     jam();
224     return;
225   }
226   if (unlikely((apiPtr.p->transid[0] != buddyApiPtr.p->transid[0]) ||
227                (apiPtr.p->transid[1] != buddyApiPtr.p->transid[1])))
228   {
229     jam();
230     // Not a buddy anymore since not the same transid
231     apiPtr.p->buddyPtr = RNIL;
232     return;
233   }
234 
235   setApiConTimer(buddyApiPtr, ctcTimer, __LINE__);
236 }
237 
238 static
239 inline
240 bool
tc_testbit(Uint32 flags,Uint32 flag)241 tc_testbit(Uint32 flags, Uint32 flag)
242 {
243   return (flags & flag) != 0;
244 }
245 
246 static
247 inline
248 void
tc_clearbit(Uint32 & flags,Uint32 flag)249 tc_clearbit(Uint32 & flags, Uint32 flag)
250 {
251   flags &= ~(Uint32)flag;
252 }
253 
254 inline static void
prefetch_api_record_7(Uint32 * api_ptr)255 prefetch_api_record_7(Uint32* api_ptr)
256 {
257   NDB_PREFETCH_WRITE(api_ptr);
258   NDB_PREFETCH_WRITE(api_ptr + 16);
259   NDB_PREFETCH_WRITE(api_ptr + 32);
260   NDB_PREFETCH_WRITE(api_ptr + 48);
261   NDB_PREFETCH_WRITE(api_ptr + 64);
262   NDB_PREFETCH_WRITE(api_ptr + 80);
263   NDB_PREFETCH_WRITE(api_ptr + 96);
264 }
265 
execCONTINUEB(Signal * signal)266 void Dbtc::execCONTINUEB(Signal* signal)
267 {
268   UintR tcase;
269 
270   jamEntry();
271   tcase = signal->theData[0];
272   UintR Tdata0 = signal->theData[1];
273   UintR Tdata1 = signal->theData[2];
274   UintR Tdata2 = signal->theData[3];
275   UintR Tdata3 = signal->theData[4];
276 #ifdef ERROR_INSERT
277   UintR Tdata4 = signal->theData[5];
278   UintR Tdata5 = signal->theData[6];
279 #endif
280   switch (tcase) {
281   case TcContinueB::ZSCAN_FOR_READ_BACKUP:
282     jam();
283     scan_for_read_backup(signal, Tdata0, Tdata1, Tdata2);
284     return;
285   case TcContinueB::ZRETURN_FROM_QUEUED_DELIVERY:
286     jam();
287     ndbabort();
288     return;
289   case TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER:
290     jam();
291     tcNodeFailptr.i = Tdata0;
292     ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
293     completeTransAtTakeOverLab(signal, Tdata1);
294     return;
295   case TcContinueB::ZCONTINUE_TIME_OUT_CONTROL:
296     jam();
297     timeOutLoopStartLab(signal, Tdata0);
298     return;
299   case TcContinueB::ZNODE_TAKE_OVER_COMPLETED:
300     jam();
301     tcNodeFailptr.i = 0;
302     ptrAss(tcNodeFailptr, tcFailRecord);
303     nodeTakeOverCompletedLab(signal, Tdata0, 0);
304     return;
305   case TcContinueB::ZINITIALISE_RECORDS:
306     jam();
307     initialiseRecordsLab(signal, Tdata0, Tdata2, Tdata3);
308     return;
309   case TcContinueB::ZSEND_COMMIT_LOOP:
310   {
311     jam();
312     ApiConnectRecordPtr apiConnectptr;
313     apiConnectptr.i = Tdata0;
314     ndbrequire(c_apiConnectRecordPool.getValidPtr(apiConnectptr));
315     tcConnectptr.i = Tdata1;
316     ndbrequire(tcConnectRecord.getValidPtr(tcConnectptr));
317     commit020Lab(signal, apiConnectptr);
318     return;
319   }
320   case TcContinueB::ZSEND_COMPLETE_LOOP:
321   {
322     jam();
323     ApiConnectRecordPtr apiConnectptr;
324     apiConnectptr.i = Tdata0;
325     ndbrequire(c_apiConnectRecordPool.getValidPtr(apiConnectptr));
326     tcConnectptr.i = Tdata1;
327     ndbrequire(tcConnectRecord.getValidPtr(tcConnectptr));
328     complete010Lab(signal, apiConnectptr);
329     return;
330   }
331   case TcContinueB::ZHANDLE_FAILED_API_NODE:
332     jam();
333     handleFailedApiNode(signal, Tdata0, Tdata1);
334     return;
335   case TcContinueB::ZTRANS_EVENT_REP:
336     jam();
337     /* Send transaction counters report */
338     {
339       const Uint32 len = c_counters.build_event_rep(signal);
340       sendSignal(CMVMI_REF, GSN_EVENT_REP, signal, len, JBB);
341     }
342 
343     {
344       const Uint32 report_interval = 5000;
345       const Uint32 len = c_counters.build_continueB(signal);
346       signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
347       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, report_interval, len);
348     }
349     return;
350   case TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL:
351     jam();
352     timeOutLoopStartFragLab(signal, Tdata0);
353     return;
354   case TcContinueB::ZABORT_BREAK:
355   {
356     jam();
357     tcConnectptr.i = Tdata0;
358     ApiConnectRecordPtr apiConnectptr;
359     apiConnectptr.i = Tdata1;
360     c_apiConnectRecordPool.getPtr(apiConnectptr);
361     apiConnectptr.p->counter--;
362     abort015Lab(signal, apiConnectptr);
363     return;
364   }
365   case TcContinueB::ZABORT_TIMEOUT_BREAK:
366   {
367     jam();
368     tcConnectptr.i = Tdata0;
369     ApiConnectRecordPtr apiConnectptr;
370     apiConnectptr.i = Tdata1;
371     c_apiConnectRecordPool.getPtr(apiConnectptr);
372     apiConnectptr.p->counter--;
373     sendAbortedAfterTimeout(signal, 1, apiConnectptr);
374     return;
375   }
376   case TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS:
377     jam();
378     removeMarkerForFailedAPI(signal, Tdata0, Tdata1);
379     return;
380   case TcContinueB::ZWAIT_ABORT_ALL:
381     jam();
382     checkAbortAllTimeout(signal, Tdata0);
383     return;
384   case TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH:
385     jam();
386     checkScanActiveInFailedLqh(signal, Tdata0, Tdata1);
387     return;
388   case TcContinueB::ZNF_CHECK_TRANSACTIONS:
389     jam();
390     nodeFailCheckTransactions(signal, Tdata0, Tdata1);
391     return;
392   case TcContinueB::TRIGGER_PENDING:
393   {
394     jam();
395     ApiConnectRecordPtr transPtr;
396     transPtr.i = Tdata0;
397     c_apiConnectRecordPool.getPtr(transPtr);
398 #ifdef ERROR_INSERT
399     if (ERROR_INSERTED(8082))
400     {
401       /* Max of 100000 TRIGGER_PENDING TcContinueBs to
402        * single ApiConnectRecord
403        * See testBlobs -bug 45768
404        */
405       if (++transPtr.p->continueBCount > 100000)
406       {
407         ndbabort();
408       }
409     }
410 #endif
411     /* Check that ConnectRecord is for the same Trans Id */
412     if (likely((transPtr.p->transid[0] == Tdata1) &&
413                (transPtr.p->transid[1] == Tdata2)))
414     {
415       ndbrequire(tc_testbit(transPtr.p->m_flags,
416                             ApiConnectRecord::TF_TRIGGER_PENDING));
417       tc_clearbit(transPtr.p->m_flags, ApiConnectRecord::TF_TRIGGER_PENDING);
418       /* Try executing triggers now */
419       executeTriggers(signal, &transPtr);
420     }
421     return;
422   }
423   case TcContinueB::DelayTCKEYCONF:
424   {
425     jam();
426     ApiConnectRecordPtr apiConnectptr;
427     apiConnectptr.i = Tdata0;
428     c_apiConnectRecordPool.getPtr(apiConnectptr);
429     sendtckeyconf(signal, Tdata1, apiConnectptr);
430     return;
431   }
432   case TcContinueB::ZSEND_FIRE_TRIG_REQ:
433   {
434     jam();
435     ApiConnectRecordPtr apiConnectptr;
436     apiConnectptr.i = Tdata0;
437     c_apiConnectRecordPool.getPtr(apiConnectptr);
438     {
439       if (unlikely(! (apiConnectptr.p->transid[0] == Tdata1 &&
440                       apiConnectptr.p->transid[1] == Tdata2 &&
441                       apiConnectptr.p->isExecutingDeferredTriggers())))
442       {
443         warningReport(signal, 29);
444         return;
445       }
446     }
447 
448     ndbrequire(apiConnectptr.p->lqhkeyreqrec > 0);
449     apiConnectptr.p->lqhkeyreqrec--; // UNDO: prevent early completion
450     if (apiConnectptr.p->apiConnectstate == CS_SEND_FIRE_TRIG_REQ)
451     {
452       sendFireTrigReq(signal, apiConnectptr);
453     }
454     else
455     {
456       jam();
457       checkWaitFireTrigConfDone(signal, apiConnectptr);
458     }
459     return;
460   }
461   case TcContinueB::ZSTART_FRAG_SCANS:
462   {
463     jam();
464     ScanRecordPtr scanptr;
465     scanptr.i = signal->theData[1];
466     if (likely(scanRecordPool.getUncheckedPtrRW(scanptr)))
467     {
468       ApiConnectRecordPtr apiConnectptr;
469       apiConnectptr.i = scanptr.p->scanApiRec;
470       ndbrequire(Magic::check_ptr(scanptr.p));
471       c_apiConnectRecordPool.getValidPtr(apiConnectptr);
472       sendDihGetNodesLab(signal, scanptr, apiConnectptr);
473     }
474     return;
475   }
476   case TcContinueB::ZSEND_FRAG_SCANS:
477   {
478     jam();
479     ScanRecordPtr scanptr;
480     scanptr.i = signal->theData[1];
481     if (likely(scanRecordPool.getUncheckedPtrRW(scanptr)))
482     {
483       ApiConnectRecordPtr apiConnectptr;
484       apiConnectptr.i = scanptr.p->scanApiRec;
485       ndbrequire(Magic::check_ptr(scanptr.p));
486       c_apiConnectRecordPool.getValidPtr(apiConnectptr);
487       sendFragScansLab(signal, scanptr, apiConnectptr);
488     }
489     return;
490   }
491 #ifdef ERROR_INSERT
492   case TcContinueB::ZDEBUG_DELAYED_ABORT:
493   {
494     char buf[128];
495     BaseString::snprintf(buf, sizeof(buf), "Received CONTINUEB:ZDEBUG_DELAYED_ABORT");
496     warningEvent("%s", buf);
497 
498     jam();
499     ApiConnectRecordPtr apiConnectptr;
500     apiConnectptr.i = Tdata0;
501     c_apiConnectRecordPool.getPtr(apiConnectptr);
502     apiConnectptr.p->returncode = Tdata3;
503     apiConnectptr.p->returnsignal = (Dbtc::ReturnSignal)Tdata4;
504     SET_ERROR_INSERT_VALUE(Tdata5);
505     abort010Lab(signal, apiConnectptr);
506     break;
507   }
508   case TcContinueB::ZDEBUG_DELAY_TCROLLBACKREP:
509   {
510     char buf[128];
511     BaseString::snprintf(buf, sizeof(buf), "Received CONTINUEB:ZDEBUG_DELAY_TCROLLBACKREP");
512     warningEvent("%s", buf);
513 
514     jam();
515     if (ERROR_INSERTED(8101))
516     {
517       jam();
518       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 6);
519     }
520     else
521     {
522       TcRollbackRep * const tcRollbackRep =
523         (TcRollbackRep *) signal->getDataPtr();
524       Uint32 blockRef = Tdata5;
525 
526       tcRollbackRep->connectPtr = Tdata0;
527       tcRollbackRep->transId[0] = Tdata1;
528       tcRollbackRep->transId[1] = Tdata2;
529       tcRollbackRep->returnCode = Tdata3;
530       tcRollbackRep->errorData = Tdata4;
531       sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
532                  TcRollbackRep::SignalLength, JBB);
533     }
534     break;
535   }
536 #endif
537 #ifdef DO_TRANSIENT_POOL_STAT
538 #if defined(VM_TRACE) || defined(ERROR_INSERT)
539   case TcContinueB::ZTRANSIENT_POOL_STAT:
540   {
541     for (Uint32 pool_index = 0; pool_index < c_transient_pool_count; pool_index++)
542     {
543       g_eventLogger->info(
544         "DBTC %u: Transient slot pool %u %p: Entry size %u: Free %u: Used %u: Used high %u: Size %u: For shrink %u",
545         instance(),
546         pool_index,
547         c_transient_pools[pool_index],
548         c_transient_pools[pool_index]->getEntrySize(),
549         c_transient_pools[pool_index]->getNoOfFree(),
550         c_transient_pools[pool_index]->getUsed(),
551         c_transient_pools[pool_index]->getUsedHi(),
552         c_transient_pools[pool_index]->getSize(),
553         c_transient_pools_shrinking.get(pool_index));
554     }
555     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 1);
556     break;
557   }
558 #endif
559 #endif
560   case TcContinueB::ZSHRINK_TRANSIENT_POOLS:
561   {
562     if (signal->getLength() != 2)
563     {
564       /* Bad signal */
565       ndbassert(false);
566       break;
567     }
568 
569     const Uint32 pool_index = Tdata0;
570     const Uint32 MAX_SHRINKS = 1;
571 #ifdef VM_TRACE
572     g_eventLogger->info("SHRINK_TRANSIENT_POOLS: pool %u\n", pool_index);
573 #endif
574 
575     ndbrequire(pool_index < c_transient_pool_count);
576     if (!c_transient_pools_shrinking.get(pool_index))
577     {
578 #if defined(VM_TRACE) || defined(ERROR_INSERT)
579       ndbabort();
580 #endif
581       break;
582     }
583     if (!c_transient_pools[pool_index]->rearrange_free_list_and_shrink(MAX_SHRINKS))
584     {
585       c_transient_pools_shrinking.clear(pool_index);
586     }
587     else
588     {
589       signal->theData[1] = pool_index;
590       sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
591     }
592     break;
593   }
594   default:
595     ndbabort();
596   }//switch
597 }
598 
execDIGETNODESREF(Signal * signal,ApiConnectRecordPtr const apiConnectptr)599 void Dbtc::execDIGETNODESREF(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
600 {
601   jamEntry();
602   terrorCode = signal->theData[1];
603   releaseAtErrorLab(signal, apiConnectptr);
604 }
605 
execINCL_NODEREQ(Signal * signal)606 void Dbtc::execINCL_NODEREQ(Signal* signal)
607 {
608   jamEntry();
609   tblockref = signal->theData[0];
610   hostptr.i = signal->theData[1];
611   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
612   hostptr.p->hostStatus = HS_ALIVE;
613   c_alive_nodes.set(hostptr.i);
614 
615   signal->theData[0] = hostptr.i;
616   signal->theData[1] = cownref;
617 
618   if (ERROR_INSERTED(8039))
619   {
620     CLEAR_ERROR_INSERT_VALUE;
621     Uint32 save = signal->theData[0];
622     signal->theData[0] = 9999;
623     sendSignal(numberToRef(CMVMI, hostptr.i),
624 	       GSN_NDB_TAMPER, signal, 1, JBB);
625     signal->theData[0] = save;
626     sendSignalWithDelay(tblockref, GSN_INCL_NODECONF, signal, 5000, 2);
627     return;
628   }
629   sendSignal(tblockref, GSN_INCL_NODECONF, signal, 2, JBB);
630 }
631 
execREAD_NODESREF(Signal * signal)632 void Dbtc::execREAD_NODESREF(Signal* signal)
633 {
634   jamEntry();
635   ndbabort();
636 }
637 
638 // create table prepare
execTC_SCHVERREQ(Signal * signal)639 void Dbtc::execTC_SCHVERREQ(Signal* signal)
640 {
641   jamEntry();
642   if (! assembleFragments(signal)) {
643     jam();
644     return;
645   }
646   const TcSchVerReq* req = CAST_CONSTPTR(TcSchVerReq, signal->getDataPtr());
647   tabptr.i = req->tableId;
648   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
649   tabptr.p->currentSchemaVersion = req->tableVersion;
650   tabptr.p->m_flags = 0;
651   tabptr.p->set_storedTable((bool)req->tableLogged);
652   BlockReference retRef = req->senderRef;
653   tabptr.p->tableType = (Uint8)req->tableType;
654   BlockReference retPtr = req->senderData;
655   Uint32 noOfKeyAttr = req->noOfPrimaryKeys;
656   tabptr.p->singleUserMode = (Uint8)req->singleUserMode;
657   Uint32 userDefinedPartitioning = (Uint8)req->userDefinedPartition;
658   ndbrequire(noOfKeyAttr <= MAX_ATTRIBUTES_IN_INDEX);
659 
660   const KeyDescriptor* desc = g_key_descriptor_pool.getPtr(tabptr.i);
661   ndbrequire(noOfKeyAttr == desc->noOfKeyAttr);
662 
663   ndbrequire(tabptr.p->get_prepared() == false);
664   ndbrequire(tabptr.p->get_enabled() == false);
665   tabptr.p->set_prepared(true);
666   tabptr.p->set_enabled(false);
667   tabptr.p->set_dropping(false);
668   tabptr.p->noOfKeyAttr = desc->noOfKeyAttr;
669   tabptr.p->hasCharAttr = desc->hasCharAttr;
670   tabptr.p->noOfDistrKeys = desc->noOfDistrKeys;
671   tabptr.p->hasVarKeys = desc->noOfVarKeys > 0;
672   tabptr.p->set_user_defined_partitioning(userDefinedPartitioning);
673   if (req->readBackup)
674   {
675     jam();
676     D("Set ReadBackup Flag for table " << tabptr.i);
677     tabptr.p->m_flags |= TableRecord::TR_READ_BACKUP;
678     tabptr.p->m_flags |= TableRecord::TR_DELAY_COMMIT;
679   }
680   else
681   {
682     D("No ReadBackup Flag for table " << tabptr.i);
683   }
684 
685   if (req->fullyReplicated)
686   {
687     jam();
688     tabptr.p->m_flags |= TableRecord::TR_FULLY_REPLICATED;
689   }
690 
691   TcSchVerConf * conf = (TcSchVerConf*)signal->getDataPtr();
692   conf->senderRef = reference();
693   conf->senderData = retPtr;
694   sendSignal(retRef, GSN_TC_SCHVERCONF, signal,
695              TcSchVerConf::SignalLength, JBB);
696 }//Dbtc::execTC_SCHVERREQ()
697 
698 // create table commit
execTAB_COMMITREQ(Signal * signal)699 void Dbtc::execTAB_COMMITREQ(Signal* signal)
700 {
701   jamEntry();
702   Uint32 senderData = signal->theData[0];
703   Uint32 senderRef = signal->theData[1];
704   tabptr.i = signal->theData[2];
705   ptrCheckGuard(tabptr, ctabrecFilesize, tableRecord);
706 
707   ndbrequire(tabptr.p->get_prepared() == true);
708   ndbrequire(tabptr.p->get_enabled() == false);
709   tabptr.p->set_enabled(true);
710   tabptr.p->set_prepared(false);
711   tabptr.p->set_dropping(false);
712 
713   signal->theData[0] = senderData;
714   signal->theData[1] = reference();
715   signal->theData[2] = tabptr.i;
716   sendSignal(senderRef, GSN_TAB_COMMITCONF, signal, 3, JBB);
717 }
718 
719 void
execPREP_DROP_TAB_REQ(Signal * signal)720 Dbtc::execPREP_DROP_TAB_REQ(Signal* signal)
721 {
722   jamEntry();
723 
724   PrepDropTabReq* req = (PrepDropTabReq*)signal->getDataPtr();
725 
726   TableRecordPtr tabPtr;
727   tabPtr.i = req->tableId;
728   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
729 
730   Uint32 senderRef = req->senderRef;
731   Uint32 senderData = req->senderData;
732 
733   if(!tabPtr.p->get_enabled())
734   {
735     jam();
736     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
737     ref->senderRef = reference();
738     ref->senderData = senderData;
739     ref->tableId = tabPtr.i;
740     ref->errorCode = PrepDropTabRef::NoSuchTable;
741     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
742 	       PrepDropTabRef::SignalLength, JBB);
743     return;
744   }
745 
746   if(tabPtr.p->get_dropping())
747   {
748     jam();
749     PrepDropTabRef* ref = (PrepDropTabRef*)signal->getDataPtrSend();
750     ref->senderRef = reference();
751     ref->senderData = senderData;
752     ref->tableId = tabPtr.i;
753     ref->errorCode = PrepDropTabRef::DropInProgress;
754     sendSignal(senderRef, GSN_PREP_DROP_TAB_REF, signal,
755 	       PrepDropTabRef::SignalLength, JBB);
756     return;
757   }
758 
759   tabPtr.p->set_dropping(true);
760   tabPtr.p->set_prepared(false);
761 
762   PrepDropTabConf* conf = (PrepDropTabConf*)signal->getDataPtrSend();
763   conf->tableId = tabPtr.i;
764   conf->senderRef = reference();
765   conf->senderData = senderData;
766   sendSignal(senderRef, GSN_PREP_DROP_TAB_CONF, signal,
767              PrepDropTabConf::SignalLength, JBB);
768 }
769 
770 void
execDROP_TAB_REQ(Signal * signal)771 Dbtc::execDROP_TAB_REQ(Signal* signal)
772 {
773   jamEntry();
774 
775   DropTabReq* req = (DropTabReq*)signal->getDataPtr();
776 
777   TableRecordPtr tabPtr;
778   tabPtr.i = req->tableId;
779   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
780 
781   Uint32 senderRef = req->senderRef;
782   Uint32 senderData = req->senderData;
783   DropTabReq::RequestType rt = (DropTabReq::RequestType)req->requestType;
784 
785   if(!tabPtr.p->get_enabled() && rt == DropTabReq::OnlineDropTab){
786     jam();
787     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
788     ref->senderRef = reference();
789     ref->senderData = senderData;
790     ref->tableId = tabPtr.i;
791     ref->errorCode = DropTabRef::NoSuchTable;
792     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
793 	       DropTabRef::SignalLength, JBB);
794     return;
795   }
796 
797   if(!tabPtr.p->get_dropping() && rt == DropTabReq::OnlineDropTab){
798     jam();
799     DropTabRef* ref = (DropTabRef*)signal->getDataPtrSend();
800     ref->senderRef = reference();
801     ref->senderData = senderData;
802     ref->tableId = tabPtr.i;
803     ref->errorCode = DropTabRef::DropWoPrep;
804     sendSignal(senderRef, GSN_DROP_TAB_REF, signal,
805 	       DropTabRef::SignalLength, JBB);
806     return;
807   }
808 
809   tabPtr.p->set_enabled(false);
810   tabPtr.p->set_prepared(false);
811   tabPtr.p->set_dropping(false);
812 
813   DropTabConf * conf = (DropTabConf*)signal->getDataPtrSend();
814   conf->tableId = tabPtr.i;
815   conf->senderRef = reference();
816   conf->senderData = senderData;
817   sendSignal(senderRef, GSN_DROP_TAB_CONF, signal,
818 	     PrepDropTabConf::SignalLength, JBB);
819 }
820 
scan_for_read_backup(Signal * signal,Uint32 start_api_ptr,Uint32 senderData,Uint32 senderRef)821 void Dbtc::scan_for_read_backup(Signal *signal,
822                                 Uint32 start_api_ptr,
823                                 Uint32 senderData,
824                                 Uint32 senderRef)
825 {
826   Uint32 loop_count = 0;
827   Uint32 api_ptr = start_api_ptr;
828   while (api_ptr != RNIL &&
829          loop_count < 32)
830   {
831     ApiConnectRecordPtr ptrs[8];
832     Uint32 ptr_cnt =
833         c_apiConnectRecordPool.getUncheckedPtrs(&api_ptr,
834                                                 ptrs,
835                                                 NDB_ARRAY_SIZE(ptrs));
836     loop_count += NDB_ARRAY_SIZE(ptrs);
837     for (Uint32 i = 0; i < ptr_cnt; i++)
838     {
839       if (!Magic::match(ptrs[i].p->m_magic, ApiConnectRecord::TYPE_ID))
840       {
841         continue;
842       }
843       ApiConnectRecordPtr const& apiConnectptr = ptrs[i];
844       ApiConnectRecord * const regApiPtr = apiConnectptr.p;
845       switch (regApiPtr->apiConnectstate)
846       {
847         case CS_STARTED:
848         {
849           if (regApiPtr->tcConnect.isEmpty())
850           {
851             /**
852              * No transaction have started, safe to ignore these transactions.
853              * If it starts up the delayed commit flag will be set.
854              */
855             jam();
856           }
857           else
858           {
859             /* Transaction is ongoing, set delayed commit flag. */
860             jam();
861             regApiPtr->m_flags |= ApiConnectRecord::TF_LATE_COMMIT;
862           }
863           break;
864         }
865         case CS_RECEIVING:
866         {
867           /**
868            * Transaction is still ongoing and hasn't started commit, we will
869            * set delayed commit flag.
870            */
871           jam();
872           regApiPtr->m_flags |= ApiConnectRecord::TF_LATE_COMMIT;
873           break;
874         }
875         default:
876         {
877           jam();
878           /**
879            * The transaction is either:
880            * 1) Committing
881            * 2) Scanning
882            * 3) Aborting
883            *
884            * In neither of those cases we want to set the delayed commit flag.
885            * Committing has already started, so we don't want to mix delayed
886            * and not delayed in the same transaction. Scanning has no commit
887            * phase so delayed commit flag is uninteresting. Aborting
888            * transactions have no impact on data, so thus no delayed commit
889            * is required.
890            */
891           break;
892         }
893       }
894     }
895   }
896   if (api_ptr == RNIL)
897   {
898     jam();
899     /**
900      * We're done and will return ALTER_TAB_CONF
901      */
902     AlterTabConf *conf = (AlterTabConf*)signal->getDataPtrSend();
903     conf->senderRef = cownref;
904     conf->senderData = senderData;
905     conf->connectPtr = RNIL;
906     sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
907                AlterTabConf::SignalLength, JBB);
908     return;
909   }
910   signal->theData[0] = TcContinueB::ZSCAN_FOR_READ_BACKUP;
911   signal->theData[1] = api_ptr;
912   signal->theData[2] = senderData;
913   signal->theData[3] = senderRef;
914   sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
915 }
916 
execALTER_TAB_REQ(Signal * signal)917 void Dbtc::execALTER_TAB_REQ(Signal * signal)
918 {
919   const AlterTabReq* req = (const AlterTabReq*)signal->getDataPtr();
920   const Uint32 senderRef = req->senderRef;
921   const Uint32 senderData = req->senderData;
922   const Uint32 tableVersion = req->tableVersion;
923   const Uint32 newTableVersion = req->newTableVersion;
924   AlterTabReq::RequestType requestType =
925     (AlterTabReq::RequestType) req->requestType;
926   D("ALTER_TAB_REQ(TC)");
927 
928   TableRecordPtr tabPtr;
929   tabPtr.i = req->tableId;
930   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
931 
932   switch (requestType) {
933   case AlterTabReq::AlterTablePrepare:
934     jam();
935     if (AlterTableReq::getReadBackupFlag(req->changeMask))
936     {
937       if ((tabPtr.p->m_flags & TableRecord::TR_READ_BACKUP) != 0)
938       {
939         /**
940          * Table had Read Backup flag set and is now clearing it.
941          * No special handling we simply reset the flags in the
942          * commit phase. No more handling is needed in prepare
943          * phase.
944          */
945         D("Prepare to change ReadBackup Flag, already set for table"
946           << tabPtr.i);
947       }
948       else
949       {
950         /**
951          * Table have not set the Read Backup flag yet. We will set
952          * it in a safe manner. We do this by first ensuring that
953          * all current ongoing transactions delay their report of
954          * commit (we do this since we don't know which transactions
955          * are using this particular table and it is a very
956          * temporary delay for these transactions currently ongoing
957          * and the delay isn't very long either, no blocking will
958          * occur here.
959          *
960          * We also set delayed commit flag on this table immediately
961          * here to ensure that all transactions on this table is now
962          * delayed.
963          *
964          * This means that when we return done on the prepare phase
965          * the only transactions that are not delayed is the ones
966          * that was committing already when we came here. These
967          * have time until we're back here to commit to complete
968          * that phase. So would be a very extreme case and possibly
969          * even impossible case that not all these transactions
970          * are completed yet.
971          *
972          * Finally in the commit phase we activate the Read Backup
973          * flag also such that reads can start using the backup
974          * replicas for reading.
975          */
976         D("Prepare to set ReadBackup Flag for table: " << tabPtr.i);
977         tabPtr.p->m_flags |= TableRecord::TR_DELAY_COMMIT;
978         scan_for_read_backup(signal, 0, senderData, senderRef);
979         return;
980       }
981     }
982     break;
983   case AlterTabReq::AlterTableRevert:
984     jam();
985     tabPtr.p->currentSchemaVersion = tableVersion;
986 
987     if (AlterTableReq::getReadBackupFlag(req->changeMask))
988     {
989       if ((tabPtr.p->m_flags & TableRecord::TR_READ_BACKUP) == 0)
990       {
991         /**
992          * We have set the DELAY_COMMIT flag, so need to reset here
993          * since ALTER TABLE was reverted.
994          */
995         D("Revert ReadBackup Flag settings for table " << tabPtr.i);
996         tabPtr.p->m_flags &= (~(TableRecord::TR_DELAY_COMMIT));
997       }
998     }
999     break;
1000   case AlterTabReq::AlterTableCommit:
1001     jam();
1002     if (AlterTableReq::getReadBackupFlag(req->changeMask))
1003     {
1004       if ((tabPtr.p->m_flags & TableRecord::TR_READ_BACKUP) != 0)
1005       {
1006         jam();
1007         D("Commit clear ReadBackup Flag for table: " << tabPtr.i);
1008         tabPtr.p->m_flags &= (~(TableRecord::TR_DELAY_COMMIT));
1009         tabPtr.p->m_flags &= (~(TableRecord::TR_READ_BACKUP));
1010       }
1011       else
1012       {
1013         jam();
1014         D("Commit set ReadBackup Flag for table: " << tabPtr.i);
1015         tabPtr.p->m_flags |= TableRecord::TR_READ_BACKUP;
1016       }
1017     }
1018     tabPtr.p->currentSchemaVersion = newTableVersion;
1019     break;
1020   default:
1021     ndbabort();
1022   }
1023 
1024   // Request handled successfully
1025   AlterTabConf* conf = (AlterTabConf*)signal->getDataPtrSend();
1026   conf->senderRef = reference();
1027   conf->senderData = senderData;
1028   conf->connectPtr = RNIL;
1029   sendSignal(senderRef, GSN_ALTER_TAB_CONF, signal,
1030 	     AlterTabConf::SignalLength, JBB);
1031 }
1032 
1033 /* ***************************************************************************/
1034 /*                                START / RESTART                            */
1035 /* ***************************************************************************/
execREAD_CONFIG_REQ(Signal * signal)1036 void Dbtc::execREAD_CONFIG_REQ(Signal* signal)
1037 {
1038   const ReadConfigReq * req = (ReadConfigReq*)signal->getDataPtr();
1039   Uint32 ref = req->senderRef;
1040   Uint32 senderData = req->senderData;
1041   ndbrequire(req->noOfParameters == 0);
1042 
1043   jamEntry();
1044 
1045   const ndb_mgm_configuration_iterator * p =
1046     m_ctx.m_config.getOwnConfigIterator();
1047   ndbrequire(p != 0);
1048 
1049   initData();
1050 
1051   UintR tables;
1052 
1053   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_TABLE, &tables));
1054 
1055   ctabrecFilesize     = tables;
1056 
1057   initRecords(p);
1058   initialiseRecordsLab(signal, 0, ref, senderData);
1059 
1060   Uint32 val = 3000;
1061   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
1062   set_timeout_value(val);
1063 
1064   val = 1500;
1065   ndb_mgm_get_int_parameter(p, CFG_DB_HEARTBEAT_INTERVAL, &val);
1066   cDbHbInterval = (val < 10) ? 10 : val;
1067 
1068   val = 3000;
1069   ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_INACTIVE_TIMEOUT, &val);
1070   set_appl_timeout_value(val);
1071 
1072   val = 1;
1073   //ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_TRANSACTION_TAKEOVER, &val);
1074   set_no_parallel_takeover(val);
1075 
1076   val = ~(Uint32)0;
1077   ndb_mgm_get_int_parameter(p, CFG_DB_MAX_DML_OPERATIONS_PER_TRANSACTION, &val);
1078   m_max_writes_per_trans = val;
1079 
1080   val = ~(Uint32)0;
1081   ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TC_MAX_TO_CONNECT_RECORD, &val));
1082   m_take_over_operations = val;
1083 
1084   if (m_max_writes_per_trans == ~(Uint32)0)
1085   {
1086     m_max_writes_per_trans = m_take_over_operations;
1087   }
1088   ndbrequire(m_max_writes_per_trans <= m_take_over_operations);
1089 
1090   ctimeOutCheckDelay = 50; // 500ms
1091   ctimeOutCheckDelayScan = 40; // 400ms
1092 
1093   Pool_context pc;
1094   pc.m_block = this;
1095 
1096   c_fk_hash.setSize(16);
1097   c_fk_pool.init(RT_DBDICT_FILE, pc); // TODO
1098 
1099   time_track_init_histogram_limits();
1100 }
1101 
execSTTOR(Signal * signal)1102 void Dbtc::execSTTOR(Signal* signal)
1103 {
1104   Uint16 tphase;
1105 
1106   jamEntry();
1107                                                      /* START CASE */
1108   tphase = signal->theData[1];
1109   csignalKey = signal->theData[6];
1110   c_sttor_ref = signal->getSendersBlockRef();
1111   switch (tphase) {
1112   case ZSPH1:
1113     jam();
1114     startphase1x010Lab(signal);
1115     return;
1116   default:
1117     jam();
1118     sttorryLab(signal); /* START PHASE 255 */
1119     return;
1120   }//switch
1121 }//Dbtc::execSTTOR()
1122 
sttorryLab(Signal * signal)1123 void Dbtc::sttorryLab(Signal* signal)
1124 {
1125   signal->theData[0] = csignalKey;
1126   signal->theData[1] = 3;    /* BLOCK CATEGORY */
1127   signal->theData[2] = 2;    /* SIGNAL VERSION NUMBER */
1128   signal->theData[3] = ZSPH1;
1129   signal->theData[4] = 255;
1130   sendSignal(c_sttor_ref, GSN_STTORRY, signal, 5, JBB);
1131 }//Dbtc::sttorryLab()
1132 
1133 /* ***************************************************************************/
1134 /*                          INTERNAL  START / RESTART                        */
1135 /*****************************************************************************/
execNDB_STTOR(Signal * signal)1136 void Dbtc::execNDB_STTOR(Signal* signal)
1137 {
1138   Uint16 tndbstartphase;
1139   Uint16 tstarttype;
1140 
1141   jamEntry();
1142   NodeId nodeId = signal->theData[1];
1143   tndbstartphase = signal->theData[2];   /* START PHASE      */
1144   tstarttype = signal->theData[3];       /* START TYPE       */
1145   c_sttor_ref = signal->getSendersBlockRef();
1146   switch (tndbstartphase) {
1147   case ZINTSPH1:
1148     jam();
1149     intstartphase1x010Lab(signal, nodeId);
1150     return;
1151   case ZINTSPH2:
1152     jam();
1153     ndbsttorry010Lab(signal);
1154     return;
1155   case ZINTSPH3:
1156   {
1157     jam();
1158     intstartphase3x010Lab(signal);
1159 
1160     /* Start transaction counters event reporting. */
1161     const Uint32 len = c_counters.build_continueB(signal);
1162     signal->theData[0] = TcContinueB::ZTRANS_EVENT_REP;
1163     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 10, len);
1164 
1165 #ifdef DO_TRANSIENT_POOL_STAT
1166 #if defined(VM_TRACE) || defined(ERROR_INSERT)
1167     /* Start reporting statistics for transient pools */
1168     signal->theData[0] = TcContinueB::ZTRANSIENT_POOL_STAT;
1169     sendSignal(reference(), GSN_CONTINUEB, signal, 1, JBB);
1170 #endif
1171 #endif
1172 
1173     return;
1174   }
1175   case ZINTSPH6:
1176   {
1177     jam();
1178     c_elapsed_time_millis = 0;
1179     init_elapsed_time(signal, c_latestTIME_SIGNAL);
1180     break;
1181   }
1182   default:
1183     jam();
1184     break;
1185   }//switch
1186   ndbsttorry010Lab(signal);
1187   return;
1188 }//Dbtc::execNDB_STTOR()
1189 
ndbsttorry010Lab(Signal * signal)1190 void Dbtc::ndbsttorry010Lab(Signal* signal)
1191 {
1192   signal->theData[0] = cownref;
1193   sendSignal(c_sttor_ref, GSN_NDB_STTORRY, signal, 1, JBB);
1194 }//Dbtc::ndbsttorry010Lab()
1195 
1196 void
set_timeout_value(Uint32 timeOut)1197 Dbtc::set_timeout_value(Uint32 timeOut)
1198 {
1199   timeOut = timeOut / 10;
1200   if (timeOut < 2) {
1201     jam();
1202     timeOut = 100;
1203   }//if
1204   ctimeOutValue = timeOut;
1205 }
1206 
1207 void
set_appl_timeout_value(Uint32 timeOut)1208 Dbtc::set_appl_timeout_value(Uint32 timeOut)
1209 {
1210   if (timeOut)
1211   {
1212     timeOut /= 10;
1213     if (timeOut < ctimeOutValue) {
1214       jam();
1215       c_appl_timeout_value = ctimeOutValue;
1216     }//if
1217   }
1218   c_appl_timeout_value = timeOut;
1219 }
1220 
1221 void
set_no_parallel_takeover(Uint32 noParallelTakeOver)1222 Dbtc::set_no_parallel_takeover(Uint32 noParallelTakeOver)
1223 {
1224   if (noParallelTakeOver == 0) {
1225     jam();
1226     noParallelTakeOver = 1;
1227   } else if (noParallelTakeOver > MAX_NDB_NODES) {
1228     jam();
1229     noParallelTakeOver = MAX_NDB_NODES;
1230   }//if
1231   cnoParallelTakeOver = noParallelTakeOver;
1232 }
1233 
1234 /* ***************************************************************************/
1235 /*                        S T A R T P H A S E 1 X                            */
1236 /*                     INITIALISE BLOCKREF AND BLOCKNUMBERS                  */
1237 /* ***************************************************************************/
startphase1x010Lab(Signal * signal)1238 void Dbtc::startphase1x010Lab(Signal* signal)
1239 {
1240   ctimeOutCheckCounter = 0;
1241   ctimeOutCheckFragCounter = 0;
1242   ctimeOutMissedHeartbeats = 0;
1243   ctimeOutCheckHeartbeat = 0;
1244   ctimeOutCheckLastHeartbeat = 0;
1245   ctimeOutMissedHeartbeatsScan = 0;
1246   ctimeOutCheckHeartbeatScan = 0;
1247   ctimeOutCheckLastHeartbeatScan = 0;
1248   ctimeOutCheckActive = TOCS_FALSE;
1249   ctimeOutCheckFragActive = TOCS_FALSE;
1250   sttorryLab(signal);
1251 }//Dbtc::startphase1x010Lab()
1252 
1253 /*****************************************************************************/
1254 /*                        I N T S T A R T P H A S E 1 X                      */
1255 /*                         INITIALISE ALL RECORDS.                           */
1256 /*****************************************************************************/
intstartphase1x010Lab(Signal * signal,NodeId nodeId)1257 void Dbtc::intstartphase1x010Lab(Signal* signal, NodeId nodeId)
1258 {
1259   cownNodeid = nodeId;
1260   cownref =          reference();
1261   cdihblockref =     calcDihBlockRef(cownNodeid);
1262   cndbcntrblockref = calcNdbCntrBlockRef(cownNodeid);
1263   coperationsize = 0;
1264   cfailure_nr = 0;
1265   ndbsttorry010Lab(signal);
1266 }//Dbtc::intstartphase1x010Lab()
1267 
1268 /*****************************************************************************/
1269 /*                         I N T S T A R T P H A S E 3 X                     */
1270 /*****************************************************************************/
intstartphase3x010Lab(Signal * signal)1271 void Dbtc::intstartphase3x010Lab(Signal* signal)
1272 {
1273   signal->theData[0] = cownref;
1274   sendSignal(cndbcntrblockref, GSN_READ_NODESREQ, signal, 1, JBB);
1275 }//Dbtc::intstartphase3x010Lab()
1276 
execREAD_NODESCONF(Signal * signal)1277 void Dbtc::execREAD_NODESCONF(Signal* signal)
1278 {
1279   UintR guard0;
1280 
1281   jamEntry();
1282 
1283   ReadNodesConf * const readNodes = (ReadNodesConf *)&signal->theData[0];
1284 
1285   {
1286     ndbrequire(signal->getNoOfSections() == 1);
1287     SegmentedSectionPtr ptr;
1288     SectionHandle handle(this, signal);
1289     handle.getSection(ptr, 0);
1290     ndbrequire(ptr.sz == 5 * NdbNodeBitmask::Size);
1291     copy((Uint32*)&readNodes->definedNodes.rep.data, ptr);
1292     releaseSections(handle);
1293   }
1294 
1295   csystemnodes  = readNodes->noOfNodes;
1296   cmasterNodeId = readNodes->masterNodeId;
1297 
1298   con_lineNodes = 0;
1299   arrGuard(csystemnodes, MAX_NDB_NODES);
1300   guard0 = csystemnodes - 1;
1301   arrGuard(guard0, MAX_NDB_NODES);       // Check not zero nodes
1302 
1303   for (unsigned i = 1; i < MAX_NDB_NODES; i++) {
1304     jam();
1305     if (readNodes->definedNodes.get(i))
1306     {
1307       hostptr.i = i;
1308       ptrCheckGuard(hostptr, chostFilesize, hostRecord);
1309       hostptr.p->m_location_domain_id = 0;
1310 
1311       if (readNodes->inactiveNodes.get(i))
1312       {
1313         jam();
1314         hostptr.p->hostStatus = HS_DEAD;
1315       } else {
1316         jam();
1317         con_lineNodes++;
1318         hostptr.p->hostStatus = HS_ALIVE;
1319         c_alive_nodes.set(i);
1320       }//if
1321     }//if
1322   }//for
1323 
1324   ndb_mgm_configuration *p =
1325     m_ctx.m_config.getClusterConfig();
1326   ndb_mgm_configuration_iterator *p_iter =
1327     ndb_mgm_create_configuration_iterator(p, CFG_SECTION_NODE);
1328 
1329   for (ndb_mgm_first(p_iter);
1330        ndb_mgm_valid(p_iter);
1331        ndb_mgm_next(p_iter))
1332   {
1333     jam();
1334     Uint32 location_domain_id = 0;
1335     Uint32 nodeId = 0;
1336     Uint32 nodeType = 0;
1337     ndbrequire(!ndb_mgm_get_int_parameter(p_iter, CFG_NODE_ID, &nodeId) &&
1338                nodeId != 0);
1339     ndbrequire(!ndb_mgm_get_int_parameter(p_iter,
1340                                           CFG_TYPE_OF_SECTION,
1341                                           &nodeType));
1342     jamLine(Uint16(nodeId));
1343     if (nodeType != NODE_TYPE_DB)
1344     {
1345       jam();
1346       continue;
1347     }
1348     hostptr.i = nodeId;
1349     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
1350 
1351     ndb_mgm_get_int_parameter(p_iter,
1352                               CFG_LOCATION_DOMAIN_ID,
1353                               &location_domain_id);
1354     hostptr.p->m_location_domain_id = location_domain_id;
1355   }
1356   ndb_mgm_destroy_iterator(p_iter);
1357   {
1358     HostRecordPtr Town_hostptr;
1359     Town_hostptr.i = cownNodeid;
1360     ptrCheckGuard(Town_hostptr, chostFilesize, hostRecord);
1361     m_my_location_domain_id = Town_hostptr.p->m_location_domain_id;
1362   }
1363   ndbsttorry010Lab(signal);
1364 }//Dbtc::execREAD_NODESCONF()
1365 
1366 /*****************************************************************************/
1367 /*                     A P I _ F A I L R E Q                                 */
1368 // An API node has failed for some reason. We need to disconnect all API
1369 // connections to the API node. This also includes
1370 /*****************************************************************************/
execAPI_FAILREQ(Signal * signal)1371 void Dbtc::execAPI_FAILREQ(Signal* signal)
1372 {
1373   /***************************************************************************
1374    * Set the block reference to return API_FAILCONF to. Set the number of api
1375    * connects currently closing to one to indicate that we are still in the
1376    * process of going through the api connect records. Thus checking for zero
1377    * can only be true after all api connect records have been checked.
1378    **************************************************************************/
1379   jamEntry();
1380 
1381   if (ERROR_INSERTED(8056))
1382   {
1383     CLEAR_ERROR_INSERT_VALUE;
1384     return;
1385   }
1386 #ifdef ERROR_INSERT
1387   if (ERROR_INSERTED(8078))
1388   {
1389     c_lastFailedApi = signal->theData[0];
1390     SET_ERROR_INSERT_VALUE(8079);
1391   }
1392 #endif
1393 
1394   capiFailRef = signal->theData[1];
1395   arrGuard(signal->theData[0], MAX_NODES);
1396   capiConnectClosing[signal->theData[0]] = 1;
1397   handleFailedApiNode(signal, signal->theData[0], (UintR)0);
1398 }
1399 
1400 /**
1401  * This function is used when we need to handle API disconnect/node failure
1402  * with waiting for a few signals.
1403  * In the case of API node failure we need to keep track of how many API
1404  * connect records are in the close down phase, we cannot complete the
1405  * API node failure handling until all nodes have completed this phase.
1406  *
1407  * For API disconnect (from receiving TCRELEASEREQ on active API connect)
1408  * we need no such counter, we maintain specific states for those two
1409  * variants.
1410  */
1411 void
set_api_fail_state(Uint32 TapiFailedNode,bool apiNodeFailed,ApiConnectRecord * const regApiPtr)1412 Dbtc::set_api_fail_state(Uint32 TapiFailedNode, bool apiNodeFailed, ApiConnectRecord* const regApiPtr)
1413 {
1414   if (apiNodeFailed)
1415   {
1416     jam();
1417     capiConnectClosing[TapiFailedNode]++;
1418     regApiPtr->apiFailState = ApiConnectRecord::AFS_API_FAILED;
1419   }
1420   else
1421   {
1422     jam();
1423     regApiPtr->apiFailState = ApiConnectRecord::AFS_API_DISCONNECTED;
1424   }
1425 }
1426 
handleFailedApiConnection(Signal * signal,Uint32 * TloopCount,Uint32 TapiFailedNode,bool apiNodeFailed,ApiConnectRecordPtr const apiConnectptr)1427 bool Dbtc::handleFailedApiConnection(Signal *signal,
1428                                      Uint32 *TloopCount,
1429                                      Uint32 TapiFailedNode,
1430                                      bool apiNodeFailed,
1431                                      ApiConnectRecordPtr const apiConnectptr)
1432 {
1433   if (apiConnectptr.p->apiFailState == ApiConnectRecord::AFS_API_DISCONNECTED)
1434   {
1435     jam();
1436     /**
1437      * We are currently closing down the API connect record after receiving
1438      * a TCRELEASEREQ. Now we received an API node failure. We don't need
1439      * to restart the close down handling, it is already in progress. But
1440      * we need to add to counter and change state such that we are waiting
1441      * for API node fail handling to complete instead.
1442      *
1443      * We cannot come here from TCRELEASEREQ as we will simply send an
1444      * immediate CONF when receiving multiple TCRELEASEREQ.
1445      */
1446     ndbrequire(apiNodeFailed);
1447     set_api_fail_state(TapiFailedNode, apiNodeFailed, apiConnectptr.p);
1448     return true;
1449   }
1450 #ifdef VM_TRACE
1451   if (apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK)
1452   {
1453     ndbout << "Error in previous API fail handling discovered" << endl
1454            << "  apiConnectptr.i = " << apiConnectptr.i << endl
1455            << "  apiConnectstate = " << apiConnectptr.p->apiConnectstate
1456            << endl
1457            << "  ndbapiBlockref = " << hex
1458            << apiConnectptr.p->ndbapiBlockref << endl
1459            << "  apiNode = " << refToNode(apiConnectptr.p->ndbapiBlockref)
1460            << endl;
1461     LocalTcConnectRecord_fifo tcConList(tcConnectRecord, (apiConnectptr.p->tcConnect));
1462     if (tcConList.last(tcConnectptr))
1463     {
1464       jam();
1465       ndbout << "  tcConnectptr.i = " << tcConnectptr.i << endl
1466              << "  tcConnectstate = " << tcConnectptr.p->tcConnectstate
1467              << endl;
1468     }
1469   }//if
1470 #endif
1471 
1472   apiConnectptr.p->returnsignal = RS_NO_RETURN;
1473   /***********************************************************************/
1474   // The connected node is the failed node.
1475   /**********************************************************************/
1476   switch(apiConnectptr.p->apiConnectstate) {
1477   case CS_DISCONNECTED:
1478     /*********************************************************************/
1479     // These states do not need any special handling.
1480     // Simply continue with the next.
1481     /*********************************************************************/
1482     jam();
1483     break;
1484   case CS_ABORTING:
1485     /*********************************************************************/
1486     // This could actually mean that the API connection is already
1487     // ready to release if the abortState is IDLE.
1488     /*********************************************************************/
1489     if (apiConnectptr.p->abortState == AS_IDLE) {
1490       jam();
1491       releaseApiCon(signal, apiConnectptr.i);
1492     } else {
1493       jam();
1494       set_api_fail_state(TapiFailedNode, apiNodeFailed, apiConnectptr.p);
1495     }//if
1496     break;
1497   case CS_WAIT_ABORT_CONF:
1498   case CS_WAIT_COMMIT_CONF:
1499   case CS_START_COMMITTING:
1500   case CS_PREPARE_TO_COMMIT:
1501   case CS_COMMITTING:
1502   case CS_COMMIT_SENT:
1503     /*********************************************************************/
1504     // These states indicate that an abort process or commit process is
1505     // already ongoing. We will set a state in the api record indicating
1506     // that the API node has failed.
1507     // Also we will increase the number of outstanding api records to
1508     // wait for before we can respond with API_FAILCONF.
1509     /*********************************************************************/
1510     jam();
1511     set_api_fail_state(TapiFailedNode, apiNodeFailed, apiConnectptr.p);
1512     break;
1513   case CS_START_SCAN:
1514   {
1515     /*********************************************************************/
1516     // The api record was performing a scan operation. We need to check
1517     // on the scan state. Since completing a scan process might involve
1518     // sending several signals we will increase the loop count by 64.
1519     /*********************************************************************/
1520     jam();
1521 
1522     set_api_fail_state(TapiFailedNode, apiNodeFailed, apiConnectptr.p);
1523 
1524     ScanRecordPtr scanptr;
1525     scanptr.i = apiConnectptr.p->apiScanRec;
1526     scanRecordPool.getPtr(scanptr);
1527     close_scan_req(signal, scanptr, true, apiConnectptr);
1528 
1529     (*TloopCount) += 64;
1530     break;
1531   }
1532   case CS_CONNECTED:
1533   case CS_REC_COMMITTING:
1534   case CS_RECEIVING:
1535   case CS_STARTED:
1536   case CS_SEND_FIRE_TRIG_REQ:
1537   case CS_WAIT_FIRE_TRIG_REQ:
1538     /*********************************************************************/
1539     // The api record was in the process of performing a transaction but
1540     // had not yet sent all information.
1541     // We need to initiate an ABORT since the API will not provide any
1542     // more information.
1543     // Since the abort can send many signals we will insert a real-time
1544     // break after checking this record.
1545     /*********************************************************************/
1546     jam();
1547     set_api_fail_state(TapiFailedNode, apiNodeFailed, apiConnectptr.p);
1548     abort010Lab(signal, apiConnectptr);
1549     (*TloopCount) = 256;
1550     break;
1551   case CS_RESTART:
1552   case CS_COMPLETING:
1553   case CS_COMPLETE_SENT:
1554   case CS_WAIT_COMPLETE_CONF:
1555   case CS_FAIL_ABORTING:
1556   case CS_FAIL_ABORTED:
1557   case CS_FAIL_PREPARED:
1558   case CS_FAIL_COMMITTING:
1559   case CS_FAIL_COMMITTED:
1560     /*********************************************************************/
1561     // These states are only valid on copy and fail API connections.
1562     /*********************************************************************/
1563   default:
1564     jam();
1565     jamLine(apiConnectptr.p->apiConnectstate);
1566     return false;
1567   }//switch
1568   return true;
1569 }
1570 
1571 void
handleFailedApiNode(Signal * signal,UintR TapiFailedNode,UintR TapiConnectPtr)1572 Dbtc::handleFailedApiNode(Signal* signal,
1573                           UintR TapiFailedNode,
1574                           UintR TapiConnectPtr)
1575 {
1576   arrGuard(TapiFailedNode, MAX_NODES);
1577   Uint32 loop_count = 0;
1578   Uint32 api_ptr = TapiConnectPtr;
1579   while (api_ptr != RNIL &&
1580          loop_count < 256)
1581   {
1582     jam();
1583     ApiConnectRecordPtr ptrs[8];
1584     Uint32 ptr_cnt =
1585         c_apiConnectRecordPool.getUncheckedPtrs(&api_ptr,
1586                                                 ptrs,
1587                                                 NDB_ARRAY_SIZE(ptrs));
1588     loop_count += NDB_ARRAY_SIZE(ptrs);
1589     for (Uint32 i = 0; i < ptr_cnt; i++)
1590     {
1591       jam();
1592       if (!Magic::match(ptrs[i].p->m_magic, ApiConnectRecord::TYPE_ID))
1593       {
1594         continue;
1595       }
1596       ApiConnectRecordPtr const& apiConnectptr = ptrs[i];
1597       if (apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_USER)
1598       {
1599         jam();
1600         const UintR TapiNode = refToNode(apiConnectptr.p->ndbapiBlockref);
1601         if (TapiNode == TapiFailedNode)
1602         {
1603           bool handled = handleFailedApiConnection(
1604               signal, &loop_count, TapiFailedNode, true, apiConnectptr);
1605           if (!handled)
1606           {
1607             systemErrorLab(signal, __LINE__);
1608             return;
1609           }
1610         }
1611         else
1612         {
1613           jam();
1614         }  // if
1615       }
1616     }
1617   }
1618   if (api_ptr == RNIL)
1619   {
1620     jam();
1621     /**
1622      * Finished with scanning connection record
1623      *
1624      * Now scan markers
1625      */
1626     removeMarkerForFailedAPI(signal, TapiFailedNode, 0);
1627     return;
1628   }//if
1629   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE;
1630   signal->theData[1] = TapiFailedNode;
1631   signal->theData[2] = api_ptr;
1632   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1633 }//Dbtc::handleFailedApiNode()
1634 
1635 void
removeMarkerForFailedAPI(Signal * signal,NodeId nodeId,Uint32 startBucket)1636 Dbtc::removeMarkerForFailedAPI(Signal* signal,
1637                                NodeId nodeId,
1638                                Uint32 startBucket)
1639 {
1640   TcFailRecordPtr node_fail_ptr;
1641   node_fail_ptr.i = 0;
1642   ptrAss(node_fail_ptr, tcFailRecord);
1643   if(node_fail_ptr.p->failStatus != FS_IDLE) {
1644     jam();
1645     DEBUG("Restarting removeMarkerForFailedAPI");
1646     /**
1647      * TC take-over in progress
1648      *   needs to restart as this
1649      *   creates new markers
1650      */
1651     signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1652     signal->theData[1] = nodeId;
1653     signal->theData[2] = 0;
1654     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 500, 3);
1655     return;
1656   }
1657 
1658   CommitAckMarkerIterator iter;
1659   m_commitAckMarkerHash.next(startBucket, iter);
1660 
1661   const Uint32 RT_BREAK = 256;
1662   for(Uint32 i = 0; i<RT_BREAK || iter.bucket == startBucket; i++){
1663     jam();
1664 
1665     if(iter.curr.i == RNIL){
1666       jam();
1667       /**
1668        * Done with iteration
1669        */
1670       capiConnectClosing[nodeId]--;
1671       if (capiConnectClosing[nodeId] == 0) {
1672         jam();
1673 
1674         /********************************************************************/
1675         // No outstanding ABORT or COMMIT's of this failed API node.
1676         // Perform SimulatedBlock level cleanup before sending
1677         // API_FAILCONF
1678         /********************************************************************/
1679         Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1680                        nodeId};
1681         simBlockNodeFailure(signal, nodeId, cb);
1682       }
1683       checkPoolShrinkNeed(DBTC_COMMIT_ACK_MARKER_TRANSIENT_POOL_INDEX,
1684                           m_commitAckMarkerPool);
1685       return;
1686     }
1687 
1688     if(iter.curr.p->apiNodeId == nodeId){
1689       jam();
1690 
1691       /**
1692        * Check so that the record is not still in use
1693        *
1694        */
1695       ApiConnectRecordPtr apiConnectPtr;
1696       apiConnectPtr.i = iter.curr.p->apiConnectPtr;
1697       if (c_apiConnectRecordPool.getValidPtr(apiConnectPtr) &&
1698           !apiConnectPtr.isNull() &&
1699           apiConnectPtr.p->commitAckMarker == iter.curr.i)
1700       {
1701 	jam();
1702         /**
1703          * The record is still active, this means that the transaction is
1704          * currentlygoing through the abort or commit process as started
1705          * in the API node failure handling, we have to wait until this
1706          * phase is completed until we continue with our processing of this.
1707          * If it goes through the aborting process the record will disappear
1708          * while we're waiting for it. If it goes through the commit process
1709          * it will eventually reach copyApi whereafter we can remove the
1710          * marker from LQH.
1711          *
1712          * Don't remove it, but continueb retry with a short delay
1713          */
1714         signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1715         signal->theData[1] = nodeId;
1716         signal->theData[2] = iter.bucket;
1717         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 1, 3);
1718         return;
1719       }
1720       /**
1721        * This should only happen if we have done copyApi and the referred
1722        * apiConnect record have already moved on to the free connections or
1723        * to a new transaction. The commit ack marker is still around,
1724        * normally the API would then send TC_COMMIT_ACK, but this hasn't
1725        * happened here since the API have failed. So we need to remove the
1726        * marker on behalf of the failed API, the failed API will not be able
1727        * to communicate its hearing of the commit, so we can simply remove
1728        * the commit ack marker in LQH.
1729        */
1730       sendRemoveMarkers(signal, iter.curr.p, 1);
1731       m_commitAckMarkerHash.remove(iter.curr);
1732       m_commitAckMarkerPool.release(iter.curr);
1733       break;
1734     }
1735     m_commitAckMarkerHash.next(iter);
1736   } // for (... i<RT_BREAK ...)
1737 
1738   checkPoolShrinkNeed(DBTC_COMMIT_ACK_MARKER_TRANSIENT_POOL_INDEX,
1739                       m_commitAckMarkerPool);
1740 
1741   // Takes a RT-break to avoid starving other activity
1742   signal->theData[0] = TcContinueB::ZHANDLE_FAILED_API_NODE_REMOVE_MARKERS;
1743   signal->theData[1] = nodeId;
1744   signal->theData[2] = iter.bucket;
1745   sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
1746 }
1747 
handleApiFailState(Signal * signal,UintR TapiConnectptr)1748 void Dbtc::handleApiFailState(Signal* signal, UintR TapiConnectptr)
1749 {
1750   ApiConnectRecordPtr TlocalApiConnectptr;
1751   UintR TfailedApiNode;
1752 
1753   TlocalApiConnectptr.i = TapiConnectptr;
1754   c_apiConnectRecordPool.getPtr(TlocalApiConnectptr);
1755   Uint32 apiFailState = TlocalApiConnectptr.p->apiFailState;
1756   TfailedApiNode = refToNode(TlocalApiConnectptr.p->ndbapiBlockref);
1757   arrGuard(TfailedApiNode, MAX_NODES);
1758   TlocalApiConnectptr.p->apiFailState = ApiConnectRecord::AFS_API_OK;
1759   releaseApiCon(signal, TapiConnectptr);
1760   if (apiFailState == ApiConnectRecord::AFS_API_FAILED)
1761   {
1762     capiConnectClosing[TfailedApiNode]--;
1763     if (capiConnectClosing[TfailedApiNode] == 0)
1764     {
1765       jam();
1766 
1767       /**
1768        * Perform block-level cleanups (e.g assembleFragments...)
1769        */
1770       Callback cb = {safe_cast(&Dbtc::apiFailBlockCleanupCallback),
1771                      TfailedApiNode};
1772       simBlockNodeFailure(signal, TfailedApiNode, cb);
1773     }
1774   }//if
1775 }//Dbtc::handleApiFailState()
1776 
1777 /****************************************************************************
1778  *                                T C S E I Z E R E Q
1779  * THE APPLICATION SENDS A REQUEST TO SEIZE A CONNECT RECORD TO CARRY OUT A
1780  * TRANSACTION
1781  * TC BLOCK TAKE OUT A CONNECT RECORD FROM THE FREE LIST AND ESTABLISHES ALL
1782  * NECESSARY CONNECTION BEFORE REPLYING TO THE APPLICATION BLOCK
1783  ****************************************************************************/
execTCSEIZEREQ(Signal * signal)1784 void Dbtc::execTCSEIZEREQ(Signal* signal)
1785 {
1786   UintR tapiPointer;
1787   BlockReference tapiBlockref;       /* SENDER BLOCK REFERENCE*/
1788 
1789   jamEntry();
1790   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1791   tapiBlockref = signal->theData[1]; /* SENDERS BLOCK REFERENCE*/
1792 
1793   if (signal->getLength() > 2)
1794   {
1795     ndbassert(instance() == signal->theData[2]);
1796   }
1797 
1798   const NodeState::StartLevel sl =
1799     (NodeState::StartLevel)getNodeState().startLevel;
1800 
1801   const NodeId senderNodeId = refToNode(tapiBlockref);
1802   const bool local = senderNodeId == getOwnNodeId() || senderNodeId == 0;
1803 
1804   {
1805     {
1806       if (!(sl == NodeState::SL_STARTED ||
1807 	    (sl == NodeState::SL_STARTING && local == true))) {
1808 	jam();
1809 
1810 	Uint32 errCode = 0;
1811 	if(!local)
1812 	  {
1813 	    switch(sl){
1814 	    case NodeState::SL_STARTING:
1815 	      errCode = ZSYSTEM_NOT_STARTED_ERROR;
1816 	      break;
1817 	    case NodeState::SL_STOPPING_1:
1818 	    case NodeState::SL_STOPPING_2:
1819               if (getNodeState().getSingleUserMode())
1820                 break;
1821               // Fall through
1822             case NodeState::SL_STOPPING_3:
1823             case NodeState::SL_STOPPING_4:
1824               if(getNodeState().stopping.systemShutdown)
1825 		errCode = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
1826 	      else
1827 		errCode = ZNODE_SHUTDOWN_IN_PROGRESS;
1828 	      break;
1829 	    case NodeState::SL_SINGLEUSER:
1830 	      break;
1831 	    default:
1832 	      errCode = ZWRONG_STATE;
1833 	      break;
1834 	    }
1835             if (errCode)
1836             {
1837               ndbout << "error: " << errCode << " on " << tapiPointer << endl;
1838               signal->theData[0] = tapiPointer;
1839               signal->theData[1] = errCode;
1840               sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1841               return;
1842             }
1843 	  }//if (!(sl == SL_SINGLEUSER))
1844       } //if
1845     }
1846   }
1847 
1848   if (ERROR_INSERTED(8078) || ERROR_INSERTED(8079))
1849   {
1850     /* Clear testing of API_FAILREQ behaviour */
1851     CLEAR_ERROR_INSERT_VALUE;
1852   };
1853 
1854   ApiConnectRecordPtr apiConnectptr;
1855   if (likely(seizeApiConnect(signal, apiConnectptr)))
1856   {
1857     jam();
1858     apiConnectptr.p->ndbapiConnect = tapiPointer;
1859     apiConnectptr.p->ndbapiBlockref = tapiBlockref;
1860     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1861     signal->theData[1] = apiConnectptr.i;
1862     signal->theData[2] = reference();
1863     sendSignal(tapiBlockref, GSN_TCSEIZECONF, signal, 3, JBB);
1864     return;
1865   }
1866   ndbrequire(terrorCode != ZOK);
1867 
1868   ndbout << "4006 on " << tapiPointer << endl;
1869   signal->theData[0] = tapiPointer;
1870   signal->theData[1] = terrorCode;
1871   sendSignal(tapiBlockref, GSN_TCSEIZEREF, signal, 2, JBB);
1872 }//Dbtc::execTCSEIZEREQ()
1873 
1874 /****************************************************************************/
1875 /*                    T C R E L E A S E Q                                   */
1876 /*                  REQUEST TO RELEASE A CONNECT RECORD                     */
1877 /****************************************************************************/
execTCRELEASEREQ(Signal * signal)1878 void Dbtc::execTCRELEASEREQ(Signal* signal)
1879 {
1880   UintR tapiPointer;
1881   BlockReference tapiBlockref;     /* SENDER BLOCK REFERENCE*/
1882 
1883   jamEntry();
1884   tapiPointer = signal->theData[0]; /* REQUEST SENDERS CONNECT RECORD POINTER*/
1885   tapiBlockref = signal->theData[1];/* SENDERS BLOCK REFERENCE*/
1886   tuserpointer = signal->theData[2];
1887   ApiConnectRecordPtr apiConnectptr;
1888   apiConnectptr.i = tapiPointer;
1889   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
1890   {
1891     jam();
1892     ndbassert(false);
1893     signal->theData[0] = tuserpointer;
1894     signal->theData[1] = ZINVALID_CONNECTION;
1895     signal->theData[2] = __LINE__;
1896     sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 3, JBB);
1897     return;
1898   }
1899   if (apiConnectptr.p->apiConnectstate == CS_DISCONNECTED ||
1900       apiConnectptr.p->apiFailState == ApiConnectRecord::AFS_API_DISCONNECTED)
1901   {
1902     jam();
1903     signal->theData[0] = tuserpointer;
1904     sendSignal(tapiBlockref, GSN_TCRELEASECONF, signal, 1, JBB);
1905   }
1906   else
1907   {
1908     if (tapiBlockref == apiConnectptr.p->ndbapiBlockref)
1909     {
1910       Uint32 dummy_loop_count = 0;
1911       Uint32 dummy_api_node = 0;
1912       /**
1913        * It isn't ok to receive a signal from a node that we're still
1914        * handling the API node failure, this must be some type of bug.
1915        * It is ok to receive multiple TCRELEASEREQ on the same connection.
1916        * We will handle it according to its state.
1917        */
1918       ndbrequire(apiConnectptr.p->apiFailState == ApiConnectRecord::AFS_API_OK);
1919       bool handled = handleFailedApiConnection(signal,
1920                                                &dummy_loop_count,
1921                                                dummy_api_node,
1922                                                false,
1923                                                apiConnectptr);
1924       ndbrequire(handled);
1925       /**
1926        * We have taken care of any necessary abort of ongoing statements.
1927        * We have ensured that if there is an ongoing transaction that
1928        * needs to be concluded that the API is not communicated to. The
1929        * transaction will be silently concluded and returned to free list
1930        * when concluded.
1931        * In most cases it will be immediately returned to
1932        * free list.
1933        *
1934        * NOTE: The NDB API can still get TRANSID_AI from LQHs and TCKEYCONF
1935        * from this TC on old Transaction ID's. So it is vital that the
1936        * NDB API does validate the signals before processing them.
1937        */
1938       jam();
1939       signal->theData[0] = tuserpointer;
1940       sendSignal(tapiBlockref,
1941                  GSN_TCRELEASECONF, signal, 1, JBB);
1942     }
1943     else
1944     {
1945       jam();
1946       ndbassert(false);
1947       signal->theData[0] = tuserpointer;
1948       signal->theData[1] = ZINVALID_CONNECTION;
1949       signal->theData[2] = __LINE__;
1950       signal->theData[3] = tapiBlockref;
1951       signal->theData[4] = apiConnectptr.p->ndbapiBlockref;
1952       sendSignal(tapiBlockref, GSN_TCRELEASEREF, signal, 5, JBB);
1953     }//if
1954   }//if
1955 }//Dbtc::execTCRELEASEREQ()
1956 
1957 /****************************************************************************/
1958 // Error Handling for TCKEYREQ messages
1959 /****************************************************************************/
signalErrorRefuseLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)1960 void Dbtc::signalErrorRefuseLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
1961 {
1962   ptrGuard(apiConnectptr);
1963   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED)
1964   {
1965     jam();
1966     apiConnectptr.p->abortState = AS_IDLE;
1967     apiConnectptr.p->apiConnectstate = CS_ABORTING;
1968   }//if
1969   sendSignalErrorRefuseLab(signal, apiConnectptr);
1970 }//Dbtc::signalErrorRefuseLab()
1971 
sendSignalErrorRefuseLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)1972 void Dbtc::sendSignalErrorRefuseLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
1973 {
1974   ndbassert(false);
1975   ptrGuard(apiConnectptr);
1976   if (apiConnectptr.p->apiConnectstate != CS_DISCONNECTED) {
1977     jam();
1978     /* Force state print */
1979     printState(signal, 12, apiConnectptr, true);
1980     ndbabort();
1981     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
1982     signal->theData[1] = signal->theData[ttransid_ptr];
1983     signal->theData[2] = signal->theData[ttransid_ptr + 1];
1984     signal->theData[3] = ZSIGNAL_ERROR;
1985     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
1986 	       signal, 4, JBB);
1987   }
1988 }//Dbtc::sendSignalErrorRefuseLab()
1989 
abortBeginErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)1990 void Dbtc::abortBeginErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
1991 {
1992   apiConnectptr.p->transid[0] = signal->theData[ttransid_ptr];
1993   apiConnectptr.p->transid[1] = signal->theData[ttransid_ptr + 1];
1994   abortErrorLab(signal, apiConnectptr);
1995 }//Dbtc::abortBeginErrorLab()
1996 
printState(Signal * signal,int place,ApiConnectRecordPtr const apiConnectptr,bool force_trace)1997 void Dbtc::printState(Signal* signal, int place, ApiConnectRecordPtr const apiConnectptr, bool force_trace)
1998 {
1999   /* Always give minimal ApiConnectState trace via jam */
2000   jam();
2001   jamLine(apiConnectptr.p->apiConnectstate);
2002   jam();
2003 
2004 #ifdef VM_TRACE
2005   /* Always trace in debug mode */
2006   force_trace = true;
2007 #endif
2008 
2009   if (!force_trace)
2010     return;
2011 
2012   ndbout << "-- Dbtc::printState -- " << endl;
2013   ndbout << "Received from place = " << place
2014 	 << " apiConnectptr.i = " << apiConnectptr.i
2015 	 << " apiConnectstate = " << apiConnectptr.p->apiConnectstate << endl;
2016   ndbout << "ctcTimer = " << ctcTimer
2017 	 << " ndbapiBlockref = " << hex <<apiConnectptr.p->ndbapiBlockref
2018 	 << " Transid = " << apiConnectptr.p->transid[0]
2019 	 << " " << apiConnectptr.p->transid[1] << endl;
2020   ndbout << "apiTimer = " << getApiConTimer(apiConnectptr)
2021 	 << " counter = " << apiConnectptr.p->counter
2022 	 << " lqhkeyconfrec = " << apiConnectptr.p->lqhkeyconfrec
2023 	 << " lqhkeyreqrec = " << apiConnectptr.p->lqhkeyreqrec
2024          << " cascading_scans = " << apiConnectptr.p->cascading_scans_count
2025          << endl;
2026   ndbout << "executing_trigger_ops = "
2027          << apiConnectptr.p->m_executing_trigger_ops
2028          << " abortState = " << apiConnectptr.p->abortState
2029 	 << " apiScanRec = " << apiConnectptr.p->apiScanRec
2030 	 << " returncode = " << apiConnectptr.p->returncode << endl;
2031   ndbout << "tckeyrec = " << apiConnectptr.p->tckeyrec
2032 	 << " returnsignal = " << apiConnectptr.p->returnsignal
2033 	 << " apiFailState = " << apiConnectptr.p->apiFailState << endl;
2034   if (apiConnectptr.p->cachePtr != RNIL)
2035   {
2036     jam();
2037     CacheRecordPtr cachePtr;
2038     cachePtr.i = apiConnectptr.p->cachePtr;
2039     bool success = true;
2040     if (cachePtr.i == Uint32(~0))
2041     {
2042       cachePtr.p = &m_local_cache_record;
2043     }
2044     else
2045     {
2046       success = c_cacheRecordPool.getValidPtr(cachePtr);
2047     }
2048     if (success)
2049     {
2050       jam();
2051       CacheRecord * const regCachePtr = cachePtr.p;
2052       ndbout << "currReclenAi = " << regCachePtr->currReclenAi
2053              << " attrlength = " << regCachePtr->attrlength
2054 	     << " tableref = " << regCachePtr->tableref
2055 	     << " keylen = " << regCachePtr->keylen << endl;
2056     } else {
2057       jam();
2058       systemErrorLab(signal, __LINE__);
2059     }//if
2060   }//if
2061   return;
2062 }//Dbtc::printState()
2063 
2064 void
TCKEY_abort(Signal * signal,int place,ApiConnectRecordPtr const apiConnectptr)2065 Dbtc::TCKEY_abort(Signal* signal, int place, ApiConnectRecordPtr const apiConnectptr)
2066 {
2067   switch (place) {
2068   case 0:
2069     jam();
2070     terrorCode = ZSTATE_ERROR;
2071     apiConnectptr.p->tcConnect.init();
2072     printState(signal, 4, apiConnectptr);
2073     abortBeginErrorLab(signal, apiConnectptr);
2074     return;
2075   case 1:
2076     jam();
2077     printState(signal, 3, apiConnectptr);
2078     sendSignalErrorRefuseLab(signal, apiConnectptr);
2079     return;
2080   case 2:{
2081     printState(signal, 6, apiConnectptr);
2082     const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2083     const Uint32 t1 = tcKeyReq->transId1;
2084     const Uint32 t2 = tcKeyReq->transId2;
2085     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
2086     signal->theData[1] = t1;
2087     signal->theData[2] = t2;
2088     signal->theData[3] = ZABORT_ERROR;
2089     ndbabort();
2090     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREP,
2091 	       signal, 4, JBB);
2092     return;
2093   }
2094   case 3:
2095     jam();
2096     printState(signal, 7, apiConnectptr);
2097     noFreeConnectionErrorLab(signal, apiConnectptr);
2098     return;
2099   case 4:
2100     jam();
2101     terrorCode = ZERO_KEYLEN_ERROR;
2102     releaseAtErrorLab(signal, apiConnectptr);
2103     return;
2104   case 5:
2105     jam();
2106     terrorCode = ZNO_AI_WITH_UPDATE;
2107     releaseAtErrorLab(signal, apiConnectptr);
2108     return;
2109   case 7:
2110     jam();
2111     tabStateErrorLab(signal, apiConnectptr);
2112     return;
2113 
2114   case 8:
2115     jam();
2116     wrongSchemaVersionErrorLab(signal, apiConnectptr);
2117     return;
2118 
2119   case 9:
2120     jam();
2121     terrorCode = ZSTATE_ERROR;
2122     releaseAtErrorLab(signal, apiConnectptr);
2123     return;
2124 
2125   case 10:
2126     jam();
2127     systemErrorLab(signal, __LINE__);
2128     return;
2129 
2130   case 11:
2131     jam();
2132     terrorCode = ZMORE_AI_IN_TCKEYREQ_ERROR;
2133     releaseAtErrorLab(signal, apiConnectptr);
2134     return;
2135 
2136   case 12:
2137     jam();
2138     terrorCode = ZSIMPLE_READ_WITHOUT_AI;
2139     releaseAtErrorLab(signal, apiConnectptr);
2140     return;
2141 
2142   case 13:
2143     jam();
2144     switch (tcConnectptr.p->tcConnectstate)
2145     {
2146     case OS_WAIT_KEYINFO:
2147       jam();
2148       printState(signal, 8, apiConnectptr);
2149       terrorCode = ZSTATE_ERROR;
2150       abortErrorLab(signal, apiConnectptr);
2151       return;
2152     default:
2153       jam();
2154       /********************************************************************/
2155       /*       MISMATCH BETWEEN STATE ON API CONNECTION AND THIS          */
2156       /*       PARTICULAR TC CONNECT RECORD. THIS MUST BE CAUSED BY NDB   */
2157       /*       INTERNAL ERROR.                                            */
2158       /********************************************************************/
2159       systemErrorLab(signal, __LINE__);
2160       return;
2161     }//switch
2162     return;
2163 
2164   case 15:
2165     jam();
2166     terrorCode = ZSCAN_NODE_ERROR;
2167     releaseAtErrorLab(signal, apiConnectptr);
2168     return;
2169 
2170   case 16:
2171     jam();
2172     systemErrorLab(signal, __LINE__);
2173     return;
2174 
2175   case 17:
2176     jam();
2177     systemErrorLab(signal, __LINE__);
2178     return;
2179 
2180   case 20:
2181     jam();
2182     warningHandlerLab(signal, __LINE__);
2183     return;
2184 
2185   case 21:
2186     jam();
2187     systemErrorLab(signal, __LINE__);
2188     return;
2189 
2190   case 22:
2191     jam();
2192     systemErrorLab(signal, __LINE__);
2193     return;
2194 
2195   case 23:
2196     jam();
2197     systemErrorLab(signal, __LINE__);
2198     return;
2199 
2200   case 24:
2201     jam();
2202     appendToSectionErrorLab(signal, apiConnectptr);
2203     return;
2204 
2205   case 25:
2206     jam();
2207     warningHandlerLab(signal, __LINE__);
2208     return;
2209 
2210   case 26:
2211     jam();
2212     return;
2213 
2214   case 27:
2215     systemErrorLab(signal, __LINE__);
2216     jam();
2217     return;
2218 
2219   case 28:
2220     jam();
2221     // NOT USED
2222     return;
2223 
2224   case 29:
2225     jam();
2226     systemErrorLab(signal, __LINE__);
2227     return;
2228 
2229   case 30:
2230     jam();
2231     systemErrorLab(signal, __LINE__);
2232     return;
2233 
2234   case 31:
2235     jam();
2236     systemErrorLab(signal, __LINE__);
2237     return;
2238 
2239   case 32:
2240     jam();
2241     systemErrorLab(signal, __LINE__);
2242     return;
2243 
2244   case 33:
2245     jam();
2246     systemErrorLab(signal, __LINE__);
2247     return;
2248 
2249   case 34:
2250     jam();
2251     systemErrorLab(signal, __LINE__);
2252     return;
2253 
2254   case 35:
2255     jam();
2256     systemErrorLab(signal, __LINE__);
2257     return;
2258 
2259   case 36:
2260     jam();
2261     systemErrorLab(signal, __LINE__);
2262     return;
2263 
2264   case 37:
2265     jam();
2266     systemErrorLab(signal, __LINE__);
2267     return;
2268 
2269   case 38:
2270     jam();
2271     systemErrorLab(signal, __LINE__);
2272     return;
2273 
2274   case 39:
2275     jam();
2276     systemErrorLab(signal, __LINE__);
2277     return;
2278 
2279   case 40:
2280     jam();
2281     systemErrorLab(signal, __LINE__);
2282     return;
2283 
2284   case 42:
2285     jam();
2286     systemErrorLab(signal, __LINE__);
2287     return;
2288 
2289   case 44:
2290     jam();
2291     systemErrorLab(signal, __LINE__);
2292     return;
2293 
2294   case 45:
2295     jam();
2296     systemErrorLab(signal, __LINE__);
2297     return;
2298 
2299   case 46:
2300     jam();
2301     systemErrorLab(signal, __LINE__);
2302     return;
2303 
2304   case 47:
2305     jam();
2306     terrorCode = apiConnectptr.p->returncode;
2307     releaseAtErrorLab(signal, apiConnectptr);
2308     return;
2309 
2310   case 48:
2311     jam();
2312     terrorCode = ZCOMMIT_TYPE_ERROR;
2313     releaseAtErrorLab(signal, apiConnectptr);
2314     return;
2315 
2316   case 49:
2317     jam();
2318     abortErrorLab(signal, apiConnectptr);
2319     return;
2320 
2321   case 50:
2322     jam();
2323     systemErrorLab(signal, __LINE__);
2324     return;
2325 
2326   case 51:
2327     jam();
2328     abortErrorLab(signal, apiConnectptr);
2329     return;
2330 
2331   case 52:
2332     jam();
2333     abortErrorLab(signal, apiConnectptr);
2334     return;
2335 
2336   case 53:
2337     jam();
2338     abortErrorLab(signal, apiConnectptr);
2339     return;
2340 
2341   case 54:
2342     jam();
2343     abortErrorLab(signal, apiConnectptr);
2344     return;
2345 
2346   case 55:
2347     jam();
2348     printState(signal, 5, apiConnectptr);
2349     sendSignalErrorRefuseLab(signal, apiConnectptr);
2350     return;
2351 
2352   case 56:{
2353     jam();
2354     terrorCode = ZNO_FREE_TC_MARKER;
2355     abortErrorLab(signal, apiConnectptr);
2356     return;
2357   }
2358   case 57:{
2359     jam();
2360     /**
2361      * Initialize object before starting error handling
2362      */
2363     initApiConnectRec(signal, apiConnectptr.p, true);
2364 start_failure:
2365     switch(getNodeState().startLevel){
2366     case NodeState::SL_STOPPING_2:
2367       if (getNodeState().getSingleUserMode())
2368       {
2369         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
2370         break;
2371       }
2372       // Fall through
2373     case NodeState::SL_STOPPING_3:
2374     case NodeState::SL_STOPPING_4:
2375       if(getNodeState().stopping.systemShutdown)
2376 	terrorCode  = ZCLUSTER_SHUTDOWN_IN_PROGRESS;
2377       else
2378 	terrorCode = ZNODE_SHUTDOWN_IN_PROGRESS;
2379       break;
2380     case NodeState::SL_SINGLEUSER:
2381       terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
2382       break;
2383     case NodeState::SL_STOPPING_1:
2384       if (getNodeState().getSingleUserMode())
2385       {
2386         terrorCode  = ZCLUSTER_IN_SINGLEUSER_MODE;
2387         break;
2388       }
2389       // Fall through
2390     default:
2391       terrorCode = ZWRONG_STATE;
2392       break;
2393     }
2394     abortErrorLab(signal, apiConnectptr);
2395     return;
2396   }
2397 
2398   case 58:{
2399     jam();
2400     releaseAtErrorLab(signal, apiConnectptr);
2401     return;
2402   }
2403 
2404   case 59:{
2405     jam();
2406     terrorCode = ZABORTINPROGRESS;
2407     abortErrorLab(signal, apiConnectptr);
2408     return;
2409   }
2410 
2411   case 60:
2412   {
2413     jam();
2414     initApiConnectRec(signal, apiConnectptr.p, true);
2415     apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
2416     goto start_failure;
2417   }
2418   case 61:
2419   {
2420     jam();
2421     terrorCode = ZUNLOCKED_IVAL_TOO_HIGH;
2422     abortErrorLab(signal, apiConnectptr);
2423     return;
2424   }
2425   case 62:
2426   {
2427     jam();
2428     terrorCode = ZUNLOCKED_OP_HAS_BAD_STATE;
2429     abortErrorLab(signal, apiConnectptr);
2430     return;
2431   }
2432   case 63:
2433   {
2434     jam();
2435     /* Function not implemented yet */
2436     terrorCode = 4003;
2437     abortErrorLab(signal, apiConnectptr);
2438     return;
2439   }
2440   case 64:
2441   {
2442     jam();
2443     /* Invalid distribution key */
2444     terrorCode = ZBAD_DIST_KEY;
2445     abortErrorLab(signal, apiConnectptr);
2446     return;
2447   }
2448   case 65:
2449   {
2450     jam();
2451     terrorCode = ZTRANS_TOO_BIG;
2452     abortErrorLab(signal, apiConnectptr);
2453     return;
2454   }
2455   case 66:
2456   {
2457     jam();
2458     /* Function not implemented yet */
2459     terrorCode = 4003;
2460     abortErrorLab(signal, apiConnectptr);
2461     return;
2462   }
2463   case 67:
2464   {
2465     jam();
2466     terrorCode = ZNO_FREE_TC_MARKER_DATABUFFER;
2467     abortErrorLab(signal, apiConnectptr);
2468     return;
2469   }
2470   default:
2471     jam();
2472     systemErrorLab(signal, __LINE__);
2473     return;
2474   }//switch
2475 }
2476 
2477 static
2478 inline
2479 bool
compare_transid(Uint32 * val0,Uint32 * val1)2480 compare_transid(Uint32* val0, Uint32* val1)
2481 {
2482   Uint32 tmp0 = val0[0] ^ val1[0];
2483   Uint32 tmp1 = val0[1] ^ val1[1];
2484   return (tmp0 | tmp1) == 0;
2485 }
2486 
execKEYINFO(Signal * signal)2487 void Dbtc::execKEYINFO(Signal* signal)
2488 {
2489   jamEntry();
2490   ApiConnectRecordPtr apiConnectptr;
2491   apiConnectptr.i = signal->theData[0];
2492   tmaxData = 20;
2493   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
2494   {
2495     jam();
2496     warningHandlerLab(signal, __LINE__);
2497     return;
2498   }//if
2499   ttransid_ptr = 1;
2500   if (unlikely(compare_transid(apiConnectptr.p->transid,
2501                                signal->theData+1) == false))
2502   {
2503     jam();
2504     warningHandlerLab(signal, __LINE__);
2505     return;
2506   }//if
2507   switch (apiConnectptr.p->apiConnectstate)
2508   {
2509   case CS_RECEIVING:
2510   case CS_REC_COMMITTING:
2511   case CS_START_SCAN:
2512     jam();
2513     /*empty*/;
2514     break;
2515   case CS_ABORTING:
2516     jam();
2517     return;     /* IGNORE */
2518   case CS_CONNECTED:
2519     jam();
2520     /****************************************************************>*/
2521     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2522     /*       SET STATE TO ABORTING.                                   */
2523     /****************************************************************>*/
2524     printState(signal, 11, apiConnectptr);
2525     signalErrorRefuseLab(signal, apiConnectptr);
2526     return;
2527   case CS_STARTED:
2528     jam();
2529     /****************************************************************>*/
2530     /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2531     /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
2532     /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
2533     /****************************************************************>*/
2534     terrorCode = ZSIGNAL_ERROR;
2535     printState(signal, 2, apiConnectptr);
2536     abortErrorLab(signal, apiConnectptr);
2537     return;
2538   default:
2539     jam();
2540     ndbabort();
2541     return;
2542   }//switch
2543 
2544   UintR TtcTimer = ctcTimer;
2545   CacheRecordPtr cachePtr;
2546   cachePtr.i = apiConnectptr.p->cachePtr;
2547   ndbassert(cachePtr.i != Uint32(~0));
2548   ndbrequire(c_cacheRecordPool.getValidPtr(cachePtr));
2549   CacheRecord * const regCachePtr = cachePtr.p;
2550   setApiConTimer(apiConnectptr, TtcTimer, __LINE__);
2551 
2552   if (apiConnectptr.p->apiConnectstate == CS_START_SCAN)
2553   {
2554     jam();
2555     scanKeyinfoLab(signal, regCachePtr, apiConnectptr);
2556     return;
2557   }
2558 
2559   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, apiConnectptr.p->tcConnect);
2560   ndbrequire(tcConList.last(tcConnectptr));
2561   switch (tcConnectptr.p->tcConnectstate)
2562   {
2563   case OS_WAIT_KEYINFO:
2564     jam();
2565     tckeyreq020Lab(signal, cachePtr, apiConnectptr);
2566     return;
2567   default:
2568     jam();
2569     terrorCode = ZSTATE_ERROR;
2570     abortErrorLab(signal, apiConnectptr);
2571     return;
2572   }//switch
2573 }//Dbtc::execKEYINFO()
2574 
2575 /**
2576  * sendKeyInfoTrain
2577  * Method to send a KeyInfo signal train from KeyInfo in the supplied
2578  * Section
2579  * KeyInfo will be taken from the section, starting at the supplied
2580  * offset
2581  */
sendKeyInfoTrain(Signal * signal,BlockReference TBRef,Uint32 connectPtr,Uint32 offset,Uint32 sectionIVal,ApiConnectRecord * const regApiPtr)2582 void Dbtc::sendKeyInfoTrain(Signal* signal,
2583                             BlockReference TBRef,
2584                             Uint32 connectPtr,
2585                             Uint32 offset,
2586                             Uint32 sectionIVal,
2587                             ApiConnectRecord* const regApiPtr)
2588 {
2589   jam();
2590 
2591   signal->theData[0] = connectPtr;
2592   signal->theData[1] = regApiPtr->transid[0];
2593   signal->theData[2] = regApiPtr->transid[1];
2594   Uint32 * dst = signal->theData + KeyInfo::HeaderLength;
2595 
2596   ndbassert( sectionIVal != RNIL );
2597   SectionReader keyInfoReader(sectionIVal, getSectionSegmentPool());
2598 
2599   Uint32 totalLen= keyInfoReader.getSize();
2600 
2601   ndbassert( offset < totalLen );
2602 
2603   keyInfoReader.step(offset);
2604   totalLen-= offset;
2605 
2606   while (totalLen != 0)
2607   {
2608     Uint32 dataInSignal= MIN(KeyInfo::DataLength, totalLen);
2609     keyInfoReader.getWords(dst, dataInSignal);
2610     totalLen-= dataInSignal;
2611 
2612     sendSignal(TBRef, GSN_KEYINFO, signal,
2613                KeyInfo::HeaderLength + dataInSignal, JBB);
2614   }
2615 }//Dbtc::sendKeyInfoTrain()
2616 
2617 /**
2618  * tckeyreq020Lab
2619  * Handle received KEYINFO signal
2620  */
tckeyreq020Lab(Signal * signal,CacheRecordPtr const cachePtr,ApiConnectRecordPtr const apiConnectptr)2621 void Dbtc::tckeyreq020Lab(Signal* signal, CacheRecordPtr const cachePtr, ApiConnectRecordPtr const apiConnectptr)
2622 {
2623   CacheRecord * const regCachePtr = cachePtr.p;
2624   UintR TkeyLen = regCachePtr->keylen;
2625   UintR Tlen = regCachePtr->save1;
2626   UintR wordsInSignal= MIN(KeyInfo::DataLength,
2627                            (TkeyLen - Tlen));
2628 
2629   ndbassert(! regCachePtr->isLongTcKeyReq );
2630   ndbassert( regCachePtr->keyInfoSectionI != RNIL );
2631 
2632   /* Add received KeyInfo data to the existing KeyInfo section */
2633   if (! appendToSection(regCachePtr->keyInfoSectionI,
2634                         &signal->theData[KeyInfo::HeaderLength],
2635                         wordsInSignal))
2636   {
2637     jam();
2638     appendToSectionErrorLab(signal, apiConnectptr);
2639     return;
2640   }
2641   Tlen+= wordsInSignal;
2642 
2643   if (Tlen < TkeyLen)
2644   {
2645     /* More KeyInfo still to be read
2646      * Set timer and state and wait
2647      */
2648     jam();
2649     setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
2650     regCachePtr->save1 = Tlen;
2651     tcConnectptr.p->tcConnectstate = OS_WAIT_KEYINFO;
2652     return;
2653   }
2654   else
2655   {
2656     /* Have all the KeyInfo ... continue processing
2657      * TCKEYREQ
2658      */
2659     jam();
2660     tckeyreq050Lab(signal, cachePtr, apiConnectptr);
2661     return;
2662   }
2663 }//Dbtc::tckeyreq020Lab()
2664 
execATTRINFO(Signal * signal)2665 void Dbtc::execATTRINFO(Signal* signal)
2666 {
2667   UintR Tdata1 = signal->theData[0];
2668   UintR Tlength = signal->length();
2669 
2670   jamEntry();
2671   ApiConnectRecordPtr apiConnectptr;
2672   apiConnectptr.i = Tdata1;
2673   ttransid_ptr = 1;
2674   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
2675   {
2676     jam();
2677     DEBUG("Drop ATTRINFO, wrong apiConnectptr");
2678     warningHandlerLab(signal, __LINE__);
2679     return;
2680   }//if
2681 
2682   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
2683 
2684   if (unlikely(compare_transid(regApiPtr->transid,
2685                                signal->theData+1) == false))
2686   {
2687     jam();
2688     DEBUG("Drop ATTRINFO, wrong transid, lenght="<<Tlength
2689           << " transid("<<hex<<signal->theData[1]<<", "<<signal->theData[2]);
2690     return;
2691   }//if
2692   if (Tlength < 4)
2693   {
2694     ndbassert(false);
2695     DEBUG("Drop ATTRINFO, wrong length = " << Tlength);
2696     warningHandlerLab(signal, __LINE__);
2697     return;
2698   }
2699   Tlength -= AttrInfo::HeaderLength;
2700   UintR TcompREC_COMMIT = (regApiPtr->apiConnectstate == CS_REC_COMMITTING);
2701   UintR TcompRECEIVING = (regApiPtr->apiConnectstate == CS_RECEIVING);
2702   UintR TcompBOTH = TcompREC_COMMIT | TcompRECEIVING;
2703 
2704   if (TcompBOTH)
2705   {
2706     jam();
2707     if (ERROR_INSERTED(8015))
2708     {
2709       CLEAR_ERROR_INSERT_VALUE;
2710       return;
2711     }//if
2712     if (ERROR_INSERTED(8016))
2713     {
2714       CLEAR_ERROR_INSERT_VALUE;
2715       return;
2716     }//if
2717     UintR TtcTimer = ctcTimer;
2718     CacheRecordPtr cachePtr;
2719     cachePtr.i = regApiPtr->cachePtr;
2720     ndbrequire(c_cacheRecordPool.getValidPtr(cachePtr));
2721     CacheRecord * const regCachePtr = cachePtr.p;
2722 
2723     regCachePtr->currReclenAi+= Tlength;
2724     int TattrlengthRemain = regCachePtr->attrlength -
2725       regCachePtr->currReclenAi;
2726 
2727     /* Setup tcConnectptr to ensure that error handling etc.
2728      * can access required state
2729      */
2730     LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
2731     ndbrequire( tcConList.last(tcConnectptr));
2732 
2733     /* Add AttrInfo to any existing AttrInfo we have
2734      * Some short TCKEYREQ signals have no ATTRINFO in
2735      * the TCKEYREQ itself
2736      */
2737     if (! appendToSection(regCachePtr->attrInfoSectionI,
2738                           &signal->theData[AttrInfo::HeaderLength],
2739                           Tlength))
2740     {
2741       DEBUG("No more section segments available");
2742       appendToSectionErrorLab(signal, apiConnectptr);
2743       return;
2744     }//if
2745 
2746     setApiConTimer(apiConnectptr, TtcTimer, __LINE__);
2747 
2748     if (TattrlengthRemain == 0)
2749     {
2750       /****************************************************************>*/
2751       /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS       */
2752       /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
2753       /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
2754       /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER          */
2755       /* OPERATIONS.                                                     */
2756       /****************************************************************>*/
2757       if (TcompRECEIVING)
2758       {
2759         jam();
2760         regApiPtr->apiConnectstate = CS_STARTED;
2761       }
2762       else
2763       {
2764         jam();
2765         regApiPtr->apiConnectstate = CS_START_COMMITTING;
2766       }//if
2767       attrinfoDihReceivedLab(signal, cachePtr, apiConnectptr);
2768     }
2769     else if (TattrlengthRemain < 0)
2770     {
2771       jam();
2772       DEBUG("ATTRINFO wrong total length="<<Tlength
2773             <<", TattrlengthRemain="<<TattrlengthRemain
2774             <<", TattrLen="<< regCachePtr->attrlength
2775             <<", TcurrReclenAi="<< regCachePtr->currReclenAi);
2776       LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
2777       ndbrequire( tcConList.last(tcConnectptr));
2778       aiErrorLab(signal, apiConnectptr);
2779     }//if
2780     return;
2781   }
2782   else if (regApiPtr->apiConnectstate == CS_START_SCAN)
2783   {
2784     jam();
2785     scanAttrinfoLab(signal, Tlength, apiConnectptr);
2786     return;
2787   }
2788   else
2789   {
2790     switch (regApiPtr->apiConnectstate)
2791     {
2792     case CS_ABORTING:
2793       jam();
2794       /* JUST IGNORE THE SIGNAL*/
2795       // DEBUG("Drop ATTRINFO, CS_ABORTING");
2796       return;
2797     case CS_CONNECTED:
2798       jam();
2799       /* MOST LIKELY CAUSED BY A MISSED SIGNAL.*/
2800       // DEBUG("Drop ATTRINFO, CS_CONNECTED");
2801       return;
2802     case CS_STARTED:
2803       jam();
2804       /****************************************************************>*/
2805       /*       MOST LIKELY CAUSED BY A MISSED SIGNAL. SEND REFUSE AND   */
2806       /*       SET STATE TO ABORTING. SINCE A TRANSACTION WAS STARTED   */
2807       /*       WE ALSO NEED TO ABORT THIS TRANSACTION.                  */
2808       /****************************************************************>*/
2809       terrorCode = ZSIGNAL_ERROR;
2810       printState(signal, 1, apiConnectptr);
2811       abortErrorLab(signal, apiConnectptr);
2812       return;
2813     default:
2814       jam();
2815       /****************************************************************>*/
2816       /*       SIGNAL RECEIVED IN AN UNEXPECTED STATE. WE IGNORE SIGNAL */
2817       /*       SINCE WE DO NOT REALLY KNOW WHERE THE ERROR OCCURRED.    */
2818       /****************************************************************>*/
2819       DEBUG("Drop ATTRINFO, illegal state="<<regApiPtr->apiConnectstate);
2820       printState(signal, 9, apiConnectptr);
2821       return;
2822     }//switch
2823   }//if
2824 }//Dbtc::execATTRINFO()
2825 
2826 /* *********************************************************************>> */
2827 /*                                                                        */
2828 /*       MODULE: HASH MODULE                                              */
2829 /*       DESCRIPTION: CONTAINS THE HASH VALUE CALCULATION                 */
2830 /* *********************************************************************> */
hash(Signal * signal,CacheRecord * const regCachePtr)2831 void Dbtc::hash(Signal* signal, CacheRecord * const regCachePtr)
2832 {
2833   UintR*  Tdata32;
2834 
2835   SegmentedSectionPtr keyInfoSection;
2836   UintR keylen = (UintR)regCachePtr->keylen;
2837   Uint32 distKey = regCachePtr->distributionKeyIndicator;
2838 
2839   getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
2840 
2841   ndbassert( keyInfoSection.sz <= MAX_KEY_SIZE_IN_WORDS );
2842   ndbassert( keyInfoSection.sz == keylen );
2843   /* Copy KeyInfo section from segmented storage into linear storage
2844    * in signal->theData
2845    */
2846   if (keylen <= SectionSegment::DataLength)
2847   {
2848     /* No need to copy keyinfo into a linear space
2849      * Note that we require that the data in the section is
2850      * 64-bit aligned for md5_hash below
2851      */
2852     ndbassert( keyInfoSection.p != NULL );
2853 
2854     Tdata32= &keyInfoSection.p->theData[0];
2855   }
2856   else
2857   {
2858     /* Copy segmented keyinfo into linear space in the signal */
2859     Tdata32= signal->theData;
2860     copy(Tdata32, keyInfoSection);
2861   }
2862 
2863   Uint32 tmp[4];
2864   if(!regCachePtr->m_special_hash)
2865   {
2866     md5_hash(tmp, (Uint64*)&Tdata32[0], keylen);
2867   }
2868   else
2869   {
2870     if (regCachePtr->m_no_hash)
2871     {
2872       /* No need for tuple key hash at LQH */
2873       ndbassert(distKey); /* User must supply distkey */
2874       Uint32 zero[4] = {0, 0, 0, 0};
2875       *tmp = *zero;
2876     }
2877     else
2878     {
2879       handle_special_hash(tmp, Tdata32, keylen, regCachePtr->tableref, !distKey);
2880     }
2881   }
2882 
2883   /* Primary key hash value is first word of hash on PK columns
2884    * Distribution key hash value is second word of hash on distribution
2885    * key columns, or a user defined value
2886    */
2887   thashValue = tmp[0];
2888   if (distKey){
2889     jam();
2890     tdistrHashValue = regCachePtr->distributionKey;
2891   } else {
2892     jamDebug();
2893     tdistrHashValue = tmp[1];
2894   }//if
2895 }//Dbtc::hash()
2896 
2897 bool
handle_special_hash(Uint32 dstHash[4],const Uint32 * src,Uint32 srcLen,Uint32 tabPtrI,bool distr)2898 Dbtc::handle_special_hash(Uint32 dstHash[4],
2899                           const Uint32* src, Uint32 srcLen,
2900 			  Uint32 tabPtrI,
2901 			  bool distr)
2902 {
2903   const Uint32 MAX_KEY_SIZE_IN_LONG_WORDS=
2904     (MAX_KEY_SIZE_IN_WORDS + 1) / 2;
2905   Uint64 alignedWorkspace[MAX_KEY_SIZE_IN_LONG_WORDS * MAX_XFRM_MULTIPLY];
2906   Uint32* workspace= (Uint32*)alignedWorkspace;
2907   const TableRecord* tabPtrP = &tableRecord[tabPtrI];
2908   const bool hasVarKeys = tabPtrP->hasVarKeys;
2909   const bool hasCharAttr = tabPtrP->hasCharAttr;
2910   const bool compute_distkey = distr && (tabPtrP->noOfDistrKeys > 0);
2911 
2912   const Uint32 *hashInput = workspace;
2913   Uint32 inputLen = 0;
2914   Uint32 keyPartLen[MAX_ATTRIBUTES_IN_INDEX];
2915   Uint32 * keyPartLenPtr;
2916 
2917   /* Normalise KeyInfo into workspace if necessary */
2918   if(hasCharAttr || (compute_distkey && hasVarKeys))
2919   {
2920     keyPartLenPtr = keyPartLen;
2921     inputLen = xfrm_key_hash(tabPtrI,
2922                              src,
2923                              workspace,
2924                              sizeof(alignedWorkspace) >> 2,
2925                              keyPartLenPtr);
2926     if (unlikely(inputLen == 0))
2927     {
2928       goto error;
2929     }
2930   }
2931   else
2932   {
2933     /* Keyinfo already suitable for hash */
2934     hashInput = src;
2935     inputLen = srcLen;
2936     keyPartLenPtr = 0;
2937   }
2938 
2939   /* Calculate primary key hash */
2940   md5_hash(dstHash, (Uint64*)hashInput, inputLen);
2941 
2942   /* If the distribution key != primary key then we have to
2943    * form a distribution key from the primary key and calculate
2944    * a separate distribution hash based on this
2945    */
2946   if(compute_distkey)
2947   {
2948     jam();
2949 
2950     Uint32 distrKeyHash[4];
2951     /* Reshuffle primary key columns to get just distribution key */
2952     Uint32 len = create_distr_key(tabPtrI, hashInput, workspace, keyPartLenPtr);
2953     /* Calculate distribution key hash */
2954     md5_hash(distrKeyHash, (Uint64*) workspace, len);
2955 
2956     /* Just one word used for distribution */
2957     dstHash[1] = distrKeyHash[1];
2958   }
2959   return true;  // success
2960 
2961 error:
2962   terrorCode = ZINVALID_KEY;
2963   return false;
2964 }
2965 
2966 /*
2967 INIT_API_CONNECT_REC
2968 ---------------------------
2969 */
2970 /* ========================================================================= */
2971 /* =======                       INIT_API_CONNECT_REC                ======= */
2972 /*                                                                           */
2973 /* ========================================================================= */
initApiConnectRec(Signal * signal,ApiConnectRecord * const regApiPtr,bool releaseIndexOperations)2974 void Dbtc::initApiConnectRec(Signal* signal,
2975                              ApiConnectRecord * const regApiPtr,
2976 			     bool releaseIndexOperations)
2977 {
2978   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
2979   UintR TfailureNr = cfailure_nr;
2980   UintR Ttransid0 = tcKeyReq->transId1;
2981   UintR Ttransid1 = tcKeyReq->transId2;
2982 
2983   tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
2984   regApiPtr->returncode = 0;
2985   regApiPtr->returnsignal = RS_TCKEYCONF;
2986   ndbassert(regApiPtr->tcConnect.isEmpty());
2987   regApiPtr->tcConnect.init();
2988   regApiPtr->firedFragId = RNIL;
2989   regApiPtr->globalcheckpointid = 0;
2990   regApiPtr->lqhkeyconfrec = 0;
2991   regApiPtr->lqhkeyreqrec = 0;
2992   regApiPtr->tckeyrec = 0;
2993   regApiPtr->tcindxrec = 0;
2994   tc_clearbit(regApiPtr->m_flags,
2995               ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
2996   regApiPtr->failureNr = TfailureNr;
2997   regApiPtr->transid[0] = Ttransid0;
2998   regApiPtr->transid[1] = Ttransid1;
2999   ndbrequire(regApiPtr->commitAckMarker == RNIL);
3000   ndbrequire(regApiPtr->num_commit_ack_markers == 0);
3001 /**
3002  * We wanted to verify those variables around commitAckMarkers,
3003  * So we have an ndbrequire around them, this means we can
3004  * remove the setting of them since we already verified that
3005  * they already have the correct value.
3006  * regApiPtr->num_commit_ack_markers = 0;
3007  * regApiPtr->commitAckMarker = RNIL;
3008  */
3009   regApiPtr->buddyPtr = RNIL;
3010   regApiPtr->currSavePointId = 0;
3011   regApiPtr->m_transaction_nodes.clear();
3012   regApiPtr->singleUserMode = 0;
3013   regApiPtr->m_pre_commit_pass = 0;
3014   regApiPtr->cascading_scans_count = 0;
3015   regApiPtr->m_executing_trigger_ops = 0;
3016   regApiPtr->m_inExecuteTriggers = false;
3017   // FiredTriggers should have been released when previous transaction ended.
3018   ndbrequire(regApiPtr->theFiredTriggers.isEmpty());
3019   // Index data
3020   tc_clearbit(regApiPtr->m_flags,
3021               ApiConnectRecord::TF_INDEX_OP_RETURN);
3022   regApiPtr->noIndexOp = 0;
3023   if(releaseIndexOperations)
3024   {
3025     releaseAllSeizedIndexOperations(regApiPtr);
3026   }
3027   else
3028   {
3029     regApiPtr->m_start_ticks = getHighResTimer();
3030   }
3031   regApiPtr->immediateTriggerId = RNIL;
3032 
3033   tc_clearbit(regApiPtr->m_flags,
3034               ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
3035   tc_clearbit(regApiPtr->m_flags,
3036               ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS);
3037   c_counters.ctransCount++;
3038 
3039 #ifdef ERROR_INSERT
3040   regApiPtr->continueBCount = 0;
3041 #endif
3042 
3043   regApiPtr->m_outstanding_fire_trig_req = 0;
3044   regApiPtr->m_write_count = 0;
3045   regApiPtr->m_firstTcConnectPtrI_FT = RNIL;
3046   regApiPtr->m_lastTcConnectPtrI_FT = RNIL;
3047 }//Dbtc::initApiConnectRec()
3048 
3049 void
sendPoolShrink(const Uint32 pool_index)3050 Dbtc::sendPoolShrink(const Uint32 pool_index)
3051 {
3052   const bool need_send = c_transient_pools_shrinking.get(pool_index) == 0;
3053   c_transient_pools_shrinking.set(pool_index);
3054   if (need_send)
3055   {
3056     SignalT<2> signal2[1];
3057     Signal* signal = new (&signal2[0]) Signal(0);
3058     bzero(signal2, sizeof(signal2));
3059     signal->theData[0] = TcContinueB::ZSHRINK_TRANSIENT_POOLS;
3060     signal->theData[1] = pool_index;
3061     sendSignal(cownref, GSN_CONTINUEB, (Signal*)signal, 2, JBB);
3062   }
3063 }
3064 
3065 int
seizeTcRecord(Signal * signal,ApiConnectRecordPtr const apiConnectptr)3066 Dbtc::seizeTcRecord(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
3067 {
3068   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3069   if (unlikely(!tcConnectRecord.seize(tcConnectptr)))
3070   {
3071     int place = 3;
3072     TCKEY_abort(signal, place, apiConnectptr);
3073     return 1;
3074   }
3075   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3076 
3077   c_counters.cconcurrentOp++;
3078 
3079   regTcPtr->numFiredTriggers = 0;
3080   regTcPtr->numReceivedTriggers = 0;
3081   regTcPtr->triggerExecutionCount = 0;
3082   regTcPtr->tcConnectstate = OS_ABORTING;
3083 
3084   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
3085   tcConList.addLast(tcConnectptr);
3086 
3087   return 0;
3088 }//Dbtc::seizeTcRecord()
3089 
3090 int
seizeCacheRecord(Signal * signal,CacheRecordPtr & cachePtr,ApiConnectRecord * const regApiPtr)3091 Dbtc::seizeCacheRecord(Signal* signal, CacheRecordPtr& cachePtr, ApiConnectRecord* const regApiPtr)
3092 {
3093   if (unlikely(!c_cacheRecordPool.seize(cachePtr)))
3094   {
3095     return 1;
3096   }
3097   CacheRecord * const regCachePtr = cachePtr.p;
3098 
3099   regApiPtr->cachePtr = cachePtr.i;
3100   regCachePtr->currReclenAi = 0;
3101   regCachePtr->keyInfoSectionI = RNIL;
3102   regCachePtr->attrInfoSectionI = RNIL;
3103   return 0;
3104 }//Dbtc::seizeCacheRecord()
3105 
3106 void
releaseCacheRecord(ApiConnectRecordPtr transPtr,CacheRecord * regCachePtr)3107 Dbtc::releaseCacheRecord(ApiConnectRecordPtr transPtr, CacheRecord* regCachePtr)
3108 {
3109   ApiConnectRecord * const regApiPtr = transPtr.p;
3110   CacheRecordPtr cachePtr;
3111   cachePtr.p = regCachePtr;
3112   cachePtr.i = regApiPtr->cachePtr;
3113   ndbassert(cachePtr.i != Uint32(~0));
3114   c_cacheRecordPool.release(cachePtr);
3115   regApiPtr->cachePtr = RNIL;
3116   checkPoolShrinkNeed(DBTC_CACHE_RECORD_TRANSIENT_POOL_INDEX,
3117                       c_cacheRecordPool);
3118 }
3119 
3120 void
dump_trans(ApiConnectRecordPtr transPtr)3121 Dbtc::dump_trans(ApiConnectRecordPtr transPtr)
3122 {
3123   printf("transid %u [ 0x%x 0x%x ] state: %u flags: 0x%x m_pre_commit_pass: %u\n",
3124          transPtr.i,
3125          transPtr.p->transid[0],
3126          transPtr.p->transid[1],
3127          transPtr.p->apiConnectstate,
3128          transPtr.p->m_flags,
3129          transPtr.p->m_pre_commit_pass);
3130 
3131   Uint32 i = 0;
3132   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, transPtr.p->tcConnect);
3133   if (tcConList.first(tcConnectptr)) do
3134   {
3135     jam();
3136     Ptr<TcDefinedTriggerData> trigPtr;
3137     if (tcConnectptr.p->currentTriggerId != RNIL)
3138     {
3139       c_theDefinedTriggers.getPtr(trigPtr, tcConnectptr.p->currentTriggerId);
3140     }
3141 
3142     printf(" %u : opPtrI: 0x%x op: %u state: %u triggeringOperation: 0x%x flags: 0x%x triggerType: %u apiConnect: %u\n",
3143            i++,
3144            tcConnectptr.i,
3145            tcConnectptr.p->operation,
3146            tcConnectptr.p->tcConnectstate,
3147            tcConnectptr.p->triggeringOperation,
3148            tcConnectptr.p->m_special_op_flags,
3149            tcConnectptr.p->currentTriggerId == RNIL ? RNIL :
3150            (Uint32)trigPtr.p->triggerType,
3151            tcConnectptr.p->apiConnect);
3152   } while (tcConList.next(tcConnectptr));
3153 }
3154 
3155 bool
hasOp(ApiConnectRecordPtr transPtr,Uint32 opPtrI)3156 Dbtc::hasOp(ApiConnectRecordPtr transPtr, Uint32 opPtrI)
3157 {
3158   TcConnectRecordPtr tcPtr;
3159   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, transPtr.p->tcConnect);
3160   if (tcConList.first(tcPtr)) do
3161   {
3162     jam();
3163     if (tcPtr.i == opPtrI)
3164     {
3165       return tcPtr.p->apiConnect == transPtr.i;
3166     }
3167   } while (tcConList.next(tcPtr));
3168 
3169   return false;
3170 }
3171 
3172 /*****************************************************************************/
3173 /*                               T C K E Y R E Q                             */
3174 /* AFTER HAVING ESTABLISHED THE CONNECT, THE APPLICATION BLOCK SENDS AN      */
3175 /* OPERATION REQUEST TO TC. ALL NECESSARY INFORMATION TO CARRY OUT REQUEST   */
3176 /* IS FURNISHED IN PARAMETERS. TC STORES THIS INFORMATION AND ENQUIRES       */
3177 /* FROM DIH ABOUT THE NODES WHICH MAY HAVE THE REQUESTED DATA                */
3178 /*****************************************************************************/
execTCKEYREQ(Signal * signal)3179 void Dbtc::execTCKEYREQ(Signal* signal)
3180 {
3181   if (!assembleFragments(signal))
3182   {
3183     jam();
3184     return;
3185   }
3186   Uint32 sendersBlockRef = signal->getSendersBlockRef();
3187   UintR compare_transid1, compare_transid2;
3188   const TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtr();
3189   UintR Treqinfo;
3190   SectionHandle handle(this, signal);
3191 
3192   jamEntry();
3193   /*-------------------------------------------------------------------------
3194    * Common error routines are used for several signals, they need to know
3195    * where to find the transaction identifier in the signal.
3196    *-------------------------------------------------------------------------*/
3197   const UintR TapiIndex = tcKeyReq->apiConnectPtr;
3198   const UintR TtabIndex = tcKeyReq->tableId;
3199   const UintR TtabMaxIndex = ctabrecFilesize;
3200 
3201   ttransid_ptr = 6;
3202   ApiConnectRecordPtr apiConnectptr;
3203   apiConnectptr.i = TapiIndex;
3204   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
3205   {
3206     jam();
3207     releaseSections(handle);
3208     warningHandlerLab(signal, __LINE__);
3209     return;
3210   }//if
3211   if (unlikely(TtabIndex >= TtabMaxIndex))
3212   {
3213     releaseSections(handle);
3214     TCKEY_abort(signal, 7, apiConnectptr);
3215     return;
3216   }//if
3217 
3218 #ifdef ERROR_INSERT
3219   if (ERROR_INSERTED(8079))
3220   {
3221     /* Test that no signals received after API_FAILREQ */
3222     if (refToNode(sendersBlockRef) == c_lastFailedApi)
3223     {
3224       /* Signal from API node received *after* API_FAILREQ */
3225       ndbabort();
3226     }
3227   }
3228 #endif
3229 
3230   Treqinfo = tcKeyReq->requestInfo;
3231   //--------------------------------------------------------------------------
3232   // Optimised version of ptrAss(tabptr, tableRecord)
3233   // Optimised version of ptrAss(apiConnectptr, apiConnectRecord)
3234   //--------------------------------------------------------------------------
3235   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
3236   prefetch_api_record_7((Uint32*)regApiPtr);
3237 
3238   Uint32 TstartFlag = TcKeyReq::getStartFlag(Treqinfo);
3239   Uint32 TexecFlag =
3240     TcKeyReq::getExecuteFlag(Treqinfo) ? ApiConnectRecord::TF_EXEC_FLAG : 0;
3241 
3242   Uint16 Tspecial_op_flags = regApiPtr->m_special_op_flags;
3243   bool isIndexOpReturn = tc_testbit(regApiPtr->m_flags,
3244                                     ApiConnectRecord::TF_INDEX_OP_RETURN);
3245   bool isExecutingTrigger = Tspecial_op_flags & TcConnectRecord::SOF_TRIGGER;
3246   regApiPtr->m_special_op_flags = 0; // Reset marker
3247   regApiPtr->m_flags |= TexecFlag;
3248   TableRecordPtr localTabptr;
3249   localTabptr.i = TtabIndex;
3250   localTabptr.p = &tableRecord[TtabIndex];
3251   switch (regApiPtr->apiConnectstate) {
3252   case CS_CONNECTED:{
3253     if (likely(TstartFlag == 1 &&
3254                getAllowStartTransaction(refToNode(sendersBlockRef),
3255                                  localTabptr.p->singleUserMode) == true))
3256     {
3257       //---------------------------------------------------------------------
3258       // Initialise API connect record if transaction is started.
3259       //---------------------------------------------------------------------
3260       jam();
3261       initApiConnectRec(signal, regApiPtr);
3262       regApiPtr->m_flags |= TexecFlag;
3263     } else {
3264       releaseSections(handle);
3265       if (getAllowStartTransaction(refToNode(sendersBlockRef),
3266                                    localTabptr.p->singleUserMode) == true)
3267       {
3268 
3269 	/*------------------------------------------------------------------
3270 	 * WE EXPECTED A START TRANSACTION. SINCE NO OPERATIONS HAVE BEEN
3271 	 * RECEIVED WE INDICATE THIS BY SETTING FIRST_TC_CONNECT TO RNIL TO
3272 	 * ENSURE PROPER OPERATION OF THE COMMON ABORT HANDLING.
3273 	 *-----------------------------------------------------------------*/
3274         TCKEY_abort(signal, 0, apiConnectptr);
3275 	return;
3276       } else {
3277 	/**
3278 	 * getAllowStartTransaction(refToNode(sendersBlockRef)) == false
3279 	 */
3280         TCKEY_abort(signal, TexecFlag ? 60 : 57, apiConnectptr);
3281 	return;
3282       }//if
3283     }
3284   }
3285   break;
3286   case CS_STARTED:
3287     if (TstartFlag == 1 && regApiPtr->tcConnect.isEmpty())
3288     {
3289       /**
3290        * If last operation in last transaction was a simple/dirty read
3291        *  it does not have to be committed or rollbacked hence,
3292        *  the state will be CS_STARTED
3293        */
3294       jam();
3295       if (unlikely(getNodeState().getSingleUserMode()) &&
3296           getNodeState().getSingleUserApi() != refToNode(sendersBlockRef) &&
3297           !localTabptr.p->singleUserMode)
3298       {
3299         releaseSections(handle);
3300         TCKEY_abort(signal, TexecFlag ? 60 : 57, apiConnectptr);
3301         return;
3302       }
3303       initApiConnectRec(signal, regApiPtr);
3304       regApiPtr->m_flags |= TexecFlag;
3305     } else {
3306       //----------------------------------------------------------------------
3307       // Transaction is started already.
3308       // Check that the operation is on the same transaction.
3309       //-----------------------------------------------------------------------
3310       compare_transid1 = regApiPtr->transid[0] ^ tcKeyReq->transId1;
3311       compare_transid2 = regApiPtr->transid[1] ^ tcKeyReq->transId2;
3312       jam();
3313       compare_transid1 = compare_transid1 | compare_transid2;
3314       if (unlikely(compare_transid1 != 0))
3315       {
3316         releaseSections(handle);
3317         TCKEY_abort(signal, 1, apiConnectptr);
3318 	return;
3319       }//if
3320       ndbrequire(regApiPtr->apiCopyRecord != RNIL);
3321     }
3322     break;
3323   case CS_ABORTING:
3324     if (regApiPtr->abortState == AS_IDLE) {
3325       if (TstartFlag == 1) {
3326         if(getAllowStartTransaction(refToNode(sendersBlockRef),
3327                                     localTabptr.p->singleUserMode) == false)
3328         {
3329           releaseSections(handle);
3330           TCKEY_abort(signal, TexecFlag ? 60 : 57, apiConnectptr);
3331           return;
3332         }
3333 	//--------------------------------------------------------------------
3334 	// Previous transaction had been aborted and the abort was completed.
3335 	// It is then OK to start a new transaction again.
3336 	//--------------------------------------------------------------------
3337         jam();
3338         initApiConnectRec(signal, regApiPtr);
3339 	regApiPtr->m_flags |= TexecFlag;
3340       } else if(TexecFlag) {
3341         releaseSections(handle);
3342         TCKEY_abort(signal, 59, apiConnectptr);
3343 	return;
3344       } else {
3345 	//--------------------------------------------------------------------
3346 	// The current transaction was aborted successfully.
3347 	// We will not do anything before we receive an operation
3348 	// with a start indicator. We will ignore this signal.
3349 	//--------------------------------------------------------------------
3350 	jam();
3351 	DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, ==AS_IDLE");
3352         releaseSections(handle);
3353         return;
3354       }//if
3355     } else {
3356       //----------------------------------------------------------------------
3357       // Previous transaction is still aborting
3358       //----------------------------------------------------------------------
3359       jam();
3360       releaseSections(handle);
3361       if (TstartFlag == 1) {
3362 	//--------------------------------------------------------------------
3363 	// If a new transaction tries to start while the old is
3364 	// still aborting, we will report this to the starting API.
3365 	//--------------------------------------------------------------------
3366         TCKEY_abort(signal, 2, apiConnectptr);
3367         return;
3368       } else if(TexecFlag) {
3369         TCKEY_abort(signal, 59, apiConnectptr);
3370         return;
3371       }
3372       //----------------------------------------------------------------------
3373       // Ignore signals without start indicator set when aborting transaction.
3374       //----------------------------------------------------------------------
3375       DEBUG("Drop TCKEYREQ - apiConnectState=CS_ABORTING, !=AS_IDLE");
3376       return;
3377     }//if
3378     break;
3379   case CS_START_COMMITTING:
3380   case CS_SEND_FIRE_TRIG_REQ:
3381   case CS_WAIT_FIRE_TRIG_REQ:
3382     jam();
3383     if(isIndexOpReturn || isExecutingTrigger){
3384       break;
3385     }
3386     // Fall through
3387   default:
3388     jam();
3389     jamLine(regApiPtr->apiConnectstate);
3390     /*----------------------------------------------------------------------
3391      * IN THIS CASE THE NDBAPI IS AN UNTRUSTED ENTITY THAT HAS SENT A SIGNAL
3392      * WHEN IT WAS NOT EXPECTED TO.
3393      * WE MIGHT BE IN A PROCESS TO RECEIVE, PREPARE,
3394      * COMMIT OR COMPLETE AND OBVIOUSLY THIS IS NOT A DESIRED EVENT.
3395      * WE WILL ALWAYS COMPLETE THE ABORT HANDLING BEFORE WE ALLOW
3396      * ANYTHING TO HAPPEN ON THIS CONNECTION AGAIN.
3397      * THUS THERE IS NO ACTION FROM THE API THAT CAN SPEED UP THIS PROCESS.
3398      *---------------------------------------------------------------------*/
3399     releaseSections(handle);
3400     TCKEY_abort(signal, 55, apiConnectptr);
3401     return;
3402   }//switch
3403 
3404   if (regApiPtr->apiCopyRecord == RNIL)
3405   {
3406     ndbrequire(TstartFlag == 1);
3407     if (unlikely(!seizeApiConnectCopy(signal, apiConnectptr.p)))
3408     {
3409       jam();
3410       releaseSections(handle);
3411       terrorCode = ZSEIZE_API_COPY_ERROR;
3412       abortErrorLab(signal, apiConnectptr);
3413       return;
3414     }
3415   }
3416 
3417   if (likely(localTabptr.p->checkTable(tcKeyReq->tableSchemaVersion)))
3418   {
3419     ;
3420   } else {
3421     /*-----------------------------------------------------------------------*/
3422     /* THE API IS WORKING WITH AN OLD SCHEMA VERSION. IT NEEDS REPLACEMENT.  */
3423     /* COULD ALSO BE THAT THE TABLE IS NOT DEFINED.                          */
3424     /*-----------------------------------------------------------------------*/
3425     releaseSections(handle);
3426     TCKEY_abort(signal, 8, apiConnectptr);
3427     return;
3428   }//if
3429 
3430   //-------------------------------------------------------------------------
3431   // Error Insertion for testing purposes. Test to see what happens when no
3432   // more TC records available.
3433   //-------------------------------------------------------------------------
3434   if (ERROR_INSERTED(8032)) {
3435     releaseSections(handle);
3436     TCKEY_abort(signal, 3, apiConnectptr);
3437     return;
3438   }//if
3439 
3440   if (unlikely(seizeTcRecord(signal, apiConnectptr) != 0))
3441   {
3442     releaseSections(handle);
3443     return;
3444   }//if
3445 
3446   CacheRecordPtr cachePtr;
3447   if (likely(handle.m_cnt != 0))
3448   {
3449     jamDebug();
3450     /* If we have any sections at all then this is a long TCKEYREQ */
3451     cachePtr.i = Uint32(~0);
3452     cachePtr.p = &m_local_cache_record;
3453     regApiPtr->cachePtr = cachePtr.i;
3454     cachePtr.p->currReclenAi = 0;
3455     cachePtr.p->keyInfoSectionI = RNIL;
3456     cachePtr.p->attrInfoSectionI = RNIL;
3457     cachePtr.p->isLongTcKeyReq= true;
3458   }
3459   else
3460   {
3461     jamDebug();
3462     if (unlikely(seizeCacheRecord(signal, cachePtr, apiConnectptr.p) != 0))
3463     {
3464       releaseSections(handle);
3465       TCKEY_abort(signal, 3, apiConnectptr);
3466       return;
3467     }//if
3468     /* If we have any sections at all then this is a long TCKEYREQ */
3469     cachePtr.p->isLongTcKeyReq= false;
3470   }
3471 
3472   CRASH_INSERTION(8063);
3473 
3474   TcConnectRecord * const regTcPtr = tcConnectptr.p;
3475   CacheRecord * const regCachePtr = cachePtr.p;
3476 
3477   /*
3478     INIT_TC_CONNECT_REC
3479     -------------------------
3480   */
3481   /* ---------------------------------------------------------------------- */
3482   /* -------     INIT OPERATION RECORD WITH SIGNAL DATA AND RNILS   ------- */
3483   /*                                                                        */
3484   /* ---------------------------------------------------------------------- */
3485 
3486   UintR Tlqhkeyreqrec = regApiPtr->lqhkeyreqrec;
3487   regApiPtr->lqhkeyreqrec = Tlqhkeyreqrec + 1;
3488 
3489   UintR TapiConnectptrIndex = apiConnectptr.i;
3490   UintR TsenderData = tcKeyReq->senderData;
3491 
3492   if (ERROR_INSERTED(8065))
3493   {
3494     ErrorSignalReceive= DBTC;
3495     ErrorMaxSegmentsToSeize= 10;
3496   }
3497   if (ERROR_INSERTED(8066))
3498   {
3499     ErrorSignalReceive= DBTC;
3500     ErrorMaxSegmentsToSeize= 1;
3501   }
3502   if (ERROR_INSERTED(8067))
3503   {
3504     ErrorSignalReceive= DBTC;
3505     ErrorMaxSegmentsToSeize= 0;
3506   }
3507   if (ERROR_INSERTED(8068))
3508   {
3509     ErrorSignalReceive= 0;
3510     ErrorMaxSegmentsToSeize= 0;
3511     CLEAR_ERROR_INSERT_VALUE;
3512     DEBUG("Max segments to seize cleared");
3513   }
3514 #ifdef ERROR_INSERT
3515   if (ErrorSignalReceive == DBTC)
3516   {
3517     DEBUG("Max segments to seize : "
3518           << ErrorMaxSegmentsToSeize);
3519   }
3520 #endif
3521 
3522   /* Key and attribute lengths are passed in the header for
3523    * short TCKEYREQ and  passed as section lengths for long
3524    * TCKEYREQ
3525    */
3526   UintR TkeyLength = 0;
3527   UintR TattrLen = 0;
3528   UintR titcLenAiInTckeyreq = 0;
3529 
3530   if (likely(regCachePtr->isLongTcKeyReq))
3531   {
3532     SegmentedSectionPtr keyInfoSec;
3533     if (handle.getSection(keyInfoSec, TcKeyReq::KeyInfoSectionNum))
3534       TkeyLength= keyInfoSec.sz;
3535 
3536     SegmentedSectionPtr attrInfoSec;
3537     if (handle.getSection(attrInfoSec, TcKeyReq::AttrInfoSectionNum))
3538       TattrLen= attrInfoSec.sz;
3539 
3540     if (TcKeyReq::getDeferredConstraints(Treqinfo))
3541     {
3542       regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
3543     }
3544 
3545     if (TcKeyReq::getDisableFkConstraints(Treqinfo))
3546     {
3547       regApiPtr->m_flags |= ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS;
3548     }
3549     regCachePtr->m_read_committed_base =
3550                               TcKeyReq::getReadCommittedBaseFlag(Treqinfo);
3551 
3552     regCachePtr->m_noWait = TcKeyReq::getNoWaitFlag(Treqinfo);
3553   }
3554   else
3555   {
3556     TkeyLength = TcKeyReq::getKeyLength(Treqinfo);
3557     TattrLen= TcKeyReq::getAttrinfoLen(tcKeyReq->attrLen);
3558     titcLenAiInTckeyreq = TcKeyReq::getAIInTcKeyReq(Treqinfo);
3559     regCachePtr->m_read_committed_base = 0;
3560     regCachePtr->m_noWait = 0;
3561   }
3562   if (unlikely(refToMain(sendersBlockRef) == DBUTIL))
3563   {
3564     jam();
3565     Tspecial_op_flags |= TcConnectRecord::SOF_UTIL_FLAG;
3566   }
3567   regCachePtr->keylen = TkeyLength;
3568   regCachePtr->lenAiInTckeyreq = titcLenAiInTckeyreq;
3569   regCachePtr->currReclenAi = titcLenAiInTckeyreq;
3570 
3571   regTcPtr->apiConnect = TapiConnectptrIndex;
3572   regTcPtr->clientData = TsenderData;
3573   regTcPtr->commitAckMarker = RNIL;
3574   regTcPtr->m_special_op_flags = Tspecial_op_flags;
3575   regTcPtr->indexOp = regApiPtr->executingIndexOp;
3576   regTcPtr->savePointId = regApiPtr->currSavePointId;
3577   regApiPtr->executingIndexOp = RNIL;
3578 
3579   regApiPtr->singleUserMode |= 1 << localTabptr.p->singleUserMode;
3580 
3581   if (isExecutingTrigger)
3582   {
3583     jamDebug();
3584     // Save the TcOperationPtr for fireing operation
3585     ndbrequire(TsenderData != RNIL);
3586     regTcPtr->triggeringOperation = TsenderData;
3587     // ndbrequire(hasOp(apiConnectptr, TsenderData));
3588 
3589     // Grab trigger Id from ApiConnectRecord
3590     ndbrequire(regApiPtr->immediateTriggerId != RNIL);
3591     regTcPtr->currentTriggerId= regApiPtr->immediateTriggerId;
3592 
3593     Ptr<TcDefinedTriggerData> trigPtr;
3594     c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
3595     trigPtr.p->refCount++;
3596   }
3597 
3598   ndbassert(isExecutingTrigger ||
3599             (regApiPtr->immediateTriggerId == RNIL));
3600 
3601   if (TexecFlag){
3602     const Uint32 currSPId = regApiPtr->currSavePointId;
3603     regApiPtr->currSavePointId = currSPId+1;
3604   }
3605 
3606   regCachePtr->attrlength = TattrLen;
3607   c_counters.cattrinfoCount += TattrLen;
3608 
3609   UintR TtabptrIndex = localTabptr.i;
3610   UintR TtableSchemaVersion = tcKeyReq->tableSchemaVersion;
3611   Uint8 TOperationType = TcKeyReq::getOperationType(Treqinfo);
3612   regCachePtr->tableref = TtabptrIndex;
3613   regCachePtr->schemaVersion = TtableSchemaVersion;
3614   regTcPtr->operation = TOperationType;
3615 
3616   Uint8 TSimpleFlag         = TcKeyReq::getSimpleFlag(Treqinfo);
3617   Uint8 TDirtyFlag          = TcKeyReq::getDirtyFlag(Treqinfo);
3618   Uint8 TInterpretedFlag    = TcKeyReq::getInterpretedFlag(Treqinfo);
3619   Uint8 TDistrKeyFlag       = TcKeyReq::getDistributionKeyFlag(Treqinfo);
3620   Uint8 TNoDiskFlag         = TcKeyReq::getNoDiskFlag(Treqinfo);
3621 
3622   regTcPtr->dirtyOp  = TDirtyFlag;
3623   regTcPtr->opSimple = TSimpleFlag;
3624   regCachePtr->opExec   = TInterpretedFlag;
3625   regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
3626   regCachePtr->m_no_disk_flag = TNoDiskFlag;
3627 
3628   Uint8 TexecuteFlag        = TexecFlag;
3629   Uint8 Treorg              = TcKeyReq::getReorgFlag(Treqinfo);
3630   if (unlikely(Treorg))
3631   {
3632     if (TOperationType == ZWRITE)
3633       regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_COPY;
3634     else if (TOperationType == ZDELETE)
3635       regTcPtr->m_special_op_flags = TcConnectRecord::SOF_REORG_DELETE;
3636     else
3637     {
3638       ndbassert(false);
3639     }
3640   }
3641 
3642   const Uint8 TViaSPJFlag   = TcKeyReq::getViaSPJFlag(Treqinfo);
3643   const Uint8 Tqueue        = TcKeyReq::getQueueOnRedoProblemFlag(Treqinfo);
3644 
3645   regCachePtr->viaSPJFlag = TViaSPJFlag;
3646   regCachePtr->m_op_queue = Tqueue;
3647 
3648   //-------------------------------------------------------------
3649   // The next step is to read the upto three conditional words.
3650   //-------------------------------------------------------------
3651   Uint32 TkeyIndex;
3652   Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
3653   {
3654     Uint32  TDistrGHIndex    = TcKeyReq::getScanIndFlag(Treqinfo);
3655     Uint32  TDistrKeyIndex   = TDistrGHIndex;
3656 
3657     Uint32 TscanInfo = TcKeyReq::getTakeOverScanInfo(TOptionalDataPtr[0]);
3658 
3659     regCachePtr->scanTakeOverInd = TDistrGHIndex;
3660     regCachePtr->scanInfo = TscanInfo;
3661 
3662     regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
3663 
3664     TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
3665   }
3666 
3667   regCachePtr->m_no_hash = false;
3668 
3669   if (unlikely(TOperationType == ZUNLOCK))
3670   {
3671     /* Unlock op has distribution key containing
3672      * LQH nodeid and fragid
3673      */
3674     ndbassert( regCachePtr->distributionKeyIndicator );
3675     regCachePtr->m_no_hash = 1;
3676     regCachePtr->unlockNodeId = (regCachePtr->distributionKey >> 16);
3677     regCachePtr->distributionKey &= 0xffff;
3678   }
3679 
3680   regCachePtr->m_special_hash =
3681     localTabptr.p->hasCharAttr |
3682     (localTabptr.p->noOfDistrKeys > 0) |
3683     regCachePtr->m_no_hash;
3684 
3685   if (unlikely(TkeyLength == 0))
3686   {
3687     releaseSections(handle);
3688     TCKEY_abort(signal, 4, apiConnectptr);
3689     return;
3690   }
3691 
3692   /* KeyInfo and AttrInfo are buffered in segmented sections
3693    * If they arrived in segmented sections then there's nothing to do
3694    * If they arrived in short signals then they are appended into
3695    * segmented sections
3696    */
3697   if (likely(regCachePtr->isLongTcKeyReq))
3698   {
3699     ndbassert( titcLenAiInTckeyreq == 0);
3700     /* Long TcKeyReq - KI and AI already in sections */
3701     SegmentedSectionPtr keyInfoSection, attrInfoSection;
3702 
3703     /* Store i value for first long section of KeyInfo
3704      * and AttrInfo in Cache Record
3705      */
3706     handle.getSection(keyInfoSection,
3707                       TcKeyReq::KeyInfoSectionNum);
3708 
3709     regCachePtr->keyInfoSectionI= keyInfoSection.i;
3710 
3711     if (regCachePtr->attrlength != 0)
3712     {
3713       ndbassert( handle.m_cnt == 2 );
3714       handle.getSection(attrInfoSection,
3715                         TcKeyReq::AttrInfoSectionNum);
3716       regCachePtr->attrInfoSectionI= attrInfoSection.i;
3717     }
3718     else
3719     {
3720       ndbassert( handle.m_cnt == 1 );
3721     }
3722 
3723     /* Detach sections from the handle, we are now responsible
3724      * for always freeing them before returning
3725      * For a long TcKeyReq, they will be freed at the end
3726      * of the processing this signal.
3727      */
3728     handle.clear();
3729   }
3730   else
3731   {
3732     /* Short TcKeyReq - need to receive KI and AI into
3733      * segmented sections
3734      * We store any KI and AI from the TCKeyReq now and
3735      * will then wait for further signals if necessary
3736      */
3737     ndbassert( handle.m_cnt == 0 );
3738     Uint32 keyInfoInTCKeyReq= MIN(TkeyLength, TcKeyReq::MaxKeyInfo);
3739 
3740     bool ok= appendToSection(regCachePtr->keyInfoSectionI,
3741                              &TOptionalDataPtr[TkeyIndex],
3742                              keyInfoInTCKeyReq);
3743     if (!ok)
3744     {
3745       jam();
3746       appendToSectionErrorLab(signal, apiConnectptr);
3747       return;
3748     }
3749 
3750     if (titcLenAiInTckeyreq != 0)
3751     {
3752       Uint32 TAIDataIndex= TkeyIndex + keyInfoInTCKeyReq;
3753 
3754       ok= appendToSection(regCachePtr->attrInfoSectionI,
3755                           &TOptionalDataPtr[TAIDataIndex],
3756                           titcLenAiInTckeyreq);
3757       if (!ok)
3758       {
3759         jam();
3760         appendToSectionErrorLab(signal, apiConnectptr);
3761         return;
3762       }
3763     }
3764   }
3765 
3766   if (unlikely(TOperationType == ZUNLOCK))
3767   {
3768     jam();
3769     // TODO : Consider adding counter for unlock operations
3770   }
3771   else if (TOperationType == ZREAD || TOperationType == ZREAD_EX) {
3772     jam();
3773     c_counters.creadCount++;
3774     if (regTcPtr->opSimple == ZFALSE)
3775     {
3776       jam();
3777       if (unlikely(m_concurrent_overtakeable_operations >=
3778                    m_take_over_operations))
3779       {
3780         jam();
3781         TCKEY_abort(signal, 65, apiConnectptr);
3782         return;
3783       }
3784       regTcPtr->m_overtakeable_operation = 1;
3785       m_concurrent_overtakeable_operations++;
3786     }
3787   }
3788   else
3789   {
3790     /**
3791      * Insert, Update, Write, Delete
3792      * Markers are created on all nodes in a nodegroup
3793      * (as changes affect all replicas)
3794      * Therefore any survivable node failure will have a live
3795      * node with a marker for any marked write transaction.
3796      * Therefore only need one nodegroup marked - after that
3797      * needn't bother.
3798      */
3799     if (!tc_testbit(regApiPtr->m_flags,
3800                     ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED))
3801     {
3802       if(regApiPtr->commitAckMarker != RNIL)
3803         regTcPtr->commitAckMarker = regApiPtr->commitAckMarker;
3804       else
3805       {
3806         jam();
3807         CommitAckMarkerPtr tmp;
3808         if (ERROR_INSERTED(8087))
3809         {
3810           CLEAR_ERROR_INSERT_VALUE;
3811           TCKEY_abort(signal, 56, apiConnectptr);
3812           return;
3813         }
3814 
3815         if (unlikely(!m_commitAckMarkerPool.seize(tmp)))
3816         {
3817           TCKEY_abort(signal, 56, apiConnectptr);
3818           return;
3819         }
3820         else
3821         {
3822           regTcPtr->commitAckMarker = tmp.i;
3823           regApiPtr->commitAckMarker = tmp.i;
3824           tmp.p->transid1      = tcKeyReq->transId1;
3825           tmp.p->transid2      = tcKeyReq->transId2;
3826           tmp.p->apiNodeId     = refToNode(regApiPtr->ndbapiBlockref);
3827           tmp.p->apiConnectPtr = TapiIndex;
3828 #if defined VM_TRACE || defined ERROR_INSERT
3829 	  {
3830 	    CommitAckMarkerPtr check;
3831 	    ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
3832           }
3833 #endif
3834           m_commitAckMarkerHash.add(tmp);
3835         }
3836       }
3837       regApiPtr->num_commit_ack_markers++;
3838     }
3839 
3840     UintR Toperationsize = coperationsize;
3841     /* --------------------------------------------------------------------
3842      *   THIS IS A TEMPORARY TABLE, DON'T UPDATE coperationsize.
3843      *   THIS VARIABLE CONTROLS THE INTERVAL BETWEEN LCP'S AND
3844      *   TEMP TABLES DON'T PARTICIPATE.
3845      * -------------------------------------------------------------------- */
3846     if (localTabptr.p->get_storedTable()) {
3847       coperationsize = ((Toperationsize + TattrLen) + TkeyLength) + 17;
3848     }
3849     c_counters.cwriteCount++;
3850     switch (TOperationType) {
3851     case ZUPDATE:
3852     case ZINSERT:
3853     case ZDELETE:
3854     case ZWRITE:
3855     case ZREFRESH:
3856       jam();
3857       regApiPtr->m_write_count++;
3858       if (unlikely(regApiPtr->m_flags &
3859                    ApiConnectRecord::TF_DEFERRED_CONSTRAINTS))
3860       {
3861         /**
3862          * Allow slave applier to ignore m_max_writes_per_trans
3863          */
3864         if (unlikely(regApiPtr->m_write_count > m_take_over_operations))
3865         {
3866           jam();
3867           TCKEY_abort(signal, 65, apiConnectptr);
3868           return;
3869         }
3870       }
3871       else if (unlikely(regApiPtr->m_write_count > m_max_writes_per_trans))
3872       {
3873         jam();
3874         TCKEY_abort(signal, 65, apiConnectptr);
3875         return;
3876       }
3877       if (unlikely(m_concurrent_overtakeable_operations >=
3878                    m_take_over_operations))
3879       {
3880         jam();
3881         TCKEY_abort(signal, 65, apiConnectptr);
3882         return;
3883       }
3884       regTcPtr->m_overtakeable_operation = 1;
3885       m_concurrent_overtakeable_operations++;
3886       break;
3887     default:
3888       TCKEY_abort(signal, 9, apiConnectptr);
3889       return;
3890     }//switch
3891   }//if
3892 
3893   Uint32 TabortOption = TcKeyReq::getAbortOption(Treqinfo);
3894   regTcPtr->m_execAbortOption = TabortOption;
3895 
3896   /*-------------------------------------------------------------------------
3897    * Check error handling per operation
3898    * If CommitFlag is set state accordingly and check for early abort
3899    *------------------------------------------------------------------------*/
3900   if (TcKeyReq::getCommitFlag(Treqinfo) == 1) {
3901     ndbrequire(TexecuteFlag);
3902     regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3903   } else {
3904     /* ---------------------------------------------------------------------
3905      *       PREPARE TRANSACTION IS NOT IMPLEMENTED YET.
3906      * ---------------------------------------------------------------------
3907      *       ELSIF (TREQINFO => 3) (*) 1 = 1 THEN
3908      * IF PREPARE TRANSACTION THEN
3909      *   API_CONNECTPTR:API_CONNECTSTATE = REC_PREPARING
3910      * SET STATE TO PREPARING
3911      * --------------------------------------------------------------------- */
3912     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
3913       jam();
3914       // Trigger execution at commit
3915       regApiPtr->apiConnectstate = CS_REC_COMMITTING;
3916     } else if (!regApiPtr->isExecutingDeferredTriggers()) {
3917       jam();
3918       regApiPtr->apiConnectstate = CS_RECEIVING;
3919     }//if
3920   }//if
3921 
3922   if (likely(regCachePtr->isLongTcKeyReq))
3923   {
3924     jamDebug();
3925     /* Have all the KeyInfo (and AttrInfo), process now */
3926     tckeyreq050Lab(signal, cachePtr, apiConnectptr);
3927   }
3928   else if (TkeyLength <= TcKeyReq::MaxKeyInfo)
3929   {
3930     jam();
3931     /* Have all the KeyInfo, get any extra AttrInfo */
3932     tckeyreq050Lab(signal, cachePtr, apiConnectptr);
3933   }
3934   else
3935   {
3936     jam();
3937     /* --------------------------------------------------------------------
3938      * THE TCKEYREQ DIDN'T CONTAIN ALL KEY DATA,
3939      * SAVE STATE AND WAIT FOR KEYINFO
3940      * --------------------------------------------------------------------*/
3941     setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
3942     regCachePtr->save1 = 8;
3943     regTcPtr->tcConnectstate = OS_WAIT_KEYINFO;
3944     return;
3945   }//if
3946 
3947   return;
3948 }//Dbtc::execTCKEYREQ()
3949 
3950 static
3951 void
handle_reorg_trigger(DiGetNodesConf * conf)3952 handle_reorg_trigger(DiGetNodesConf * conf)
3953 {
3954   if (conf->reqinfo & DiGetNodesConf::REORG_MOVING)
3955   {
3956     conf->fragId = conf->nodes[MAX_REPLICAS];
3957     conf->reqinfo = conf->nodes[MAX_REPLICAS+1];
3958     memcpy(conf->nodes, conf->nodes+MAX_REPLICAS+2,
3959            sizeof(Uint32)*MAX_REPLICAS);
3960   }
3961   else
3962   {
3963     conf->nodes[0] = 0; // Should not execute...
3964   }
3965 }
3966 
3967 /**
3968  * This method comes in with a list of nodes.
3969  * We have already verified that our own node
3970  * isn't in this list. If we have a node in this
3971  * list that is in the same location domain as
3972  * this node, it will be selected before any
3973  * other node. So we will always try to keep
3974  * the read coming from the same location domain.
3975  *
3976  * To avoid radical imbalances we provide a bit
3977  * of round robin on a node bases. It isn't
3978  * any perfect round robin. We simply rotate a
3979  * bit among the selected nodes instead of
3980  * always selecting the first one we find.
3981  */
3982 Uint32
check_own_location_domain(Uint16 * nodes,Uint32 end)3983 Dbtc::check_own_location_domain(Uint16 *nodes,
3984                                 Uint32 end)
3985 {
3986   Uint32 loc_nodes[MAX_NDB_NODES];
3987   Uint32 loc_node_count = 0;
3988   Uint32 my_location_domain_id = m_my_location_domain_id;
3989 
3990   if (my_location_domain_id == 0)
3991   {
3992     jam();
3993     return 0;
3994   }
3995   for (Uint32 i = 0; i < end; i++)
3996   {
3997     jam();
3998     Uint32 node = nodes[i];
3999     HostRecordPtr Tnode_hostptr;
4000     Tnode_hostptr.i = node;
4001     ptrCheckGuard(Tnode_hostptr, chostFilesize, hostRecord);
4002     if (my_location_domain_id ==
4003         Tnode_hostptr.p->m_location_domain_id)
4004     {
4005       jam();
4006       loc_nodes[loc_node_count++] = node;
4007     }
4008   }
4009   if (loc_node_count > 0)
4010   {
4011     return loc_nodes[m_load_balancer_location++ % loc_node_count];
4012   }
4013   return 0;
4014 }
4015 
4016 /**
4017  * tckeyreq050Lab
4018  * This method is executed once all KeyInfo has been obtained for
4019  * the TcKeyReq signal
4020  */
tckeyreq050Lab(Signal * signal,CacheRecordPtr const cachePtr,ApiConnectRecordPtr const apiConnectptr)4021 void Dbtc::tckeyreq050Lab(Signal* signal, CacheRecordPtr const cachePtr, ApiConnectRecordPtr const apiConnectptr)
4022 {
4023   CacheRecord* const regCachePtr = cachePtr.p;
4024   UintR tnoOfBackup;
4025   UintR tnoOfStandby;
4026 
4027   terrorCode = 0;
4028 
4029   hash(signal, regCachePtr); /* NOW IT IS TIME TO CALCULATE THE HASH VALUE*/
4030 
4031   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4032   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4033 
4034   UintR TtcTimer = ctcTimer;
4035   UintR ThashValue = thashValue;
4036   UintR TdistrHashValue = tdistrHashValue;
4037   UintR Ttableref = regCachePtr->tableref;
4038   Uint16 Tspecial_op_flags = regTcPtr->m_special_op_flags;
4039 
4040   TableRecordPtr localTabptr;
4041   localTabptr.i = Ttableref;
4042   localTabptr.p = &tableRecord[localTabptr.i];
4043   Uint32 schemaVersion = regCachePtr->schemaVersion;
4044   if (likely(localTabptr.p->checkTable(schemaVersion)))
4045   {
4046     ;
4047   } else {
4048     terrorCode = localTabptr.p->getErrorCode(schemaVersion);
4049     TCKEY_abort(signal, 58, apiConnectptr);
4050     return;
4051   }
4052 
4053   setApiConTimer(apiConnectptr, TtcTimer, __LINE__);
4054   regCachePtr->hashValue = ThashValue;
4055 
4056   ndbassert( signal->getNoOfSections() == 0 );
4057 
4058   DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
4059   req->tableId = Ttableref;
4060   req->hashValue = TdistrHashValue;
4061   req->distr_key_indicator = regCachePtr->distributionKeyIndicator;
4062   req->scan_indicator = 0;
4063   req->anyNode = 0;
4064   req->get_next_fragid_indicator = 0;
4065   req->jamBufferPtr = jamBuffer();
4066 
4067   if (localTabptr.p->m_flags & TableRecord::TR_FULLY_REPLICATED)
4068   {
4069     if (regTcPtr->operation == ZREAD)
4070     {
4071       /**
4072        * inform DIH if TreadAny is even relevent...so it does not have to loop
4073        *   unless really needing to...
4074        */
4075       if (regTcPtr->dirtyOp || regTcPtr->opSimple ||
4076           regCachePtr->m_read_committed_base)
4077       {
4078         jam();
4079         req->anyNode = 1;
4080       }
4081     }
4082     else if (Tspecial_op_flags & TcConnectRecord::SOF_REORG_COPY)
4083     {
4084       /**
4085        * We want DIH to return the first new fragment, this is a copy
4086        * of the row, it has been read from a main fragment and needs
4087        * to be copied to the new fragments. We get the first new
4088        * fragment and trust the fully replicated triggers to ensure
4089        * that any more new fragments are also written using the
4090        * iterator on the fully replicated trigger.
4091        */
4092       jam();
4093       regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_COPY;
4094       req->anyNode = 2;
4095     }
4096     else if (Tspecial_op_flags & TcConnectRecord::SOF_FULLY_REPLICATED_TRIGGER)
4097     {
4098       jam();
4099       req->anyNode = 3;
4100     }
4101   }
4102 
4103   /*-------------------------------------------------------------*/
4104   /* FOR EFFICIENCY REASONS WE AVOID THE SIGNAL SENDING HERE AND */
4105   /* PROCEED IMMEDIATELY TO DIH. IN MULTI-THREADED VERSIONS WE   */
4106   /* HAVE TO INSERT A MUTEX ON DIH TO ENSURE PROPER OPERATION.   */
4107   /* SINCE THIS SIGNAL AND DIVERIFYREQ ARE THE ONLY SIGNALS SENT */
4108   /* TO DIH IN TRAFFIC IT SHOULD BE OK (3% OF THE EXECUTION TIME */
4109   /* IS SPENT IN DIH AND EVEN LESS IN REPLICATED NDB.            */
4110   /*-------------------------------------------------------------*/
4111   EXECUTE_DIRECT_MT(DBDIH, GSN_DIGETNODESREQ, signal,
4112                     DiGetNodesReq::SignalLength, 0);
4113   DiGetNodesConf * conf = (DiGetNodesConf *)&signal->theData[0];
4114   UintR Tdata2 = conf->reqinfo;
4115   UintR TerrorIndicator = signal->theData[0];
4116   jamEntry();
4117   if (unlikely(TerrorIndicator != 0))
4118   {
4119     execDIGETNODESREF(signal, apiConnectptr);
4120     return;
4121   }
4122 
4123   /****************>>*/
4124   /* DIGETNODESCONF >*/
4125   /* ***************>*/
4126   Tspecial_op_flags = regTcPtr->m_special_op_flags;
4127   if (unlikely(Tspecial_op_flags & TcConnectRecord::SOF_REORG_TRIGGER))
4128   {
4129     if (conf->reqinfo & DiGetNodesConf::REORG_MOVING &&
4130         (conf->nodes[MAX_REPLICAS] == regApiPtr->firedFragId))
4131     {
4132       jam();
4133       /**
4134        * The new fragment id is what we already written. This can happen
4135        * if the change of table distribution between the first write and
4136        * the triggered write that comes here. We will swap and instead
4137        * write the now original fragment which is really the new
4138        * fragment.
4139        */
4140       Tdata2 = conf->reqinfo & (~DiGetNodesConf::REORG_MOVING);
4141     }
4142     else
4143     {
4144       jam();
4145       handle_reorg_trigger(conf);
4146       Tdata2 = conf->reqinfo;
4147     }
4148     /**
4149      * Ensure that firedFragId is restored to RNIL to ensure it has a defined
4150      * value when not used.
4151      */
4152     regApiPtr->firedFragId = RNIL;
4153   }
4154   else if (unlikely(Tspecial_op_flags & TcConnectRecord::SOF_REORG_DELETE))
4155   {
4156     jam();
4157     handle_reorg_trigger(conf);
4158     Tdata2 = conf->reqinfo;
4159   }
4160   else if (unlikely(Tdata2 & DiGetNodesConf::REORG_MOVING))
4161   {
4162     jam();
4163     regTcPtr->m_special_op_flags |= TcConnectRecord::SOF_REORG_MOVING;
4164   }
4165   else if (unlikely(Tspecial_op_flags & TcConnectRecord::SOF_REORG_COPY))
4166   {
4167     jam();
4168     conf->nodes[0] = 0;
4169   }
4170 
4171   UintR Tdata1 = conf->fragId;
4172   UintR Tdata3 = conf->nodes[0];
4173   UintR Tdata4 = conf->nodes[1];
4174   UintR Tdata5 = conf->nodes[2];
4175   UintR Tdata6 = conf->nodes[3];
4176 
4177   regCachePtr->fragmentid = Tdata1;
4178   Uint32 tnodeinfo = Tdata2;
4179 
4180   regTcPtr->tcNodedata[0] = Tdata3;
4181   regTcPtr->tcNodedata[1] = Tdata4;
4182   regTcPtr->tcNodedata[2] = Tdata5;
4183   regTcPtr->tcNodedata[3] = Tdata6;
4184 
4185   regTcPtr->lqhInstanceKey = (Tdata2 >> 24) & 127;// 1 bit used for reorg moving
4186 
4187   tnoOfBackup = tnodeinfo & 3;
4188   tnoOfStandby = (tnodeinfo >> 8) & 3;
4189   Uint8 Toperation = regTcPtr->operation;
4190 
4191   regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
4192   Uint32 TreadBackup = (localTabptr.p->m_flags & TableRecord::TR_READ_BACKUP);
4193   if (Toperation == ZREAD || Toperation == ZREAD_EX)
4194   {
4195     Uint8 TopSimple = regTcPtr->opSimple;
4196     Uint8 TopDirty = regTcPtr->dirtyOp;
4197     bool checkingFKConstraint = Tspecial_op_flags & TcConnectRecord::SOF_TRIGGER;
4198 
4199     regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
4200     /**
4201      * As an optimization, we may read from a local backup replica
4202      * instead of from the remote primary replica...if:
4203      * 1) Simple-read, since this will wait in lock queue for any pending
4204      *    commit/complete
4205      * 2) Simple/CommittedRead if TreadBackup-table property is set
4206      *    (since transactions updating such table will wait with sending API
4207      *    commit until complete-phase has been run)
4208      * 3) Locking reads that have signalled that they have had their locks
4209      *    upgraded due to being read of a base table of BLOB table or
4210      *    reads of unique key for Committed reads.
4211      *
4212      * Note that if the operation is part of verifying a FK-constraint,
4213      * the primary replica has to be used in order to avoid races where
4214      * an update of the primary replica has not reached backup replicas
4215      * when the constraint is verified.
4216      */
4217     if (regTcPtr->tcNodedata[0] != cownNodeid &&  // Primary replica is remote, and
4218         !checkingFKConstraint &&                  // Not verifying a FK-constraint.
4219         ((TopSimple != 0 && TopDirty == 0) ||                        // 1)
4220          (TreadBackup != 0 && (TopSimple != 0 || TopDirty != 0)) ||  // 2)
4221          (TreadBackup != 0 && regCachePtr->m_read_committed_base)))  // 3)
4222     {
4223       jam();
4224       /*-------------------------------------------------------------*/
4225       /*       A SIMPLE READ CAN SELECT ANY OF THE PRIMARY AND       */
4226       /*       BACKUP NODES TO READ. WE WILL TRY TO SELECT THIS      */
4227       /*       NODE IF POSSIBLE TO AVOID UNNECESSARY COMMUNICATION   */
4228       /*       WITH SIMPLE READS.                                    */
4229       /*-------------------------------------------------------------*/
4230       arrGuard(tnoOfBackup, MAX_REPLICAS);
4231       UintR Tindex;
4232       UintR TownNode = cownNodeid;
4233       bool foundOwnNode = false;
4234       for (Tindex = 1; Tindex <= tnoOfBackup; Tindex++) {
4235         UintR Tnode = regTcPtr->tcNodedata[Tindex];
4236         jam();
4237         if (Tnode == TownNode) {
4238           jam();
4239           regTcPtr->tcNodedata[0] = Tnode;
4240           foundOwnNode = true;
4241         }//if
4242       }//for
4243       if (!foundOwnNode)
4244       {
4245         Uint32 node;
4246         jam();
4247         if ((node = check_own_location_domain(&regTcPtr->tcNodedata[0],
4248                                               tnoOfBackup+1)) != 0)
4249         {
4250           regTcPtr->tcNodedata[0] = node;
4251         }
4252       }
4253       if(ERROR_INSERTED(8048) || ERROR_INSERTED(8049))
4254       {
4255 	for (Tindex = 0; Tindex <= tnoOfBackup; Tindex++)
4256 	{
4257 	  UintR Tnode = regTcPtr->tcNodedata[Tindex];
4258 	  jam();
4259 	  if (Tnode != TownNode) {
4260 	    jam();
4261 	    regTcPtr->tcNodedata[0] = Tnode;
4262 	    ndbout_c("Choosing %d", Tnode);
4263 	  }//if
4264 	}//for
4265       }
4266     }//if
4267     jam();
4268     regTcPtr->lastReplicaNo = 0;
4269     regTcPtr->noOfNodes = 1;
4270 
4271     if (regTcPtr->tcNodedata[0] == getOwnNodeId())
4272       c_counters.clocalReadCount++;
4273 #ifdef ERROR_INSERT
4274     else if (ERROR_INSERTED(8083))
4275     {
4276       ndbabort();  // Only node-local reads
4277     }
4278 #endif
4279   }
4280   else if (unlikely(Toperation == ZUNLOCK))
4281   {
4282     regTcPtr->m_special_op_flags &= ~TcConnectRecord::SOF_REORG_MOVING;
4283 
4284     const Uint32 numNodes = tnoOfBackup + 1;
4285     /* Check that node from dist key is one of the nodes returned */
4286     bool found = false;
4287     for (Uint32 idx = 0; idx < numNodes; idx ++)
4288     {
4289       NodeId nodeId = regTcPtr->tcNodedata[ idx ];
4290       jam();
4291       if (nodeId == regCachePtr->unlockNodeId)
4292       {
4293         jam();
4294         found = true;
4295         break;
4296       }
4297     }
4298 
4299     if (unlikely(!found))
4300     {
4301       /* DIH says the specified node does not store the fragment
4302        * requested
4303        */
4304       jam();
4305       TCKEY_abort(signal, 64, apiConnectptr);
4306       return;
4307     }
4308 
4309     /* Select the specified node for the unlock op */
4310     regTcPtr->tcNodedata[0] = regCachePtr->unlockNodeId;
4311     regTcPtr->lastReplicaNo = 0;
4312     regTcPtr->noOfNodes = 1;
4313   }
4314   else
4315   {
4316     UintR TlastReplicaNo;
4317     jam();
4318     TlastReplicaNo = tnoOfBackup + tnoOfStandby;
4319     regTcPtr->lastReplicaNo = (Uint8)TlastReplicaNo;
4320     regTcPtr->noOfNodes = (Uint8)(TlastReplicaNo + 1);
4321     if (regTcPtr->tcNodedata[0] == getOwnNodeId())
4322       c_counters.clocalWriteCount++;
4323 
4324     if ((localTabptr.p->m_flags & TableRecord::TR_DELAY_COMMIT) != 0)
4325     {
4326       jam();
4327       /**
4328        * Set TF_LATE_COMMIT transaction property if INS/UPD/DEL is performed
4329        *   when running with readBackup property set.
4330        *
4331        * This causes api-commit to be sent after complete-phase has been run
4332        * (instead of when commit phase has run, but complete-phase has not yet
4333        * started)
4334        */
4335       regApiPtr->m_flags |= ApiConnectRecord::TF_LATE_COMMIT;
4336     }
4337   }//if
4338 
4339   if((ERROR_INSERTED(8071) || ERROR_INSERTED(8072)) &&
4340      (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) &&
4341      regTcPtr->tcNodedata[0] != getOwnNodeId())
4342   {
4343     ndbassert(false);
4344     signal->theData[1] = 626;
4345     execDIGETNODESREF(signal, apiConnectptr);
4346     return;
4347   }
4348 
4349   if((ERROR_INSERTED(8050) || ERROR_INSERTED(8072)) &&
4350      refToBlock(regApiPtr->ndbapiBlockref) != DBUTIL &&
4351      regTcPtr->m_special_op_flags == 0 &&
4352      (regTcPtr->tcNodedata[0] != getOwnNodeId()))
4353   {
4354     ndbassert(false);
4355     signal->theData[1] = 626;
4356     execDIGETNODESREF(signal, apiConnectptr);
4357     return;
4358   }
4359 
4360   if (likely(regCachePtr->isLongTcKeyReq ||
4361             (regCachePtr->lenAiInTckeyreq == regCachePtr->attrlength)))
4362   {
4363     /****************************************************************>*/
4364     /* HERE WE HAVE FOUND THAT THE LAST SIGNAL BELONGING TO THIS      */
4365     /* OPERATION HAVE BEEN RECEIVED. THIS MEANS THAT WE CAN NOW REUSE */
4366     /* THE API CONNECT RECORD. HOWEVER IF PREPARE OR COMMIT HAVE BEEN */
4367     /* RECEIVED THEN IT IS NOT ALLOWED TO RECEIVE ANY FURTHER         */
4368     /* OPERATIONS. WE KNOW THAT WE WILL WAIT FOR DICT NEXT. IT IS NOT */
4369     /* POSSIBLE FOR THE TC CONNECTION TO BE READY YET.                */
4370     /****************************************************************>*/
4371     switch (regApiPtr->apiConnectstate) {
4372     case CS_RECEIVING:
4373       jam();
4374       regApiPtr->apiConnectstate = CS_STARTED;
4375       break;
4376     case CS_REC_COMMITTING:
4377       jam();
4378       regApiPtr->apiConnectstate = CS_START_COMMITTING;
4379       break;
4380     case CS_SEND_FIRE_TRIG_REQ:
4381     case CS_WAIT_FIRE_TRIG_REQ:
4382       jam();
4383       break;
4384     default:
4385       jam();
4386       systemErrorLab(signal, __LINE__);
4387       return;
4388     }//switch
4389     attrinfoDihReceivedLab(signal, cachePtr, apiConnectptr);
4390     return;
4391   }
4392   else
4393   {
4394     if (regCachePtr->lenAiInTckeyreq < regCachePtr->attrlength)
4395     {
4396       TtcTimer = ctcTimer;
4397       jam();
4398       setApiConTimer(apiConnectptr, TtcTimer, __LINE__);
4399       regTcPtr->tcConnectstate = OS_WAIT_ATTR;
4400       return;
4401     }
4402     else
4403     {
4404       TCKEY_abort(signal, 11, apiConnectptr);
4405       return;
4406     }//if
4407   }//if
4408   return;
4409 }//Dbtc::tckeyreq050Lab()
4410 
attrinfoDihReceivedLab(Signal * signal,CacheRecordPtr cachePtr,ApiConnectRecordPtr const apiConnectptr)4411 void Dbtc::attrinfoDihReceivedLab(Signal* signal, CacheRecordPtr cachePtr, ApiConnectRecordPtr const apiConnectptr)
4412 {
4413   CacheRecord * const regCachePtr = cachePtr.p;
4414   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4415   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4416   Uint16 Tnode = regTcPtr->tcNodedata[0];
4417 
4418   TableRecordPtr localTabptr;
4419   localTabptr.i = regCachePtr->tableref;
4420   localTabptr.p = &tableRecord[localTabptr.i];
4421 
4422   if (likely(localTabptr.p->checkTable(regCachePtr->schemaVersion)))
4423   {
4424     ;
4425   } else {
4426     terrorCode = localTabptr.p->getErrorCode(regCachePtr->schemaVersion);
4427     TCKEY_abort(signal, 58, apiConnectptr);
4428     return;
4429   }
4430   if (likely(Tnode != 0))
4431   {
4432     jam();
4433     arrGuard(Tnode, MAX_NDB_NODES);
4434     BlockReference lqhRef;
4435     if (regCachePtr->viaSPJFlag)
4436     {
4437       if (Tnode == getOwnNodeId())
4438       {
4439         //Node local req; send to SPJ-instance in own block-thread
4440         lqhRef = numberToRef(DBSPJ, instance(), Tnode);
4441       }
4442       else
4443       {
4444         /* Round robin the SPJ requests:
4445          *
4446          * Note that our protocol allows non existing block instances
4447          * to be adressed, in which case the receiver will modulo fold
4448          * among the existing SPJ instances.
4449          * Distribute among 120 'virtual' SPJ blocks as this is dividable
4450          * by most commom number of SPJ blocks (1,2,3,4,5,6,8,10...)
4451          */
4452         const Uint32 blockInstance = (cspjInstanceRR++ % 120) + 1;
4453         lqhRef = numberToRef(DBSPJ, blockInstance, Tnode);
4454       }
4455     }
4456     else
4457     {
4458       const Uint32 instanceKey = regTcPtr->lqhInstanceKey;
4459       lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
4460     }
4461     packLqhkeyreq(signal, lqhRef, cachePtr, apiConnectptr);
4462   }
4463   else
4464   {
4465     /**
4466      * 1) This is when a reorg trigger fired...
4467      *   but the tuple should *not* move
4468      *   This should be prevented using the LqhKeyReq::setReorgFlag
4469      *
4470      * 2) This also happens during reorg copy, when a row should *not* be moved
4471      */
4472     jam();
4473     Uint32 trigOp = regTcPtr->triggeringOperation;
4474     Uint32 TclientData = regTcPtr->clientData;
4475     releaseKeys(regCachePtr);
4476     releaseAttrinfo(cachePtr, apiConnectptr.p);
4477     regApiPtr->lqhkeyreqrec--;
4478     unlinkReadyTcCon(apiConnectptr.p);
4479     clearCommitAckMarker(regApiPtr, regTcPtr);
4480     releaseTcCon();
4481     checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
4482                         tcConnectRecord);
4483 
4484     if (trigOp != RNIL)
4485     {
4486       jam();
4487       //ndbassert(false); // see above
4488       TcConnectRecordPtr opPtr;
4489       opPtr.i = trigOp;
4490       tcConnectRecord.getPtr(opPtr);
4491       ndbrequire(apiConnectptr.p->m_executing_trigger_ops > 0);
4492       apiConnectptr.p->m_executing_trigger_ops--;
4493       trigger_op_finished(signal, apiConnectptr, RNIL, opPtr.p, 0);
4494 
4495       ApiConnectRecordPtr transPtr = apiConnectptr;
4496       executeTriggers(signal, &transPtr);
4497 
4498       return;
4499     }
4500     else
4501     {
4502       jam();
4503       Uint32 Ttckeyrec = regApiPtr->tckeyrec;
4504       regApiPtr->tcSendArray[Ttckeyrec] = TclientData;
4505       regApiPtr->tcSendArray[Ttckeyrec + 1] = 0;
4506       regApiPtr->tckeyrec = Ttckeyrec + 2;
4507       lqhKeyConf_checkTransactionState(signal, apiConnectptr);
4508     }
4509   }
4510 }//Dbtc::attrinfoDihReceivedLab()
4511 
packLqhkeyreq(Signal * signal,BlockReference TBRef,CacheRecordPtr cachePtr,ApiConnectRecordPtr const apiConnectptr)4512 void Dbtc::packLqhkeyreq(Signal* signal,
4513                          BlockReference TBRef,
4514                          CacheRecordPtr cachePtr,
4515                          ApiConnectRecordPtr const apiConnectptr)
4516 {
4517   CacheRecord * const regCachePtr = cachePtr.p;
4518   UintR Tkeylen = regCachePtr->keylen;
4519 
4520   ndbassert( signal->getNoOfSections() == 0 );
4521 
4522   ApiConnectRecord* const regApiPtr = apiConnectptr.p;
4523   sendlqhkeyreq(signal, TBRef, regCachePtr, regApiPtr);
4524 
4525   /* Do we need to send a KeyInfo signal train? */
4526   if (unlikely((! regCachePtr->useLongLqhKeyReq) &&
4527                (Tkeylen > LqhKeyReq::MaxKeyInfo)))
4528   {
4529     /* Build KeyInfo train from KeyInfo long signal section */
4530     sendKeyInfoTrain(signal,
4531                      TBRef,
4532                      tcConnectptr.i,
4533                      LqhKeyReq::MaxKeyInfo,
4534                      regCachePtr->keyInfoSectionI,
4535                      apiConnectptr.p);
4536   }//if
4537 
4538   /* Release key storage */
4539   releaseKeys(regCachePtr);
4540   packLqhkeyreq040Lab(signal, TBRef, cachePtr, apiConnectptr);
4541 }//Dbtc::packLqhkeyreq()
4542 
4543 
sendlqhkeyreq(Signal * signal,BlockReference TBRef,CacheRecord * const regCachePtr,ApiConnectRecord * const regApiPtr)4544 void Dbtc::sendlqhkeyreq(Signal* signal,
4545                          BlockReference TBRef,
4546                          CacheRecord * const regCachePtr,
4547                          ApiConnectRecord* const regApiPtr)
4548 {
4549   UintR tslrAttrLen;
4550   UintR Tdata10;
4551   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4552   Uint32 version = getNodeInfo(refToNode(TBRef)).m_version;
4553   UintR sig0, sig1, sig2, sig3, sig4, sig5, sig6;
4554 #ifdef ERROR_INSERT
4555   if (ERROR_INSERTED(8002)) {
4556     systemErrorLab(signal, __LINE__);
4557   }//if
4558   if (ERROR_INSERTED(8007)) {
4559     if (regApiPtr->apiConnectstate == CS_STARTED)
4560     {
4561       CLEAR_ERROR_INSERT_VALUE;
4562       return;
4563     }//if
4564   }//if
4565   if (ERROR_INSERTED(8008)) {
4566     if (regApiPtr->apiConnectstate == CS_START_COMMITTING)
4567     {
4568       CLEAR_ERROR_INSERT_VALUE;
4569       return;
4570     }//if
4571   }//if
4572   if (ERROR_INSERTED(8009)) {
4573     if (regApiPtr->apiConnectstate == CS_STARTED)
4574     {
4575       return;
4576     }//if
4577   }//if
4578   if (ERROR_INSERTED(8010)) {
4579     if (regApiPtr->apiConnectstate == CS_START_COMMITTING)
4580     {
4581       return;
4582     }//if
4583   }//if
4584 #endif
4585   Uint32 Tdeferred = tc_testbit(regApiPtr->m_flags,
4586                                 ApiConnectRecord::TF_DEFERRED_CONSTRAINTS);
4587   Uint32 Tdisable_fk = tc_testbit(regApiPtr->m_flags,
4588                                   ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS);
4589   Uint32 reorg = ScanFragReq::REORG_ALL;
4590   Uint32 Tspecial_op = regTcPtr->m_special_op_flags;
4591   if (likely(Tspecial_op == 0))
4592   {
4593   }
4594   else if (Tspecial_op & (TcConnectRecord::SOF_REORG_TRIGGER |
4595                           TcConnectRecord::SOF_REORG_DELETE))
4596   {
4597     reorg = ScanFragReq::REORG_NOT_MOVED;
4598   }
4599   else if (Tspecial_op & TcConnectRecord::SOF_REORG_MOVING)
4600   {
4601     reorg = ScanFragReq::REORG_MOVED;
4602   }
4603 
4604   Uint32 inlineKeyLen= 0;
4605   Uint32 inlineAttrLen= 0;
4606 
4607   /* We normally send long LQHKEYREQ unless the
4608    * destination cannot handle it or we are
4609    * testing
4610    */
4611   if (unlikely(ERROR_INSERTED(8069)))
4612   {
4613     /* Short LQHKEYREQ, with some key/attr data inline */
4614     regCachePtr->useLongLqhKeyReq= 0;
4615     inlineKeyLen= regCachePtr->keylen;
4616     inlineAttrLen= regCachePtr->attrlength;
4617   }
4618   else
4619     /* Long LQHKEYREQ, with key/attr data in long sections */
4620     regCachePtr->useLongLqhKeyReq= 1;
4621 
4622   tslrAttrLen = 0;
4623   LqhKeyReq::setAttrLen(tslrAttrLen, inlineAttrLen);
4624   /* ---------------------------------------------------------------------- */
4625   // Bit16 == 0 since StoredProcedures are not yet supported.
4626   /* ---------------------------------------------------------------------- */
4627   LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
4628   LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
4629   LqhKeyReq::setReorgFlag(tslrAttrLen, reorg);
4630 
4631   Tdata10 = 0;
4632   sig0 = regTcPtr->opSimple;
4633   sig1 = regTcPtr->operation;
4634   sig2 = regTcPtr->dirtyOp;
4635   bool dirtyRead = (sig1 == ZREAD && sig2 == ZTRUE);
4636   LqhKeyReq::setLastReplicaNo(Tdata10, regTcPtr->lastReplicaNo);
4637   /* ---------------------------------------------------------------------- */
4638   // Indicate Application Reference is present in bit 15
4639   /* ---------------------------------------------------------------------- */
4640   LqhKeyReq::setApplicationAddressFlag(Tdata10, 1);
4641   LqhKeyReq::setDirtyFlag(Tdata10, sig2);
4642   LqhKeyReq::setInterpretedFlag(Tdata10, regCachePtr->opExec);
4643   LqhKeyReq::setSimpleFlag(Tdata10, sig0);
4644   LqhKeyReq::setOperation(Tdata10, sig1);
4645   LqhKeyReq::setNoDiskFlag(Tdata10, regCachePtr->m_no_disk_flag);
4646   LqhKeyReq::setQueueOnRedoProblemFlag(Tdata10, regCachePtr->m_op_queue);
4647   LqhKeyReq::setDeferredConstraints(Tdata10, (Tdeferred & m_deferred_enabled));
4648   LqhKeyReq::setDisableFkConstraints(Tdata10, Tdisable_fk);
4649   LqhKeyReq::setNoWaitFlag(Tdata10, regCachePtr->m_noWait);
4650 
4651   /* -----------------------------------------------------------------------
4652    * If we are sending a short LQHKEYREQ, then there will be some AttrInfo
4653    * in the LQHKEYREQ.
4654    * Work out how much we'll send
4655    * ----------------------------------------------------------------------- */
4656   UintR aiInLqhKeyReq= 0;
4657 
4658   if (likely(regCachePtr->useLongLqhKeyReq))
4659   {
4660     LqhKeyReq::setNoTriggersFlag(Tdata10,
4661       !!(regTcPtr->m_special_op_flags &
4662          TcConnectRecord::SOF_FULLY_REPLICATED_TRIGGER));
4663   }
4664   else
4665   {
4666     /* Short LQHKEYREQ :
4667      * Send max 5 words of AttrInfo in LQHKEYREQ
4668      */
4669     aiInLqhKeyReq= MIN(LqhKeyReq::MaxAttrInfo, regCachePtr->attrlength);
4670     LqhKeyReq::setKeyLen(Tdata10, inlineKeyLen);
4671   }
4672 
4673   LqhKeyReq::setAIInLqhKeyReq(Tdata10, aiInLqhKeyReq);
4674   /* -----------------------------------------------------------------------
4675    * Bit 27 == 0 since TC record is the same as the client record.
4676    * Bit 28 == 0 since readLenAi can only be set after reading in LQH.
4677    * ----------------------------------------------------------------------- */
4678   LqhKeyReq::setMarkerFlag(Tdata10, regTcPtr->commitAckMarker != RNIL ? 1 : 0);
4679 
4680   if (unlikely(regTcPtr->m_special_op_flags &
4681                TcConnectRecord::SOF_FK_READ_COMMITTED))
4682   {
4683     LqhKeyReq::setNormalProtocolFlag(Tdata10, 1);
4684     LqhKeyReq::setDirtyFlag(Tdata10, 1);
4685   }
4686   /* ************************************************************> */
4687   /* NO READ LENGTH SENT FROM TC. SEQUENTIAL NUMBER IS 1 AND IT    */
4688   /* IS SENT TO A PRIMARY NODE.                                    */
4689   /* ************************************************************> */
4690 
4691   LqhKeyReq * const lqhKeyReq = (LqhKeyReq *)signal->getDataPtrSend();
4692 
4693   sig0 = tcConnectptr.i;
4694   sig2 = regCachePtr->hashValue;
4695   sig4 = cownref;
4696   sig5 = regTcPtr->savePointId;
4697 
4698   lqhKeyReq->clientConnectPtr = sig0;
4699   lqhKeyReq->attrLen = tslrAttrLen;
4700   lqhKeyReq->hashValue = sig2;
4701   lqhKeyReq->requestInfo = Tdata10;
4702   lqhKeyReq->tcBlockref = sig4;
4703   lqhKeyReq->savePointId = sig5;
4704 
4705   sig0 = regCachePtr->tableref + ((regCachePtr->schemaVersion << 16) & 0xFFFF0000);
4706   sig1 = regCachePtr->fragmentid + (regTcPtr->tcNodedata[1] << 16);
4707   sig2 = regApiPtr->transid[0];
4708   sig3 = regApiPtr->transid[1];
4709   sig4 =
4710     (regTcPtr->m_special_op_flags & TcConnectRecord::SOF_INDEX_TABLE_READ) ?
4711     reference() : regApiPtr->ndbapiBlockref;
4712   sig5 = regTcPtr->clientData;
4713   sig6 = regCachePtr->scanInfo;
4714 
4715   if (! dirtyRead)
4716   {
4717     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[0]);
4718     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[1]);
4719     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[2]);
4720     regApiPtr->m_transaction_nodes.set(regTcPtr->tcNodedata[3]);
4721   }
4722 
4723   lqhKeyReq->tableSchemaVersion = sig0;
4724   lqhKeyReq->fragmentData = sig1;
4725   lqhKeyReq->transId1 = sig2;
4726   lqhKeyReq->transId2 = sig3;
4727   lqhKeyReq->scanInfo = sig6;
4728 
4729   lqhKeyReq->variableData[0] = sig4;
4730   lqhKeyReq->variableData[1] = sig5;
4731 
4732   UintR nextPos = 2;
4733 
4734   if (regTcPtr->lastReplicaNo > 1) {
4735     sig0 = (UintR)regTcPtr->tcNodedata[2] +
4736            (UintR)(regTcPtr->tcNodedata[3] << 16);
4737     lqhKeyReq->variableData[nextPos] = sig0;
4738     nextPos++;
4739   }//if
4740 
4741   // Reset trigger count
4742   regTcPtr->numFiredTriggers = 0;
4743   regTcPtr->triggerExecutionCount = 0;
4744   regTcPtr->m_start_ticks = getHighResTimer();
4745 
4746   if (likely(regCachePtr->useLongLqhKeyReq))
4747   {
4748     /* Build long LQHKeyReq using Key + AttrInfo sections */
4749     SectionHandle handle(this);
4750     SegmentedSectionPtr keyInfoSection;
4751 
4752     getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
4753 
4754     handle.m_ptr[ LqhKeyReq::KeyInfoSectionNum ]= keyInfoSection;
4755     handle.m_cnt= 1;
4756 
4757     if (unlikely(regTcPtr->m_special_op_flags &
4758                  TcConnectRecord::SOF_UTIL_FLAG))
4759     {
4760       LqhKeyReq::setUtilFlag(lqhKeyReq->requestInfo, 1);
4761     }
4762     if (regCachePtr->attrlength != 0)
4763     {
4764       SegmentedSectionPtr attrInfoSection;
4765 
4766       ndbassert(regCachePtr->attrInfoSectionI != RNIL);
4767       getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
4768 
4769       handle.m_ptr[ LqhKeyReq::AttrInfoSectionNum ]= attrInfoSection;
4770       handle.m_cnt= 2;
4771     }
4772     if (ndbd_frag_lqhkeyreq(version))
4773     {
4774       jamDebug();
4775       sendBatchedFragmentedSignal(TBRef,
4776                                   GSN_LQHKEYREQ,
4777                                   signal,
4778                                   LqhKeyReq::FixedSignalLength + nextPos,
4779                                   JBB,
4780                                   &handle,
4781                                   false);
4782      }
4783     else
4784     {
4785       jamDebug();
4786       sendSignal(TBRef, GSN_LQHKEYREQ, signal,
4787                  nextPos + LqhKeyReq::FixedSignalLength, JBB,
4788                  &handle);
4789     }
4790 
4791     /* Long sections were freed as part of sendSignal */
4792     ndbassert( handle.m_cnt == 0 );
4793     regCachePtr->keyInfoSectionI= RNIL;
4794     regCachePtr->attrInfoSectionI= RNIL;
4795   }
4796   else
4797   {
4798     /* Build short LQHKeyReq from Key + AttrInfo sections
4799      *
4800      * Read upto 4 words of KeyInfo from TCKEYREQ KeyInfo section into
4801      * LqhKeyReq signal
4802      */
4803     SegmentedSectionPtr keyInfoSection;
4804 
4805     getSection(keyInfoSection, regCachePtr->keyInfoSectionI);
4806     SectionReader keyInfoReader(keyInfoSection, getSectionSegmentPool());
4807 
4808     UintR keyLenInLqhKeyReq= MIN(LqhKeyReq::MaxKeyInfo, regCachePtr->keylen);
4809 
4810     keyInfoReader.getWords(&lqhKeyReq->variableData[nextPos], keyLenInLqhKeyReq);
4811 
4812     nextPos+= keyLenInLqhKeyReq;
4813 
4814     if (aiInLqhKeyReq != 0)
4815     {
4816       /* Read upto 5 words of AttrInfo from TCKEYREQ KeyInfo section into
4817        * LqhKeyReq signal
4818        */
4819       SegmentedSectionPtr attrInfoSection;
4820 
4821       ndbassert(regCachePtr->attrInfoSectionI != RNIL);
4822 
4823       getSection(attrInfoSection, regCachePtr->attrInfoSectionI);
4824       SectionReader attrInfoReader(attrInfoSection, getSectionSegmentPool());
4825 
4826       attrInfoReader.getWords(&lqhKeyReq->variableData[nextPos], aiInLqhKeyReq);
4827 
4828       nextPos+= aiInLqhKeyReq;
4829     }
4830 
4831     sendSignal(TBRef, GSN_LQHKEYREQ, signal,
4832                nextPos + LqhKeyReq::FixedSignalLength, JBB);
4833   }
4834 }//Dbtc::sendlqhkeyreq()
4835 
packLqhkeyreq040Lab(Signal * signal,BlockReference TBRef,CacheRecordPtr cachePtr,ApiConnectRecordPtr const apiConnectptr)4836 void Dbtc::packLqhkeyreq040Lab(Signal* signal,
4837                                BlockReference TBRef,
4838                                CacheRecordPtr cachePtr,
4839                                ApiConnectRecordPtr const apiConnectptr)
4840 {
4841   CacheRecord * const regCachePtr = cachePtr.p;
4842   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4843   PrefetchApiConTimer apiConTimer(c_apiConTimersPool, apiConnectptr, true);
4844 #ifdef ERROR_INSERT
4845   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
4846   if (ERROR_INSERTED(8009)) {
4847     if (regApiPtr->apiConnectstate == CS_STARTED) {
4848       CLEAR_ERROR_INSERT_VALUE;
4849       return;
4850     }//if
4851   }//if
4852   if (ERROR_INSERTED(8010)) {
4853     if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
4854       CLEAR_ERROR_INSERT_VALUE;
4855       return;
4856     }//if
4857   }//if
4858 #endif
4859 
4860   /* Do we have an ATTRINFO train to send? */
4861   if (unlikely(!regCachePtr->useLongLqhKeyReq))
4862   {
4863     /* Short LqhKeyReq */
4864     if (regCachePtr->attrlength > LqhKeyReq::MaxAttrInfo)
4865     {
4866       if (unlikely( !sendAttrInfoTrain(signal,
4867                                        TBRef,
4868                                        tcConnectptr.i,
4869                                        LqhKeyReq::MaxAttrInfo,
4870                                        regCachePtr->attrInfoSectionI,
4871                                        apiConnectptr.p)))
4872       {
4873         jam();
4874         TCKEY_abort(signal, 17, apiConnectptr);
4875         return;
4876       }
4877     }
4878   } // useLongLqhKeyReq
4879 
4880   /* Release AttrInfo related storage, and the Cache Record */
4881   releaseAttrinfo(cachePtr, apiConnectptr.p);
4882 
4883   UintR TtcTimer = ctcTimer;
4884   UintR Tread = (regTcPtr->operation == ZREAD);
4885   UintR Tdirty = (regTcPtr->dirtyOp == ZTRUE);
4886   UintR Tboth = Tread & Tdirty;
4887   apiConTimer.set_timer(TtcTimer, __LINE__);
4888   jamDebug();
4889   /*--------------------------------------------------------------------
4890    *   WE HAVE SENT ALL THE SIGNALS OF THIS OPERATION. SET STATE AND EXIT.
4891    *---------------------------------------------------------------------*/
4892   if (Tboth) {
4893     jam();
4894     releaseDirtyRead(signal, apiConnectptr, tcConnectptr.p);
4895     return;
4896   }//if
4897   regTcPtr->tcConnectstate = OS_OPERATING;
4898   return;
4899 }//Dbtc::packLqhkeyreq040Lab()
4900 
4901 /* ========================================================================= */
4902 /* -------      RELEASE ALL ATTRINFO RECORDS IN AN OPERATION RECORD  ------- */
4903 /* ========================================================================= */
releaseAttrinfo(CacheRecordPtr cachePtr,ApiConnectRecord * const regApiPtr)4904 void Dbtc::releaseAttrinfo(CacheRecordPtr cachePtr, ApiConnectRecord* const regApiPtr)
4905 {
4906   Uint32 attrInfoSectionI= cachePtr.p->attrInfoSectionI;
4907 
4908   /* Release AttrInfo section if there is one */
4909   releaseSection( attrInfoSectionI );
4910   cachePtr.p->attrInfoSectionI= RNIL;
4911 
4912   //---------------------------------------------------
4913   // Now we will release the cache record at the same
4914   // time as releasing the attrinfo records.
4915   //---------------------------------------------------
4916   if (unlikely(regApiPtr->cachePtr != Uint32(~0)))
4917   {
4918     c_cacheRecordPool.release(cachePtr);
4919     checkPoolShrinkNeed(DBTC_CACHE_RECORD_TRANSIENT_POOL_INDEX,
4920                         c_cacheRecordPool);
4921   }
4922   regApiPtr->cachePtr = RNIL;
4923   return;
4924 }//Dbtc::releaseAttrinfo()
4925 
4926 /* ========================================================================= */
4927 /* -------   RELEASE ALL RECORDS CONNECTED TO A DIRTY OPERATION     ------- */
4928 /* ========================================================================= */
releaseDirtyRead(Signal * signal,ApiConnectRecordPtr const apiConnectptr,TcConnectRecord * regTcPtr)4929 void Dbtc::releaseDirtyRead(Signal* signal,
4930                             ApiConnectRecordPtr const apiConnectptr,
4931                             TcConnectRecord* regTcPtr)
4932 {
4933   Uint32 Ttckeyrec = apiConnectptr.p->tckeyrec;
4934   Uint32 TclientData = regTcPtr->clientData;
4935   Uint32 Tnode = regTcPtr->tcNodedata[0];
4936   Uint32 Tlqhkeyreqrec = apiConnectptr.p->lqhkeyreqrec;
4937   ConnectionState state = apiConnectptr.p->apiConnectstate;
4938 
4939   apiConnectptr.p->tcSendArray[Ttckeyrec] = TclientData;
4940   apiConnectptr.p->tcSendArray[Ttckeyrec + 1] = TcKeyConf::DirtyReadBit | Tnode;
4941   apiConnectptr.p->tckeyrec = Ttckeyrec + 2;
4942 
4943   unlinkReadyTcCon(apiConnectptr.p);
4944   releaseTcCon();
4945   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
4946                       tcConnectRecord);
4947 
4948   /**
4949    * No LQHKEYCONF in Simple/Dirty read
4950    * Therefore decrese no LQHKEYCONF(REF) we are waiting for
4951    */
4952   c_counters.csimpleReadCount++;
4953   apiConnectptr.p->lqhkeyreqrec = --Tlqhkeyreqrec;
4954 
4955   if(Tlqhkeyreqrec == 0)
4956   {
4957     /**
4958      * Special case of lqhKeyConf_checkTransactionState:
4959      * - commit with zero operations: handle only for simple read
4960      */
4961     sendtckeyconf(signal, state == CS_START_COMMITTING, apiConnectptr);
4962     apiConnectptr.p->apiConnectstate =
4963       (state == CS_START_COMMITTING ? CS_CONNECTED : state);
4964     setApiConTimer(apiConnectptr, 0, __LINE__);
4965 
4966     return;
4967   }
4968 
4969   /**
4970    * Emulate LQHKEYCONF
4971    */
4972   lqhKeyConf_checkTransactionState(signal, apiConnectptr);
4973 }//Dbtc::releaseDirtyRead()
4974 
4975 /* ------------------------------------------------------------------------- */
4976 /* -------        CHECK IF ALL TC CONNECTIONS ARE COMPLETED          ------- */
4977 /* ------------------------------------------------------------------------- */
unlinkReadyTcCon(ApiConnectRecord * const regApiPtr)4978 void Dbtc::unlinkReadyTcCon(ApiConnectRecord* const regApiPtr)
4979 {
4980   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
4981   tcConList.remove(tcConnectptr);
4982 }//Dbtc::unlinkReadyTcCon()
4983 
releaseTcCon()4984 void Dbtc::releaseTcCon()
4985 {
4986   TcConnectRecord * const regTcPtr = tcConnectptr.p;
4987 
4988   ndbrequire(regTcPtr->commitAckMarker == RNIL);
4989   regTcPtr->tcConnectstate = OS_CONNECTED;
4990   regTcPtr->apiConnect = RNIL;
4991   regTcPtr->m_special_op_flags = 0;
4992   regTcPtr->indexOp = RNIL;
4993 
4994   if (regTcPtr->m_overtakeable_operation == 1)
4995   {
4996     jam();
4997     m_concurrent_overtakeable_operations--;
4998   }
4999   if (regTcPtr->triggeringOperation != RNIL &&
5000       regTcPtr->currentTriggerId != RNIL)
5001   {
5002     jam();
5003     Ptr<TcDefinedTriggerData> trigPtr;
5004     c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
5005     ndbrequire(trigPtr.p->refCount > 0);
5006     trigPtr.p->refCount--;
5007   }
5008 
5009   if (!regTcPtr->thePendingTriggers.isEmpty())
5010   {
5011     releaseFiredTriggerData(&regTcPtr->thePendingTriggers);
5012   }
5013 
5014   ndbrequire(regTcPtr->thePendingTriggers.isEmpty());
5015 
5016   tcConnectRecord.release(tcConnectptr);
5017   c_counters.cconcurrentOp--;
5018 }//Dbtc::releaseTcCon()
5019 
execPACKED_SIGNAL(Signal * signal)5020 void Dbtc::execPACKED_SIGNAL(Signal* signal)
5021 {
5022   LqhKeyConf * const lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
5023 
5024   UintR Ti;
5025   UintR Tstep = 0;
5026   UintR Tlength;
5027   UintR TpackedData[28];
5028   UintR Tdata1, Tdata2, Tdata3, Tdata4;
5029 
5030   jamEntry();
5031   Tlength = signal->length();
5032   if (unlikely(Tlength > 25))
5033   {
5034     jam();
5035     systemErrorLab(signal, __LINE__);
5036     return;
5037   }//if
5038   Uint32* TpackDataPtr;
5039   for (Ti = 0; Ti < Tlength; Ti += 4) {
5040     Uint32* TsigDataPtr = &signal->theData[Ti];
5041     Tdata1 = TsigDataPtr[0];
5042     Tdata2 = TsigDataPtr[1];
5043     Tdata3 = TsigDataPtr[2];
5044     Tdata4 = TsigDataPtr[3];
5045 
5046     TpackDataPtr = &TpackedData[Ti];
5047     TpackDataPtr[0] = Tdata1;
5048     TpackDataPtr[1] = Tdata2;
5049     TpackDataPtr[2] = Tdata3;
5050     TpackDataPtr[3] = Tdata4;
5051   }//for
5052 
5053   if (VERIFY_PACKED_RECEIVE)
5054   {
5055     ndbrequire(PackedSignal::verify(&TpackedData[0],
5056                                     Tlength,
5057                                     cownref,
5058                                     TC_RECEIVE_TYPES,
5059                                     0)); /* Irrelevant */
5060   }
5061   while (Tlength > Tstep) {
5062 
5063     TpackDataPtr = &TpackedData[Tstep];
5064     Tdata1 = TpackDataPtr[0];
5065     Tdata2 = TpackDataPtr[1];
5066     Tdata3 = TpackDataPtr[2];
5067 
5068     lqhKeyConf->connectPtr = Tdata1 & 0x0FFFFFFF;
5069     lqhKeyConf->opPtr = Tdata2;
5070     lqhKeyConf->userRef = Tdata3;
5071 
5072     switch (Tdata1 >> 28) {
5073     case ZCOMMITTED:
5074       signal->header.theLength = 3;
5075       jamBuffer()->markEndOfSigExec();
5076       execCOMMITTED(signal);
5077       Tstep += 3;
5078       break;
5079     case ZCOMPLETED:
5080       signal->header.theLength = 3;
5081       jamBuffer()->markEndOfSigExec();
5082       execCOMPLETED(signal);
5083       Tstep += 3;
5084       break;
5085     case ZLQHKEYCONF:
5086       jamDebug();
5087       Tdata1 = TpackDataPtr[3];
5088       Tdata2 = TpackDataPtr[4];
5089       Tdata3 = TpackDataPtr[5];
5090       Tdata4 = TpackDataPtr[6];
5091 
5092       lqhKeyConf->readLen = Tdata1;
5093       lqhKeyConf->transId1 = Tdata2;
5094       lqhKeyConf->transId2 = Tdata3;
5095       lqhKeyConf->numFiredTriggers = Tdata4;
5096       signal->header.theLength = LqhKeyConf::SignalLength;
5097       jamBuffer()->markEndOfSigExec();
5098       execLQHKEYCONF(signal);
5099       Tstep += LqhKeyConf::SignalLength;
5100       break;
5101     case ZFIRE_TRIG_CONF:
5102       jamDebug();
5103       signal->header.theLength = 4;
5104       signal->theData[3] = TpackDataPtr[3];
5105       jamBuffer()->markEndOfSigExec();
5106       execFIRE_TRIG_CONF(signal);
5107       Tstep += 4;
5108       break;
5109     default:
5110       systemErrorLab(signal, __LINE__);
5111       return;
5112     }//switch
5113   }//while
5114   return;
5115 }//Dbtc::execPACKED_SIGNAL()
5116 
5117 
execSIGNAL_DROPPED_REP(Signal * signal)5118 void Dbtc::execSIGNAL_DROPPED_REP(Signal* signal)
5119 {
5120   /* An incoming signal was dropped, handle it
5121    * Dropped signal really means that we ran out of
5122    * long signal buffering to store its sections
5123    */
5124   jamEntry();
5125 
5126   if (!assembleDroppedFragments(signal))
5127   {
5128     jam();
5129     return;
5130   }
5131 
5132   const SignalDroppedRep* rep = (SignalDroppedRep*) &signal->theData[0];
5133   Uint32 originalGSN= rep->originalGsn;
5134 
5135   DEBUG("SignalDroppedRep received for GSN " << originalGSN);
5136 
5137   switch(originalGSN) {
5138   case GSN_TCKEYREQ:
5139     jam();
5140     /* Fall through */
5141   case GSN_TCINDXREQ:
5142   {
5143     jam();
5144 
5145     /* Get original signal data - unfortunately it may
5146      * have been truncated.  We must not read beyond
5147      * word # 22
5148      * We will send an Abort to the Api using info from
5149      * the received signal and clean up our transaction
5150      * state
5151      */
5152     const TcKeyReq * const truncatedTcKeyReq =
5153       (TcKeyReq *) &rep->originalData[0];
5154 
5155     const UintR apiIndex = truncatedTcKeyReq->apiConnectPtr;
5156 
5157     ApiConnectRecordPtr apiConnectptr;
5158     apiConnectptr.i = apiIndex;
5159     if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
5160     {
5161       jam();
5162       warningHandlerLab(signal, __LINE__);
5163       return;
5164     }
5165 
5166     /* We have a valid Api ConnectPtr...
5167      * Ensure that we have the  necessary information
5168      * to send a rollback to the client
5169      */
5170     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5171     UintR transId1= truncatedTcKeyReq->transId1;
5172     UintR transId2= truncatedTcKeyReq->transId2;
5173 
5174     /* Ensure that the apiConnectptr global is initialised
5175      * may not be in cases where we drop the first signal of
5176      * a transaction
5177      */
5178     regApiPtr->transid[0] = transId1;
5179     regApiPtr->transid[1] = transId2;
5180     regApiPtr->returncode = ZGET_DATAREC_ERROR;
5181 
5182     /* Set m_exec_flag according to the dropped request */
5183     regApiPtr->m_flags |=
5184       TcKeyReq::getExecuteFlag(truncatedTcKeyReq->requestInfo) ?
5185       ApiConnectRecord::TF_EXEC_FLAG : 0;
5186 
5187     DEBUG(" Execute flag set to " << tc_testbit(regApiPtr->m_flags,
5188                                                 ApiConnectRecord::TF_EXEC_FLAG)
5189           );
5190 
5191     abortErrorLab(signal, apiConnectptr);
5192 
5193     break;
5194   }
5195   case GSN_SCAN_TABREQ:
5196   {
5197     jam();
5198     /* Get information necessary to send SCAN_TABREF back to client */
5199     // TODO : Handle dropped signal fragments
5200     const ScanTabReq * const truncatedScanTabReq =
5201       (ScanTabReq *) &rep->originalData[0];
5202 
5203     Uint32 apiConnectPtr= truncatedScanTabReq->apiConnectPtr;
5204     Uint32 transId1= truncatedScanTabReq->transId1;
5205     Uint32 transId2= truncatedScanTabReq->transId2;
5206 
5207     ApiConnectRecordPtr apiConnectptr;
5208     apiConnectptr.i = apiConnectPtr;
5209     if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
5210     {
5211       jam();
5212       warningHandlerLab(signal, __LINE__);
5213       return;
5214     }//if
5215 
5216     ApiConnectRecord * transP = apiConnectptr.p;
5217 
5218     /* Now send the SCAN_TABREF */
5219     ScanTabRef* ref= (ScanTabRef*)&signal->theData[0];
5220     ref->apiConnectPtr = transP->ndbapiConnect;
5221     ref->transId1= transId1;
5222     ref->transId2= transId2;
5223     ref->errorCode= ZGET_ATTRBUF_ERROR;
5224     ref->closeNeeded= 0;
5225 
5226     sendSignal(transP->ndbapiBlockref, GSN_SCAN_TABREF,
5227                signal, ScanTabRef::SignalLength, JBB);
5228     break;
5229   }
5230   case GSN_TRANSID_AI: //TUP -> TC
5231   {
5232     jam();
5233     /**
5234      * TRANSID_AI is received as a result of performing a read on
5235      * the index table as part of a (unique) index operation.
5236      */
5237     const TransIdAI * const truncatedTransIdAI =
5238       reinterpret_cast<const TransIdAI*>(&rep->originalData[0]);
5239 
5240     TcIndexOperationPtr indexOpPtr;
5241     indexOpPtr.i = truncatedTransIdAI->connectPtr;
5242     if (unlikely(indexOpPtr.i == RNIL ||
5243                  !c_theIndexOperationPool.getValidPtr(indexOpPtr)))
5244     {
5245       jam();
5246       // Missing or invalid index operation - ignore
5247       break;
5248     }
5249     TcIndexOperation* indexOp = indexOpPtr.p;
5250 
5251     /* No more TransIdAI will arrive, abort */
5252     ApiConnectRecordPtr apiConnectptr;
5253     apiConnectptr.i = indexOp->connectionIndex;
5254     if (unlikely(apiConnectptr.i == RNIL ||
5255                  !c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
5256     {
5257       jam();
5258       // Missing or invalid api connection - ignore
5259       break;
5260     }
5261 
5262     terrorCode = ZGET_DATAREC_ERROR;
5263     abortErrorLab(signal, apiConnectptr);
5264     break;
5265   }
5266   case GSN_TRANSID_AI_R:  //TODO
5267     jam();
5268     // Fall through
5269   default:
5270     jam();
5271     /* Don't expect dropped signals for other GSNs,
5272      * default handling
5273      * TODO : Can TC get long TRANSID_AI as part of
5274      * Unique index operations?
5275      */
5276     SimulatedBlock::execSIGNAL_DROPPED_REP(signal);
5277   };
5278 
5279   return;
5280 }
5281 
5282 bool
insert_in_commit_ack_marker(Dbtc * tc,Uint32 instanceKey,NodeId node_id)5283 Dbtc::CommitAckMarker::insert_in_commit_ack_marker(Dbtc *tc,
5284                                                    Uint32 instanceKey,
5285                                                    NodeId node_id)
5286 {
5287   const NodeInfo& nodeInfo = tc->getNodeInfo(node_id);
5288   Uint32 workers = nodeInfo.m_lqh_workers;
5289   assert(instanceKey != 0);
5290   Uint32 instanceNo = workers == 0 ? 0 : 1 + (instanceKey - 1) % workers;
5291   Uint32 item = instanceNo + (node_id << 16);
5292   CommitAckMarkerBuffer::DataBufferPool & pool =
5293     tc->c_theCommitAckMarkerBufferPool;
5294   // check for duplicate (todo DataBuffer method find-or-append)
5295   {
5296     LocalCommitAckMarkerBuffer tmp(pool, this->theDataBuffer);
5297     CommitAckMarkerBuffer::Iterator iter;
5298     bool next_flag = tmp.first(iter);
5299     while (next_flag)
5300     {
5301       Uint32 dataWord = *iter.data;
5302       if (dataWord == item)
5303       {
5304         return true;
5305       }
5306       next_flag = tmp.next(iter, 1);
5307     }
5308   }
5309   LocalCommitAckMarkerBuffer tmp(pool, this->theDataBuffer);
5310   return tmp.append(&item, (Uint32)1);
5311 }
5312 bool
insert_in_commit_ack_marker_all(Dbtc * tc,NodeId node_id)5313 Dbtc::CommitAckMarker::insert_in_commit_ack_marker_all(Dbtc *tc,
5314                                                        NodeId node_id)
5315 {
5316   for (Uint32 ikey = 1; ikey <= MAX_NDBMT_LQH_THREADS; ikey++)
5317   {
5318     if (!insert_in_commit_ack_marker(tc, ikey, node_id))
5319       return false;
5320   }
5321   return true;
5322 }
5323 
execLQHKEYCONF(Signal * signal)5324 void Dbtc::execLQHKEYCONF(Signal* signal)
5325 {
5326   const LqhKeyConf * lqhKeyConf = CAST_CONSTPTR(LqhKeyConf,
5327                                                 signal->getDataPtr());
5328 #ifdef UNUSED
5329   ndbout << "TC: Received LQHKEYCONF"
5330          << " transId1=" << lqhKeyConf-> transId1
5331          << " transId2=" << lqhKeyConf-> transId2
5332 	 << endl;
5333 #endif /*UNUSED*/
5334   UintR compare_transid1, compare_transid2;
5335   BlockReference tlastLqhBlockref;
5336   UintR tlastLqhConnect;
5337   UintR treadlenAi;
5338   UintR TtcConnectptrIndex;
5339 
5340   tlastLqhConnect = lqhKeyConf->connectPtr;
5341   TtcConnectptrIndex = lqhKeyConf->opPtr;
5342   tlastLqhBlockref = lqhKeyConf->userRef;
5343   treadlenAi = lqhKeyConf->readLen;
5344 
5345   /*------------------------------------------------------------------------
5346    * NUMBER OF EXTERNAL TRIGGERS FIRED IN DATA[6]
5347    * OPERATION IS NOW COMPLETED. CHECK FOR CORRECT OPERATION POINTER
5348    * TO ENSURE NO CRASHES BECAUSE OF ERRONEUS NODES. CHECK STATE OF
5349    * OPERATION. THEN SET OPERATION STATE AND RETRIEVE ALL POINTERS
5350    * OF THIS OPERATION. PUT COMPLETED OPERATION IN LIST OF COMPLETED
5351    * OPERATIONS ON THE LQH CONNECT RECORD.
5352    *------------------------------------------------------------------------
5353    * THIS SIGNAL ALWAYS ARRIVE BEFORE THE ABORTED SIGNAL ARRIVES SINCE IT USES
5354    * THE SAME PATH BACK TO TC AS THE ABORTED SIGNAL DO. WE DO HOWEVER HAVE A
5355    * PROBLEM  WHEN WE ENCOUNTER A TIME-OUT WAITING FOR THE ABORTED SIGNAL.
5356    * THEN THIS SIGNAL MIGHT ARRIVE WHEN THE TC CONNECT RECORD HAVE BEEN REUSED
5357    * BY OTHER TRANSACTION THUS WE CHECK THE TRANSACTION ID OF THE SIGNAL
5358    * BEFORE ACCEPTING THIS SIGNAL.
5359    * Due to packing of LQHKEYCONF the ABORTED signal can now arrive before
5360    * this.
5361    * This is more reason to ignore the signal if not all states are correct.
5362    *------------------------------------------------------------------------*/
5363   tcConnectptr.i = TtcConnectptrIndex;
5364   if (unlikely(!tcConnectRecord.getValidPtr(tcConnectptr)))
5365   {
5366     jam();
5367     warningReport(signal, 23);
5368     return;
5369   }//if
5370   /**
5371    * getUncheckedPtrRW returning true means that tcConnectptr.p points to
5372    * a valid TcConnect record. It could still be a released record. In
5373    * this case the magic is wrong AND the tcConnectState is OS_CONNECTED.
5374    * Thus if state is OS_OPERATING we have verified that it is a
5375    * correct record and thus apiConnect should point to a valid
5376    * API connect record.
5377    */
5378   TcConnectRecord* const regTcPtr = tcConnectptr.p;
5379   ApiConnectRecordPtr apiConnectptr;
5380   CommitAckMarkerPtr commitAckMarker;
5381 
5382   apiConnectptr.i = regTcPtr->apiConnect;
5383   commitAckMarker.i = regTcPtr->commitAckMarker;
5384 
5385   OperationState TtcConnectstate = regTcPtr->tcConnectstate;
5386   if (unlikely(TtcConnectstate != OS_OPERATING))
5387   {
5388     warningReport(signal, 23);
5389     return;
5390   }//if
5391 
5392   ndbrequire(c_apiConnectRecordPool.getUncheckedPtrRW(apiConnectptr));
5393 
5394   UintR Ttrans1 = lqhKeyConf->transId1;
5395   UintR Ttrans2 = lqhKeyConf->transId2;
5396   Uint32 numFired = LqhKeyConf::getFiredCount(lqhKeyConf->numFiredTriggers);
5397   Uint32 deferreduk = LqhKeyConf::getDeferredUKBit(lqhKeyConf->numFiredTriggers);
5398   Uint32 deferredfk = LqhKeyConf::getDeferredFKBit(lqhKeyConf->numFiredTriggers);
5399 
5400   ApiConnectRecordPtr const regApiPtr = apiConnectptr;
5401   compare_transid1 = regApiPtr.p->transid[0] ^ Ttrans1;
5402   compare_transid2 = regApiPtr.p->transid[1] ^ Ttrans2;
5403   compare_transid1 = compare_transid1 | compare_transid2;
5404   if (unlikely(compare_transid1 != 0))
5405   {
5406     /**
5407      * Even with a valid record it is possible for the transaction id to
5408      * be wrong. In this case the record has been used in a new transaction
5409      * and we need to throw away this signal.
5410      */
5411     warningReport(signal, 24);
5412     return;
5413   }//if
5414   ndbrequire(Magic::check_ptr(apiConnectptr.p));
5415   PrefetchApiConTimer apiConTimer(c_apiConTimersPool, apiConnectptr, true);
5416 
5417 #ifdef ERROR_INSERT
5418   if (ERROR_INSERTED(8029)) {
5419     systemErrorLab(signal, __LINE__);
5420   }//if
5421   if (ERROR_INSERTED(8003)) {
5422     if (regApiPtr.p->apiConnectstate == CS_STARTED) {
5423       CLEAR_ERROR_INSERT_VALUE;
5424       return;
5425     }//if
5426   }//if
5427   if (ERROR_INSERTED(8004)) {
5428     if (regApiPtr.p->apiConnectstate == CS_RECEIVING) {
5429       CLEAR_ERROR_INSERT_VALUE;
5430       return;
5431     }//if
5432   }//if
5433   if (ERROR_INSERTED(8005)) {
5434     if (regApiPtr.p->apiConnectstate == CS_REC_COMMITTING) {
5435       CLEAR_ERROR_INSERT_VALUE;
5436       return;
5437     }//if
5438   }//if
5439   if (ERROR_INSERTED(8006)) {
5440     if (regApiPtr.p->apiConnectstate == CS_START_COMMITTING) {
5441       CLEAR_ERROR_INSERT_VALUE;
5442       return;
5443     }//if
5444   }//if
5445   if (ERROR_INSERTED(8023)) {
5446     SET_ERROR_INSERT_VALUE(8024);
5447     return;
5448   }//if
5449   if (ERROR_INSERTED(8107))
5450   {
5451     jam();
5452     ndbout_c("Error 8107, timing out transaction");
5453     timeOutFoundLab(signal, apiConnectptr.i, ZTIME_OUT_ERROR);
5454     return;
5455   }
5456 
5457 #endif
5458   UintR TtcTimer = ctcTimer;
5459   regTcPtr->lastLqhCon = tlastLqhConnect;
5460   regTcPtr->lastLqhNodeId = refToNode(tlastLqhBlockref);
5461   regTcPtr->numFiredTriggers = numFired;
5462   regTcPtr->m_special_op_flags |=
5463     ((deferreduk) ? TcConnectRecord::SOF_DEFERRED_UK_TRIGGER : 0 ) |
5464     ((deferredfk) ? TcConnectRecord::SOF_DEFERRED_FK_TRIGGER : 0 );
5465   regApiPtr.p->m_flags |=
5466     ((deferreduk) ? ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS : 0) |
5467     ((deferredfk) ? ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS : 0);
5468 
5469   UintR Ttckeyrec = (UintR)regApiPtr.p->tckeyrec;
5470   UintR TclientData = regTcPtr->clientData;
5471   UintR TdirtyOp = regTcPtr->dirtyOp;
5472   Uint32 TopSimple = regTcPtr->opSimple;
5473   Uint32 Toperation = regTcPtr->operation;
5474   ConnectionState TapiConnectstate = regApiPtr.p->apiConnectstate;
5475 
5476   if (unlikely(TapiConnectstate == CS_ABORTING))
5477   {
5478     jam();
5479     warningReport(signal, 27);
5480     return;
5481   }//if
5482 
5483   Uint32 lockingOpI = RNIL;
5484   if (unlikely(Toperation == ZUNLOCK))
5485   {
5486     /* For unlock operations readlen in TCKEYCONF carries
5487      * the locking operation TC reference
5488      */
5489     lockingOpI = treadlenAi;
5490     treadlenAi = 0;
5491   }
5492 
5493   /* Handle case where LQHKEYREQ requested an LQH CommitAckMarker */
5494   apiConTimer.set_timer(TtcTimer, __LINE__);
5495   if (commitAckMarker.i != RNIL)
5496   {
5497     ndbrequire(m_commitAckMarkerPool.getUncheckedPtrRW(commitAckMarker));
5498     jam();
5499     /* Update TC CommitAckMarker record to track LQH CommitAckMarkers */
5500     const Uint32 noOfLqhs = regTcPtr->noOfNodes;
5501     /**
5502      * Now that we have a marker in all nodes in at least one nodegroup,
5503      * don't need to request any more for this transaction
5504      */
5505     regApiPtr.p->m_flags |= ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED;
5506 
5507     /**
5508      * Populate LQH array
5509      */
5510     ndbrequire(Magic::check_ptr(commitAckMarker.p));
5511     for(Uint32 i = 0; i < noOfLqhs; i++)
5512     {
5513       jamDebug();
5514       if (ERROR_INSERTED(8096) && i+1 == noOfLqhs)
5515       {
5516         CLEAR_ERROR_INSERT_VALUE;
5517         TCKEY_abort(signal, 67, apiConnectptr);
5518         return;
5519       }
5520       if (!commitAckMarker.p->insert_in_commit_ack_marker(this,
5521                                             regTcPtr->lqhInstanceKey,
5522                                             regTcPtr->tcNodedata[i]))
5523       {
5524         TCKEY_abort(signal, 67, apiConnectptr);
5525         return;
5526       }
5527     }
5528   }
5529   TcConnectRecordPtr triggeringOp;
5530   triggeringOp.i = regTcPtr->triggeringOperation;
5531   if (unlikely(regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)))
5532   {
5533     jam();
5534     // This was an internal TCKEYREQ
5535     // will be returned unpacked
5536     regTcPtr->attrInfoLen = treadlenAi;
5537   }
5538   else if (numFired == 0 && triggeringOp.i == RNIL)
5539   {
5540     jam();
5541 
5542     if (unlikely(Ttckeyrec > (ZTCOPCONF_SIZE - 2)))
5543     {
5544       TCKEY_abort(signal, 30, apiConnectptr);
5545       return;
5546     }
5547 
5548     /*
5549      * Skip counting triggering operations the first round
5550      * since they will enter execLQHKEYCONF a second time
5551      * Skip counting internally generated TcKeyReq
5552      */
5553     regApiPtr.p->tcSendArray[Ttckeyrec] = TclientData;
5554     regApiPtr.p->tcSendArray[Ttckeyrec + 1] = treadlenAi;
5555     regApiPtr.p->tckeyrec = Ttckeyrec + 2;
5556   }
5557   bool do_releaseTcCon = false;
5558   TcConnectRecordPtr save_tcConnectptr;
5559   if (TdirtyOp == ZTRUE)
5560   {
5561     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5562     jam();
5563     releaseDirtyWrite(signal, apiConnectptr);
5564     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
5565   }
5566   else if (Toperation == ZREAD && TopSimple)
5567   {
5568     UintR Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
5569     jam();
5570     unlinkReadyTcCon(apiConnectptr.p);
5571     do_releaseTcCon = true;
5572     save_tcConnectptr = tcConnectptr;
5573     regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
5574   }
5575   else if (unlikely(Toperation == ZUNLOCK))
5576   {
5577     jam();
5578     /* We've unlocked and released a read operation in LQH
5579      * The readLenAi member contains the TC OP reference
5580      * for the unlocked operation.
5581      * So here we :
5582      * 1) Validate the TC OP reference
5583      * 2) Release the referenced TC op
5584      * 3) Send TCKEYCONF back to the user
5585      * 4) Release our own TC op
5586      */
5587     const TcConnectRecordPtr unlockOp = tcConnectptr;
5588 
5589     ndbrequire( numFired == 0 );
5590     ndbrequire( triggeringOp.i == RNIL );
5591 
5592     /* Switch to the original locking operation */
5593     if (unlikely(lockingOpI == RNIL))
5594     {
5595       jam();
5596       TCKEY_abort(signal, 61, apiConnectptr);
5597       return;
5598     }
5599     tcConnectptr.i = lockingOpI;
5600     ndbrequire(tcConnectRecord.getValidPtr(tcConnectptr));
5601 
5602     const TcConnectRecord * regLockTcPtr = tcConnectptr.p;
5603 
5604     /* Validate the locking operation's state */
5605     bool locking_op_ok =
5606       ( ( regLockTcPtr->apiConnect == regTcPtr->apiConnect ) &&
5607         ( ( regLockTcPtr->operation == ZREAD ) ||
5608           ( regLockTcPtr->operation == ZREAD_EX ) ) &&
5609         ( regLockTcPtr->tcConnectstate == OS_PREPARED ) &&
5610         ( ! regLockTcPtr->dirtyOp ) &&
5611         ( ! regLockTcPtr->opSimple ) &&
5612         ( ! TcConnectRecord::isIndexOp(regLockTcPtr->m_special_op_flags) ) &&
5613         ( regLockTcPtr->commitAckMarker == RNIL ) );
5614 
5615     if (unlikely (! locking_op_ok ))
5616     {
5617       jam();
5618       TCKEY_abort(signal, 63, apiConnectptr);
5619       return;
5620     }
5621 
5622     /* Ok, all checks passed, release the original locking op */
5623     unlinkReadyTcCon(apiConnectptr.p);
5624     releaseTcCon();
5625     checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
5626                         tcConnectRecord);
5627 
5628     /* Remove record of original locking op's LQHKEYREQ/CONF
5629      * etc.
5630      */
5631     ndbrequire( regApiPtr.p->lqhkeyreqrec );
5632     ndbrequire( regApiPtr.p->lqhkeyconfrec );
5633     regApiPtr.p->lqhkeyreqrec -= 1;
5634     regApiPtr.p->lqhkeyconfrec -= 1;
5635 
5636     /* Switch back to the unlock operation */
5637     tcConnectptr = unlockOp;
5638 
5639     /* Release the unlock operation */
5640     unlinkReadyTcCon(apiConnectptr.p);
5641     do_releaseTcCon = true;
5642     save_tcConnectptr = tcConnectptr;
5643 
5644     /* Remove record of unlock op's LQHKEYREQ */
5645     ndbrequire( regApiPtr.p->lqhkeyreqrec );
5646     regApiPtr.p->lqhkeyreqrec -= 1;
5647 
5648     /* TCKEYCONF sent below */
5649   }
5650   else
5651   {
5652     if (numFired == 0)
5653     {
5654       // No triggers to execute
5655       UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
5656       regApiPtr.p->lqhkeyconfrec = Tlqhkeyconfrec + 1;
5657       regTcPtr->tcConnectstate = OS_PREPARED;
5658     }
5659     else
5660     {
5661       jam();
5662     }
5663   }//if
5664 
5665   if (unlikely(triggeringOp.i != RNIL))
5666   {
5667     // A trigger op execution ends.
5668     jam();
5669     ndbrequire(regApiPtr.p->m_executing_trigger_ops > 0);
5670     regApiPtr.p->m_executing_trigger_ops--;
5671   }
5672 
5673   /**
5674    * And now decide what to do next
5675    * 1) First check if there are fired triggers
5676    * 2) Then check if it's a index-table read
5677    * 3) Then check if op was created by trigger
5678    * 4) Else it's a normal op
5679    *
5680    * - trigger op, can cause new trigger ops (cascade)
5681    * - trigger op can be using uk
5682    */
5683   if (numFired)
5684   {
5685     // We have fired triggers
5686     jam();
5687     time_track_complete_key_operation(regTcPtr,
5688                                refToNode(regApiPtr.p->ndbapiBlockref),
5689                                regTcPtr->tcNodedata[0]);
5690     saveTriggeringOpState(signal, regTcPtr);
5691     if (regTcPtr->numReceivedTriggers == numFired)
5692     {
5693       // We have received all data
5694       jam();
5695       Local_TcFiredTriggerData_fifo
5696         list(c_theFiredTriggerPool, regApiPtr.p->theFiredTriggers);
5697       list.appendList(regTcPtr->thePendingTriggers);
5698       executeTriggers(signal, &regApiPtr);
5699     }
5700     // else wait for more trigger data
5701   }
5702   else if (unlikely(regTcPtr->isIndexOp(regTcPtr->m_special_op_flags)))
5703   {
5704     // This is a index-table read
5705     jam();
5706     time_track_complete_index_key_operation(regTcPtr,
5707                                   refToNode(regApiPtr.p->ndbapiBlockref),
5708                                   regTcPtr->tcNodedata[0]);
5709     setupIndexOpReturn(regApiPtr.p, regTcPtr);
5710     lqhKeyConf_checkTransactionState(signal, regApiPtr);
5711   }
5712   else if (likely(triggeringOp.i == RNIL))
5713   {
5714     // This is "normal" path
5715     jamDebug();
5716     time_track_complete_key_operation(regTcPtr,
5717                                refToNode(regApiPtr.p->ndbapiBlockref),
5718                                regTcPtr->tcNodedata[0]);
5719     lqhKeyConf_checkTransactionState(signal, regApiPtr);
5720   }
5721   else
5722   {
5723     jam();
5724     /**
5725      * This operation was created by a trigger executing operation
5726      * Thus no need to handle the operation any further, return to
5727      * the original operation instead. There can be many triggering
5728      * operations waiting on each other here.
5729      *
5730      * Restart the original operation if we have executed all it's
5731      * triggers.
5732      */
5733     time_track_complete_index_key_operation(regTcPtr,
5734                                   refToNode(regApiPtr.p->ndbapiBlockref),
5735                                   regTcPtr->tcNodedata[0]);
5736     ndbrequire(tcConnectRecord.getValidPtr(triggeringOp));
5737     trigger_op_finished(signal, regApiPtr, regTcPtr->currentTriggerId,
5738                         triggeringOp.p, 0);
5739     executeTriggers(signal, &regApiPtr);
5740   }
5741   if (do_releaseTcCon)
5742   {
5743     tcConnectptr = save_tcConnectptr;
5744     releaseTcCon();
5745     checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
5746                         tcConnectRecord);
5747   }
5748 }//Dbtc::execLQHKEYCONF()
5749 
setupIndexOpReturn(ApiConnectRecord * regApiPtr,TcConnectRecord * regTcPtr)5750 void Dbtc::setupIndexOpReturn(ApiConnectRecord* regApiPtr,
5751 			      TcConnectRecord* regTcPtr)
5752 {
5753   regApiPtr->m_flags |= ApiConnectRecord::TF_INDEX_OP_RETURN;
5754   regApiPtr->indexOp = regTcPtr->indexOp;
5755   TcIndexOperationPtr indexOpPtr;
5756   indexOpPtr.i = regApiPtr->indexOp;
5757   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
5758   if (tc_testbit(indexOp->savedFlags,
5759                  ApiConnectRecord::TF_DEFERRED_CONSTRAINTS))
5760   {
5761     regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
5762   }
5763 
5764   if (tc_testbit(indexOp->savedFlags,
5765                  ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS))
5766   {
5767     regApiPtr->m_flags |= ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS;
5768   }
5769   regApiPtr->clientData = regTcPtr->clientData;
5770   regApiPtr->attrInfoLen = regTcPtr->attrInfoLen;
5771 }
5772 
5773 /**
5774  * lqhKeyConf_checkTransactionState
5775  *
5776  * This functions checks state variables, and
5777  *   decides if it should wait for more LQHKEYCONF signals
5778  *   or if it should start commiting
5779  */
5780 void
lqhKeyConf_checkTransactionState(Signal * signal,ApiConnectRecordPtr apiConnectptr)5781 Dbtc::lqhKeyConf_checkTransactionState(Signal * signal,
5782                                        ApiConnectRecordPtr apiConnectptr)
5783 {
5784 /*---------------------------------------------------------------*/
5785 /* IF THE COMMIT FLAG IS SET IN SIGNAL TCKEYREQ THEN DBTC HAS TO */
5786 /* SEND TCKEYCONF FOR ALL OPERATIONS EXCEPT THE LAST ONE. WHEN   */
5787 /* THE TRANSACTION THEN IS COMMITTED TCKEYCONF IS SENT FOR THE   */
5788 /* WHOLE TRANSACTION                                             */
5789 /* IF THE COMMIT FLAG IS NOT RECECIVED DBTC WILL SEND TCKEYCONF  */
5790 /* FOR ALL OPERATIONS, AND THEN WAIT FOR THE API TO CONCLUDE THE */
5791 /* TRANSACTION                                                   */
5792 /*---------------------------------------------------------------*/
5793   ConnectionState TapiConnectstate = apiConnectptr.p->apiConnectstate;
5794   UintR Tlqhkeyconfrec = apiConnectptr.p->lqhkeyconfrec;
5795   UintR Tlqhkeyreqrec = apiConnectptr.p->lqhkeyreqrec;
5796   int TnoOfOutStanding = Tlqhkeyreqrec - Tlqhkeyconfrec;
5797 
5798   switch (TapiConnectstate) {
5799   case CS_START_COMMITTING:
5800     if (TnoOfOutStanding == 0) {
5801       jam();
5802       diverify010Lab(signal, apiConnectptr);
5803       return;
5804     } else if (TnoOfOutStanding > 0) {
5805       if (apiConnectptr.p->tckeyrec == ZTCOPCONF_SIZE)
5806       {
5807         jam();
5808         sendtckeyconf(signal, 0, apiConnectptr);
5809         return;
5810       }
5811       else if (tc_testbit(apiConnectptr.p->m_flags,
5812                           ApiConnectRecord::TF_INDEX_OP_RETURN))
5813       {
5814 	jam();
5815         sendtckeyconf(signal, 0, apiConnectptr);
5816         return;
5817       }//if
5818       jam();
5819       return;
5820     } else {
5821       TCKEY_abort(signal, 44, apiConnectptr);
5822       return;
5823     }//if
5824     return;
5825   case CS_STARTED:
5826   case CS_RECEIVING:
5827     if (TnoOfOutStanding == 0) {
5828       jam();
5829       sendtckeyconf(signal, 2, apiConnectptr);
5830       return;
5831     } else {
5832       if (apiConnectptr.p->tckeyrec == ZTCOPCONF_SIZE)
5833       {
5834         jam();
5835         sendtckeyconf(signal, 0, apiConnectptr);
5836         return;
5837       }
5838       else if (tc_testbit(apiConnectptr.p->m_flags,
5839                           ApiConnectRecord::TF_INDEX_OP_RETURN))
5840       {
5841 	jam();
5842         sendtckeyconf(signal, 0, apiConnectptr);
5843         return;
5844       }//if
5845       jam();
5846     }//if
5847     return;
5848   case CS_REC_COMMITTING:
5849     if (TnoOfOutStanding > 0) {
5850       if (apiConnectptr.p->tckeyrec == ZTCOPCONF_SIZE)
5851       {
5852         jam();
5853         sendtckeyconf(signal, 0, apiConnectptr);
5854         return;
5855       }
5856       else if (tc_testbit(apiConnectptr.p->m_flags,
5857                           ApiConnectRecord::TF_INDEX_OP_RETURN))
5858       {
5859         jam();
5860         sendtckeyconf(signal, 0, apiConnectptr);
5861         return;
5862       }//if
5863       jam();
5864       return;
5865     }//if
5866     TCKEY_abort(signal, 45, apiConnectptr);
5867     return;
5868   case CS_CONNECTED:
5869     jam();
5870 /*---------------------------------------------------------------*/
5871 /*       WE HAVE CONCLUDED THE TRANSACTION SINCE IT WAS ONLY     */
5872 /*       CONSISTING OF DIRTY WRITES AND ALL OF THOSE WERE        */
5873 /*       COMPLETED. ENSURE TCKEYREC IS ZERO TO PREVENT ERRORS.   */
5874 /*---------------------------------------------------------------*/
5875     apiConnectptr.p->tckeyrec = 0;
5876     return;
5877   case CS_SEND_FIRE_TRIG_REQ:
5878     return;
5879   case CS_WAIT_FIRE_TRIG_REQ:
5880     if (tc_testbit(apiConnectptr.p->m_flags,
5881                    ApiConnectRecord::TF_INDEX_OP_RETURN))
5882     {
5883       jam();
5884       sendtckeyconf(signal, 0, apiConnectptr);
5885       return;
5886     }
5887     else if (TnoOfOutStanding == 0 && apiConnectptr.p->pendingTriggers == 0)
5888     {
5889       jam();
5890       apiConnectptr.p->apiConnectstate = CS_START_COMMITTING;
5891       diverify010Lab(signal, apiConnectptr);
5892       return;
5893     }
5894     return;
5895   default:
5896     TCKEY_abort(signal, 46, apiConnectptr);
5897     return;
5898   }//switch
5899 }//Dbtc::lqhKeyConf_checkTransactionState()
5900 
sendtckeyconf(Signal * signal,UintR TcommitFlag,ApiConnectRecordPtr const apiConnectptr)5901 void Dbtc::sendtckeyconf(Signal* signal, UintR TcommitFlag, ApiConnectRecordPtr const apiConnectptr)
5902 {
5903   if(ERROR_INSERTED(8049)){
5904     CLEAR_ERROR_INSERT_VALUE;
5905     signal->theData[0] = TcContinueB::DelayTCKEYCONF;
5906     signal->theData[1] = apiConnectptr.i;
5907     signal->theData[2] = TcommitFlag;
5908     sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 3000, 3);
5909     return;
5910   }
5911 
5912   HostRecordPtr localHostptr;
5913   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
5914   const UintR TopWords = (UintR)regApiPtr->tckeyrec;
5915   localHostptr.i = refToNode(regApiPtr->ndbapiBlockref);
5916   const Uint32 type = getNodeInfo(localHostptr.i).m_type;
5917   const bool is_api = (type >= NodeInfo::API && type <= NodeInfo::MGM);
5918   const BlockNumber TblockNum = refToBlock(regApiPtr->ndbapiBlockref);
5919   const Uint32 Tmarker = (regApiPtr->commitAckMarker == RNIL) ? 0 : 1;
5920   ptrAss(localHostptr, hostRecord);
5921   struct PackedWordsContainer * container = &localHostptr.p->packTCKEYCONF;
5922   UintR TcurrLen = container->noOfPackedWords;
5923   UintR confInfo = 0;
5924   TcKeyConf::setCommitFlag(confInfo, TcommitFlag == 1);
5925   TcKeyConf::setMarkerFlag(confInfo, Tmarker);
5926   const UintR TpacketLen = 6 + TopWords;
5927   regApiPtr->tckeyrec = 0;
5928 
5929   if (tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN))
5930   {
5931     jam();
5932     // Return internally generated TCKEY
5933     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
5934     TcKeyConf::setNoOfOperations(confInfo, 1);
5935     tcKeyConf->apiConnectPtr = regApiPtr->indexOp;
5936     tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
5937     Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[1];
5938     * gci_lo = Uint32(regApiPtr->globalcheckpointid);
5939     tcKeyConf->confInfo = confInfo;
5940     tcKeyConf->transId1 = regApiPtr->transid[0];
5941     tcKeyConf->transId2 = regApiPtr->transid[1];
5942     tcKeyConf->operations[0].apiOperationPtr = regApiPtr->clientData;
5943     tcKeyConf->operations[0].attrInfoLen = regApiPtr->attrInfoLen;
5944     Uint32 sigLen = 1 /** gci_lo */ +
5945       TcKeyConf::StaticLength + TcKeyConf::OperationLength;
5946     EXECUTE_DIRECT(DBTC, GSN_TCKEYCONF, signal, sigLen);
5947     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_INDEX_OP_RETURN);
5948     if (TopWords == 0) {
5949       jamDebug();
5950       return; // No queued TcKeyConf
5951     }//if
5952   }//if
5953   if(TcommitFlag)
5954   {
5955     jam();
5956     tc_clearbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
5957     if (TcommitFlag == 1)
5958     {
5959       time_track_complete_transaction(regApiPtr);
5960     }
5961   }
5962   TcKeyConf::setNoOfOperations(confInfo, (TopWords >> 1));
5963   if ((TpacketLen + 1 /** gci_lo */ > 25) ||!is_api){
5964     TcKeyConf * const tcKeyConf = (TcKeyConf *)signal->getDataPtrSend();
5965 
5966     jam();
5967     tcKeyConf->apiConnectPtr = regApiPtr->ndbapiConnect;
5968     tcKeyConf->gci_hi = Uint32(regApiPtr->globalcheckpointid >> 32);
5969     Uint32* gci_lo = (Uint32*)&tcKeyConf->operations[TopWords >> 1];
5970     tcKeyConf->confInfo = confInfo;
5971     tcKeyConf->transId1 = regApiPtr->transid[0];
5972     tcKeyConf->transId2 = regApiPtr->transid[1];
5973     copyFromToLen(&regApiPtr->tcSendArray[0],
5974 		  (UintR*)&tcKeyConf->operations,
5975 		  (UintR)ZTCOPCONF_SIZE);
5976     * gci_lo = Uint32(regApiPtr->globalcheckpointid);
5977     sendSignal(regApiPtr->ndbapiBlockref,
5978 	       GSN_TCKEYCONF, signal, (TpacketLen - 1) + 1 /** gci_lo */, JBB);
5979     return;
5980   } else if (((TcurrLen + TpacketLen + 1 /** gci_lo */) > 25) &&
5981              (TcurrLen > 0)) {
5982     jam();
5983     sendPackedTCKEYCONF(signal, localHostptr.p, localHostptr.i);
5984     TcurrLen = 0;
5985   } else {
5986     jam();
5987     updatePackedList(signal, localHostptr.p, localHostptr.i);
5988   }//if
5989   // -------------------------------------------------------------------------
5990   // The header contains the block reference of receiver plus the real signal
5991   // length - 3, since we have the real signal length plus one additional word
5992   // for the header we have to do - 4.
5993   // -------------------------------------------------------------------------
5994   container->noOfPackedWords = TcurrLen + TpacketLen + 1 /** gci_lo */;
5995 
5996   UintR Tpack0 = (TblockNum << 16) + (TpacketLen - 4 + 1 /** gci_lo */);
5997   UintR Tpack1 = regApiPtr->ndbapiConnect;
5998   UintR Tpack2 = Uint32(regApiPtr->globalcheckpointid >> 32);
5999   UintR Tpack3 = confInfo;
6000   UintR Tpack4 = regApiPtr->transid[0];
6001   UintR Tpack5 = regApiPtr->transid[1];
6002   UintR Tpack6 = Uint32(regApiPtr->globalcheckpointid);
6003 
6004   container->packedWords[TcurrLen + 0] = Tpack0;
6005   container->packedWords[TcurrLen + 1] = Tpack1;
6006   container->packedWords[TcurrLen + 2] = Tpack2;
6007   container->packedWords[TcurrLen + 3] = Tpack3;
6008   container->packedWords[TcurrLen + 4] = Tpack4;
6009   container->packedWords[TcurrLen + 5] = Tpack5;
6010 
6011   container->packedWords[TcurrLen + TpacketLen] = Tpack6;
6012 
6013   for (Uint32 Ti = 6; Ti < TpacketLen; Ti++) {
6014     container->packedWords[TcurrLen + Ti] = regApiPtr->tcSendArray[Ti - 6];
6015   }//for
6016 }//Dbtc::sendtckeyconf()
6017 
copyFromToLen(UintR * sourceBuffer,UintR * destBuffer,UintR Tlen)6018 void Dbtc::copyFromToLen(UintR* sourceBuffer, UintR* destBuffer, UintR Tlen)
6019 {
6020   UintR Tindex = 0;
6021   UintR Ti;
6022   while (Tlen >= 4) {
6023     UintR Tdata0 = sourceBuffer[Tindex + 0];
6024     UintR Tdata1 = sourceBuffer[Tindex + 1];
6025     UintR Tdata2 = sourceBuffer[Tindex + 2];
6026     UintR Tdata3 = sourceBuffer[Tindex + 3];
6027     Tlen -= 4;
6028     destBuffer[Tindex + 0] = Tdata0;
6029     destBuffer[Tindex + 1] = Tdata1;
6030     destBuffer[Tindex + 2] = Tdata2;
6031     destBuffer[Tindex + 3] = Tdata3;
6032     Tindex += 4;
6033   }//while
6034   for (Ti = 0; Ti < Tlen; Ti++, Tindex++) {
6035     destBuffer[Tindex] = sourceBuffer[Tindex];
6036   }//for
6037 }//Dbtc::copyFromToLen()
6038 
execSEND_PACKED(Signal * signal)6039 void Dbtc::execSEND_PACKED(Signal* signal)
6040 {
6041   HostRecordPtr Thostptr;
6042   HostRecord *localHostRecord = hostRecord;
6043   UintR i;
6044   UintR TpackedListIndex = cpackedListIndex;
6045   jamEntryDebug();
6046   for (i = 0; i < TpackedListIndex; i++) {
6047     jam();
6048     Thostptr.i = cpackedList[i];
6049     ptrAss(Thostptr, localHostRecord);
6050     arrGuard(Thostptr.i - 1, MAX_NODES - 1);
6051     for (Uint32 j = 0; j < NDB_ARRAY_SIZE(Thostptr.p->lqh_pack); j++)
6052     {
6053       struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[j];
6054       jamDebug();
6055       if (container->noOfPackedWords > 0) {
6056         jamDebug();
6057         sendPackedSignal(signal, container);
6058       }
6059     }
6060     struct PackedWordsContainer * container = &Thostptr.p->packTCKEYCONF;
6061     if (container->noOfPackedWords > 0) {
6062       jamDebug();
6063       sendPackedTCKEYCONF(signal, Thostptr.p, (Uint32)Thostptr.i);
6064     }//if
6065     Thostptr.p->inPackedList = false;
6066   }//for
6067   cpackedListIndex = 0;
6068   return;
6069 }//Dbtc::execSEND_PACKED()
6070 
6071 void
updatePackedList(Signal * signal,HostRecord * ahostptr,Uint16 ahostIndex)6072 Dbtc::updatePackedList(Signal* signal, HostRecord* ahostptr, Uint16 ahostIndex)
6073 {
6074   if (ahostptr->inPackedList == false) {
6075     UintR TpackedListIndex = cpackedListIndex;
6076     jamDebug();
6077     ahostptr->inPackedList = true;
6078     cpackedList[TpackedListIndex] = ahostIndex;
6079     cpackedListIndex = TpackedListIndex + 1;
6080   }//if
6081 }//Dbtc::updatePackedList()
6082 
sendPackedSignal(Signal * signal,struct PackedWordsContainer * container)6083 void Dbtc::sendPackedSignal(Signal* signal,
6084                             struct PackedWordsContainer * container)
6085 {
6086   UintR TnoOfWords = container->noOfPackedWords;
6087   ndbassert(TnoOfWords <= 25);
6088   container->noOfPackedWords = 0;
6089   memcpy(&signal->theData[0], &container->packedWords[0], 4 * TnoOfWords);
6090   if (VERIFY_PACKED_SEND)
6091   {
6092     ndbrequire(refToMain(container->hostBlockRef) == DBLQH);
6093     ndbrequire(PackedSignal::verify(&signal->theData[0],
6094                                     TnoOfWords,
6095                                     container->hostBlockRef,
6096                                     LQH_RECEIVE_TYPES,
6097                                     5)); /* Commit signal length */
6098   }
6099   sendSignal(container->hostBlockRef,
6100              GSN_PACKED_SIGNAL,
6101              signal,
6102              TnoOfWords,
6103              JBB);
6104 }//Dbtc::sendPackedSignal()
6105 
sendPackedTCKEYCONF(Signal * signal,HostRecord * ahostptr,UintR hostId)6106 void Dbtc::sendPackedTCKEYCONF(Signal* signal,
6107                                HostRecord * ahostptr,
6108                                UintR hostId)
6109 {
6110   struct PackedWordsContainer * container = &ahostptr->packTCKEYCONF;
6111   UintR TnoOfWords = container->noOfPackedWords;
6112   ndbassert(TnoOfWords <= 25);
6113   container->noOfPackedWords = 0;
6114   BlockReference TBref = numberToRef(API_PACKED, hostId);
6115   memcpy(&signal->theData[0], &container->packedWords[0], 4 * TnoOfWords);
6116   sendSignal(TBref, GSN_TCKEYCONF, signal, TnoOfWords, JBB);
6117 }//Dbtc::sendPackedTCKEYCONF()
6118 
6119 void
startSendFireTrigReq(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)6120 Dbtc::startSendFireTrigReq(Signal* signal, Ptr<ApiConnectRecord> regApiPtr)
6121 {
6122   const Uint32 pass = regApiPtr.p->m_pre_commit_pass;
6123   const Uint32 step = pass & Uint32(TriggerPreCommitPass::TPCP_PASS_MAX);
6124   regApiPtr.p->pendingTriggers = 0;
6125   if (tc_testbit(regApiPtr.p->m_flags,
6126                  ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS))
6127   {
6128     jam();
6129     if (step == TriggerPreCommitPass::UK_PASS_1)
6130     {
6131       jam();
6132       // clear on second pass...
6133       tc_clearbit(regApiPtr.p->m_flags,
6134                   ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS);
6135     }
6136   }
6137   else
6138   {
6139     ndbassert(tc_testbit(regApiPtr.p->m_flags,
6140                          ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS));
6141     tc_clearbit(regApiPtr.p->m_flags,
6142                 ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS);
6143 
6144     Uint32 newpass = pass;
6145     newpass = newpass & ~Uint32(TriggerPreCommitPass::TPCP_PASS_MAX);
6146     newpass = newpass + TriggerPreCommitPass::FK_PASS_0;
6147     regApiPtr.p->m_pre_commit_pass = newpass;
6148   }
6149 
6150   ndbassert(regApiPtr.p->m_firstTcConnectPtrI_FT == RNIL);
6151   ndbassert(regApiPtr.p->m_lastTcConnectPtrI_FT == RNIL);
6152   regApiPtr.p->m_firstTcConnectPtrI_FT = regApiPtr.p->tcConnect.getFirst();
6153   regApiPtr.p->m_lastTcConnectPtrI_FT = regApiPtr.p->tcConnect.getLast();
6154   sendFireTrigReq(signal, regApiPtr);
6155 }
6156 
6157 /*
6158 4.3.11 DIVERIFY
6159 ---------------
6160 */
6161 /*****************************************************************************/
6162 /*                               D I V E R I F Y                             */
6163 /*                                                                           */
6164 /*****************************************************************************/
diverify010Lab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)6165 void Dbtc::diverify010Lab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
6166 {
6167   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6168   signal->theData[0] = apiConnectptr.i;
6169   signal->theData[1] = instance() ? instance() - 1 : 0;
6170   if (ERROR_INSERTED(8022)) {
6171     jam();
6172     systemErrorLab(signal, __LINE__);
6173   }//if
6174 
6175   ndbassert(regApiPtr->m_executing_trigger_ops == 0);
6176   if (tc_testbit(regApiPtr->m_flags,
6177                  (ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS +
6178                   ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS)))
6179   {
6180     /**
6181      * If trans has deferred triggers, let them fire just before
6182      *   transaction starts to commit
6183      */
6184     startSendFireTrigReq(signal, apiConnectptr);
6185     return;
6186   }
6187 
6188   ndbassert(!tc_testbit(regApiPtr->m_flags,
6189                         (ApiConnectRecord::TF_INDEX_OP_RETURN |
6190                          ApiConnectRecord::TF_TRIGGER_PENDING)));
6191 
6192   if (regApiPtr->lqhkeyreqrec)
6193   {
6194     ndbrequire(regApiPtr->apiCopyRecord != RNIL);
6195     tc_clearbit(regApiPtr->m_flags,
6196                 ApiConnectRecord::TF_TRIGGER_PENDING);
6197     regApiPtr->m_special_op_flags = 0;
6198 
6199     regApiPtr->apiConnectstate = CS_PREPARE_TO_COMMIT;
6200     /*-----------------------------------------------------------------------
6201      * WE COME HERE ONLY IF THE TRANSACTION IS PREPARED ON ALL TC CONNECTIONS
6202      * THUS WE CAN START THE COMMIT PHASE BY SENDING DIVERIFY ON ALL TC
6203      * CONNECTIONS AND THEN WHEN ALL DIVERIFYCONF HAVE BEEN RECEIVED THE
6204      * COMMIT MESSAGE CAN BE SENT TO ALL INVOLVED PARTS.
6205      *---------------------------------------------------------------------*/
6206     * (EmulatedJamBuffer**)(signal->theData+2) = jamBuffer();
6207     EXECUTE_DIRECT_MT(DBDIH, GSN_DIVERIFYREQ, signal,
6208                       2 + sizeof(void*)/sizeof(Uint32), 0);
6209     if (!capiConnectPREPARE_TO_COMMITList.isEmpty() || signal->theData[3] != 0)
6210     {
6211       /* Put transaction last in verification queue */
6212       ndbrequire(regApiPtr == apiConnectptr.p);
6213       ndbrequire(regApiPtr->nextApiConnect == RNIL);
6214       ndbrequire(regApiPtr->apiConnectkind == ApiConnectRecord::CK_USER);
6215       LocalApiConnectRecord_api_fifo apiConList(
6216           c_apiConnectRecordPool, capiConnectPREPARE_TO_COMMITList);
6217       apiConList.addLast(apiConnectptr);
6218       /**
6219        * If execDIVERIFYCONF is called below, make it pop a transaction
6220        * from verifiction queue.
6221        * Note, that even if DBDIH says ok without queue, DBTC can still
6222        * have a queue since there can be DIVERIFYCONF still in flight.
6223        */
6224       signal->theData[0] = RNIL;
6225     }
6226     if (signal->theData[3] == 0)
6227     {
6228       execDIVERIFYCONF(signal);
6229     }
6230     return;
6231   }
6232   else
6233   {
6234     jam();
6235     sendtckeyconf(signal, 1, apiConnectptr);
6236     regApiPtr->apiConnectstate = CS_CONNECTED;
6237     regApiPtr->m_transaction_nodes.clear();
6238     setApiConTimer(apiConnectptr, 0, __LINE__);
6239   }
6240 }//Dbtc::diverify010Lab()
6241 
6242 /* ------------------------------------------------------------------------- */
6243 /* -------                  SEIZE_API_CONNECT                        ------- */
6244 /*                  SEIZE CONNECT RECORD FOR A REQUEST                       */
6245 /* ------------------------------------------------------------------------- */
6246 
ApiConnectRecord()6247 Dbtc::ApiConnectRecord::ApiConnectRecord()
6248 : m_magic(Magic::make(TYPE_ID)),
6249   m_apiConTimer(RNIL),
6250   m_apiConTimer_line(0),
6251   apiConnectstate(CS_RESTART), /* CS_DISCONNECTED (CS_RESTART for Copy and Fail) */
6252   apiConnectkind(CK_FREE),
6253   lqhkeyconfrec(0),
6254   cachePtr(RNIL),
6255   currSavePointId(0),
6256   nextApiConnect(RNIL),
6257   ndbapiBlockref(0xFFFFFFFF), // Invalid ref
6258   apiCopyRecord(RNIL),
6259   globalcheckpointid(0),
6260   lqhkeyreqrec(0),
6261   buddyPtr(RNIL),
6262   commitAckMarker(RNIL),
6263   num_commit_ack_markers(0),
6264   m_write_count(0),
6265   m_flags(0),
6266   takeOverRec((Uint8)Z8NIL),
6267   tckeyrec(0),
6268   tcindxrec(0),
6269   apiFailState(ApiConnectRecord::AFS_API_OK),
6270   singleUserMode(0),
6271   m_pre_commit_pass(0),
6272   cascading_scans_count(0),
6273   m_special_op_flags(0),
6274   returncode(0),
6275   noIndexOp(0),
6276   immediateTriggerId(RNIL),
6277   firedFragId(RNIL),
6278 #ifdef ERROR_INSERT
6279   continueBCount(0),
6280 #endif
6281   accumulatingIndexOp(RNIL),
6282   executingIndexOp(RNIL)
6283 {
6284   NdbTick_Invalidate(&m_start_ticks);
6285   tcConnect.init();
6286   theFiredTriggers.init();
6287   theSeizedIndexOperations.init();
6288 
6289   m_transaction_nodes.clear();
6290 }
6291 
seizeApiConnectCopy(Signal * signal,ApiConnectRecord * const regApiPtr)6292 bool Dbtc::seizeApiConnectCopy(Signal* signal,
6293                                ApiConnectRecord* const regApiPtr)
6294 {
6295   ApiConnectRecordPtr locApiConnectptr;
6296 
6297   if (unlikely(!c_apiConnectRecordPool.seize(locApiConnectptr)))
6298   {
6299     return false;
6300   }
6301   locApiConnectptr.p->apiConnectkind = ApiConnectRecord::CK_COPY;
6302   if (!seizeApiConTimer(locApiConnectptr))
6303   {
6304     c_apiConnectRecordPool.release(locApiConnectptr);
6305     return false;
6306   }
6307   setApiConTimer(locApiConnectptr, 0, __LINE__);
6308   ndbassert(regApiPtr->apiCopyRecord == RNIL);
6309   regApiPtr->apiCopyRecord = locApiConnectptr.i;
6310   tc_clearbit(regApiPtr->m_flags,
6311               ApiConnectRecord::TF_TRIGGER_PENDING);
6312   regApiPtr->m_special_op_flags = 0;
6313   return true;
6314 }//Dbtc::seizeApiConnectCopy()
6315 
execDIVERIFYCONF(Signal * signal)6316 void Dbtc::execDIVERIFYCONF(Signal* signal)
6317 {
6318   UintR TapiConnectptrIndex = signal->theData[0];
6319   UintR Tgci_hi = signal->theData[1];
6320   UintR Tgci_lo = signal->theData[2];
6321   Uint64 Tgci = Tgci_lo | (Uint64(Tgci_hi) << 32);
6322 
6323   jamEntry();
6324   if (ERROR_INSERTED(8017))
6325   {
6326     CLEAR_ERROR_INSERT_VALUE;
6327     return;
6328   }  // if
6329   LocalApiConnectRecord_api_fifo apiConList(c_apiConnectRecordPool,
6330                                             capiConnectPREPARE_TO_COMMITList);
6331   ApiConnectRecordPtr apiConnectptr;
6332   if (TapiConnectptrIndex == RNIL)
6333   {
6334     /* Pop first transaction in verification queue */
6335     if (unlikely(!apiConList.removeFirst(apiConnectptr)))
6336     {
6337       /**
6338        * DIVERIFYCONF from DBDIH
6339        * There should be transactions queue for verification.
6340        */
6341       ndbassert(!capiConnectPREPARE_TO_COMMITList.isEmpty());
6342       return;
6343     }
6344     ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_USER);
6345   }
6346   else
6347   {
6348     /**
6349      * DIVERIFYCONF from DBTC
6350      * There should be no transactions queue for verification.
6351      */
6352     apiConnectptr.i = TapiConnectptrIndex;
6353     if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
6354     {
6355       TCKEY_abort(signal, 31, ApiConnectRecordPtr::get(NULL, RNIL));
6356       return;
6357     }
6358   }
6359   ApiConnectRecord* const regApiPtr = apiConnectptr.p;
6360   ndbrequire(regApiPtr->apiConnectkind == ApiConnectRecord::CK_USER);
6361   ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
6362   UintR TApifailureNr = regApiPtr->failureNr;
6363   UintR Tfailure_nr = cfailure_nr;
6364   if (unlikely(TapiConnectstate != CS_PREPARE_TO_COMMIT))
6365   {
6366     TCKEY_abort(signal, 32, apiConnectptr);
6367     return;
6368   }//if
6369   /*--------------------------------------------------------------------------
6370    * THIS IS THE COMMIT POINT. IF WE ARRIVE HERE THE TRANSACTION IS COMMITTED
6371    * UNLESS EVERYTHING CRASHES BEFORE WE HAVE BEEN ABLE TO REPORT THE COMMIT
6372    * DECISION. THERE IS NO TURNING BACK FROM THIS DECISION FROM HERE ON.
6373    * WE WILL INSERT THE TRANSACTION INTO ITS PROPER QUEUE OF
6374    * TRANSACTIONS FOR ITS GLOBAL CHECKPOINT.
6375    *-------------------------------------------------------------------------*/
6376   if (unlikely(TApifailureNr != Tfailure_nr ||
6377       ERROR_INSERTED(8094)))
6378   {
6379     jam();
6380     DIVER_node_fail_handling(signal, Tgci, apiConnectptr);
6381     return;
6382   }//if
6383   commitGciHandling(signal, Tgci, apiConnectptr);
6384 
6385   /**************************************************************************
6386    *                                 C O M M I T
6387    * THE TRANSACTION HAVE NOW BEEN VERIFIED AND NOW THE COMMIT PHASE CAN START
6388    **************************************************************************/
6389 
6390   if (ERROR_INSERTED(8110))
6391   {
6392     jam();
6393     /* Disconnect API now that commit decided upon */
6394     const Uint32 apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
6395     if (getNodeInfo(apiNodeId).getType() == NodeInfo::API)
6396     {
6397       ndbout_c("Error insert 8110, disconnecting API during COMMIT");
6398       signal->theData[0] = apiNodeId;
6399       sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBA);
6400 
6401       SET_ERROR_INSERT_VALUE(8089); /* Slow committing... */
6402     }
6403   }
6404 
6405   regApiPtr->counter = regApiPtr->lqhkeyconfrec;
6406   regApiPtr->apiConnectstate = CS_COMMITTING;
6407 
6408   if (unlikely(regApiPtr->tcConnect.isEmpty()))
6409   {
6410     TCKEY_abort(signal, 33, apiConnectptr); // Not really invalid, rather just empty
6411     return;
6412   }
6413 
6414   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
6415   tcConList.first(tcConnectptr);
6416 
6417   commit020Lab(signal, apiConnectptr);
6418 }//Dbtc::execDIVERIFYCONF()
6419 
6420 /*--------------------------------------------------------------------------*/
6421 /*                             COMMIT_GCI_HANDLING                          */
6422 /*       SET UP GLOBAL CHECKPOINT DATA STRUCTURE AT THE COMMIT POINT.       */
6423 /*--------------------------------------------------------------------------*/
commitGciHandling(Signal * signal,Uint64 Tgci,ApiConnectRecordPtr const apiConnectptr)6424 void Dbtc::commitGciHandling(Signal* signal, Uint64 Tgci, ApiConnectRecordPtr const apiConnectptr)
6425 {
6426   GcpRecordPtr localGcpPointer;
6427 
6428   Ptr<ApiConnectRecord> regApiPtr = apiConnectptr;
6429   regApiPtr.p->globalcheckpointid = Tgci;
6430 
6431   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
6432   if (gcp_list.first(localGcpPointer))
6433   {
6434     /* IF THIS GLOBAL CHECKPOINT ALREADY EXISTS */
6435     do {
6436       if (regApiPtr.p->globalcheckpointid == localGcpPointer.p->gcpId) {
6437         jam();
6438         linkApiToGcp(localGcpPointer, regApiPtr);
6439         return;
6440       }
6441       if (unlikely(! (regApiPtr.p->globalcheckpointid > localGcpPointer.p->gcpId)))
6442       {
6443         ndbout_c("%u/%u %u/%u",
6444                  Uint32(regApiPtr.p->globalcheckpointid >> 32),
6445                  Uint32(regApiPtr.p->globalcheckpointid),
6446                  Uint32(localGcpPointer.p->gcpId >> 32),
6447                  Uint32(localGcpPointer.p->gcpId));
6448         crash_gcp(__LINE__, "Can not find global checkpoint record for commit.");
6449       }
6450       jam();
6451     } while (gcp_list.next(localGcpPointer));
6452   }
6453 
6454   seizeGcp(localGcpPointer, Tgci);
6455   linkApiToGcp(localGcpPointer, regApiPtr);
6456 }//Dbtc::commitGciHandling()
6457 
6458 /* --------------------------------------------------------------------------*/
6459 /* -LINK AN API CONNECT RECORD IN STATE PREPARED INTO THE LIST WITH GLOBAL - */
6460 /* CHECKPOINTS. WHEN THE TRANSACTION I COMPLETED THE API CONNECT RECORD IS   */
6461 /* LINKED OUT OF THE LIST.                                                   */
6462 /*---------------------------------------------------------------------------*/
linkApiToGcp(Ptr<GcpRecord> regGcpPtr,Ptr<ApiConnectRecord> regApiPtr)6463 void Dbtc::linkApiToGcp(Ptr<GcpRecord> regGcpPtr,
6464                         Ptr<ApiConnectRecord> regApiPtr)
6465 {
6466   LocalApiConnectRecord_gcp_list apiConList(c_apiConnectRecordPool,
6467                                             regGcpPtr.p->apiConnectList);
6468   apiConList.addLast(regApiPtr);
6469   regApiPtr.p->gcpPointer = regGcpPtr.i;
6470 }
6471 
6472 void
crash_gcp(Uint32 line,const char msg[])6473 Dbtc::crash_gcp(Uint32 line, const char msg[])
6474 {
6475   GcpRecordPtr localGcpPointer;
6476 
6477   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
6478   if (gcp_list.first(localGcpPointer))
6479   {
6480     do
6481     {
6482       ndbout_c("%u : %u/%u nomoretrans: %u api %u %u next: %u",
6483                localGcpPointer.i,
6484                Uint32(localGcpPointer.p->gcpId >> 32),
6485                Uint32(localGcpPointer.p->gcpId),
6486                localGcpPointer.p->gcpNomoretransRec,
6487                localGcpPointer.p->apiConnectList.getFirst(),
6488                localGcpPointer.p->apiConnectList.getLast(),
6489                localGcpPointer.p->nextList);
6490     } while (gcp_list.next(localGcpPointer));
6491   }
6492   progError(line, NDBD_EXIT_NDBREQUIRE, msg);
6493   ndbabort();
6494 }
6495 
seizeGcp(Ptr<GcpRecord> & dst,Uint64 Tgci)6496 void Dbtc::seizeGcp(Ptr<GcpRecord> & dst, Uint64 Tgci)
6497 {
6498   GcpRecordPtr localGcpPointer;
6499 
6500   if (unlikely(!c_gcpRecordPool.seize(localGcpPointer)))
6501   {
6502     ndbout_c("%u/%u", Uint32(Tgci >> 32), Uint32(Tgci));
6503     crash_gcp(__LINE__, "Too many active global checkpoints.");
6504   }
6505   localGcpPointer.p->gcpId = Tgci;
6506   localGcpPointer.p->apiConnectList.init();
6507   localGcpPointer.p->gcpNomoretransRec = ZFALSE;
6508 
6509   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
6510   gcp_list.addLast(localGcpPointer);
6511   dst = localGcpPointer;
6512 }//Dbtc::seizeGcp()
6513 
6514 /*---------------------------------------------------------------------------*/
6515 // Send COMMIT messages to all LQH operations involved in the transaction.
6516 /*---------------------------------------------------------------------------*/
commit020Lab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)6517 void Dbtc::commit020Lab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
6518 {
6519   TcConnectRecordPtr localTcConnectptr;
6520   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
6521 
6522   localTcConnectptr.p = tcConnectptr.p;
6523   setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
6524   UintR Tcount = 0;
6525   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
6526   do {
6527     /*-----------------------------------------------------------------------
6528      * WE ARE NOW READY TO RELEASE ALL OPERATIONS ON THE LQH
6529      *-----------------------------------------------------------------------*/
6530     /* *********< */
6531     /*  COMMIT  < */
6532     /* *********< */
6533     /* Clear per-operation record CommitAckMarker ref if necessary */
6534     if (localTcConnectptr.p->commitAckMarker != RNIL)
6535     {
6536       ndbassert(regApiPtr->commitAckMarker != RNIL);
6537       ndbrequire(regApiPtr->num_commit_ack_markers--);
6538       localTcConnectptr.p->commitAckMarker = RNIL;
6539     }
6540     localTcConnectptr.p->tcConnectstate = OS_COMMITTING;
6541     Tcount += sendCommitLqh(signal, localTcConnectptr.p, apiConnectptr.p);
6542 
6543     if (tcConList.next(localTcConnectptr))
6544     {
6545       if (Tcount < 16 &&
6546           ! (ERROR_INSERTED(8057) ||
6547              ERROR_INSERTED(8073) ||
6548              ERROR_INSERTED(8089)))
6549       {
6550         jam();
6551         continue;
6552       } else {
6553         jam();
6554         if (ERROR_INSERTED(8014)) {
6555           CLEAR_ERROR_INSERT_VALUE;
6556           return;
6557         }//if
6558 
6559         if (ERROR_INSERTED(8073))
6560         {
6561           execSEND_PACKED(signal);
6562           signal->theData[0] = 9999;
6563           sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
6564           return;
6565         }
6566         signal->theData[0] = TcContinueB::ZSEND_COMMIT_LOOP;
6567         signal->theData[1] = apiConnectptr.i;
6568         signal->theData[2] = localTcConnectptr.i;
6569         if (ERROR_INSERTED(8089))
6570         {
6571           sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
6572           return;
6573         }
6574         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
6575         return;
6576       }//if
6577     } else {
6578       jam();
6579       if (ERROR_INSERTED(8057))
6580         CLEAR_ERROR_INSERT_VALUE;
6581 
6582       if (ERROR_INSERTED(8089))
6583         CLEAR_ERROR_INSERT_VALUE;
6584 
6585       regApiPtr->apiConnectstate = CS_COMMIT_SENT;
6586       ndbrequire(regApiPtr->num_commit_ack_markers == 0);
6587       return;
6588     }//if
6589   } while (1);
6590 }//Dbtc::commit020Lab()
6591 
6592 Uint32
sendCommitLqh(Signal * signal,TcConnectRecord * const regTcPtr,ApiConnectRecord * const regApiPtr)6593 Dbtc::sendCommitLqh(Signal* signal,
6594                     TcConnectRecord * const regTcPtr,
6595                     ApiConnectRecord* const regApiPtr)
6596 {
6597   HostRecordPtr Thostptr;
6598   UintR ThostFilesize = chostFilesize;
6599   Uint32 instanceKey = regTcPtr->lqhInstanceKey;
6600   Thostptr.i = regTcPtr->lastLqhNodeId;
6601   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
6602 
6603   if (ERROR_INSERTED(8113))
6604   {
6605     jam();
6606     /* Don't actually send -> timeout */
6607     return 0;
6608   }
6609 
6610   Uint32 Tnode = Thostptr.i;
6611   Uint32 self = getOwnNodeId();
6612   Uint32 ret = (Tnode == self) ? 4 : 1;
6613 
6614   Uint32 Tdata[5];
6615   Tdata[0] = regTcPtr->lastLqhCon;
6616   Tdata[1] = Uint32(regApiPtr->globalcheckpointid >> 32);
6617   Tdata[2] = regApiPtr->transid[0];
6618   Tdata[3] = regApiPtr->transid[1];
6619   Tdata[4] = Uint32(regApiPtr->globalcheckpointid);
6620   Uint32 len = 5;
6621 
6622   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
6623     memcpy(&signal->theData[0], &Tdata[0], len << 2);
6624     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
6625     sendSignal(lqhRef, GSN_COMMIT, signal, len, JBB);
6626     return ret;
6627   }
6628 
6629   struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[instanceKey];
6630 
6631   if (container->noOfPackedWords > 25 - len) {
6632     jam();
6633     sendPackedSignal(signal, container);
6634   } else {
6635     jam();
6636     ret = 1;
6637     updatePackedList(signal, Thostptr.p, Thostptr.i);
6638   }
6639 
6640   Tdata[0] |= (ZCOMMIT << 28);
6641   UintR Tindex = container->noOfPackedWords;
6642   container->noOfPackedWords = Tindex + len;
6643   UintR* TDataPtr = &container->packedWords[Tindex];
6644   memcpy(TDataPtr, &Tdata[0], len << 2);
6645   return ret;
6646 }
6647 
6648 void
DIVER_node_fail_handling(Signal * signal,Uint64 Tgci,ApiConnectRecordPtr const apiConnectptr)6649 Dbtc::DIVER_node_fail_handling(Signal* signal, Uint64 Tgci, ApiConnectRecordPtr const apiConnectptr)
6650 {
6651   /*------------------------------------------------------------------------
6652    * AT LEAST ONE NODE HAS FAILED DURING THE TRANSACTION. WE NEED TO CHECK IF
6653    * THIS IS SO SERIOUS THAT WE NEED TO ABORT THE TRANSACTION. IN BOTH THE
6654    * ABORT AND THE COMMIT CASES WE NEED  TO SET-UP THE DATA FOR THE
6655    * ABORT/COMMIT/COMPLETE  HANDLING AS ALSO USED BY TAKE OVER FUNCTIONALITY.
6656    *------------------------------------------------------------------------*/
6657   tabortInd = ZFALSE;
6658   setupFailData(signal, apiConnectptr.p);
6659   if (false && tabortInd == ZFALSE) {
6660     jam();
6661     commitGciHandling(signal, Tgci, apiConnectptr);
6662     toCommitHandlingLab(signal, apiConnectptr);
6663   } else {
6664     jam();
6665     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
6666     apiConnectptr.p->returncode = ZNODEFAIL_BEFORE_COMMIT;
6667     toAbortHandlingLab(signal, apiConnectptr);
6668   }//if
6669   return;
6670 }//Dbtc::DIVER_node_fail_handling()
6671 
6672 
6673 /* ------------------------------------------------------------------------- */
6674 /* -------                       ENTER COMMITTED                     ------- */
6675 /*                                                                           */
6676 /* ------------------------------------------------------------------------- */
execCOMMITTED(Signal * signal)6677 void Dbtc::execCOMMITTED(Signal* signal)
6678 {
6679   TcConnectRecordPtr localTcConnectptr;
6680   ApiConnectRecordPtr localApiConnectptr;
6681   ApiConnectRecordPtr localCopyPtr;
6682 
6683 #ifdef ERROR_INSERT
6684   if (ERROR_INSERTED(8018)) {
6685     CLEAR_ERROR_INSERT_VALUE;
6686     return;
6687   }//if
6688   CRASH_INSERTION(8030);
6689   if (ERROR_INSERTED(8025)) {
6690     SET_ERROR_INSERT_VALUE(8026);
6691     return;
6692   }//if
6693   if (ERROR_INSERTED(8041)) {
6694     CLEAR_ERROR_INSERT_VALUE;
6695     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 3);
6696     return;
6697   }//if
6698   if (ERROR_INSERTED(8042)) {
6699     SET_ERROR_INSERT_VALUE(8046);
6700     sendSignalWithDelay(cownref, GSN_COMMITTED, signal, 2000, 4);
6701     return;
6702   }//if
6703 #endif
6704   localTcConnectptr.i = signal->theData[0];
6705   jamEntry();
6706   if (unlikely(!tcConnectRecord.getValidPtr(localTcConnectptr)))
6707   {
6708     jam();
6709     warningReport(signal, 4);
6710     return;
6711   }
6712   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
6713   if (unlikely(localTcConnectptr.p->tcConnectstate != OS_COMMITTING))
6714   {
6715     jam();
6716     warningReport(signal, 4);
6717     return;
6718   }//if
6719   if (unlikely(!c_apiConnectRecordPool.getValidPtr(localApiConnectptr)))
6720   {
6721     warningReport(signal, 5);
6722     return;
6723   }
6724   UintR Tcounter = localApiConnectptr.p->counter - 1;
6725   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
6726   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
6727   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
6728   Tdata1 = Tdata1 | Tdata2;
6729   bool TcheckCondition =
6730     (TapiConnectstate != CS_COMMIT_SENT) || (Tcounter != 0);
6731 
6732   localTcConnectptr.p->tcConnectstate = OS_COMMITTED;
6733   if (unlikely(Tdata1 != 0))
6734   {
6735     jam();
6736     warningReport(signal, 5);
6737     return;
6738   }//if
6739   setApiConTimer(localApiConnectptr, ctcTimer, __LINE__);
6740   localApiConnectptr.p->counter = Tcounter;
6741   if (unlikely(TcheckCondition))
6742   {
6743     jam();
6744     /*-------------------------------------------------------*/
6745     // We have not sent all COMMIT requests yet. We could be
6746     // in the state that all sent are COMMITTED but we are
6747     // still waiting for a CONTINUEB to send the rest of the
6748     // COMMIT requests.
6749     /*-------------------------------------------------------*/
6750     return;
6751   }//if
6752   if (ERROR_INSERTED(8020)) {
6753     jam();
6754     systemErrorLab(signal, __LINE__);
6755   }//if
6756   /*-------------------------------------------------------*/
6757   /* THE ENTIRE TRANSACTION IS NOW COMMITED                */
6758   /* NOW WE NEED TO SEND THE RESPONSE TO THE APPLICATION.  */
6759   /* THE APPLICATION CAN THEN REUSE THE API CONNECTION AND */
6760   /* THEREFORE WE NEED TO MOVE THE API CONNECTION TO A     */
6761   /* NEW API CONNECT RECORD.                               */
6762   /*-------------------------------------------------------*/
6763 
6764   ApiConnectRecordPtr apiConnectptr;
6765   apiConnectptr = localApiConnectptr;
6766   localCopyPtr = sendApiCommitAndCopy(signal, apiConnectptr);
6767 
6768   UintR Tlqhkeyconfrec = localCopyPtr.p->lqhkeyconfrec;
6769   localCopyPtr.p->counter = Tlqhkeyconfrec;
6770 
6771   if (ERROR_INSERTED(8111))
6772   {
6773     jam();
6774     /* Disconnect API now that entering the Complete phase */
6775     const Uint32 apiNodeId = refToNode(apiConnectptr.p->ndbapiBlockref);
6776     if (getNodeInfo(apiNodeId).getType() == NodeInfo::API)
6777     {
6778       ndbout_c("Error insert 8111, disconnecting API during COMPLETE");
6779       signal->theData[0] = apiNodeId;
6780       sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBA);
6781 
6782       SET_ERROR_INSERT_VALUE(8112); /* Slow completing... */
6783     }
6784   }
6785 
6786   apiConnectptr = localCopyPtr;
6787 
6788   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, localCopyPtr.p->tcConnect);
6789   ndbrequire( tcConList.first(tcConnectptr));
6790   complete010Lab(signal, apiConnectptr);
6791   return;
6792 
6793 }//Dbtc::execCOMMITTED()
6794 
6795 void
sendApiCommitSignal(Signal * signal,ApiConnectRecordPtr const apiConnectptr)6796 Dbtc::sendApiCommitSignal(Signal *signal, ApiConnectRecordPtr const apiConnectptr)
6797 {
6798   ReturnSignal save = apiConnectptr.p->returnsignal;
6799 
6800   if (tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_LATE_COMMIT))
6801   {
6802     jam();
6803     apiConnectptr.p->returnsignal = RS_NO_RETURN;
6804   }
6805   if (apiConnectptr.p->returnsignal == RS_TCKEYCONF)
6806   {
6807     if (ERROR_INSERTED(8054))
6808     {
6809       signal->theData[0] = 9999;
6810       sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 5000, 1);
6811     }
6812     else
6813     {
6814       sendtckeyconf(signal, 1, apiConnectptr);
6815     }
6816   }
6817   else if (apiConnectptr.p->returnsignal == RS_TC_COMMITCONF)
6818   {
6819     jam();
6820     TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
6821     if (apiConnectptr.p->commitAckMarker == RNIL)
6822     {
6823       jam();
6824       commitConf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
6825     }
6826     else
6827     {
6828       jam();
6829       commitConf->apiConnectPtr = apiConnectptr.p->ndbapiConnect | 1;
6830     }
6831     commitConf->transId1 = apiConnectptr.p->transid[0];
6832     commitConf->transId2 = apiConnectptr.p->transid[1];
6833     commitConf->gci_hi = Uint32(apiConnectptr.p->globalcheckpointid >> 32);
6834     commitConf->gci_lo = Uint32(apiConnectptr.p->globalcheckpointid);
6835 
6836     if (!ERROR_INSERTED(8054) && !ERROR_INSERTED(8108))
6837     {
6838       sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TC_COMMITCONF, signal,
6839                  TcCommitConf::SignalLength, JBB);
6840     }
6841     time_track_complete_transaction(apiConnectptr.p);
6842   }
6843   else if (apiConnectptr.p->returnsignal == RS_NO_RETURN)
6844   {
6845     jam();
6846   }
6847   else
6848   {
6849     apiConnectptr.p->returnsignal = save;
6850     TCKEY_abort(signal, 37, apiConnectptr);
6851     return;
6852   }//if
6853   apiConnectptr.p->returnsignal = save;
6854 }
6855 
6856 /*-------------------------------------------------------*/
6857 /*                       SEND_API_COMMIT                 */
6858 /*       SEND COMMIT DECISION TO THE API.                */
6859 /*-------------------------------------------------------*/
6860 Ptr<Dbtc::ApiConnectRecord>
sendApiCommitAndCopy(Signal * signal,ApiConnectRecordPtr const apiConnectptr)6861 Dbtc::sendApiCommitAndCopy(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
6862 {
6863   if (ERROR_INSERTED(8055))
6864   {
6865     /**
6866      * 1) Kill self
6867      * 2) Disconnect API
6868      * 3) Prevent execAPI_FAILREQ from handling trans...
6869      */
6870     signal->theData[0] = 9999;
6871     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 1000, 1);
6872     Uint32 node = refToNode(apiConnectptr.p->ndbapiBlockref);
6873     signal->theData[0] = node;
6874     sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBB);
6875 
6876     SET_ERROR_INSERT_VALUE(8056);
6877 
6878     goto err8055;
6879   }
6880 
6881   sendApiCommitSignal(signal, apiConnectptr);
6882 
6883 err8055:
6884   Ptr<ApiConnectRecord> copyPtr;
6885   /**
6886    * Unlink copy connect record from main connect record to allow main record
6887    * re-use.
6888    */
6889   copyPtr.i = apiConnectptr.p->apiCopyRecord;
6890   apiConnectptr.p->apiCopyRecord = RNIL;
6891   UintR TapiFailState = apiConnectptr.p->apiFailState;
6892 
6893   c_counters.ccommitCount++;
6894   c_apiConnectRecordPool.getPtr(copyPtr);
6895   copyApi(copyPtr, apiConnectptr);
6896   if (TapiFailState == ApiConnectRecord::AFS_API_OK)
6897   {
6898     return copyPtr;
6899   }
6900   else
6901   {
6902     jam();
6903     handleApiFailState(signal, apiConnectptr.i);
6904     return copyPtr;
6905   }//if
6906 }//Dbtc::sendApiCommitAndCopy()
6907 
6908 /* ========================================================================= */
6909 /* =======                  COPY_API                                 ======= */
6910 /*   COPY API RECORD ALSO RESET THE OLD API RECORD SO THAT IT                */
6911 /*   IS PREPARED TO RECEIVE A NEW TRANSACTION.                               */
6912 /*===========================================================================*/
copyApi(ApiConnectRecordPtr copyPtr,ApiConnectRecordPtr regApiPtr)6913 void Dbtc::copyApi(ApiConnectRecordPtr copyPtr, ApiConnectRecordPtr regApiPtr)
6914 {
6915   UintR TndbapiConnect = regApiPtr.p->ndbapiConnect;
6916   UintR Ttransid1 = regApiPtr.p->transid[0];
6917   UintR Ttransid2 = regApiPtr.p->transid[1];
6918   UintR Tlqhkeyconfrec = regApiPtr.p->lqhkeyconfrec;
6919   UintR TgcpPointer = regApiPtr.p->gcpPointer;
6920   Uint32 Tmarker = regApiPtr.p->commitAckMarker;
6921   NdbNodeBitmask Tnodes = regApiPtr.p->m_transaction_nodes;
6922 
6923   copyPtr.p->ndbapiBlockref = regApiPtr.p->ndbapiBlockref;
6924   copyPtr.p->ndbapiConnect = TndbapiConnect;
6925   copyPtr.p->tcConnect = regApiPtr.p->tcConnect;
6926   copyPtr.p->apiConnectstate = CS_COMPLETING;
6927   ndbrequire(copyPtr.p->nextApiConnect == RNIL);
6928   copyPtr.p->transid[0] = Ttransid1;
6929   copyPtr.p->transid[1] = Ttransid2;
6930   copyPtr.p->lqhkeyconfrec = Tlqhkeyconfrec;
6931   copyPtr.p->commitAckMarker = RNIL;
6932   copyPtr.p->m_transaction_nodes = Tnodes;
6933   copyPtr.p->num_commit_ack_markers = 0;
6934   copyPtr.p->singleUserMode = 0;
6935 
6936   GcpRecordPtr gcpPtr;
6937   gcpPtr.i = TgcpPointer;
6938   c_gcpRecordPool.getPtr(gcpPtr);
6939   unlinkApiConnect(gcpPtr, regApiPtr);
6940   linkApiToGcp(gcpPtr, copyPtr);
6941   setApiConTimer(regApiPtr, 0, __LINE__);
6942   regApiPtr.p->apiConnectstate = CS_CONNECTED;
6943   regApiPtr.p->commitAckMarker = RNIL;
6944   regApiPtr.p->tcConnect.init();
6945   regApiPtr.p->m_transaction_nodes.clear();
6946   regApiPtr.p->singleUserMode = 0;
6947   regApiPtr.p->num_commit_ack_markers = 0;
6948   releaseAllSeizedIndexOperations(regApiPtr.p);
6949 
6950   ndbassert(!tc_testbit(regApiPtr.p->m_flags,
6951                         (ApiConnectRecord::TF_INDEX_OP_RETURN |
6952                          ApiConnectRecord::TF_TRIGGER_PENDING)));
6953 
6954   if (tc_testbit(regApiPtr.p->m_flags, ApiConnectRecord::TF_LATE_COMMIT))
6955   {
6956     jam();
6957     if (unlikely(regApiPtr.p->apiFailState != ApiConnectRecord::AFS_API_OK))
6958     {
6959       jam();
6960       /* API failed during commit, no need to bother with LATE_COMMIT */
6961       regApiPtr.p->m_flags &= ~ Uint32(ApiConnectRecord::TF_LATE_COMMIT);
6962 
6963       /* Normal API failure handling will find + remove COMMIT_ACK_MARKER */
6964     }
6965     else
6966     {
6967       /**
6968        * Put pointer from copyPtr to regApiPtr
6969        */
6970       copyPtr.p->apiCopyRecord = regApiPtr.i;
6971 
6972       /**
6973        * Modify state of regApiPtr to prevent future operations...
6974        *   timeout is already reset to 0 above so it won't be found
6975        *   by timeOutLoopStartLab
6976        */
6977       regApiPtr.p->apiConnectstate = CS_COMMITTING;
6978 
6979       /**
6980        * save marker for sendApiCommitSignal
6981        */
6982       copyPtr.p->commitAckMarker = Tmarker;
6983 
6984       /**
6985        * Set ApiConnectRecord::TF_LATE_COMMIT on copyPtr so remember
6986        *  to call sendApiCommitSignal at receive of COMPLETED signal
6987        */
6988       copyPtr.p->m_flags |= ApiConnectRecord::TF_LATE_COMMIT;
6989     }
6990   }
6991 
6992 }//Dbtc::copyApi()
6993 
unlinkApiConnect(Ptr<GcpRecord> gcpPtr,Ptr<ApiConnectRecord> regApiPtr)6994 void Dbtc::unlinkApiConnect(Ptr<GcpRecord> gcpPtr,
6995                             Ptr<ApiConnectRecord> regApiPtr)
6996 {
6997   LocalApiConnectRecord_gcp_list apiConList(c_apiConnectRecordPool,
6998                                             gcpPtr.p->apiConnectList);
6999   apiConList.remove(regApiPtr);
7000 }
7001 
complete010Lab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)7002 void Dbtc::complete010Lab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
7003 {
7004   TcConnectRecordPtr localTcConnectptr;
7005   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
7006 
7007   localTcConnectptr.p = tcConnectptr.p;
7008   setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
7009   UintR TapiConnectptrIndex = apiConnectptr.i;
7010   UintR Tcount = 0;
7011   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
7012   do {
7013     localTcConnectptr.p->apiConnect = TapiConnectptrIndex;
7014     localTcConnectptr.p->tcConnectstate = OS_COMPLETING;
7015 
7016     /* ************ */
7017     /*  COMPLETE  < */
7018     /* ************ */
7019     Tcount += sendCompleteLqh(signal, localTcConnectptr.p, apiConnectptr.p);
7020     if (tcConList.next(localTcConnectptr))
7021     {
7022       if (Tcount < 16 &&
7023           !ERROR_INSERTED(8112))
7024       {
7025         jam();
7026         continue;
7027       } else {
7028         jam();
7029         if (ERROR_INSERTED(8013)) {
7030           CLEAR_ERROR_INSERT_VALUE;
7031           return;
7032         }//if
7033         signal->theData[0] = TcContinueB::ZSEND_COMPLETE_LOOP;
7034         signal->theData[1] = apiConnectptr.i;
7035         signal->theData[2] = localTcConnectptr.i;
7036         if (ERROR_INSERTED(8112))
7037         {
7038           sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
7039           return;
7040         }
7041         sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
7042         return;
7043       }//if
7044     } else {
7045       jam();
7046       regApiPtr->apiConnectstate = CS_COMPLETE_SENT;
7047 
7048       if (ERROR_INSERTED(8112))
7049       {
7050         CLEAR_ERROR_INSERT_VALUE;
7051       }
7052 
7053       return;
7054     }//if
7055   } while (1);
7056 }//Dbtc::complete010Lab()
7057 
7058 Uint32
sendCompleteLqh(Signal * signal,TcConnectRecord * const regTcPtr,ApiConnectRecord * const regApiPtr)7059 Dbtc::sendCompleteLqh(Signal* signal,
7060                       TcConnectRecord * const regTcPtr,
7061                       ApiConnectRecord* const regApiPtr)
7062 {
7063   HostRecordPtr Thostptr;
7064   UintR ThostFilesize = chostFilesize;
7065   Uint32 instanceKey = regTcPtr->lqhInstanceKey;
7066   Thostptr.i = regTcPtr->lastLqhNodeId;
7067   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
7068 
7069   if (ERROR_INSERTED(8114))
7070   {
7071     jam();
7072     /* Don't send COMPLETE to LQH ---> TIMEOUT */
7073     return 0;
7074   }
7075 
7076   Uint32 Tnode = Thostptr.i;
7077   Uint32 self = getOwnNodeId();
7078   Uint32 ret = (Tnode == self) ? 4 : 1;
7079 
7080   Uint32 Tdata[3];
7081   Tdata[0] = regTcPtr->lastLqhCon;
7082   Tdata[1] = regApiPtr->transid[0];
7083   Tdata[2] = regApiPtr->transid[1];
7084   Uint32 len = 3;
7085 
7086   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
7087     memcpy(&signal->theData[0], &Tdata[0], len << 2);
7088     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
7089     sendSignal(lqhRef, GSN_COMPLETE, signal, 3, JBB);
7090     return ret;
7091   }
7092 
7093   struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[instanceKey];
7094 
7095   if (container->noOfPackedWords > 22) {
7096     jam();
7097     sendPackedSignal(signal, container);
7098   } else {
7099     jam();
7100     ret = 1;
7101     updatePackedList(signal, Thostptr.p, Thostptr.i);
7102   }
7103 
7104   Tdata[0] |= (ZCOMPLETE << 28);
7105   UintR Tindex = container->noOfPackedWords;
7106   container->noOfPackedWords = Tindex + len;
7107   UintR* TDataPtr = &container->packedWords[Tindex];
7108   memcpy(TDataPtr, &Tdata[0], len << 2);
7109   return ret;
7110 }
7111 
7112 static
7113 inline
7114 Uint32
getTcConnectRecordDeferredFlag(Uint32 pass)7115 getTcConnectRecordDeferredFlag(Uint32 pass)
7116 {
7117   switch(pass & TriggerPreCommitPass::TPCP_PASS_MAX){
7118   case TriggerPreCommitPass::UK_PASS_0:
7119   case TriggerPreCommitPass::UK_PASS_1:
7120     return Dbtc::TcConnectRecord::SOF_DEFERRED_UK_TRIGGER;
7121   case TriggerPreCommitPass::FK_PASS_0:
7122     return Dbtc::TcConnectRecord::SOF_DEFERRED_FK_TRIGGER;
7123   }
7124   assert(false);
7125   return 0;
7126 }
7127 
7128 static
7129 inline
7130 Uint8
getNextDeferredPass(Uint32 pass)7131 getNextDeferredPass(Uint32 pass)
7132 {
7133   Uint32 loop = (pass & ~Uint32(TriggerPreCommitPass::TPCP_PASS_MAX));
7134   switch(pass & TriggerPreCommitPass::TPCP_PASS_MAX){
7135   case TriggerPreCommitPass::UK_PASS_0:
7136     return loop + TriggerPreCommitPass::UK_PASS_1;
7137   case TriggerPreCommitPass::UK_PASS_1:
7138     return loop + TriggerPreCommitPass::FK_PASS_0;
7139   case TriggerPreCommitPass::FK_PASS_0:
7140     return loop + Uint32(TriggerPreCommitPass::TPCP_PASS_MAX) + 1;
7141   }
7142   assert(false);
7143   return 255;
7144 }
7145 
7146 void
sendFireTrigReq(Signal * signal,Ptr<ApiConnectRecord> regApiPtr)7147 Dbtc::sendFireTrigReq(Signal* signal,
7148                       Ptr<ApiConnectRecord> regApiPtr)
7149 {
7150   ndbrequire(regApiPtr.p->apiConnectstate != CS_WAIT_FIRE_TRIG_REQ);
7151   TcConnectRecordPtr localTcConnectptr;
7152 
7153   setApiConTimer(regApiPtr, ctcTimer, __LINE__);
7154   regApiPtr.p->apiConnectstate = CS_SEND_FIRE_TRIG_REQ;
7155 
7156   UintR TopPtrI = regApiPtr.p->m_firstTcConnectPtrI_FT;
7157   ndbassert(TopPtrI != RNIL);
7158   UintR TlastOpPtrI = regApiPtr.p->m_lastTcConnectPtrI_FT;
7159   ndbassert(TlastOpPtrI != RNIL);
7160   localTcConnectptr.i = TopPtrI;
7161 
7162   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
7163   const Uint32 pass = regApiPtr.p->m_pre_commit_pass;
7164   const Uint32 passflag = getTcConnectRecordDeferredFlag(pass);
7165   Uint32 prevOpPtrI = RNIL;
7166 
7167   /**
7168    * We iterate over a range of Operation records, sending
7169    * FIRE_TRIG_REQ for them if appropriate
7170    *
7171    * We only iterate a few at a time, and we only send a few
7172    * signals at a time, and have a limit on the max
7173    * outstanding
7174    *
7175    * CONTINUEB is used for real-time breaks.
7176    * FIRE_TRIG_CONF is used to wake the iteration when the
7177    * max outstanding limit is reached
7178    */
7179   Uint32 currentFireTrigReqs = regApiPtr.p->m_outstanding_fire_trig_req;
7180   const Uint32 ProcessingUnitsLimit = 16; /* Avoid excessive work and fan-out */
7181   ndbassert(currentFireTrigReqs <= MaxOutstandingFireTrigReqPerTrans);
7182   Uint32 concurrentLimit =
7183     MaxOutstandingFireTrigReqPerTrans - currentFireTrigReqs;
7184 
7185   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr.p->tcConnect);
7186   tcConnectRecord.getPtr(localTcConnectptr);
7187 
7188   for (Uint32 i = 0;
7189        prevOpPtrI != TlastOpPtrI &&
7190          i < ProcessingUnitsLimit &&
7191          concurrentLimit > 0 &&
7192          (regApiPtr.p->m_executing_trigger_ops <
7193           MaxExecutingTriggerOpsPerTrans);
7194        i++)
7195   {
7196     Uint32 flags = localTcConnectptr.p->m_special_op_flags;
7197     if (flags & passflag)
7198     {
7199       jam();
7200       tc_clearbit(flags, passflag);
7201       if (unlikely(! (localTcConnectptr.p->tcConnectstate == OS_PREPARED)))
7202       {
7203         ndbout_c("op: 0x%x trans [ 0x%.8x 0x%.8x ] state: %u (TopPtrI: %x)",
7204                  localTcConnectptr.i,
7205                  regApiPtr.p->transid[0],
7206                  regApiPtr.p->transid[1],
7207                  localTcConnectptr.p->tcConnectstate,
7208                  TopPtrI);
7209         dump_trans(regApiPtr);
7210       }
7211 
7212       ndbrequire(localTcConnectptr.p->tcConnectstate == OS_PREPARED);
7213       localTcConnectptr.p->tcConnectstate = OS_FIRE_TRIG_REQ;
7214       localTcConnectptr.p->m_special_op_flags = flags;
7215       i += sendFireTrigReqLqh(signal, localTcConnectptr, pass, regApiPtr.p);
7216       Tlqhkeyreqrec++;
7217       currentFireTrigReqs++;
7218       concurrentLimit--;
7219     }
7220 
7221     prevOpPtrI = localTcConnectptr.i;
7222 
7223     /**
7224      * next TcConnectRecord can go beyond the TlastOpPtrI.
7225      * However at this point, apiConnectState will go over to
7226      * CS_WAIT_FIRE_TRIG_REQ.
7227      * After reaching this state, this method will not be called.
7228      * So no need to check next TcConnectRecord going out of range.
7229      */
7230     tcConList.next(localTcConnectptr);
7231     regApiPtr.p->m_firstTcConnectPtrI_FT = localTcConnectptr.i;
7232   }
7233 
7234   regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec;
7235   regApiPtr.p->m_outstanding_fire_trig_req = currentFireTrigReqs;
7236 
7237   ndbassert(regApiPtr.p->m_outstanding_fire_trig_req <=
7238             MaxOutstandingFireTrigReqPerTrans);
7239 
7240   if (prevOpPtrI == TlastOpPtrI)
7241   {
7242     /**
7243      * All sent, now wait for FIRE_TRIG_CONF
7244      */
7245     jam();
7246     regApiPtr.p->apiConnectstate = CS_WAIT_FIRE_TRIG_REQ;
7247     regApiPtr.p->m_firstTcConnectPtrI_FT = RNIL;
7248     regApiPtr.p->m_lastTcConnectPtrI_FT = RNIL;
7249     ndbrequire(pass < 255);
7250     regApiPtr.p->m_pre_commit_pass = getNextDeferredPass(pass);
7251 
7252     /**
7253      * Check if we are already finished...
7254      */
7255     checkWaitFireTrigConfDone(signal, regApiPtr);
7256     return;
7257   }
7258   else if (concurrentLimit > 0)
7259   {
7260     /**
7261      * Allowed more outstanding, but have reached single signal
7262      * fan-out limit, use immediate CONTINUEB to send more.
7263      * When sendFireTrigReq resumes sending from execFireTrigConf (limit=1),
7264      * it is enough to send one req at a time, no need to continueB.
7265      */
7266     jam();
7267     regApiPtr.p->lqhkeyreqrec++; // prevent early completion
7268     signal->theData[0] = TcContinueB::ZSEND_FIRE_TRIG_REQ;
7269     signal->theData[1] = regApiPtr.i;
7270     signal->theData[2] = regApiPtr.p->transid[0];
7271     signal->theData[3] = regApiPtr.p->transid[1];
7272 
7273     if (ERROR_INSERTED_CLEAR(8090))
7274     {
7275       sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 5000, 4);
7276     }
7277     else
7278     {
7279       sendSignal(cownref, GSN_CONTINUEB, signal, 4, JBB);
7280     }
7281   }
7282   // else: Reached max outstanding, will attempt to
7283   // send more in FIRE_TRIG_CONF
7284 }
7285 
7286 Uint32
sendFireTrigReqLqh(Signal * signal,Ptr<TcConnectRecord> regTcPtr,Uint32 pass,ApiConnectRecord * const regApiPtr)7287 Dbtc::sendFireTrigReqLqh(Signal* signal,
7288                          Ptr<TcConnectRecord> regTcPtr,
7289                          Uint32 pass,
7290                          ApiConnectRecord* const regApiPtr)
7291 {
7292   HostRecordPtr Thostptr;
7293   UintR ThostFilesize = chostFilesize;
7294   Uint32 instanceKey = regTcPtr.p->lqhInstanceKey;
7295   Thostptr.i = regTcPtr.p->tcNodedata[0];
7296   ptrCheckGuard(Thostptr, ThostFilesize, hostRecord);
7297 
7298   Uint32 Tnode = Thostptr.i;
7299   Uint32 self = getOwnNodeId();
7300   Uint32 ret = (Tnode == self) ? 4 : 1;
7301 
7302   Uint32 Tdata[FireTrigReq::SignalLength];
7303   FireTrigReq * req = CAST_PTR(FireTrigReq, Tdata);
7304   req->tcOpRec = regTcPtr.i;
7305   req->transId[0] = regApiPtr->transid[0];
7306   req->transId[1] = regApiPtr->transid[1];
7307   req->pass = pass;
7308   Uint32 len = FireTrigReq::SignalLength;
7309 
7310   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
7311     memcpy(signal->theData, Tdata, len << 2);
7312     BlockReference lqhRef = numberToRef(DBLQH, instanceKey, Tnode);
7313     sendSignal(lqhRef, GSN_FIRE_TRIG_REQ, signal, len, JBB);
7314     return ret;
7315   }
7316 
7317   struct PackedWordsContainer * container = &Thostptr.p->lqh_pack[instanceKey];
7318 
7319   if (container->noOfPackedWords > 25 - len) {
7320     jam();
7321     sendPackedSignal(signal, container);
7322   } else {
7323     jam();
7324     ret = 1;
7325     updatePackedList(signal, Thostptr.p, Thostptr.i);
7326   }
7327 
7328   Tdata[0] |= (ZFIRE_TRIG_REQ << 28);
7329   UintR Tindex = container->noOfPackedWords;
7330   container->noOfPackedWords = Tindex + len;
7331   UintR* TDataPtr = &container->packedWords[Tindex];
7332   memcpy(TDataPtr, Tdata, len << 2);
7333   return ret;
7334 }
7335 
7336 void
checkWaitFireTrigConfDone(Signal * signal,Ptr<ApiConnectRecord> apiPtr)7337 Dbtc::checkWaitFireTrigConfDone(Signal* signal,
7338                                Ptr<ApiConnectRecord> apiPtr)
7339 {
7340   jam();
7341   ndbassert(apiPtr.p->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ);
7342 
7343   if ( apiPtr.p->m_outstanding_fire_trig_req == 0 &&  // All FireTrigReq sent
7344        apiPtr.p->lqhkeyreqrec == apiPtr.p->lqhkeyconfrec &&  // Any CONTINUEBs done
7345        apiPtr.p->pendingTriggers == 0) // No triggers waiting to execute
7346   {
7347     jam();
7348 
7349     lqhKeyConf_checkTransactionState(signal, apiPtr);
7350   }
7351   else
7352   {
7353     jam();
7354     executeTriggers(signal, &apiPtr);
7355   }
7356 
7357   return;
7358 }
7359 
7360 
7361 void
execFIRE_TRIG_CONF(Signal * signal)7362 Dbtc::execFIRE_TRIG_CONF(Signal* signal)
7363 {
7364   TcConnectRecordPtr localTcConnectptr;
7365   ApiConnectRecordPtr regApiPtr;
7366 
7367   const FireTrigConf * conf = CAST_CONSTPTR(FireTrigConf, signal->theData);
7368   localTcConnectptr.i = conf->tcOpRec;
7369   jamEntry();
7370   if (unlikely(!tcConnectRecord.getValidPtr(localTcConnectptr)))
7371   {
7372     jam();
7373     warningReport(signal, 28);
7374     return;
7375   }
7376   regApiPtr.i = localTcConnectptr.p->apiConnect;
7377   OperationState tcConState = localTcConnectptr.p->tcConnectstate;
7378   if (unlikely(tcConState != OS_FIRE_TRIG_REQ))
7379   {
7380     warningReport(signal, 28);
7381     return;
7382   }//if
7383 
7384   ndbrequire(c_apiConnectRecordPool.getUncheckedPtrRW(regApiPtr));
7385   Uint32 Tlqhkeyreqrec = regApiPtr.p->lqhkeyreqrec;
7386   Uint32 TapiConnectstate = regApiPtr.p->apiConnectstate;
7387   UintR Tdata1 = regApiPtr.p->transid[0] - conf->transId[0];
7388   UintR Tdata2 = regApiPtr.p->transid[1] - conf->transId[1];
7389 
7390   Tdata1 = Tdata1 | Tdata2 | !regApiPtr.p->isExecutingDeferredTriggers();
7391 
7392   ndbrequire(Magic::check_ptr(regApiPtr.p));
7393   if (unlikely(Tdata1 != 0))
7394   {
7395     jam();
7396     warningReport(signal, 28);
7397     return;
7398   }//if
7399 
7400   if (ERROR_INSERTED_CLEAR(8091))
7401   {
7402     jam();
7403     return;
7404   }
7405 
7406   CRASH_INSERTION(8092);
7407 
7408   setApiConTimer(regApiPtr, ctcTimer, __LINE__);
7409   ndbassert(Tlqhkeyreqrec > 0);
7410   regApiPtr.p->lqhkeyreqrec = Tlqhkeyreqrec - 1;
7411   localTcConnectptr.p->tcConnectstate = OS_PREPARED;
7412 
7413   Uint32 numFired  = FireTrigConf::getFiredCount(conf->numFiredTriggers);
7414   Uint32 deferreduk = FireTrigConf::getDeferredUKBit(conf->numFiredTriggers);
7415   Uint32 deferredfk = FireTrigConf::getDeferredFKBit(conf->numFiredTriggers);
7416 
7417   regApiPtr.p->pendingTriggers += numFired;
7418   regApiPtr.p->m_flags |=
7419     ((deferreduk) ? ApiConnectRecord::TF_DEFERRED_UK_TRIGGERS : 0) |
7420     ((deferredfk) ? ApiConnectRecord::TF_DEFERRED_FK_TRIGGERS : 0);
7421   localTcConnectptr.p->m_special_op_flags |=
7422     ((deferreduk) ? TcConnectRecord::SOF_DEFERRED_UK_TRIGGER : 0) |
7423     ((deferredfk) ? TcConnectRecord::SOF_DEFERRED_FK_TRIGGER : 0);
7424 
7425   const bool resumeSearch =
7426     (regApiPtr.p->m_outstanding_fire_trig_req ==
7427      MaxOutstandingFireTrigReqPerTrans);
7428   ndbrequire(regApiPtr.p->m_outstanding_fire_trig_req > 0);
7429   regApiPtr.p->m_outstanding_fire_trig_req--;
7430 
7431   // Resume sending FireTrigReq if possible.
7432   if (TapiConnectstate == CS_SEND_FIRE_TRIG_REQ)
7433   {
7434     jam();
7435     if (resumeSearch)
7436     {
7437       jam();
7438       /* Continue the iteration */
7439       sendFireTrigReq(signal, regApiPtr);
7440     }
7441   }
7442   else
7443   {
7444     jam();
7445     checkWaitFireTrigConfDone(signal, regApiPtr);
7446   }
7447 }
7448 
7449 void
execFIRE_TRIG_REF(Signal * signal)7450 Dbtc::execFIRE_TRIG_REF(Signal* signal)
7451 {
7452   TcConnectRecordPtr localTcConnectptr;
7453   ApiConnectRecordPtr apiConnectptr;
7454 
7455   const FireTrigRef * ref = CAST_CONSTPTR(FireTrigRef, signal->theData);
7456   localTcConnectptr.i = ref->tcOpRec;
7457   jamEntry();
7458   if (unlikely(!tcConnectRecord.getValidPtr(localTcConnectptr)))
7459   {
7460     warningReport(signal, 28);
7461     return;
7462   }
7463   apiConnectptr.i = localTcConnectptr.p->apiConnect;
7464   if (unlikely(localTcConnectptr.p->tcConnectstate != OS_FIRE_TRIG_REQ))
7465   {
7466     warningReport(signal, 28);
7467     return;
7468   }//if
7469   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
7470   {
7471     warningReport(signal, 28);
7472     return;
7473   }
7474 
7475   UintR Tdata1 = apiConnectptr.p->transid[0] - ref->transId[0];
7476   UintR Tdata2 = apiConnectptr.p->transid[1] - ref->transId[1];
7477   Tdata1 = Tdata1 | Tdata2;
7478   if (Tdata1 != 0)
7479   {
7480     jam();
7481     warningReport(signal, 28);
7482     return;
7483   }//if
7484 
7485   if (!apiConnectptr.p->isExecutingDeferredTriggers())
7486   {
7487     jam();
7488     warningReport(signal, 28);
7489     return;
7490   }
7491 
7492   terrorCode = ref->errCode;
7493   abortErrorLab(signal, apiConnectptr);
7494 }
7495 
7496 /**
7497  * The NDB API has now reported that it has heard about the commit of
7498  * transaction, this means that we're ready to remove the commit ack
7499  * markers, both here in DBTC and in all the participating DBLQH's.
7500  */
7501 void
execTC_COMMIT_ACK(Signal * signal)7502 Dbtc::execTC_COMMIT_ACK(Signal* signal)
7503 {
7504   jamEntry();
7505 
7506   CommitAckMarker key;
7507   key.transid1 = signal->theData[0];
7508   key.transid2 = signal->theData[1];
7509 
7510   CommitAckMarkerPtr removedMarker;
7511   m_commitAckMarkerHash.remove(removedMarker, key);
7512   if (unlikely(removedMarker.i == RNIL))
7513   {
7514     jam();
7515     warningHandlerLab(signal, __LINE__);
7516     return;
7517   }//if
7518   sendRemoveMarkers(signal, removedMarker.p, 0);
7519   m_commitAckMarkerPool.release(removedMarker);
7520   checkPoolShrinkNeed(DBTC_COMMIT_ACK_MARKER_TRANSIENT_POOL_INDEX,
7521                       m_commitAckMarkerPool);
7522 }
7523 
7524 void
sendRemoveMarkers(Signal * signal,CommitAckMarker * marker,Uint32 removed_by_fail_api)7525 Dbtc::sendRemoveMarkers(Signal* signal,
7526                         CommitAckMarker * marker,
7527                         Uint32 removed_by_fail_api)
7528 {
7529   jam();
7530   const Uint32 transId1 = marker->transid1;
7531   const Uint32 transId2 = marker->transid2;
7532 
7533   CommitAckMarkerBuffer::DataBufferPool & pool =
7534     c_theCommitAckMarkerBufferPool;
7535   LocalCommitAckMarkerBuffer commitAckMarkers(pool, marker->theDataBuffer);
7536   CommitAckMarkerBuffer::DataBufferIterator iter;
7537   bool next_flag = commitAckMarkers.first(iter);
7538   while (next_flag)
7539   {
7540     jam();
7541     Uint32 dataWord = *iter.data;
7542     NodeId nodeId = dataWord >> 16;
7543     Uint32 instanceKey = dataWord & 0xFFFF;
7544     sendRemoveMarker(signal,
7545                      nodeId,
7546                      instanceKey,
7547                      transId1,
7548                      transId2,
7549                      removed_by_fail_api);
7550     next_flag = commitAckMarkers.next(iter, 1);
7551   }
7552   commitAckMarkers.release();
7553   checkPoolShrinkNeed(DBTC_COMMIT_ACK_MARKER_BUFFER_TRANSIENT_POOL_INDEX,
7554                       c_theCommitAckMarkerBufferPool);
7555 }
7556 
7557 void
sendRemoveMarker(Signal * signal,NodeId nodeId,Uint32 instanceKey,Uint32 transid1,Uint32 transid2,Uint32 removed_by_fail_api)7558 Dbtc::sendRemoveMarker(Signal* signal,
7559                        NodeId nodeId,
7560                        Uint32 instanceKey,
7561                        Uint32 transid1,
7562                        Uint32 transid2,
7563                        Uint32 removed_by_fail_api){
7564   /**
7565    * Seize host ptr
7566    */
7567   HostRecordPtr hostPtr;
7568   const UintR ThostFilesize = chostFilesize;
7569   hostPtr.i = nodeId;
7570   ptrCheckGuard(hostPtr, ThostFilesize, hostRecord);
7571 
7572   Uint32 Tdata[3];
7573   Tdata[0] = removed_by_fail_api;
7574   Tdata[1] = transid1;
7575   Tdata[2] = transid2;
7576   Uint32 len = 3;
7577 
7578   if (instanceKey > MAX_NDBMT_LQH_THREADS) {
7579     jam();
7580     // first word omitted
7581     memcpy(&signal->theData[0], &Tdata[1], (len - 1) << 2);
7582     Uint32 Tnode = hostPtr.i;
7583     BlockReference ref = numberToRef(DBLQH, instanceKey, Tnode);
7584     sendSignal(ref, GSN_REMOVE_MARKER_ORD, signal, len - 1, JBB);
7585     return;
7586   }
7587 
7588   struct PackedWordsContainer * container = &hostPtr.p->lqh_pack[instanceKey];
7589 
7590   if (container->noOfPackedWords > (25 - 3)){
7591     jam();
7592     sendPackedSignal(signal, container);
7593   } else {
7594     jam();
7595     updatePackedList(signal, hostPtr.p, hostPtr.i);
7596   }
7597 
7598   UintR  numWord = container->noOfPackedWords;
7599   UintR* dataPtr = &container->packedWords[numWord];
7600 
7601   container->noOfPackedWords = numWord + len;
7602   Tdata[0] |= (ZREMOVE_MARKER << 28);
7603   memcpy(dataPtr, &Tdata[0], len << 2);
7604 }
7605 
7606 /**
7607  * sendApiLateCommitSignal
7608  *
7609  * This is called at the end of a transaction's
7610  * COMPLETE phase when it has the TF_LATE_COMMIT flag set.
7611  * The Commit notification is sent to the API, and
7612  * the user ApiConnectRecord is returned to a ready state
7613  * for further API interaction.
7614  */
7615 void
sendApiLateCommitSignal(Signal * signal,Ptr<ApiConnectRecord> apiCopy)7616 Dbtc::sendApiLateCommitSignal(Signal* signal,
7617                               Ptr<ApiConnectRecord> apiCopy)
7618 {
7619   jam();
7620 
7621   ApiConnectRecordPtr apiConnectptr;
7622   apiConnectptr.i = apiCopy.p->apiCopyRecord;
7623   c_apiConnectRecordPool.getPtr(apiConnectptr);
7624   /**
7625    * CS_COMMITTING on user ApiCon is inferred by
7626    * TF_LATE_COMMIT on user ApiCon
7627    */
7628   ndbrequire(apiConnectptr.p->apiConnectstate == CS_COMMITTING);
7629   ndbrequire(tc_testbit(apiConnectptr.p->m_flags,
7630                         ApiConnectRecord::TF_LATE_COMMIT));
7631 
7632   apiCopy.p->apiCopyRecord = RNIL;
7633   tc_clearbit(apiCopy.p->m_flags,
7634               ApiConnectRecord::TF_LATE_COMMIT);
7635   apiConnectptr.p->apiConnectstate = CS_CONNECTED;
7636   tc_clearbit(apiConnectptr.p->m_flags,
7637               ApiConnectRecord::TF_LATE_COMMIT);
7638 
7639   /* Transiently re-set the commitAckMarker on the user's
7640    * connectRecord so that we inform API of the need to
7641    * send a COMMIT_ACK.
7642    *
7643    * TODO : Don't actually need the full CommitAckMarker, just a bit
7644    */
7645   ndbassert(apiConnectptr.p->commitAckMarker == RNIL);
7646   apiConnectptr.p->commitAckMarker = apiCopy.p->commitAckMarker;
7647 
7648   sendApiCommitSignal(signal, apiConnectptr);
7649 
7650   apiConnectptr.p->commitAckMarker = RNIL;
7651   apiCopy.p->commitAckMarker = RNIL;
7652 
7653   if (apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK)
7654   {
7655     jam();
7656     /**
7657      * handle if API failed while we were running complete phase
7658      */
7659     handleApiFailState(signal, apiConnectptr.i);
7660   }
7661 }
7662 
execCOMPLETED(Signal * signal)7663 void Dbtc::execCOMPLETED(Signal* signal)
7664 {
7665   TcConnectRecordPtr localTcConnectptr;
7666   ApiConnectRecordPtr localApiConnectptr;
7667 
7668 #ifdef ERROR_INSERT
7669   if (ERROR_INSERTED(8031)) {
7670     systemErrorLab(signal, __LINE__);
7671   }//if
7672   if (ERROR_INSERTED(8019)) {
7673     CLEAR_ERROR_INSERT_VALUE;
7674     return;
7675   }//if
7676   if (ERROR_INSERTED(8027)) {
7677     SET_ERROR_INSERT_VALUE(8028);
7678     return;
7679   }//if
7680   if (ERROR_INSERTED(8043)) {
7681     CLEAR_ERROR_INSERT_VALUE;
7682     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
7683     return;
7684   }//if
7685   if (ERROR_INSERTED(8044)) {
7686     SET_ERROR_INSERT_VALUE(8047);
7687     sendSignalWithDelay(cownref, GSN_COMPLETED, signal, 2000, 3);
7688     return;
7689   }//if
7690 #endif
7691   localTcConnectptr.i = signal->theData[0];
7692   jamEntry();
7693   bool valid_tc_ptr = tcConnectRecord.getValidPtr(localTcConnectptr);
7694   if (!valid_tc_ptr)
7695   {
7696     jam();
7697     warningReport(signal, 6);
7698     return;
7699   }//if
7700   bool Tcond1 = (localTcConnectptr.p->tcConnectstate != OS_COMPLETING);
7701   localApiConnectptr.i = localTcConnectptr.p->apiConnect;
7702   if (Tcond1)
7703   {
7704     jam();
7705     warningReport(signal, 6);
7706     return;
7707   }
7708   ndbrequire(c_apiConnectRecordPool.getUncheckedPtrRW(localApiConnectptr));
7709   PrefetchApiConTimer apiConTimer(c_apiConTimersPool, localApiConnectptr, true);
7710   UintR Tdata1 = localApiConnectptr.p->transid[0] - signal->theData[1];
7711   UintR Tdata2 = localApiConnectptr.p->transid[1] - signal->theData[2];
7712   UintR Tcounter = localApiConnectptr.p->counter - 1;
7713   ConnectionState TapiConnectstate = localApiConnectptr.p->apiConnectstate;
7714   Tdata1 = Tdata1 | Tdata2;
7715   bool TcheckCondition =
7716     (TapiConnectstate != CS_COMPLETE_SENT) || (Tcounter != 0);
7717   ndbrequire(Magic::check_ptr(localApiConnectptr.p));
7718   if (unlikely(Tdata1 != 0))
7719   {
7720     jam();
7721     warningReport(signal, 7);
7722     return;
7723   }//if
7724   localApiConnectptr.p->counter = Tcounter;
7725   localTcConnectptr.p->tcConnectstate = OS_COMPLETED;
7726   localTcConnectptr.p->noOfNodes = 0; // == releaseNodes(signal)
7727   apiConTimer.set_timer(ctcTimer, __LINE__);
7728   if (TcheckCondition) {
7729     jam();
7730     /*-------------------------------------------------------*/
7731     // We have not sent all COMPLETE requests yet. We could be
7732     // in the state that all sent are COMPLETED but we are
7733     // still waiting for a CONTINUEB to send the rest of the
7734     // COMPLETE requests.
7735     /*-------------------------------------------------------*/
7736     return;
7737   }//if
7738   if (ERROR_INSERTED(8021)) {
7739     jam();
7740     systemErrorLab(signal, __LINE__);
7741   }//if
7742 
7743   if (tc_testbit(localApiConnectptr.p->m_flags,
7744                  ApiConnectRecord::TF_LATE_COMMIT))
7745   {
7746     jam();
7747 
7748     sendApiLateCommitSignal(signal, localApiConnectptr);
7749   }
7750   releaseTransResources(signal, localApiConnectptr);
7751   CRASH_INSERTION(8054);
7752 }//Dbtc::execCOMPLETED()
7753 
7754 /*---------------------------------------------------------------------------*/
7755 /*                               RELEASE_TRANS_RESOURCES                     */
7756 /*       RELEASE ALL RESOURCES THAT ARE CONNECTED TO THIS TRANSACTION.       */
7757 /*---------------------------------------------------------------------------*/
releaseTransResources(Signal * signal,ApiConnectRecordPtr const apiConnectptr)7758 void Dbtc::releaseTransResources(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
7759 {
7760   apiConnectptr.p->m_transaction_nodes.clear();
7761   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, apiConnectptr.p->tcConnect);
7762   while (tcConList.removeFirst(tcConnectptr))
7763   {
7764     jam();
7765     releaseTcCon();
7766   }
7767 jam();
7768   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
7769                       tcConnectRecord);
7770 jam();
7771   handleGcp(signal, apiConnectptr);
7772 jam();
7773   releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
7774 jam();
7775   releaseAllSeizedIndexOperations(apiConnectptr.p);
7776 jam();
7777   releaseApiConCopy(signal, apiConnectptr);
7778 jam();
7779 }//Dbtc::releaseTransResources()
7780 
7781 /* *********************************************************************>> */
7782 /*       MODULE: HANDLE_GCP                                                */
7783 /*       DESCRIPTION: HANDLES GLOBAL CHECKPOINT HANDLING AT THE COMPLETION */
7784 /*       OF THE COMMIT PHASE AND THE ABORT PHASE. WE MUST ENSURE THAT TC   */
7785 /*       SENDS GCP_TCFINISHED WHEN ALL TRANSACTIONS BELONGING TO A CERTAIN */
7786 /*       GLOBAL CHECKPOINT HAVE COMPLETED.                                 */
7787 /* *********************************************************************>> */
handleGcp(Signal * signal,ApiConnectRecordPtr const apiConnectptr)7788 void Dbtc::handleGcp(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
7789 {
7790   GcpRecordPtr localGcpPtr;
7791   localGcpPtr.i = apiConnectptr.p->gcpPointer;
7792   c_gcpRecordPool.getPtr(localGcpPtr);
7793   unlinkApiConnect(localGcpPtr, apiConnectptr);
7794   if (localGcpPtr.p->apiConnectList.isEmpty())
7795   {
7796     if (localGcpPtr.p->gcpNomoretransRec == ZTRUE) {
7797       if (c_ongoing_take_over_cnt == 0)
7798       {
7799         jam();
7800         gcpTcfinished(signal, localGcpPtr.p->gcpId);
7801         unlinkAndReleaseGcp(localGcpPtr);
7802       }
7803     }//if
7804   }
7805 }//Dbtc::handleGcp()
7806 
releaseApiConCopy(Signal * signal,ApiConnectRecordPtr const apiConnectptr)7807 void Dbtc::releaseApiConCopy(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
7808 {
7809   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
7810   ndbrequire(regApiPtr->apiConnectkind == ApiConnectRecord::CK_COPY);
7811   ndbassert(regApiPtr->nextApiConnect == RNIL);
7812   setApiConTimer(apiConnectptr, 0, __LINE__);
7813   regApiPtr->apiConnectstate = CS_RESTART;
7814   ndbrequire(regApiPtr->commitAckMarker == RNIL);
7815   regApiPtr->apiConnectkind = ApiConnectRecord::CK_FREE;
7816   releaseApiConTimer(apiConnectptr);
7817   c_apiConnectRecordPool.release(apiConnectptr);
7818   checkPoolShrinkNeed(DBTC_API_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
7819                       c_apiConnectRecordPool);
7820 }//Dbtc::releaseApiConCopy()
7821 
7822 /* ========================================================================= */
7823 /* -------  RELEASE ALL RECORDS CONNECTED TO A DIRTY WRITE OPERATION ------- */
7824 /* ========================================================================= */
releaseDirtyWrite(Signal * signal,ApiConnectRecordPtr const apiConnectptr)7825 void Dbtc::releaseDirtyWrite(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
7826 {
7827   clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
7828   unlinkReadyTcCon(apiConnectptr.p);
7829   releaseTcCon();
7830   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
7831                       tcConnectRecord);
7832   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
7833   if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
7834     if (regApiPtr->tcConnect.isEmpty())
7835     {
7836       jam();
7837       regApiPtr->apiConnectstate = CS_CONNECTED;
7838       setApiConTimer(apiConnectptr, 0, __LINE__);
7839       sendtckeyconf(signal, 1, apiConnectptr);
7840     }//if
7841   }//if
7842 }//Dbtc::releaseDirtyWrite()
7843 
7844 /*****************************************************************************
7845  *                               L Q H K E Y R E F
7846  * WHEN LQHKEYREF IS RECEIVED DBTC WILL CHECK IF COMMIT FLAG WAS SENT FROM THE
7847  * APPLICATION. IF SO, THE WHOLE TRANSACTION WILL BE ROLLED BACK AND SIGNAL
7848  * TCROLLBACKREP WILL BE SENT TO THE API.
7849  *
7850  * OTHERWISE TC WILL CHECK THE ERRORCODE. IF THE ERRORCODE IS INDICATING THAT
7851  * THE "ROW IS NOT FOUND" FOR UPDATE/READ/DELETE OPERATIONS AND "ROW ALREADY
7852  * EXISTS" FOR INSERT OPERATIONS, DBTC WILL RELEASE THE OPERATION AND THEN
7853  * SEND RETURN SIGNAL TCKEYREF TO THE USER. THE USER THEN HAVE TO SEND
7854  * SIGNAL TC_COMMITREQ OR TC_ROLLBACKREQ TO CONCLUDE THE TRANSACTION.
7855  * IF ANY TCKEYREQ WITH COMMIT IS RECEIVED AND API_CONNECTSTATE EQUALS
7856  * "REC_LQHREFUSE",
7857  * THE OPERATION WILL BE TREATED AS AN OPERATION WITHOUT COMMIT. WHEN ANY
7858  * OTHER FAULTCODE IS RECEIVED THE WHOLE TRANSACTION MUST BE ROLLED BACK
7859  *****************************************************************************/
execLQHKEYREF(Signal * signal)7860 void Dbtc::execLQHKEYREF(Signal* signal)
7861 {
7862   const LqhKeyRef * const lqhKeyRef = (LqhKeyRef *)signal->getDataPtr();
7863   Uint32 indexId = 0;
7864   jamEntry();
7865 
7866   UintR compare_transid1, compare_transid2;
7867   /*-------------------------------------------------------------------------
7868    *
7869    * RELEASE NODE BUFFER(S) TO INDICATE THAT THIS OPERATION HAVE NO
7870    * TRANSACTION PARTS ACTIVE ANYMORE.
7871    * LQHKEYREF HAVE CLEARED ALL PARTS ON ITS PATH BACK TO TC.
7872    *-------------------------------------------------------------------------*/
7873   tcConnectptr.i = lqhKeyRef->connectPtr;
7874   if (unlikely(!tcConnectRecord.getValidPtr(tcConnectptr)))
7875   {
7876     jam();
7877     warningReport(signal, 25);
7878     return;
7879   }
7880   {
7881     /*-----------------------------------------------------------------------
7882      * WE HAVE TO CHECK THAT THE TRANSACTION IS STILL VALID. FIRST WE CHECK
7883      * THAT THE LQH IS STILL CONNECTED TO A TC, IF THIS HOLDS TRUE THEN THE
7884      * TC MUST BE CONNECTED TO AN API CONNECT RECORD.
7885      * WE MUST ENSURE THAT THE TRANSACTION ID OF THIS API CONNECT
7886      * RECORD IS STILL THE SAME AS THE ONE LQHKEYREF REFERS TO.
7887      * IF NOT SIMPLY EXIT AND FORGET THE SIGNAL SINCE THE TRANSACTION IS
7888      * ALREADY COMPLETED (ABORTED).
7889      *-----------------------------------------------------------------------*/
7890     Uint32 errCode = terrorCode = lqhKeyRef->errorCode;
7891     TcConnectRecord * const regTcPtr = tcConnectptr.p;
7892     if (regTcPtr->tcConnectstate == OS_OPERATING)
7893     {
7894       ApiConnectRecordPtr apiConnectptr;
7895       Uint32 save = apiConnectptr.i = regTcPtr->apiConnect;
7896       if (!c_apiConnectRecordPool.getValidPtr(apiConnectptr))
7897       {
7898 	warningReport(signal, 25);
7899 	return;
7900       }
7901       ApiConnectRecord * const regApiPtr = apiConnectptr.p;
7902       compare_transid1 = regApiPtr->transid[0] ^ lqhKeyRef->transId1;
7903       compare_transid2 = regApiPtr->transid[1] ^ lqhKeyRef->transId2;
7904       compare_transid1 = compare_transid1 | compare_transid2;
7905       if (compare_transid1 != 0) {
7906 	warningReport(signal, 25);
7907 	return;
7908       }//if
7909 
7910       const Uint32 triggeringOp = regTcPtr->triggeringOperation;
7911       ConnectionState TapiConnectstate = regApiPtr->apiConnectstate;
7912 
7913       time_track_complete_key_operation_error(regTcPtr,
7914                                     refToNode(regApiPtr->ndbapiBlockref),
7915                                     regTcPtr->tcNodedata[0]);
7916 
7917       if (unlikely(TapiConnectstate == CS_ABORTING))
7918       {
7919         jam();
7920         goto do_abort;
7921       }
7922 
7923       if (triggeringOp != RNIL) {
7924         jam();
7925 	// This operation was created by a trigger executing operation
7926         ndbrequire(regApiPtr->m_executing_trigger_ops > 0);
7927         regApiPtr->m_executing_trigger_ops--;
7928 
7929 	TcConnectRecordPtr opPtr;
7930 
7931         opPtr.i = triggeringOp;
7932         tcConnectRecord.getPtr(opPtr);
7933 
7934         const Uint32 opType = regTcPtr->operation;
7935         Ptr<TcDefinedTriggerData> trigPtr;
7936         c_theDefinedTriggers.getPtr(trigPtr, regTcPtr->currentTriggerId);
7937         switch(trigPtr.p->triggerType){
7938         case TriggerType::SECONDARY_INDEX:{
7939           jam();
7940 
7941           // The operation executed an index trigger
7942           TcIndexData* indexData = c_theIndexes.getPtr(trigPtr.p->indexId);
7943           indexId = indexData->indexId;
7944           regApiPtr->errorData = indexId;
7945           if (errCode == ZALREADYEXIST)
7946           {
7947             jam();
7948             errCode = terrorCode = ZNOTUNIQUE;
7949             goto do_abort;
7950           }
7951           else if (!(opType == ZDELETE && errCode == ZNOT_FOUND)) {
7952             jam();
7953             /**
7954              * "Normal path"
7955              */
7956             goto do_abort;
7957           }
7958           else
7959           {
7960             jam();
7961             /** ZDELETE && NOT_FOUND */
7962             if (indexData->indexState != IS_BUILDING)
7963             {
7964               jam();
7965               goto do_abort;
7966             }
7967           }
7968           goto do_ignore;
7969         }
7970         case TriggerType::FULLY_REPLICATED_TRIGGER:
7971         {
7972           jam();
7973           /**
7974            * We have successfully inserted/updated/deleted in main
7975            * fragment, but failed in a copy fragment. In this case
7976            * we need to abort transaction. There are no error codes
7977            * that makes this behaviour ok.
7978            */
7979           goto do_abort;
7980         }
7981         case TriggerType::REORG_TRIGGER:
7982           jam();
7983           if (opType == ZINSERT && errCode == ZALREADYEXIST)
7984           {
7985             jam();
7986             ndbout_c("reorg, ignore ZALREADYEXIST");
7987             goto do_ignore;
7988           }
7989           else if (errCode == ZNOT_FOUND)
7990           {
7991             jam();
7992             ndbout_c("reorg, ignore ZNOT_FOUND");
7993             goto do_ignore;
7994           }
7995           else if (errCode == 839)
7996           {
7997             jam();
7998             ndbout_c("reorg, ignore 839");
7999             goto do_ignore;
8000           }
8001           else
8002           {
8003             ndbout_c("reorg: opType: %u errCode: %u", opType, errCode);
8004           }
8005           // fall-through
8006           goto do_abort;
8007         case TriggerType::FK_CHILD:
8008           jam();
8009           if (errCode == ZNOT_FOUND)
8010           {
8011             errCode = terrorCode = ZFK_NO_PARENT_ROW_EXISTS;
8012             regApiPtr->errorData = trigPtr.p->fkId;
8013           }
8014           goto do_abort;
8015         case TriggerType::FK_PARENT:
8016           jam();
8017           /**
8018            * on delete/update of parent...
8019            *   we found no child row...
8020            *   that means FK not violated...
8021            */
8022           if (errCode == ZNOT_FOUND)
8023           {
8024             jam();
8025             if (regTcPtr->isIndexOp(regTcPtr->m_special_op_flags))
8026             {
8027               jam();
8028               /**
8029                * execTCINDXREQ adds an extra regApiPtr->lqhkeyreqrec++
8030                *   undo this...
8031                */
8032               ndbassert(regApiPtr->lqhkeyreqrec > 0);
8033               regApiPtr->lqhkeyreqrec--;
8034             }
8035             goto do_ignore;
8036           }
8037           else
8038           {
8039             goto do_abort;
8040           }
8041         default:
8042           jam();
8043           ndbassert(false);
8044           goto do_abort;
8045         }
8046 
8047     do_ignore:
8048         jam();
8049         /**
8050          * Ignore error
8051          */
8052         regApiPtr->lqhkeyreqrec--;
8053 
8054         /**
8055          * An failing op in LQH, never leaves the commit ack marker around
8056          * TODO: This can be bug in ordinary code too!!!
8057          */
8058         clearCommitAckMarker(regApiPtr, regTcPtr);
8059 
8060         unlinkReadyTcCon(apiConnectptr.p);
8061         releaseTcCon();
8062         checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
8063                             tcConnectRecord);
8064 
8065         trigger_op_finished(signal, apiConnectptr, RNIL, opPtr.p, 0);
8066 
8067         if (ERROR_INSERTED(8105))
8068         {
8069           abortTransFromTrigger(signal, apiConnectptr, ZGET_DATAREC_ERROR);
8070         }
8071 
8072         ApiConnectRecordPtr transPtr = apiConnectptr;
8073         executeTriggers(signal, &transPtr);
8074         return;
8075       }
8076 
8077   do_abort:
8078       markOperationAborted(regApiPtr, regTcPtr);
8079 
8080       if(regApiPtr->apiConnectstate == CS_ABORTING){
8081 	/**
8082 	 * We're already aborting' so don't send an "extra" TCKEYREF
8083 	 */
8084 	jam();
8085 	return;
8086       }
8087 
8088       const Uint32 abort = regTcPtr->m_execAbortOption;
8089       if (abort == TcKeyReq::AbortOnError || triggeringOp != RNIL) {
8090 	/**
8091 	 * No error is allowed on this operation
8092 	 */
8093         TCKEY_abort(signal, 49, apiConnectptr);
8094 	return;
8095       }//if
8096 
8097       /* *************** */
8098       /*    TCKEYREF   < */
8099       /* *************** */
8100       TcKeyRef * const tcKeyRef = (TcKeyRef *) signal->getDataPtrSend();
8101       tcKeyRef->transId[0] = regApiPtr->transid[0];
8102       tcKeyRef->transId[1] = regApiPtr->transid[1];
8103       tcKeyRef->errorCode = terrorCode;
8104       bool isIndexOp = regTcPtr->isIndexOp(regTcPtr->m_special_op_flags);
8105       Uint32 indexOp = tcConnectptr.p->indexOp;
8106       Uint32 clientData = regTcPtr->clientData;
8107       unlinkReadyTcCon(apiConnectptr.p);   /* LINK TC CONNECT RECORD OUT OF  */
8108       releaseTcCon();       /* RELEASE THE TC CONNECT RECORD  */
8109       checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
8110                           tcConnectRecord);
8111       setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
8112       if (isIndexOp) {
8113         jam();
8114 	regApiPtr->lqhkeyreqrec--; // Compensate for extra during read
8115 	tcKeyRef->connectPtr = indexOp;
8116         tcKeyRef->errorData = indexId;
8117 	EXECUTE_DIRECT(DBTC, GSN_TCKEYREF, signal, TcKeyRef::SignalLength);
8118 	apiConnectptr.i = save;
8119 	apiConnectptr.p = regApiPtr;
8120       } else {
8121         jam();
8122 	tcKeyRef->connectPtr = clientData;
8123         tcKeyRef->errorData = indexId;
8124 	sendSignal(regApiPtr->ndbapiBlockref,
8125 		   GSN_TCKEYREF, signal, TcKeyRef::SignalLength, JBB);
8126       }//if
8127 
8128       /*---------------------------------------------------------------------
8129        * SINCE WE ARE NOT ABORTING WE NEED TO UPDATE THE COUNT OF HOW MANY
8130        * LQHKEYREQ THAT HAVE RETURNED.
8131        * IF NO MORE OUTSTANDING LQHKEYREQ'S THEN WE NEED TO
8132        * TCKEYCONF (IF THERE IS ANYTHING TO SEND).
8133        *---------------------------------------------------------------------*/
8134       regApiPtr->lqhkeyreqrec--;
8135       if (regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec) {
8136 	if (regApiPtr->apiConnectstate == CS_START_COMMITTING) {
8137           jam();
8138           diverify010Lab(signal, apiConnectptr);
8139 	  return;
8140 	}
8141         else if (regApiPtr->tckeyrec > 0 ||
8142                  tc_testbit(regApiPtr->m_flags, ApiConnectRecord::TF_EXEC_FLAG))
8143         {
8144 	  jam();
8145           sendtckeyconf(signal, 2, apiConnectptr);
8146 	  return;
8147 	}
8148       }//if
8149       return;
8150     }
8151     else
8152     {
8153       warningReport(signal, 25);
8154     }//if
8155   }
8156   return;
8157 }//Dbtc::execLQHKEYREF()
8158 
clearCommitAckMarker(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)8159 void Dbtc::clearCommitAckMarker(ApiConnectRecord * const regApiPtr,
8160 				TcConnectRecord * const regTcPtr)
8161 {
8162   jam();
8163   const Uint32 commitAckMarker = regTcPtr->commitAckMarker;
8164   if (regApiPtr->commitAckMarker == RNIL)
8165   {
8166     jam();
8167     ndbassert(commitAckMarker == RNIL);
8168   }
8169 
8170   if(commitAckMarker != RNIL)
8171   {
8172     jam();
8173     ndbrequire(regApiPtr->commitAckMarker == commitAckMarker);
8174     ndbrequire(regApiPtr->num_commit_ack_markers > 0);
8175     regApiPtr->num_commit_ack_markers--;
8176     regTcPtr->commitAckMarker = RNIL;
8177     if (regApiPtr->num_commit_ack_markers == 0)
8178     {
8179       jam();
8180       tc_clearbit(regApiPtr->m_flags,
8181                   ApiConnectRecord::TF_COMMIT_ACK_MARKER_RECEIVED);
8182       releaseMarker(regApiPtr);
8183     }
8184   }
8185 }
8186 
markOperationAborted(ApiConnectRecord * const regApiPtr,TcConnectRecord * const regTcPtr)8187 void Dbtc::markOperationAborted(ApiConnectRecord * const regApiPtr,
8188 				TcConnectRecord * const regTcPtr)
8189 {
8190   /*------------------------------------------------------------------------
8191    * RELEASE NODES TO INDICATE THAT THE OPERATION IS ALREADY ABORTED IN THE
8192    * LQH'S ALSO SET STATE TO ABORTING TO INDICATE THE ABORT IS
8193    * ALREADY COMPLETED.
8194    *------------------------------------------------------------------------*/
8195   regTcPtr->noOfNodes = 0; // == releaseNodes(signal)
8196   regTcPtr->tcConnectstate = OS_ABORTING;
8197   clearCommitAckMarker(regApiPtr, regTcPtr);
8198 }
8199 
8200 /*--------------------------------------*/
8201 /* EXIT AND WAIT FOR SIGNAL TCOMMITREQ  */
8202 /* OR TCROLLBACKREQ FROM THE USER TO    */
8203 /* CONTINUE THE TRANSACTION             */
8204 /*--------------------------------------*/
execTC_COMMITREQ(Signal * signal)8205 void Dbtc::execTC_COMMITREQ(Signal* signal)
8206 {
8207   UintR compare_transid1, compare_transid2;
8208 
8209   jamEntry();
8210   ApiConnectRecordPtr apiConnectptr;
8211   apiConnectptr.i = signal->theData[0];
8212   if (likely(c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
8213   {
8214     compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
8215     compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
8216     if (unlikely(compare_transid1 != 0 || compare_transid2 != 0))
8217     {
8218       jam();
8219       return;
8220     }//if
8221 
8222     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
8223 
8224     const Uint32 apiConnectPtr = regApiPtr->ndbapiConnect;
8225     const Uint32 apiBlockRef   = regApiPtr->ndbapiBlockref;
8226     const Uint32 transId1      = regApiPtr->transid[0];
8227     const Uint32 transId2      = regApiPtr->transid[1];
8228     Uint32 errorCode           = 0;
8229 
8230     regApiPtr->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
8231     switch (regApiPtr->apiConnectstate) {
8232     case CS_STARTED:
8233       if (likely(!regApiPtr->tcConnect.isEmpty()))
8234       {
8235         tcConnectptr.i = regApiPtr->tcConnect.getFirst();
8236         tcConnectRecord.getPtr(tcConnectptr);
8237         if (likely(regApiPtr->lqhkeyconfrec == regApiPtr->lqhkeyreqrec))
8238         {
8239           jam();
8240           /*******************************************************************/
8241           // The proper case where the application is waiting for commit or
8242           // abort order.
8243           // Start the commit order.
8244           /*******************************************************************/
8245           regApiPtr->returnsignal = RS_TC_COMMITCONF;
8246           setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
8247           diverify010Lab(signal, apiConnectptr);
8248           return;
8249         } else {
8250           jam();
8251           /*******************************************************************/
8252           // The transaction is started but not all operations are completed.
8253           // It is not possible to commit the transaction in this state.
8254           // We will abort it instead.
8255           /*******************************************************************/
8256           regApiPtr->returnsignal = RS_NO_RETURN;
8257           errorCode = ZTRANS_STATUS_ERROR;
8258           abort010Lab(signal, apiConnectptr);
8259         }//if
8260       } else {
8261         jam();
8262         /**
8263          * No operations, accept commit
8264          */
8265         TcCommitConf * const commitConf = (TcCommitConf *)&signal->theData[0];
8266         commitConf->apiConnectPtr = apiConnectPtr;
8267         commitConf->transId1 = transId1;
8268         commitConf->transId2 = transId2;
8269         commitConf->gci_hi = 0;
8270         commitConf->gci_lo = 0;
8271         sendSignal(apiBlockRef, GSN_TC_COMMITCONF, signal,
8272 		   TcCommitConf::SignalLength, JBB);
8273 
8274         regApiPtr->returnsignal = RS_NO_RETURN;
8275         releaseAbortResources(signal, apiConnectptr);
8276         return;
8277       }//if
8278       break;
8279     case CS_RECEIVING:
8280       jam();
8281       /***********************************************************************/
8282       // A transaction is still receiving data. We cannot commit an unfinished
8283       // transaction. We will abort it instead.
8284       /***********************************************************************/
8285       regApiPtr->returnsignal = RS_NO_RETURN;
8286       errorCode = ZPREPAREINPROGRESS;
8287       abort010Lab(signal, apiConnectptr);
8288       break;
8289 
8290     case CS_START_COMMITTING:
8291     case CS_COMMITTING:
8292     case CS_COMMIT_SENT:
8293     case CS_COMPLETING:
8294     case CS_COMPLETE_SENT:
8295     case CS_REC_COMMITTING:
8296     case CS_PREPARE_TO_COMMIT:
8297       jam();
8298       /***********************************************************************/
8299       // The transaction is already performing a commit but it is not concluded
8300       // yet.
8301       /***********************************************************************/
8302       errorCode = ZCOMMITINPROGRESS;
8303       break;
8304     case CS_ABORTING:
8305       jam();
8306       errorCode = regApiPtr->returncode ?
8307 	regApiPtr->returncode : ZABORTINPROGRESS;
8308       break;
8309     case CS_START_SCAN:
8310       jam();
8311       /***********************************************************************/
8312       // The transaction is a scan. Scans cannot commit
8313       /***********************************************************************/
8314       errorCode = ZSCANINPROGRESS;
8315       break;
8316     default:
8317       warningHandlerLab(signal, __LINE__);
8318       return;
8319     }//switch
8320     TcCommitRef * const commitRef = (TcCommitRef*)&signal->theData[0];
8321     commitRef->apiConnectPtr = apiConnectPtr;
8322     commitRef->transId1 = transId1;
8323     commitRef->transId2 = transId2;
8324     commitRef->errorCode = errorCode;
8325     sendSignal(apiBlockRef, GSN_TC_COMMITREF, signal,
8326 	       TcCommitRef::SignalLength, JBB);
8327     return;
8328   }
8329   else
8330   {
8331     jam();
8332     warningHandlerLab(signal, __LINE__);
8333     return;
8334   }
8335 }//Dbtc::execTC_COMMITREQ()
8336 
8337 /**
8338  * TCROLLBACKREQ
8339  *
8340  * Format is:
8341  *
8342  * thedata[0] = apiconnectptr
8343  * thedata[1] = transid[0]
8344  * thedata[2] = transid[1]
8345  * OPTIONAL thedata[3] = flags
8346  *
8347  * Flags:
8348  *    0x1  =  potentiallyBad data from API (try not to assert)
8349  */
execTCROLLBACKREQ(Signal * signal)8350 void Dbtc::execTCROLLBACKREQ(Signal* signal)
8351 {
8352   bool potentiallyBad= false;
8353   UintR compare_transid1, compare_transid2;
8354 
8355   jamEntry();
8356 
8357   if(unlikely((signal->getLength() >= 4) && (signal->theData[3] & 0x1)))
8358   {
8359     ndbout_c("Trying to roll back potentially bad txn\n");
8360     potentiallyBad= true;
8361   }
8362 
8363   ApiConnectRecordPtr apiConnectptr;
8364   apiConnectptr.i = signal->theData[0];
8365   if (!unlikely(c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
8366   {
8367     goto TC_ROLL_warning;
8368   }//if
8369   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
8370   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
8371   compare_transid1 = compare_transid1 | compare_transid2;
8372   if (unlikely(compare_transid1 != 0))
8373   {
8374     jam();
8375     return;
8376   }//if
8377 
8378   apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
8379   switch (apiConnectptr.p->apiConnectstate) {
8380   case CS_STARTED:
8381   case CS_RECEIVING:
8382     jam();
8383     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
8384     abort010Lab(signal, apiConnectptr);
8385     return;
8386   case CS_CONNECTED:
8387     jam();
8388     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
8389     signal->theData[1] = apiConnectptr.p->transid[0];
8390     signal->theData[2] = apiConnectptr.p->transid[1];
8391     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
8392 	       signal, 3, JBB);
8393     break;
8394   case CS_START_SCAN:
8395   case CS_PREPARE_TO_COMMIT:
8396   case CS_COMMITTING:
8397   case CS_COMMIT_SENT:
8398   case CS_COMPLETING:
8399   case CS_COMPLETE_SENT:
8400   case CS_WAIT_COMMIT_CONF:
8401   case CS_WAIT_COMPLETE_CONF:
8402   case CS_RESTART:
8403   case CS_DISCONNECTED:
8404   case CS_START_COMMITTING:
8405   case CS_REC_COMMITTING:
8406     jam();
8407     /* ***************< */
8408     /* TC_ROLLBACKREF < */
8409     /* ***************< */
8410     signal->theData[0] = apiConnectptr.p->ndbapiConnect;
8411     signal->theData[1] = apiConnectptr.p->transid[0];
8412     signal->theData[2] = apiConnectptr.p->transid[1];
8413     signal->theData[3] = ZROLLBACKNOTALLOWED;
8414     signal->theData[4] = apiConnectptr.p->apiConnectstate;
8415     sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKREF,
8416 	       signal, 5, JBB);
8417     break;
8418                                                  /* SEND A REFUSAL SIGNAL*/
8419   case CS_ABORTING:
8420     jam();
8421     if (apiConnectptr.p->abortState == AS_IDLE) {
8422       jam();
8423       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
8424       signal->theData[1] = apiConnectptr.p->transid[0];
8425       signal->theData[2] = apiConnectptr.p->transid[1];
8426       sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_TCROLLBACKCONF,
8427 		 signal, 3, JBB);
8428     } else {
8429       jam();
8430       apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
8431     }//if
8432     break;
8433   case CS_WAIT_ABORT_CONF:
8434     jam();
8435     apiConnectptr.p->returnsignal = RS_TCROLLBACKCONF;
8436     break;
8437   default:
8438     goto TC_ROLL_system_error;
8439     break;
8440   }//switch
8441   return;
8442 
8443 TC_ROLL_warning:
8444   jam();
8445   if(likely(potentiallyBad==false))
8446   {
8447     jam();
8448     warningHandlerLab(signal, __LINE__);
8449   }
8450   return;
8451 
8452 TC_ROLL_system_error:
8453   jam();
8454   if(likely(potentiallyBad==false))
8455     systemErrorLab(signal, __LINE__);
8456   return;
8457 }//Dbtc::execTCROLLBACKREQ()
8458 
execTC_HBREP(Signal * signal)8459 void Dbtc::execTC_HBREP(Signal* signal)
8460 {
8461   const TcHbRep * const tcHbRep =
8462     (TcHbRep *)signal->getDataPtr();
8463 
8464   jamEntry();
8465   ApiConnectRecordPtr apiConnectptr;
8466   apiConnectptr.i = tcHbRep->apiConnectPtr;
8467   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
8468   {
8469     jam();
8470     warningHandlerLab(signal, __LINE__);
8471     return;
8472   }
8473 
8474   if (likely(apiConnectptr.p->transid[0] == tcHbRep->transId1 &&
8475              apiConnectptr.p->transid[1] == tcHbRep->transId2))
8476   {
8477 
8478     if (likely(getApiConTimer(apiConnectptr) != 0))
8479     {
8480       setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
8481     } else {
8482       DEBUG("TCHBREP received when timer was off apiConnectptr.i="
8483 	    << apiConnectptr.i);
8484     }
8485   }
8486 }//Dbtc::execTCHBREP()
8487 
8488 /*
8489 4.3.15 ABORT
8490 -----------
8491 */
8492 /*****************************************************************************/
8493 /*                                  A B O R T                                */
8494 /*                                                                           */
8495 /*****************************************************************************/
warningReport(Signal * signal,int place)8496 void Dbtc::warningReport(Signal* signal, int place)
8497 {
8498   switch (place) {
8499   case 0:
8500     jam();
8501 #ifdef ABORT_TRACE
8502     ndbout << "ABORTED to not active TC record" << endl;
8503 #endif
8504     break;
8505   case 1:
8506     jam();
8507 #ifdef ABORT_TRACE
8508     ndbout << "ABORTED to TC record active with new transaction" << endl;
8509 #endif
8510     break;
8511   case 2:
8512     jam();
8513 #ifdef ABORT_TRACE
8514     ndbout << "ABORTED to active TC record not expecting ABORTED" << endl;
8515 #endif
8516     break;
8517   case 3:
8518     jam();
8519 #ifdef ABORT_TRACE
8520     ndbout << "ABORTED to TC rec active with trans but wrong node" << endl;
8521     ndbout << "This is ok when aborting in node failure situations" << endl;
8522 #endif
8523     break;
8524   case 4:
8525     jam();
8526 #ifdef ABORT_TRACE
8527     ndbout << "Received COMMITTED in wrong state in Dbtc" << endl;
8528 #endif
8529     break;
8530   case 5:
8531     jam();
8532 #ifdef ABORT_TRACE
8533     ndbout << "Received COMMITTED with wrong transid in Dbtc" << endl;
8534 #endif
8535     break;
8536   case 6:
8537     jam();
8538 #ifdef ABORT_TRACE
8539     ndbout << "Received COMPLETED in wrong state in Dbtc" << endl;
8540 #endif
8541     break;
8542   case 7:
8543     jam();
8544 #ifdef ABORT_TRACE
8545     ndbout << "Received COMPLETED with wrong transid in Dbtc" << endl;
8546 #endif
8547     break;
8548   case 8:
8549     jam();
8550 #ifdef ABORT_TRACE
8551     ndbout << "Received COMMITCONF with tc-rec in wrong state in Dbtc" << endl;
8552 #endif
8553     break;
8554   case 9:
8555     jam();
8556 #ifdef ABORT_TRACE
8557     ndbout << "Received COMMITCONF with api-rec in wrong state in Dbtc" <<endl;
8558 #endif
8559     break;
8560   case 10:
8561     jam();
8562 #ifdef ABORT_TRACE
8563     ndbout << "Received COMMITCONF with wrong transid in Dbtc" << endl;
8564 #endif
8565     break;
8566   case 11:
8567     jam();
8568 #ifdef ABORT_TRACE
8569     ndbout << "Received COMMITCONF from wrong nodeid in Dbtc" << endl;
8570 #endif
8571     break;
8572   case 12:
8573     jam();
8574 #ifdef ABORT_TRACE
8575     ndbout << "Received COMPLETECONF, tc-rec in wrong state in Dbtc" << endl;
8576 #endif
8577     break;
8578   case 13:
8579     jam();
8580 #ifdef ABORT_TRACE
8581     ndbout << "Received COMPLETECONF, api-rec in wrong state in Dbtc" << endl;
8582 #endif
8583     break;
8584   case 14:
8585     jam();
8586 #ifdef ABORT_TRACE
8587     ndbout << "Received COMPLETECONF with wrong transid in Dbtc" << endl;
8588 #endif
8589     break;
8590   case 15:
8591     jam();
8592 #ifdef ABORT_TRACE
8593     ndbout << "Received COMPLETECONF from wrong nodeid in Dbtc" << endl;
8594 #endif
8595     break;
8596   case 16:
8597     jam();
8598 #ifdef ABORT_TRACE
8599     ndbout << "Received ABORTCONF, tc-rec in wrong state in Dbtc" << endl;
8600 #endif
8601     break;
8602   case 17:
8603     jam();
8604 #ifdef ABORT_TRACE
8605     ndbout << "Received ABORTCONF, api-rec in wrong state in Dbtc" << endl;
8606 #endif
8607     break;
8608   case 18:
8609     jam();
8610 #ifdef ABORT_TRACE
8611     ndbout << "Received ABORTCONF with wrong transid in Dbtc" << endl;
8612 #endif
8613     break;
8614   case 19:
8615     jam();
8616 #ifdef ABORT_TRACE
8617     ndbout << "Received ABORTCONF from wrong nodeid in Dbtc" << endl;
8618 #endif
8619     break;
8620   case 20:
8621     jam();
8622 #ifdef ABORT_TRACE
8623     ndbout << "Time-out waiting for ABORTCONF in Dbtc" << endl;
8624 #endif
8625     break;
8626   case 21:
8627     jam();
8628 #ifdef ABORT_TRACE
8629     ndbout << "Time-out waiting for COMMITCONF in Dbtc" << endl;
8630 #endif
8631     break;
8632   case 22:
8633     jam();
8634 #ifdef ABORT_TRACE
8635     ndbout << "Time-out waiting for COMPLETECONF in Dbtc" << endl;
8636 #endif
8637     break;
8638   case 23:
8639     jam();
8640 #ifdef ABORT_TRACE
8641     ndbout << "Received LQHKEYCONF in wrong tc-state in Dbtc" << endl;
8642 #endif
8643     break;
8644   case 24:
8645     jam();
8646 #ifdef ABORT_TRACE
8647     ndbout << "Received LQHKEYREF to wrong transid in Dbtc" << endl;
8648 #endif
8649     break;
8650   case 25:
8651     jam();
8652 #ifdef ABORT_TRACE
8653     ndbout << "Received LQHKEYREF in wrong state in Dbtc" << endl;
8654 #endif
8655     break;
8656   case 26:
8657     jam();
8658 #ifdef ABORT_TRACE
8659     ndbout << "Received LQHKEYCONF to wrong transid in Dbtc" << endl;
8660 #endif
8661     break;
8662   case 27:
8663     jam();
8664     // printState(signal, 27, apiConnectptr);
8665 #ifdef ABORT_TRACE
8666     ndbout << "Received LQHKEYCONF in wrong api-state in Dbtc" << endl;
8667 #endif
8668     break;
8669   case 28:
8670     jam();
8671 #ifdef ABORT_TRACE
8672     ndbout << "Discarding FIRE_TRIG_REF/CONF in Dbtc" << endl;
8673 #endif
8674     break;
8675   case 29:
8676     jam();
8677 #ifdef ABORT_TRACE
8678     ndbout << "Discarding TcContinueB::ZSEND_FIRE_TRIG_REQ in Dbtc" << endl;
8679 #endif
8680     break;
8681   default:
8682     jam();
8683 #ifdef ABORT_TRACE
8684     ndbout << "Dbtc::warningReport(%u)" << place << endl;
8685 #endif
8686     break;
8687   }//switch
8688   return;
8689 }//Dbtc::warningReport()
8690 
errorReport(Signal * signal,int place)8691 void Dbtc::errorReport(Signal* signal, int place)
8692 {
8693   switch (place) {
8694   case 0:
8695     jam();
8696     break;
8697   case 1:
8698     jam();
8699     break;
8700   case 2:
8701     jam();
8702     break;
8703   case 3:
8704     jam();
8705     break;
8706   case 4:
8707     jam();
8708     break;
8709   case 5:
8710     jam();
8711     break;
8712   case 6:
8713     jam();
8714     break;
8715   default:
8716     jam();
8717     break;
8718   }//switch
8719   systemErrorLab(signal, __LINE__);
8720   return;
8721 }//Dbtc::errorReport()
8722 
8723 /* ------------------------------------------------------------------------- */
8724 /* -------                       ENTER ABORTED                       ------- */
8725 /*                                                                           */
8726 /*-------------------------------------------------------------------------- */
execABORTED(Signal * signal)8727 void Dbtc::execABORTED(Signal* signal)
8728 {
8729   UintR compare_transid1, compare_transid2;
8730 
8731   jamEntry();
8732   tcConnectptr.i = signal->theData[0];
8733   UintR Tnodeid = signal->theData[3];
8734   UintR TlastLqhInd = signal->theData[4];
8735 
8736   if (ERROR_INSERTED(8040)) {
8737     CLEAR_ERROR_INSERT_VALUE;
8738     sendSignalWithDelay(cownref, GSN_ABORTED, signal, 2000, 5);
8739     return;
8740   }//if
8741   /*------------------------------------------------------------------------
8742    *    ONE PARTICIPANT IN THE TRANSACTION HAS REPORTED THAT IT IS ABORTED.
8743    *------------------------------------------------------------------------*/
8744   /*-------------------------------------------------------------------------
8745    *     WE HAVE TO CHECK THAT THIS IS NOT AN OLD SIGNAL BELONGING TO A
8746    *     TRANSACTION ALREADY ABORTED. THIS CAN HAPPEN WHEN TIME-OUT OCCURS
8747    *     IN TC WAITING FOR ABORTED.
8748    *-------------------------------------------------------------------------*/
8749   if (unlikely(!tcConnectRecord.getValidPtr(tcConnectptr)))
8750   {
8751     warningReport(signal, 2);
8752     return;
8753     /*-----------------------------------------------------------------------*/
8754     // ABORTED reported on an operation not expecting ABORT.
8755     /*-----------------------------------------------------------------------*/
8756   }//if
8757   ApiConnectRecordPtr apiConnectptr;
8758   apiConnectptr.i = tcConnectptr.p->apiConnect;
8759   ndbrequire(c_apiConnectRecordPool.getUncheckedPtrRW(apiConnectptr));
8760   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[1];
8761   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[2];
8762   compare_transid1 = compare_transid1 | compare_transid2;
8763   if (unlikely(compare_transid1 != 0))
8764   {
8765     jam();
8766     warningReport(signal, 1);
8767     return;
8768   }//if
8769   if (ERROR_INSERTED(8024))
8770   {
8771     jam();
8772     systemErrorLab(signal, __LINE__);
8773   }//if
8774 
8775   /**
8776    * Release marker
8777    */
8778   clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
8779 
8780   Uint32 i;
8781   Uint32 Tfound = 0;
8782   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
8783     jam();
8784     if (tcConnectptr.p->tcNodedata[i] == Tnodeid) {
8785       /*---------------------------------------------------------------------
8786        * We have received ABORTED from one of the participants in this
8787        * operation in this aborted transaction.
8788        * Record all nodes that have completed abort.
8789        * If last indicator is set it means that no more replica has
8790        * heard of the operation and are thus also aborted.
8791        *---------------------------------------------------------------------*/
8792       jam();
8793       Tfound = 1;
8794       clearTcNodeData(signal, TlastLqhInd, i);
8795     }//if
8796   }//for
8797   if (unlikely(Tfound == 0))
8798   {
8799     warningReport(signal, 3);
8800     return;
8801   }
8802   for (i = 0; i < tcConnectptr.p->noOfNodes; i++) {
8803     if (tcConnectptr.p->tcNodedata[i] != 0) {
8804       /*--------------------------------------------------------------------
8805        * There are still outstanding ABORTED's to wait for.
8806        *--------------------------------------------------------------------*/
8807       jam();
8808       return;
8809     }//if
8810   }//for
8811   tcConnectptr.p->noOfNodes = 0;
8812   tcConnectptr.p->tcConnectstate = OS_ABORTING;
8813   setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
8814   apiConnectptr.p->counter--;
8815   if (apiConnectptr.p->counter > 0) {
8816     jam();
8817     /*----------------------------------------------------------------------
8818      *       WE ARE STILL WAITING FOR MORE PARTICIPANTS TO SEND ABORTED.
8819      *----------------------------------------------------------------------*/
8820     return;
8821   }//if
8822   /*------------------------------------------------------------------------*/
8823   /*                                                                        */
8824   /*     WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED  */
8825   /*     FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL   */
8826   /*     RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE */
8827   /*------------------------------------------------------------------------*/
8828   releaseAbortResources(signal, apiConnectptr);
8829 }//Dbtc::execABORTED()
8830 
clearTcNodeData(Signal * signal,UintR TLastLqhIndicator,UintR Tstart)8831 void Dbtc::clearTcNodeData(Signal* signal,
8832                            UintR TLastLqhIndicator,
8833                            UintR Tstart)
8834 {
8835   UintR Ti;
8836   if (TLastLqhIndicator == ZTRUE) {
8837     for (Ti = Tstart ; Ti < tcConnectptr.p->noOfNodes; Ti++) {
8838       jam();
8839       tcConnectptr.p->tcNodedata[Ti] = 0;
8840     }//for
8841   } else {
8842     jam();
8843     tcConnectptr.p->tcNodedata[Tstart] = 0;
8844   }//for
8845 }//clearTcNodeData()
8846 
abortErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)8847 void Dbtc::abortErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
8848 {
8849   ptrGuard(apiConnectptr);
8850   ApiConnectRecord * transP = apiConnectptr.p;
8851   if (transP->apiConnectstate == CS_ABORTING && transP->abortState != AS_IDLE){
8852     jam();
8853     return;
8854   }
8855   transP->returnsignal = RS_TCROLLBACKREP;
8856   if(transP->returncode == 0){
8857     jam();
8858     transP->returncode = terrorCode;
8859   }
8860   abort010Lab(signal, apiConnectptr);
8861 }//Dbtc::abortErrorLab()
8862 
abort010Lab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)8863 void Dbtc::abort010Lab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
8864 {
8865   ApiConnectRecord * transP = apiConnectptr.p;
8866   if (unlikely(transP->apiConnectstate == CS_ABORTING &&
8867                transP->abortState != AS_IDLE))
8868   {
8869     jam();
8870     return;
8871   }
8872   transP->apiConnectstate = CS_ABORTING;
8873   /*------------------------------------------------------------------------*/
8874   /*     AN ABORT DECISION HAS BEEN TAKEN FOR SOME REASON. WE NEED TO ABORT */
8875   /*     ALL PARTICIPANTS IN THE TRANSACTION.                               */
8876   /*------------------------------------------------------------------------*/
8877   transP->abortState = AS_ACTIVE;
8878   transP->counter = 0;
8879 
8880   if (transP->tcConnect.isEmpty())
8881   {
8882     jam();
8883     /*--------------------------------------------------------------------*/
8884     /* WE HAVE NO PARTICIPANTS IN THE TRANSACTION.                        */
8885     /*--------------------------------------------------------------------*/
8886     releaseAbortResources(signal, apiConnectptr);
8887     return;
8888   }//if
8889   tcConnectptr.i = transP->tcConnect.getFirst();
8890   abort015Lab(signal, apiConnectptr);
8891 }//Dbtc::abort010Lab()
8892 
8893 /*--------------------------------------------------------------------------*/
8894 /*                                                                          */
8895 /*       WE WILL ABORT ONE NODE PER OPERATION AT A TIME. THIS IS TO KEEP    */
8896 /*       ERROR HANDLING OF THIS PROCESS FAIRLY SIMPLE AND TRACTABLE.        */
8897 /*       EVEN IF NO NODE OF THIS PARTICULAR NODE NUMBER NEEDS ABORTION WE   */
8898 /*       MUST ENSURE THAT ALL NODES ARE CHECKED. THUS A FAULTY NODE DOES    */
8899 /*       NOT MEAN THAT ALL NODES IN AN OPERATION IS ABORTED. FOR THIS REASON*/
8900 /*       WE SET THE TCONTINUE_ABORT TO TRUE WHEN A FAULTY NODE IS DETECTED. */
8901 /*--------------------------------------------------------------------------*/
abort015Lab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)8902 void Dbtc::abort015Lab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
8903 {
8904   Uint32 TloopCount = 0;
8905 ABORT020:
8906   jam();
8907   TloopCount++;
8908   tcConnectRecord.getPtr(tcConnectptr);
8909   switch (tcConnectptr.p->tcConnectstate)
8910   {
8911   case OS_WAIT_DIH:
8912   case OS_WAIT_KEYINFO:
8913   case OS_WAIT_ATTR:
8914     jam();
8915     /*----------------------------------------------------------------------*/
8916     /* WE ARE STILL WAITING FOR MORE KEYINFO/ATTRINFO. WE HAVE NOT CONTACTED*/
8917     /* ANY LQH YET AND SO WE CAN SIMPLY SET STATE TO ABORTING.              */
8918     /*----------------------------------------------------------------------*/
8919     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
8920     tcConnectptr.p->tcConnectstate = OS_ABORTING;
8921     break;
8922   case OS_CONNECTED:
8923     jam();
8924     /*-----------------------------------------------------------------------
8925      *   WE ARE STILL IN THE INITIAL PHASE OF THIS OPERATION.
8926      *   NEED NOT BOTHER ABOUT ANY LQH ABORTS.
8927      *-----------------------------------------------------------------------*/
8928     tcConnectptr.p->noOfNodes = 0; // == releaseAbort(signal)
8929     tcConnectptr.p->tcConnectstate = OS_ABORTING;
8930     break;
8931   case OS_PREPARED:
8932     jam();
8933     // Fall through
8934   case OS_OPERATING:
8935     jam();
8936     // Fall through
8937   case OS_FIRE_TRIG_REQ:
8938     jam();
8939     /*----------------------------------------------------------------------
8940      * WE HAVE SENT LQHKEYREQ AND ARE IN SOME STATE OF EITHER STILL
8941      * SENDING THE OPERATION, WAITING FOR REPLIES, WAITING FOR MORE
8942      * ATTRINFO OR OPERATION IS PREPARED. WE NEED TO ABORT ALL LQH'S.
8943      *----------------------------------------------------------------------*/
8944     releaseAndAbort(signal, apiConnectptr.p);
8945     tcConnectptr.p->tcConnectstate = OS_ABORT_SENT;
8946     TloopCount += 127;
8947     break;
8948   case OS_ABORTING:
8949     jam();
8950     break;
8951   case OS_ABORT_SENT:
8952     jam();
8953     DEBUG("ABORT_SENT state in abort015Lab(), not expected");
8954     systemErrorLab(signal, __LINE__);
8955     return;
8956   default:
8957     jam();
8958     DEBUG("tcConnectstate = " << tcConnectptr.p->tcConnectstate);
8959     systemErrorLab(signal, __LINE__);
8960     return;
8961   }//switch
8962 
8963   if (tcConnectptr.p->nextList != RNIL)
8964   {
8965     jam();
8966     tcConnectptr.i = tcConnectptr.p->nextList;
8967     if (TloopCount < 1024 &&
8968         !ERROR_INSERTED(8089) &&
8969         !ERROR_INSERTED(8105))
8970     {
8971       goto ABORT020;
8972     }
8973     else
8974     {
8975       jam();
8976       /*---------------------------------------------------------------------
8977        * Reset timer to avoid time-out in real-time break.
8978        * Increase counter to ensure that we don't think that all ABORTED have
8979        * been received before all have been sent.
8980        *---------------------------------------------------------------------*/
8981       apiConnectptr.p->counter++;
8982       setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
8983       signal->theData[0] = TcContinueB::ZABORT_BREAK;
8984       signal->theData[1] = tcConnectptr.i;
8985       signal->theData[2] = apiConnectptr.i;
8986       signal->theData[3] = apiConnectptr.p->transid[0];
8987       signal->theData[4] = apiConnectptr.p->transid[1];
8988       if (ERROR_INSERTED(8089))
8989       {
8990         sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 100, 3);
8991         return;
8992       }
8993       sendSignal(cownref, GSN_CONTINUEB, signal, 5, JBB);
8994       return;
8995     }//if
8996   }//if
8997 
8998   if (ERROR_INSERTED(8089))
8999   {
9000     CLEAR_ERROR_INSERT_VALUE;
9001   }
9002 
9003   if (apiConnectptr.p->counter > 0) {
9004     jam();
9005     setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
9006     return;
9007   }//if
9008   /*-----------------------------------------------------------------------
9009    *    WE HAVE NOW COMPLETED THE ABORT PROCESS. WE HAVE RECEIVED ABORTED
9010    *    FROM ALL PARTICIPANTS IN THE TRANSACTION. WE CAN NOW RELEASE ALL
9011    *    RESOURCES CONNECTED TO THE TRANSACTION AND SEND THE ABORT RESPONSE
9012    *------------------------------------------------------------------------*/
9013   releaseAbortResources(signal, apiConnectptr);
9014 }//Dbtc::abort015Lab()
9015 
9016 /*--------------------------------------------------------------------------*/
9017 /*       RELEASE KEY AND ATTRINFO OBJECTS AND SEND ABORT TO THE LQH BLOCK.  */
9018 /*--------------------------------------------------------------------------*/
releaseAndAbort(Signal * signal,ApiConnectRecord * const regApiPtr)9019 int Dbtc::releaseAndAbort(Signal* signal, ApiConnectRecord* const regApiPtr)
9020 {
9021   HostRecordPtr localHostptr;
9022   UintR TnoLoops = tcConnectptr.p->noOfNodes;
9023 
9024   regApiPtr->counter++;
9025   bool prevAlive = false;
9026   for (Uint32 Ti = 0; Ti < TnoLoops ; Ti++) {
9027     localHostptr.i = tcConnectptr.p->tcNodedata[Ti];
9028     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
9029     if (localHostptr.p->hostStatus == HS_ALIVE) {
9030       jam();
9031       if (prevAlive) {
9032         // if previous is alive, its LQH forwards abort to this node
9033         jam();
9034         continue;
9035       }
9036       /* ************< */
9037       /*    ABORT    < */
9038       /* ************< */
9039       Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9040       tblockref = numberToRef(DBLQH, instanceKey, localHostptr.i);
9041       signal->theData[0] = tcConnectptr.i;
9042       signal->theData[1] = cownref;
9043       signal->theData[2] = regApiPtr->transid[0];
9044       signal->theData[3] = regApiPtr->transid[1];
9045       sendSignal(tblockref, GSN_ABORT, signal, 4, JBB);
9046       prevAlive = true;
9047     } else {
9048       jam();
9049       signal->theData[0] = tcConnectptr.i;
9050       signal->theData[1] = regApiPtr->transid[0];
9051       signal->theData[2] = regApiPtr->transid[1];
9052       signal->theData[3] = localHostptr.i;
9053       signal->theData[4] = ZFALSE;
9054       sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
9055       prevAlive = false;
9056     }//if
9057   }//for
9058   return 1;
9059 }//Dbtc::releaseAndAbort()
9060 
9061 /* ------------------------------------------------------------------------- */
9062 /* -------                       ENTER TIME_SIGNAL                   ------- */
9063 /*                                                                           */
9064 /* ------------------------------------------------------------------------- */
execTIME_SIGNAL(Signal * signal)9065 void Dbtc::execTIME_SIGNAL(Signal* signal)
9066 {
9067   jamEntry();
9068 
9069   const NDB_TICKS currentTime = NdbTick_getCurrentTicks();
9070   Uint64 num_ms_elapsed = elapsed_time(signal,
9071                                        currentTime,
9072                                        c_latestTIME_SIGNAL,
9073                                        Uint32(TC_TIME_SIGNAL_DELAY));
9074   sendTIME_SIGNAL(signal, currentTime, Uint32(TC_TIME_SIGNAL_DELAY));
9075 
9076   /**
9077    * The code here will make calls to timer_handling that appears to happen
9078    * every 10ms but in reality they come in batches of up to 10 10ms
9079    * intervals. The timer_handling will check if a new scan of PK timeouts
9080    * is to start, this happens after an idle check period of 500ms. So
9081    * we actually need only check this a divisor of 500 ms and 400ms. 400ms
9082    * is how long we are idle between scans to check for scan timeouts.
9083    * The reason to separate those is to make sure that they don't run
9084    * at the same time as much.
9085    *
9086    * One reason to run the updates of the timer_handling as often as once
9087    * per 50ms is that it is also then that we update the timer that is used
9088    * to check for timeouts on transaction. So 50ms is the granularity of
9089    * when we see timeouts.
9090    *
9091    * The reason for keeping the 10ms appearance of timer_handling is to
9092    * decrease changes in this part of the code. This could be changed
9093    * in the future.
9094    */
9095   c_elapsed_time_millis += num_ms_elapsed;
9096   while (c_elapsed_time_millis > Uint64(10))
9097   {
9098     jam();
9099     c_elapsed_time_millis -= Uint64(10);
9100     timer_handling(signal);
9101   }
9102 }//execTIME_SIGNAL()
9103 
timer_handling(Signal * signal)9104 void Dbtc::timer_handling(Signal *signal)
9105 {
9106   ctcTimer++;
9107   checkStartTimeout(signal);
9108   checkStartFragTimeout(signal);
9109 }
9110 
9111 /*------------------------------------------------*/
9112 /* Start timeout handling if not already going on */
9113 /*------------------------------------------------*/
checkStartTimeout(Signal * signal)9114 void Dbtc::checkStartTimeout(Signal* signal)
9115 {
9116   ctimeOutCheckCounter++;
9117   if (ctimeOutCheckActive == TOCS_TRUE) {
9118     jam();
9119     // Check heartbeat of timeout loop
9120     if(ctimeOutCheckHeartbeat > ctimeOutCheckLastHeartbeat){
9121       jam();
9122       ctimeOutMissedHeartbeats = 0;
9123     }else{
9124       jam();
9125       /**
9126        * This code simply checks that the scan for PK timeouts haven't
9127        * lost itself, a sort of watchdog for that code. If that would
9128        * occur we would no longer have any timeout handling of
9129        * transactions which would render the system useless. This is
9130        * to protect ourselves for future bugs in the code that we
9131        * might introduce by mistake.
9132        *
9133        * 100 is simply an arbitrary number that needs to be bigger
9134        * than the maximum number of calls to timer_handling that
9135        * we can have in one call to execTIME_SIGNAL. This is
9136        * currently 10 but could change in the future.
9137        */
9138       ctimeOutMissedHeartbeats++;
9139       if (ctimeOutMissedHeartbeats > 100){
9140 	jam();
9141 	systemErrorLab(signal, __LINE__);
9142       }
9143     }
9144     ctimeOutCheckLastHeartbeat = ctimeOutCheckHeartbeat;
9145     return;
9146   }//if
9147   if (ctimeOutCheckCounter < ctimeOutCheckDelay) {
9148     jam();
9149     /*------------------------------------------------------------------*/
9150     /*                                                                  */
9151     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
9152     /*------------------------------------------------------------------*/
9153     return;
9154   }//if
9155   ctimeOutCheckActive = TOCS_TRUE;
9156   ctimeOutCheckCounter = 0;
9157   ctimeOutMissedHeartbeats = 0;
9158   timeOutLoopStartLab(signal, 0); // 0 is first api connect timers record
9159   return;
9160 }//checkStartTimeout()
9161 
9162 /*----------------------------------------------------------------*/
9163 /* Start fragment (scan) timeout handling if not already going on */
9164 /*----------------------------------------------------------------*/
checkStartFragTimeout(Signal * signal)9165 void Dbtc::checkStartFragTimeout(Signal* signal)
9166 {
9167   ctimeOutCheckFragCounter++;
9168   if (ctimeOutCheckFragActive == TOCS_TRUE) {
9169     jam();
9170     // Check heartbeat of scan timeout loop
9171     if(ctimeOutCheckHeartbeatScan > ctimeOutCheckLastHeartbeatScan)
9172     {
9173       jam();
9174       ctimeOutMissedHeartbeatsScan = 0;
9175     }
9176     else
9177     {
9178       /**
9179        * Exactly the same code as for PK timeouts, but here to check the
9180        * scan for scan timeouts. Same comments apply as above.
9181        */
9182       jam();
9183       ctimeOutMissedHeartbeatsScan++;
9184       if (ctimeOutMissedHeartbeatsScan > 100){
9185 	jam();
9186 	systemErrorLab(signal, __LINE__);
9187       }
9188     }
9189     ctimeOutCheckLastHeartbeatScan = ctimeOutCheckHeartbeatScan;
9190     return;
9191   }//if
9192   if (ctimeOutCheckFragCounter < ctimeOutCheckDelayScan) {
9193     jam();
9194     /*------------------------------------------------------------------*/
9195     /*       NO TIME-OUT CHECKED THIS TIME. WAIT MORE.                  */
9196     /*------------------------------------------------------------------*/
9197     return;
9198   }//if
9199 
9200   // Go through the fragment records and look for timeout in a scan.
9201   ctimeOutCheckFragActive = TOCS_TRUE;
9202   ctimeOutCheckFragCounter = 0;
9203   ctimeOutMissedHeartbeatsScan = 0;
9204   timeOutLoopStartFragLab(signal, 0); // 0 means first scan record
9205 }//checkStartFragTimeout()
9206 
9207 /*------------------------------------------------------------------*/
9208 /*       IT IS NOW TIME TO CHECK WHETHER ANY TRANSACTIONS HAVE      */
9209 /*       BEEN DELAYED FOR SO LONG THAT WE ARE FORCED TO PERFORM     */
9210 /*       SOME ACTION, EITHER ABORT OR RESEND OR REMOVE A NODE FROM  */
9211 /*       THE WAITING PART OF A PROTOCOL.                            */
9212 /*
9213 The algorithm used here is to check 1024 transactions at a time before
9214 doing a real-time break.
9215 To avoid aborting both transactions in a deadlock detected by time-out
9216 we insert a random extra time-out of upto 630 ms by using the lowest
9217 six bits of the api connect reference.
9218 We spread it out from 0 to 630 ms if base time-out is larger than 3 sec,
9219 we spread it out from 0 to 70 ms if base time-out is smaller than 300 msec,
9220 and otherwise we spread it out 310 ms.
9221 */
9222 /*------------------------------------------------------------------*/
timeOutLoopStartLab(Signal * signal,Uint32 api_con_timer_ptr)9223 void Dbtc::timeOutLoopStartLab(Signal* signal, Uint32 api_con_timer_ptr)
9224 {
9225   Uint32 time_passed, time_out_value, mask_value;
9226   Uint32 old_mask_value= 0;
9227   const Uint32 tc_timer= ctcTimer;
9228   const Uint32 time_out_param= ctimeOutValue;
9229   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
9230 
9231   ctimeOutCheckHeartbeat = tc_timer;
9232 
9233   if (time_out_param > 300) {
9234     jam();
9235     mask_value= 63;
9236   } else if (time_out_param < 30) {
9237     jam();
9238     mask_value= 7;
9239   } else {
9240     jam();
9241     mask_value= 31;
9242   }
9243   if (time_out_param != old_time_out_param &&
9244       getNodeState().getSingleUserMode())
9245   {
9246     // abort during single user mode, use old_mask_value as flag
9247     // and calculate value to be used for connections with allowed api
9248     if (old_time_out_param > 300) {
9249       jam();
9250       old_mask_value= 63;
9251     } else if (old_time_out_param < 30) {
9252       jam();
9253       old_mask_value= 7;
9254     } else {
9255       jam();
9256       old_mask_value= 31;
9257     }
9258   }
9259   Uint32 timers_ptr_count = 0;
9260   Uint32 api_con_timers_ptr = (api_con_timer_ptr == RNIL)
9261                                   ? RNIL
9262                                   : (api_con_timer_ptr >> ApiConTimers::INDEX_BITS);
9263   bool found = false;
9264   while (api_con_timers_ptr != RNIL &&
9265          timers_ptr_count < 1024)
9266   {
9267     ApiConTimersPtr timers[8];
9268     Uint32 ptr_cnt =
9269         c_apiConTimersPool.getUncheckedPtrs(&api_con_timers_ptr,
9270                                             timers,
9271                                             NDB_ARRAY_SIZE(timers));
9272     timers_ptr_count += NDB_ARRAY_SIZE(timers);
9273     for (Uint32 i = 0; i < ptr_cnt; i++)
9274     {
9275       if (!Magic::match(timers[i].p->m_magic, ApiConTimers::TYPE_ID))
9276       {
9277         continue;
9278       }
9279       Uint32 timer_index = 0;
9280       if (i == 0 &&
9281           timers[i].i == (api_con_timer_ptr >> ApiConTimers::INDEX_BITS))
9282       {
9283         timer_index = api_con_timer_ptr & ApiConTimers::INDEX_MASK;
9284       }
9285       for (;
9286            timer_index < timers[i].p->m_top;
9287            timer_index++)
9288       {
9289         Uint32 api_timer = timers[i].p->m_entries[timer_index].m_timer;
9290         if (api_timer == 0)
9291         {
9292           continue;
9293         }
9294         ApiConnectRecordPtr apiConnectptr;
9295         apiConnectptr.i =
9296             timers[i].p->m_entries[timer_index].m_apiConnectRecord;
9297         ndbrequire(apiConnectptr.i != RNIL);
9298         jam();
9299         jamLine(apiConnectptr.i & 0xFFFF);
9300         c_apiConnectRecordPool.getPtr(apiConnectptr);
9301         Uint32 error= ZTIME_OUT_ERROR;
9302         time_out_value= time_out_param + (ndb_rand() & mask_value);
9303         if (unlikely(old_mask_value)) // abort during single user mode
9304         {
9305           if ((getNodeState().getSingleUserApi() ==
9306                refToNode(apiConnectptr.p->ndbapiBlockref)) ||
9307               !(apiConnectptr.p->singleUserMode & (1 << NDB_SUM_LOCKED)))
9308           {
9309             // api allowed during single user, use original timeout
9310             time_out_value=
9311               old_time_out_param + (apiConnectptr.i & old_mask_value);
9312           }
9313           else
9314           {
9315             error= ZCLUSTER_IN_SINGLEUSER_MODE;
9316           }
9317         }
9318         time_passed= tc_timer - api_timer;
9319         if (time_passed > time_out_value)
9320         {
9321           jam();
9322           timeOutFoundLab(signal, apiConnectptr.i, error);
9323           timer_index++;
9324           if (timer_index < ApiConTimers::INDEX_MAX_COUNT)
9325           {
9326             api_con_timer_ptr =
9327               (timers[i].i << ApiConTimers::INDEX_BITS) | timer_index;
9328           }
9329           else if (i + 1 < ptr_cnt)
9330           {
9331             api_con_timer_ptr = timers[i + 1].i << ApiConTimers::INDEX_BITS;
9332           }
9333           else if (api_con_timers_ptr != RNIL)
9334           {
9335             api_con_timer_ptr = api_con_timers_ptr << ApiConTimers::INDEX_BITS;
9336           }
9337           else
9338           {
9339             api_con_timer_ptr = RNIL;
9340           }
9341           found = true;
9342           break;
9343         }
9344       }
9345       if (found)
9346       {
9347         break;
9348       }
9349     }
9350     if (found)
9351     {
9352       break;
9353     }
9354     if (api_con_timers_ptr == RNIL)
9355     {
9356       api_con_timer_ptr = RNIL;
9357     }
9358     else
9359     {
9360       api_con_timer_ptr = (api_con_timers_ptr << ApiConTimers::INDEX_BITS);
9361     }
9362   }
9363   if (api_con_timer_ptr == RNIL)
9364   {
9365     jam();
9366     /*------------------------------------------------------------------*/
9367     /*                                                                  */
9368     /*       WE HAVE NOW CHECKED ALL TRANSACTIONS FOR TIME-OUT AND ALSO */
9369     /*       STARTED TIME-OUT HANDLING OF THOSE WE FOUND. WE ARE NOW    */
9370     /*       READY AND CAN WAIT FOR THE NEXT TIME-OUT CHECK.            */
9371     /*------------------------------------------------------------------*/
9372     ctimeOutCheckActive = TOCS_FALSE;
9373   } else {
9374     jam();
9375     sendContinueTimeOutControl(signal, api_con_timer_ptr);
9376   }
9377   return;
9378 }//Dbtc::timeOutLoopStartLab()
9379 
timeOutFoundLab(Signal * signal,Uint32 TapiConPtr,Uint32 errCode)9380 void Dbtc::timeOutFoundLab(Signal* signal, Uint32 TapiConPtr, Uint32 errCode)
9381 {
9382   ApiConnectRecordPtr apiConnectptr;
9383   apiConnectptr.i = TapiConPtr;
9384   c_apiConnectRecordPool.getPtr(apiConnectptr);
9385   /*------------------------------------------------------------------*/
9386   /*                                                                  */
9387   /*       THIS TRANSACTION HAVE EXPERIENCED A TIME-OUT AND WE NEED TO*/
9388   /*       FIND OUT WHAT WE NEED TO DO BASED ON THE STATE INFORMATION.*/
9389   /*------------------------------------------------------------------*/
9390   DEBUG("[ H'" << hex << apiConnectptr.p->transid[0]
9391 	<< " H'" << apiConnectptr.p->transid[1] << "] " << dec
9392 	<< "Time-out in state = " << apiConnectptr.p->apiConnectstate
9393 	<< " apiConnectptr.i = " << apiConnectptr.i
9394 	<< " - exec: "
9395         << tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG)
9396         << " - place: " << apiConnectptr.p->m_apiConTimer_line
9397 	<< " code: " << errCode
9398         << " lqhkeyreqrec: " << apiConnectptr.p->lqhkeyreqrec
9399         << " lqhkeyconfrec: " << apiConnectptr.p->lqhkeyconfrec
9400         << (apiConnectptr.p->apiConnectstate == CS_START_SCAN
9401             ? " buddyPtr: "
9402             : " pendingTriggers: ") << apiConnectptr.p->pendingTriggers
9403         << " outstanding_fire_trig_req: "
9404         << apiConnectptr.p->m_outstanding_fire_trig_req
9405         << " cascading_scans = " << apiConnectptr.p->cascading_scans_count
9406         << " executing_trigger_operations: "
9407         << apiConnectptr.p->m_executing_trigger_ops
9408         );
9409   switch (apiConnectptr.p->apiConnectstate) {
9410   case CS_STARTED:
9411     if(apiConnectptr.p->lqhkeyreqrec == apiConnectptr.p->lqhkeyconfrec &&
9412        errCode != ZCLUSTER_IN_SINGLEUSER_MODE){
9413       jam();
9414       /*
9415       We are waiting for application to continue the transaction. In this
9416       particular state we will use the application timeout parameter rather
9417       than the shorter Deadlock detection timeout.
9418       */
9419       if (c_appl_timeout_value == 0 ||
9420           (ctcTimer - getApiConTimer(apiConnectptr)) <= c_appl_timeout_value)
9421       {
9422         jam();
9423         return;
9424       }//if
9425     }
9426     apiConnectptr.p->returnsignal = RS_TCROLLBACKREP;
9427     apiConnectptr.p->returncode = errCode;
9428     abort010Lab(signal, apiConnectptr);
9429     return;
9430   case CS_RECEIVING:
9431   case CS_REC_COMMITTING:
9432   case CS_START_COMMITTING:
9433   case CS_WAIT_FIRE_TRIG_REQ:
9434   case CS_SEND_FIRE_TRIG_REQ:
9435     jam();
9436     /*------------------------------------------------------------------*/
9437     /*       WE ARE STILL IN THE PREPARE PHASE AND THE TRANSACTION HAS  */
9438     /*       NOT YET REACHED ITS COMMIT POINT. THUS IT IS NOW OK TO     */
9439     /*       START ABORTING THE TRANSACTION. ALSO START CHECKING THE    */
9440     /*       REMAINING TRANSACTIONS.                                    */
9441     /*------------------------------------------------------------------*/
9442     terrorCode = errCode;
9443     abortErrorLab(signal, apiConnectptr);
9444     return;
9445   case CS_COMMITTING:
9446     jam();
9447     /*------------------------------------------------------------------*/
9448     // We are simply waiting for a signal in the job buffer. Only extreme
9449     // conditions should get us here. We ignore it.
9450     /*------------------------------------------------------------------*/
9451     // Fall through
9452   case CS_COMPLETING:
9453     jam();
9454     /*------------------------------------------------------------------*/
9455     // We are simply waiting for a signal in the job buffer. Only extreme
9456     // conditions should get us here. We ignore it.
9457     /*------------------------------------------------------------------*/
9458     // Fall through
9459   case CS_PREPARE_TO_COMMIT:
9460   {
9461     jam();
9462     /*------------------------------------------------------------------*/
9463     /*       WE ARE WAITING FOR DIH TO COMMIT THE TRANSACTION. WE SIMPLY*/
9464     /*       KEEP WAITING SINCE THERE IS NO BETTER IDEA ON WHAT TO DO.  */
9465     /*       IF IT IS BLOCKED THEN NO TRANSACTION WILL PASS THIS GATE.  */
9466     // To ensure against strange bugs we crash the system if we have passed
9467     // time-out period by a factor of 10 and it is also at least 5 seconds.
9468     /*------------------------------------------------------------------*/
9469     Uint32 time_passed = ctcTimer - getApiConTimer(apiConnectptr);
9470     if (time_passed > 500 &&
9471         time_passed > (5 * cDbHbInterval) &&
9472         time_passed > (10 * ctimeOutValue))
9473     {
9474       jam();
9475       ndbout_c("timeOutFoundLab trans: 0x%x 0x%x state: %u",
9476                apiConnectptr.p->transid[0],
9477                apiConnectptr.p->transid[1],
9478                (Uint32)apiConnectptr.p->apiConnectstate);
9479 
9480       // Reset timeout to not flood log...
9481       setApiConTimer(apiConnectptr, 0, __LINE__);
9482     }//if
9483     break;
9484   }
9485   case CS_COMMIT_SENT:
9486     jam();
9487     /*------------------------------------------------------------------*/
9488     /*       WE HAVE SENT COMMIT TO A NUMBER OF NODES. WE ARE CURRENTLY */
9489     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE   */
9490     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMMIT SIGNAL  */
9491     /*       TO THOSE NODES THAT HAVE MISSED THE COMMIT SIGNAL DUE TO   */
9492     /*       A NODE FAILURE.                                            */
9493     /*------------------------------------------------------------------*/
9494     tabortInd = ZCOMMIT_SETUP;
9495     setupFailData(signal, apiConnectptr.p);
9496     toCommitHandlingLab(signal, apiConnectptr);
9497     return;
9498   case CS_COMPLETE_SENT:
9499     jam();
9500     /*--------------------------------------------------------------------*/
9501     /*       WE HAVE SENT COMPLETE TO A NUMBER OF NODES. WE ARE CURRENTLY */
9502     /*       WAITING FOR THEIR REPLY. WITH NODE RECOVERY SUPPORTED WE     */
9503     /*       WILL CHECK FOR CRASHED NODES AND RESEND THE COMPLETE SIGNAL  */
9504     /*       TO THOSE NODES THAT HAVE MISSED THE COMPLETE SIGNAL DUE TO   */
9505     /*       A NODE FAILURE.                                              */
9506     /*--------------------------------------------------------------------*/
9507     tabortInd = ZCOMMIT_SETUP;
9508     setupFailData(signal, apiConnectptr.p);
9509     toCompleteHandlingLab(signal, apiConnectptr);
9510     return;
9511   case CS_ABORTING:
9512     jam();
9513     /*------------------------------------------------------------------*/
9514     /*       TIME-OUT DURING ABORT. WE NEED TO SEND ABORTED FOR ALL     */
9515     /*       NODES THAT HAVE FAILED BEFORE SENDING ABORTED.             */
9516     /*------------------------------------------------------------------*/
9517     tcConnectptr.i = apiConnectptr.p->tcConnect.getFirst();
9518     sendAbortedAfterTimeout(signal, 0, apiConnectptr);
9519     break;
9520   case CS_START_SCAN:{
9521     jam();
9522 
9523     /*
9524       We are waiting for application to continue the transaction. In this
9525       particular state we will use the application timeout parameter rather
9526       than the shorter Deadlock detection timeout.
9527     */
9528     if (c_appl_timeout_value == 0 ||
9529         (ctcTimer - getApiConTimer(apiConnectptr)) <= c_appl_timeout_value)
9530     {
9531       jam();
9532       return;
9533     }//if
9534 
9535     ScanRecordPtr scanptr;
9536     scanptr.i = apiConnectptr.p->apiScanRec;
9537     scanRecordPool.getPtr(scanptr);
9538     scanError(signal, scanptr, ZSCANTIME_OUT_ERROR);
9539     break;
9540   }
9541   case CS_WAIT_ABORT_CONF:
9542     jam();
9543     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
9544     tcConnectRecord.getPtr(tcConnectptr);
9545     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9546     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
9547     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9548     if (hostptr.p->hostStatus == HS_ALIVE) {
9549       /*------------------------------------------------------------------*/
9550       // Time-out waiting for ABORTCONF. We will resend the ABORTREQ just in
9551       // case.
9552       /*------------------------------------------------------------------*/
9553       warningReport(signal, 20);
9554       apiConnectptr.p->timeOutCounter++;
9555       if (apiConnectptr.p->timeOutCounter > 3) {
9556 	/*------------------------------------------------------------------*/
9557 	// 100 time-outs are not acceptable. We will shoot down the node
9558 	// not responding.
9559 	/*------------------------------------------------------------------*/
9560         reportNodeFailed(signal, hostptr.i);
9561       }//if
9562       apiConnectptr.p->currentReplicaNo++;
9563     }//if
9564     tcurrentReplicaNo = (Uint8)Z8NIL;
9565     toAbortHandlingLab(signal, apiConnectptr);
9566     return;
9567   case CS_WAIT_COMMIT_CONF:
9568     jam();
9569     CRASH_INSERTION(8053);
9570     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
9571     tcConnectRecord.getPtr(tcConnectptr);
9572     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9573     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
9574     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9575     if (hostptr.p->hostStatus == HS_ALIVE) {
9576       /*------------------------------------------------------------------*/
9577       // Time-out waiting for COMMITCONF. We will resend the COMMITREQ just in
9578       // case.
9579       /*------------------------------------------------------------------*/
9580       warningReport(signal, 21);
9581       apiConnectptr.p->timeOutCounter++;
9582       if (apiConnectptr.p->timeOutCounter > 3) {
9583 	/*------------------------------------------------------------------*/
9584 	// 100 time-outs are not acceptable. We will shoot down the node
9585 	// not responding.
9586 	/*------------------------------------------------------------------*/
9587         reportNodeFailed(signal, hostptr.i);
9588       }//if
9589       apiConnectptr.p->currentReplicaNo++;
9590     }//if
9591     tcurrentReplicaNo = (Uint8)Z8NIL;
9592     toCommitHandlingLab(signal, apiConnectptr);
9593     return;
9594   case CS_WAIT_COMPLETE_CONF:
9595     jam();
9596     tcConnectptr.i = apiConnectptr.p->currentTcConnect;
9597     tcConnectRecord.getPtr(tcConnectptr);
9598     arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
9599     hostptr.i = tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo];
9600     ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9601     if (hostptr.p->hostStatus == HS_ALIVE) {
9602       /*------------------------------------------------------------------*/
9603       // Time-out waiting for COMPLETECONF. We will resend the COMPLETEREQ
9604       // just in case.
9605       /*------------------------------------------------------------------*/
9606       warningReport(signal, 22);
9607       apiConnectptr.p->timeOutCounter++;
9608       if (apiConnectptr.p->timeOutCounter > 100) {
9609 	/*------------------------------------------------------------------*/
9610 	// 100 time-outs are not acceptable. We will shoot down the node
9611 	// not responding.
9612 	/*------------------------------------------------------------------*/
9613         reportNodeFailed(signal, hostptr.i);
9614       }//if
9615       apiConnectptr.p->currentReplicaNo++;
9616     }//if
9617     tcurrentReplicaNo = (Uint8)Z8NIL;
9618     toCompleteHandlingLab(signal, apiConnectptr);
9619     return;
9620   case CS_FAIL_PREPARED:
9621   case CS_FAIL_COMMITTING:
9622   case CS_FAIL_COMMITTED:
9623   case CS_RESTART:
9624   case CS_FAIL_ABORTED:
9625   case CS_DISCONNECTED:
9626   default:
9627     jam();
9628     jamLine(apiConnectptr.p->apiConnectstate);
9629     /*------------------------------------------------------------------*/
9630     /*       AN IMPOSSIBLE STATE IS SET. CRASH THE SYSTEM.              */
9631     /*------------------------------------------------------------------*/
9632     DEBUG("State = " << apiConnectptr.p->apiConnectstate);
9633     systemErrorLab(signal, __LINE__);
9634     return;
9635   }//switch
9636   return;
9637 }//Dbtc::timeOutFoundLab()
9638 
sendAbortedAfterTimeout(Signal * signal,int Tcheck,ApiConnectRecordPtr const apiConnectptr)9639 void Dbtc::sendAbortedAfterTimeout(Signal* signal, int Tcheck, ApiConnectRecordPtr const apiConnectptr)
9640 {
9641   ApiConnectRecord * transP = apiConnectptr.p;
9642   if(transP->abortState == AS_IDLE){
9643     jam();
9644     warningEvent("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
9645 		 __LINE__,
9646 		 apiConnectptr.i,
9647 		 transP->apiConnectstate,
9648                  apiConnectptr.p->m_apiConTimer_line,
9649                  transP->tcConnect.getFirst(),
9650                  getApiConTimer(apiConnectptr)
9651 		 );
9652     ndbout_c("TC: %d: %d state=%d abort==IDLE place: %d fop=%d t: %d",
9653 	     __LINE__,
9654 	     apiConnectptr.i,
9655 	     transP->apiConnectstate,
9656              apiConnectptr.p->m_apiConTimer_line,
9657              transP->tcConnect.getFirst(),
9658              getApiConTimer(apiConnectptr)
9659 	     );
9660     ndbabort();
9661     setApiConTimer(apiConnectptr, 0, __LINE__);
9662     return;
9663   }
9664 
9665   bool found = false;
9666   OperationState tmp[16];
9667 
9668   Uint32 TloopCount = 0;
9669   do {
9670     jam();
9671     if (tcConnectptr.i == RNIL) {
9672       jam();
9673 
9674 #ifdef VM_TRACE
9675       ndbout_c("found: %d Tcheck: %d apiConnectptr.p->counter: %d",
9676 	       found, Tcheck, apiConnectptr.p->counter);
9677 #endif
9678       if (found || apiConnectptr.p->counter)
9679       {
9680 	jam();
9681 	/**
9682 	 * We sent atleast one ABORT/ABORTED
9683 	 *   or ZABORT_TIMEOUT_BREAK is in job buffer
9684 	 *   wait for reception...
9685 	 */
9686 	return;
9687       }
9688 
9689       if (Tcheck == 1)
9690       {
9691 	jam();
9692         releaseAbortResources(signal, apiConnectptr);
9693 	return;
9694       }
9695 
9696       if (Tcheck == 0)
9697       {
9698         jam();
9699 	/*------------------------------------------------------------------
9700 	 * All nodes had already reported ABORTED for all tcConnect records.
9701 	 * Crash since it is an error situation that we then received a
9702 	 * time-out.
9703 	 *------------------------------------------------------------------*/
9704 	char buf[96]; buf[0] = 0;
9705 	char buf2[96];
9706 	BaseString::snprintf(buf, sizeof(buf), "TC %d: %d counter: %d ops:",
9707 			     __LINE__, apiConnectptr.i,
9708 			     apiConnectptr.p->counter);
9709 	for(Uint32 i = 0; i<TloopCount; i++)
9710 	{
9711 	  BaseString::snprintf(buf2, sizeof(buf2), "%s %d", buf, tmp[i]);
9712 	  BaseString::snprintf(buf, sizeof(buf), "%s", buf2);
9713 	}
9714 	warningEvent("%s", buf);
9715 	ndbout_c("%s", buf);
9716 	ndbabort();
9717         releaseAbortResources(signal, apiConnectptr);
9718 	return;
9719       }
9720 
9721       return;
9722     }//if
9723     TloopCount++;
9724     if (TloopCount >= 1024) {
9725       jam();
9726       /*------------------------------------------------------------------*/
9727       // Insert a real-time break for large transactions to avoid blowing
9728       // away the job buffer.
9729       /*------------------------------------------------------------------*/
9730       setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
9731       apiConnectptr.p->counter++;
9732       signal->theData[0] = TcContinueB::ZABORT_TIMEOUT_BREAK;
9733       signal->theData[1] = tcConnectptr.i;
9734       signal->theData[2] = apiConnectptr.i;
9735       if (ERROR_INSERTED(8080))
9736       {
9737 	ndbout_c("sending ZABORT_TIMEOUT_BREAK delayed (%d %d)",
9738 		 Tcheck, apiConnectptr.p->counter);
9739 	sendSignalWithDelay(cownref, GSN_CONTINUEB, signal, 2000, 3);
9740       }
9741       else
9742       {
9743 	sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
9744       }
9745       return;
9746     }//if
9747     tcConnectRecord.getPtr(tcConnectptr);
9748     if(TloopCount < 16){
9749       jam();
9750       tmp[TloopCount-1] = tcConnectptr.p->tcConnectstate;
9751     }
9752 
9753     if (tcConnectptr.p->tcConnectstate == OS_ABORT_SENT) {
9754       jam();
9755       /*------------------------------------------------------------------*/
9756       // We have sent an ABORT signal to this node but not yet received any
9757       // reply. We have to send an ABORTED signal on our own in some cases.
9758       // If the node is declared as up and running and still do not respond
9759       // in time to the ABORT signal we will declare it as dead.
9760       /*------------------------------------------------------------------*/
9761       UintR Ti = 0;
9762       arrGuard(tcConnectptr.p->noOfNodes, MAX_REPLICAS+1);
9763       for (Ti = 0; Ti < tcConnectptr.p->noOfNodes; Ti++) {
9764         jam();
9765         if (tcConnectptr.p->tcNodedata[Ti] != 0) {
9766           TloopCount += 31;
9767 	  found = true;
9768           hostptr.i = tcConnectptr.p->tcNodedata[Ti];
9769           ptrCheckGuard(hostptr, chostFilesize, hostRecord);
9770           if (hostptr.p->hostStatus == HS_ALIVE) {
9771             jam();
9772 	    /*---------------------------------------------------------------
9773 	     * A backup replica has not sent ABORTED.
9774 	     * Could be that a node before him has crashed.
9775 	     * Send an ABORT signal specifically to this node.
9776 	     * We will not send to any more nodes after this
9777 	     * to avoid race problems.
9778 	     * To also ensure that we use this message also as a heartbeat
9779 	     * we will move this node to the primary replica seat.
9780 	     * The primary replica and any failed node after it will
9781 	     * be removed from the node list. Update also number of nodes.
9782 	     * Finally break the loop to ensure we don't mess
9783 	     * things up by executing another loop.
9784 	     * We also update the timer to ensure we don't get time-out
9785 	     * too early.
9786 	     *--------------------------------------------------------------*/
9787             Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
9788             BlockReference TBRef = numberToRef(DBLQH, instanceKey, hostptr.i);
9789             signal->theData[0] = tcConnectptr.i;
9790             signal->theData[1] = cownref;
9791             signal->theData[2] = apiConnectptr.p->transid[0];
9792             signal->theData[3] = apiConnectptr.p->transid[1];
9793             sendSignal(TBRef, GSN_ABORT, signal, 4, JBB);
9794             setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
9795             break;
9796           } else {
9797             jam();
9798 	    /*--------------------------------------------------------------
9799 	     * The node we are waiting for is dead. We will send ABORTED to
9800 	     * ourselves vicarious for the failed node.
9801 	     *--------------------------------------------------------------*/
9802             setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
9803             signal->theData[0] = tcConnectptr.i;
9804             signal->theData[1] = apiConnectptr.p->transid[0];
9805             signal->theData[2] = apiConnectptr.p->transid[1];
9806             signal->theData[3] = hostptr.i;
9807             signal->theData[4] = ZFALSE;
9808             sendSignal(cownref, GSN_ABORTED, signal, 5, JBB);
9809           }//if
9810         }//if
9811       }//for
9812     }//if
9813     tcConnectptr.i = tcConnectptr.p->nextList;
9814   } while (1);
9815 }//Dbtc::sendAbortedAfterTimeout()
9816 
reportNodeFailed(Signal * signal,NodeId nodeId)9817 void Dbtc::reportNodeFailed(Signal* signal, NodeId nodeId)
9818 {
9819   DisconnectRep * const rep = (DisconnectRep *)&signal->theData[0];
9820   rep->nodeId = nodeId;
9821   rep->err = DisconnectRep::TcReportNodeFailed;
9822   sendSignal(QMGR_REF, GSN_DISCONNECT_REP, signal,
9823 	     DisconnectRep::SignalLength, JBB);
9824 }//Dbtc::reportNodeFailed()
9825 
9826 /*-------------------------------------------------*/
9827 /*      Timeout-loop for scanned fragments.        */
9828 /*-------------------------------------------------*/
timeOutLoopStartFragLab(Signal * signal,Uint32 TscanConPtr)9829 void Dbtc::timeOutLoopStartFragLab(Signal* signal, Uint32 TscanConPtr)
9830 {
9831   ScanFragRecPtr timeOutPtr[8];
9832   UintR tfragTimer[8];
9833   UintR texpiredTime[8];
9834   UintR TloopCount = 0;
9835   Uint32 TtcTimer = ctcTimer;
9836 
9837   ctimeOutCheckHeartbeatScan = TtcTimer;
9838 
9839   while (TscanConPtr != RNIL)
9840   {
9841     Uint32 ptr_cnt = c_scan_frag_pool.getUncheckedPtrs(&TscanConPtr, timeOutPtr, NDB_ARRAY_SIZE(timeOutPtr));
9842     TloopCount += ptr_cnt;
9843     for (Uint32 i = 0; i < ptr_cnt; i++)
9844     {
9845       if (Magic::match(timeOutPtr[i].p->m_magic, ScanFragRec::TYPE_ID))
9846       {
9847         tfragTimer[i] = timeOutPtr[i].p->scanFragTimer;
9848       }
9849       else
9850       {
9851         tfragTimer[i] = 0;
9852       }
9853     }
9854 
9855     texpiredTime[0] = TtcTimer - tfragTimer[0];
9856     texpiredTime[1] = TtcTimer - tfragTimer[1];
9857     texpiredTime[2] = TtcTimer - tfragTimer[2];
9858     texpiredTime[3] = TtcTimer - tfragTimer[3];
9859     texpiredTime[4] = TtcTimer - tfragTimer[4];
9860     texpiredTime[5] = TtcTimer - tfragTimer[5];
9861     texpiredTime[6] = TtcTimer - tfragTimer[6];
9862     texpiredTime[7] = TtcTimer - tfragTimer[7];
9863 
9864     for (Uint32 Ti = 0; Ti < ptr_cnt; Ti++)
9865     {
9866       jam();
9867       if (tfragTimer[Ti] != 0) {
9868 
9869         if (texpiredTime[Ti] > ctimeOutValue) {
9870 	  jam();
9871 	  DEBUG("Fragment timeout found:"<<
9872 		" ctimeOutValue=" <<ctimeOutValue
9873 		<<", texpiredTime="<<texpiredTime[Ti]<<endl
9874 		<<"      tfragTimer="<<tfragTimer[Ti]
9875 		<<", ctcTimer="<<ctcTimer);
9876           timeOutFoundFragLab(signal, timeOutPtr[Ti].i);
9877           return;
9878         }//if
9879       }//if
9880     }//for
9881     /*----------------------------------------------------------------*/
9882     /* We split the process up checking 1024 fragmentrecords at a time*/
9883     /* to maintain real time behaviour.                               */
9884     /*----------------------------------------------------------------*/
9885     if (TloopCount > 1024 && TscanConPtr != RNIL)
9886     {
9887       jam();
9888       signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
9889       signal->theData[1] = TscanConPtr;
9890       sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
9891       return;
9892     }//if
9893   }//while
9894   ndbrequire(TscanConPtr == RNIL);
9895   ctimeOutCheckFragActive = TOCS_FALSE;
9896 
9897   return;
9898 }//timeOutLoopStartFragLab()
9899 
9900 /*--------------------------------------------------------------------------*/
9901 /*Handle the heartbeat signal from LQH in a scan process                    */
9902 // (Set timer on fragrec.)
9903 /*--------------------------------------------------------------------------*/
execSCAN_HBREP(Signal * signal)9904 void Dbtc::execSCAN_HBREP(Signal* signal)
9905 {
9906   jamEntry();
9907 
9908   scanFragptr.i = signal->theData[0];
9909   if (unlikely(!c_scan_frag_pool.getValidPtr(scanFragptr)))
9910   {
9911     jam();
9912     warningHandlerLab(signal, __LINE__);
9913     return;
9914   }
9915 
9916   switch (scanFragptr.p->scanFragState){
9917   case ScanFragRec::LQH_ACTIVE:
9918     break;
9919   default:
9920     DEBUG("execSCAN_HBREP: scanFragState="<<scanFragptr.p->scanFragState);
9921     systemErrorLab(signal, __LINE__);
9922     break;
9923   }
9924 
9925   ScanRecordPtr scanptr;
9926   scanptr.i = scanFragptr.p->scanRec;
9927   if (unlikely(!scanRecordPool.getUncheckedPtrRW(scanptr)))
9928   {
9929     return;
9930   }
9931 
9932   ApiConnectRecordPtr apiConnectptr;
9933   apiConnectptr.i = scanptr.p->scanApiRec;
9934   ndbrequire(Magic::check_ptr(scanptr.p));
9935   c_apiConnectRecordPool.getUncheckedPtrRW(apiConnectptr);
9936   Uint32 compare_transid1 = apiConnectptr.p->transid[0] - signal->theData[1];
9937   Uint32 compare_transid2 = apiConnectptr.p->transid[1] - signal->theData[2];
9938   ndbrequire(Magic::check_ptr(apiConnectptr.p));
9939   if (unlikely(compare_transid1 != 0 ||
9940                compare_transid2 != 0))
9941   {
9942     jam();
9943     /**
9944      * Send signal back to sender so that the crash occurs there
9945      */
9946     // Save original transid
9947     signal->theData[3] = signal->theData[0];
9948     signal->theData[4] = signal->theData[1];
9949     // Set transid to illegal values
9950     signal->theData[1] = RNIL;
9951     signal->theData[2] = RNIL;
9952 
9953     sendSignal(signal->senderBlockRef(), GSN_SCAN_HBREP, signal, 5, JBA);
9954     DEBUG("SCAN_HBREP with wrong transid("
9955 	  <<signal->theData[3]<<", "<<signal->theData[4]<<")");
9956     return;
9957   }//if
9958 
9959   // Update timer on ScanFragRec
9960   if (likely(scanFragptr.p->scanFragTimer != 0))
9961   {
9962     updateBuddyTimer(apiConnectptr);
9963     scanFragptr.p->startFragTimer(ctcTimer);
9964   } else {
9965     ndbassert(false);
9966     DEBUG("SCAN_HBREP when scanFragTimer was turned off");
9967   }
9968 }//execSCAN_HBREP()
9969 
9970 /*--------------------------------------------------------------------------*/
9971 /*      Timeout has occurred on a fragment which means a scan has timed out. */
9972 /*      If this is true we have an error in LQH/ACC.                        */
9973 /*--------------------------------------------------------------------------*/
timeOutFoundFragLab(Signal * signal,UintR TscanConPtr)9974 void Dbtc::timeOutFoundFragLab(Signal* signal, UintR TscanConPtr)
9975 {
9976   ScanFragRecPtr ptr;
9977   ptr.i = TscanConPtr;
9978   c_scan_frag_pool.getPtr(ptr);
9979 #ifdef VM_TRACE
9980   {
9981     ScanRecordPtr scanptr;
9982     scanptr.i = ptr.p->scanRec;
9983     scanRecordPool.getPtr(scanptr);
9984     ApiConnectRecordPtr TlocalApiConnectptr;
9985     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
9986     c_apiConnectRecordPool.getPtr(TlocalApiConnectptr);
9987 
9988     DEBUG("[ H'" << hex << TlocalApiConnectptr.p->transid[0]
9989         << " H'" << TlocalApiConnectptr.p->transid[1] << "] "
9990         << TscanConPtr << " timeOutFoundFragLab: scanFragState = "
9991         << ptr.p->scanFragState);
9992   }
9993 #endif
9994 
9995   const Uint32 time_out_param= ctimeOutValue;
9996   const Uint32 old_time_out_param= c_abortRec.oldTimeOutValue;
9997 
9998   if (unlikely(time_out_param != old_time_out_param &&
9999 	       getNodeState().getSingleUserMode()))
10000   {
10001     jam();
10002     ScanRecordPtr scanptr;
10003     scanptr.i = ptr.p->scanRec;
10004     scanRecordPool.getPtr(scanptr);
10005     ApiConnectRecordPtr TlocalApiConnectptr;
10006     TlocalApiConnectptr.i = scanptr.p->scanApiRec;
10007     c_apiConnectRecordPool.getPtr(TlocalApiConnectptr);
10008 
10009     if (refToNode(TlocalApiConnectptr.p->ndbapiBlockref) ==
10010 	getNodeState().getSingleUserApi())
10011     {
10012       jam();
10013       Uint32 val = ctcTimer - ptr.p->scanFragTimer;
10014       if (val <= old_time_out_param)
10015       {
10016 	jam();
10017 	goto next;
10018       }
10019     }
10020   }
10021 
10022   /*-------------------------------------------------------------------------*/
10023   // The scan fragment has expired its timeout. Check its state to decide
10024   // what to do.
10025   /*-------------------------------------------------------------------------*/
10026   switch (ptr.p->scanFragState) {
10027   case ScanFragRec::WAIT_GET_PRIMCONF:
10028     jam();
10029     /**
10030      * Time-out waiting for local DIH, we will continue waiting forever.
10031      * This should only occur when we run in an unstable environment where
10032      * the main thread goes slow.
10033      * We reset timer to avoid getting here again immediately.
10034      */
10035     ptr.p->startFragTimer(ctcTimer);
10036 #ifdef VM_TRACE
10037     g_eventLogger->warning("Time-out in WAIT_GET_PRIMCONF: scanRecord = %u",
10038                            ptr.i);
10039 #endif
10040     break;
10041   case ScanFragRec::LQH_ACTIVE:{
10042     jam();
10043 
10044     /**
10045      * The LQH expired it's timeout, try to close it
10046      */
10047     NodeId nodeId = refToNode(ptr.p->lqhBlockref);
10048     Uint32 connectCount = getNodeInfo(nodeId).m_connectCount;
10049     ScanRecordPtr scanptr;
10050     scanptr.i = ptr.p->scanRec;
10051     if (unlikely(!scanRecordPool.getValidPtr(scanptr)))
10052     {
10053       break;
10054     }
10055     if(connectCount != ptr.p->m_connectCount){
10056       jam();
10057       /**
10058        * The node has died
10059        */
10060       ptr.p->scanFragState = ScanFragRec::COMPLETED;
10061       ptr.p->stopFragTimer();
10062       {
10063         Local_ScanFragRec_dllist run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
10064         run.remove(ptr);
10065         c_scan_frag_pool.release(ptr);
10066         checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
10067                             c_scan_frag_pool);
10068       }
10069     }
10070     scanError(signal, scanptr, ZSCAN_FRAG_LQH_ERROR);
10071     break;
10072   }
10073   case ScanFragRec::DELIVERED:
10074     jam();
10075     // Fall through
10076   case ScanFragRec::IDLE:
10077     jam();
10078     // Fall through
10079   case ScanFragRec::QUEUED_FOR_DELIVERY:
10080     jam();
10081     /*-----------------------------------------------------------------------
10082      * Should never occur. We will simply report set the timer to zero and
10083      * continue. In a debug version we should crash here but not in a release
10084      * version. In a release version we will simply set the time-out to zero.
10085      *-----------------------------------------------------------------------*/
10086 #ifdef VM_TRACE
10087     systemErrorLab(signal, __LINE__);
10088 #endif
10089     scanFragptr.p->stopFragTimer();
10090     break;
10091   default:
10092     jam();
10093     /*-----------------------------------------------------------------------
10094      * Non-existent state. Crash.
10095      *-----------------------------------------------------------------------*/
10096     systemErrorLab(signal, __LINE__);
10097     break;
10098   }//switch
10099 
10100 next:
10101   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_FRAG_CONTROL;
10102   signal->theData[1] = TscanConPtr + 1;
10103   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
10104   return;
10105 }//timeOutFoundFragLab()
10106 
10107 
10108 /*
10109   4.3.16 GCP_NOMORETRANS
10110   ----------------------
10111 */
10112 /*****************************************************************************
10113  *                         G C P _ N O M O R E T R A N S
10114  *
10115  *  WHEN DBTC RECEIVES SIGNAL GCP_NOMORETRANS A CHECK IS DONE TO FIND OUT IF
10116  *  THERE ARE ANY GLOBAL CHECKPOINTS GOING ON - CFIRSTGCP /= RNIL. DBTC THEN
10117  *  SEARCHES THE GCP_RECORD FILE TO FIND OUT IF THERE ARE ANY TRANSACTIONS NOT
10118  *  CONCLUDED WITH THIS SPECIFIC CHECKPOINT - GCP_PTR:GCP_ID = TCHECK_GCP_ID.
10119  *  FOR EACH TRANSACTION WHERE API_CONNECTSTATE EQUALS PREPARED, COMMITTING,
10120  *  COMMITTED OR COMPLETING SIGNAL CONTINUEB IS SENT WITH A DELAY OF 100 MS,
10121  *  THE COUNTER GCP_PTR:OUTSTANDINGAPI IS INCREASED. WHEN CONTINUEB IS RECEIVED
10122  *  THE COUNTER IS DECREASED AND A CHECK IS DONE TO FIND OUT IF ALL
10123  *  TRANSACTIONS ARE CONCLUDED. IF SO, SIGNAL GCP_TCFINISHED IS SENT.
10124  *****************************************************************************/
execGCP_NOMORETRANS(Signal * signal)10125 void Dbtc::execGCP_NOMORETRANS(Signal* signal)
10126 {
10127   jamEntry();
10128   GCPNoMoreTrans* req = (GCPNoMoreTrans*)signal->getDataPtr();
10129   c_gcp_ref = req->senderRef;
10130   c_gcp_data = req->senderData;
10131   Uint32 gci_lo = req->gci_lo;
10132   Uint32 gci_hi = req->gci_hi;
10133   tcheckGcpId = gci_lo | (Uint64(gci_hi) << 32);
10134   const bool nfhandling = (c_ongoing_take_over_cnt > 0);
10135 
10136   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
10137   GcpRecordPtr gcpPtr;
10138   if (gcp_list.first(gcpPtr))
10139   {
10140     jam();
10141     /* A GLOBAL CHECKPOINT IS GOING ON */
10142     /* SET POINTER TO FIRST GCP IN QUEUE*/
10143     if (gcpPtr.p->gcpId == tcheckGcpId)
10144     {
10145       jam();
10146       bool empty = gcpPtr.p->apiConnectList.isEmpty();
10147 
10148       if (nfhandling)
10149       {
10150         jam();
10151         g_eventLogger->info("DBTC %u: GCP completion %u/%u waiting "
10152                             "for node failure handling (%u) to complete "
10153                             "(empty=%u)",
10154                             instance(),
10155                             gci_hi,
10156                             gci_lo,
10157                             c_ongoing_take_over_cnt,
10158                             empty);
10159 
10160         gcpPtr.p->gcpNomoretransRec = ZTRUE;
10161       }
10162       else
10163       {
10164         if (!empty)
10165         {
10166           jam();
10167           /* Wait for transactions in GCP to commit + complete */
10168           gcpPtr.p->gcpNomoretransRec = ZTRUE;
10169         }
10170         else
10171         {
10172           jam();
10173           /* All transactions completed, no nfhandling, complete it now */
10174           gcpTcfinished(signal, tcheckGcpId);
10175           unlinkAndReleaseGcp(gcpPtr);
10176         }
10177       }
10178     }
10179     else if (!nfhandling)
10180     {
10181       jam();
10182       /*------------------------------------------------------------*/
10183       /*       IF IT IS NOT THE FIRST THEN THERE SHOULD BE NO       */
10184       /*       RECORD FOR THIS GLOBAL CHECKPOINT. WE ALWAYS REMOVE  */
10185       /*       THE GLOBAL CHECKPOINTS IN ORDER.                     */
10186       /*------------------------------------------------------------*/
10187       gcpTcfinished(signal, tcheckGcpId);
10188     }
10189     else
10190     {
10191       jam();
10192       goto outoforder;
10193     }
10194   }
10195   else if (!nfhandling)
10196   {
10197     jam();
10198     gcpTcfinished(signal, tcheckGcpId);
10199   }
10200   else
10201   {
10202     g_eventLogger->info("DBTC %u: GCP completion %u/%u waiting "
10203                         "for node failure handling (%u) to complete. "
10204                         "Seizing record for GCP.",
10205                         instance(),
10206                         gci_hi,
10207                         gci_lo,
10208                         c_ongoing_take_over_cnt);
10209 seize:
10210     jam();
10211     seizeGcp(gcpPtr, tcheckGcpId);
10212     gcpPtr.p->gcpNomoretransRec = ZTRUE;
10213   }
10214   return;
10215 
10216 outoforder:
10217   g_eventLogger->info("DBTC %u: GCP completion %u/%u waiting "
10218                       "for node failure handling (%u) to complete. "
10219                       "GCP received out of order.  First GCP %u/%u",
10220                       instance(),
10221                       gci_hi, gci_lo,
10222                       c_ongoing_take_over_cnt,
10223                       Uint32(gcpPtr.p->gcpId >> 32),
10224                       Uint32(gcpPtr.p->gcpId));
10225 
10226   if (tcheckGcpId < gcpPtr.p->gcpId)
10227   {
10228     jam();
10229 
10230     GcpRecordPtr tmp;
10231     ndbrequire(c_gcpRecordPool.seize(tmp));
10232 
10233     tmp.p->gcpId = tcheckGcpId;
10234     tmp.p->apiConnectList.init();
10235     tmp.p->gcpNomoretransRec = ZTRUE;
10236 
10237     LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
10238     gcp_list.addFirst(tmp);
10239     g_eventLogger->info("DBTC %u: Out of order GCP %u/%u linked first",
10240                         instance(),
10241                         gci_hi,
10242                         gci_lo);
10243     return;
10244   }
10245   else
10246   {
10247     Ptr<GcpRecord> prev = gcpPtr;
10248     LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
10249     while (tcheckGcpId > gcpPtr.p->gcpId)
10250     {
10251       jam();
10252       if (gcpPtr.p->nextList == RNIL)
10253       {
10254         g_eventLogger->info("DBTC %u: Out of order GCP %u/%u linked last",
10255                             instance(),
10256                             gci_hi,
10257                             gci_lo);
10258         goto seize;
10259       }
10260 
10261       prev = gcpPtr;
10262       ndbrequire(gcp_list.next(gcpPtr));
10263     }
10264 
10265     if (tcheckGcpId == gcpPtr.p->gcpId)
10266     {
10267       jam();
10268       gcpPtr.p->gcpNomoretransRec = ZTRUE;
10269       g_eventLogger->info("DBTC %u: Out of order GCP %u/%u already linked",
10270                           instance(),
10271                           gci_hi,
10272                           gci_lo);
10273       return;
10274     }
10275     ndbrequire(prev.i != gcpPtr.i); // checked earlier with initial "<"
10276     ndbrequire(prev.p->gcpId < tcheckGcpId);
10277     ndbrequire(gcpPtr.p->gcpId > tcheckGcpId);
10278 
10279     GcpRecordPtr tmp;
10280     ndbrequire(c_gcpRecordPool.seize(tmp));
10281 
10282     tmp.p->gcpId = tcheckGcpId;
10283     tmp.p->apiConnectList.init();
10284     tmp.p->gcpNomoretransRec = ZTRUE;
10285     gcp_list.insertAfter(tmp, prev);
10286     ndbassert(tmp.p->nextList == gcpPtr.i);
10287     g_eventLogger->info("DBTC %u: Out of order Gcp %u/%u linked mid-list. "
10288                         "%u/%u < %u/%u < %u/%u",
10289                         instance(),
10290                         gci_hi, gci_lo,
10291                         Uint32(prev.p->gcpId >> 32),
10292                         Uint32(prev.p->gcpId),
10293                         gci_hi, gci_lo,
10294                         Uint32(gcpPtr.p->gcpId >> 32),
10295                         Uint32(gcpPtr.p->gcpId));
10296     return;
10297   }
10298 }//Dbtc::execGCP_NOMORETRANS()
10299 
10300 /*****************************************************************************/
10301 /*                                                                           */
10302 /*                            TAKE OVER MODULE                               */
10303 /*                                                                           */
10304 /*****************************************************************************/
10305 /*                                                                           */
10306 /*    THIS PART OF TC TAKES OVER THE COMMIT/ABORT OF TRANSACTIONS WHERE THE  */
10307 /*    NODE ACTING AS TC HAVE FAILED. IT STARTS BY QUERYING ALL NODES ABOUT   */
10308 /*    ANY OPERATIONS PARTICIPATING IN A TRANSACTION WHERE THE TC NODE HAVE   */
10309 /*    FAILED.                                                                */
10310 /*                                                                           */
10311 /*    AFTER RECEIVING INFORMATION FROM ALL NODES ABOUT OPERATION STATUS THIS */
10312 /*    CODE WILL ENSURE THAT ALL AFFECTED TRANSACTIONS ARE PROPERLY ABORTED OR*/
10313 /*    COMMITTED. THE ORIGINATING APPLICATION NODE WILL ALSO BE CONTACTED.    */
10314 /*    IF THE ORIGINATING APPLICATION ALSO FAILED THEN THERE IS CURRENTLY NO  */
10315 /*    WAY TO FIND OUT WHETHER A TRANSACTION WAS PERFORMED OR NOT.            */
10316 /*****************************************************************************/
execNODE_FAILREP(Signal * signal)10317 void Dbtc::execNODE_FAILREP(Signal* signal)
10318 {
10319   jamEntry();
10320 
10321   NodeFailRep * const nodeFail = (NodeFailRep *)&signal->theData[0];
10322   if(signal->getLength() == NodeFailRep::SignalLength)
10323   {
10324     ndbrequire(signal->getNoOfSections() == 1);
10325     ndbrequire(getNodeInfo(refToNode(signal->getSendersBlockRef())).m_version);
10326     SegmentedSectionPtr ptr;
10327     SectionHandle handle(this, signal);
10328     handle.getSection(ptr, 0);
10329     memset(nodeFail->theNodes, 0, sizeof(nodeFail->theNodes));
10330     copy(nodeFail->theNodes, ptr);
10331     releaseSections(handle);
10332   }
10333   else
10334   {
10335     memset(nodeFail->theNodes + NdbNodeBitmask48::Size, 0,
10336            _NDB_NBM_DIFF_BYTES);
10337   }
10338   cfailure_nr = nodeFail->failNo;
10339   const Uint32 tnoOfNodes  = nodeFail->noOfNodes;
10340   const Uint32 tnewMasterId = nodeFail->masterNodeId;
10341   Uint32 cdata[MAX_NDB_NODES];
10342 
10343   arrGuard(tnoOfNodes, MAX_NDB_NODES);
10344   Uint32 i;
10345   int index = 0;
10346   for (i = 1; i< MAX_NDB_NODES; i++)
10347   {
10348     if(NdbNodeBitmask::get(nodeFail->theNodes, i))
10349     {
10350       cdata[index] = i;
10351       index++;
10352     }//if
10353   }//for
10354 
10355   cmasterNodeId = tnewMasterId;
10356 
10357   if (ERROR_INSERTED(8098))
10358     SET_ERROR_INSERT_VALUE(8099);  /* Disable 8098 on node failure */
10359 
10360   HostRecordPtr myHostPtr;
10361 
10362   tcNodeFailptr.i = 0;
10363   ptrAss(tcNodeFailptr, tcFailRecord);
10364   for (i = 0; i < tnoOfNodes; i++)
10365   {
10366     jam();
10367     myHostPtr.i = cdata[i];
10368     ptrCheckGuard(myHostPtr, chostFilesize, hostRecord);
10369 
10370     /*------------------------------------------------------------*/
10371     /*       SET STATUS OF THE FAILED NODE TO DEAD SINCE IT HAS   */
10372     /*       FAILED.                                              */
10373     /*------------------------------------------------------------*/
10374     myHostPtr.p->hostStatus = HS_DEAD;
10375     myHostPtr.p->m_nf_bits = HostRecord::NF_NODE_FAIL_BITS;
10376     c_ongoing_take_over_cnt++;
10377     c_alive_nodes.clear(myHostPtr.i);
10378 
10379     if (tcNodeFailptr.p->failStatus == FS_LISTENING)
10380     {
10381       jam();
10382       /*------------------------------------------------------------*/
10383       /*       THE CURRENT TAKE OVER CAN BE AFFECTED BY THIS NODE   */
10384       /*       FAILURE.                                             */
10385       /*------------------------------------------------------------*/
10386       if (myHostPtr.p->lqhTransStatus == LTS_ACTIVE)
10387       {
10388 	jam();
10389 	/*------------------------------------------------------------*/
10390 	/*       WE WERE WAITING FOR THE FAILED NODE IN THE TAKE OVER */
10391 	/*       PROTOCOL FOR TC.                                     */
10392 	/*------------------------------------------------------------*/
10393 	signal->theData[0] = TcContinueB::ZNODE_TAKE_OVER_COMPLETED;
10394 	signal->theData[1] = myHostPtr.i;
10395 	sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
10396       }//if
10397     }//if
10398 
10399     jam();
10400     g_eventLogger->info("DBTC %u: Started failure handling for node %u",
10401                         instance(),
10402                         myHostPtr.i);
10403 
10404     /**
10405      * Insert into take over queue immediately to avoid complex
10406      * race conditions. Proceed with take over if our task and
10407      * we are ready to do so.
10408      */
10409     insert_take_over_failed_node(signal, myHostPtr.i);
10410 
10411     checkScanActiveInFailedLqh(signal, 0, myHostPtr.i);
10412     nodeFailCheckTransactions(signal, 0, myHostPtr.i);
10413     Callback cb = {safe_cast(&Dbtc::ndbdFailBlockCleanupCallback),
10414                   myHostPtr.i};
10415     simBlockNodeFailure(signal, myHostPtr.i, cb);
10416   }
10417 
10418   if (m_deferred_enabled == 0)
10419   {
10420     jam();
10421     m_deferred_enabled = ~Uint32(0);
10422   }
10423 }//Dbtc::execNODE_FAILREP()
10424 
10425 static
getNFBitName(const Uint32 bit)10426 const char* getNFBitName(const Uint32 bit)
10427 {
10428   switch (bit)
10429   {
10430   case Dbtc::HostRecord::NF_TAKEOVER: return "NF_TAKEOVER";
10431   case Dbtc::HostRecord::NF_CHECK_SCAN: return "NF_CHECK_SCAN";
10432   case Dbtc::HostRecord::NF_CHECK_TRANSACTION: return "NF_CHECK_TRANSACTION";
10433   case Dbtc::HostRecord::NF_BLOCK_HANDLE: return "NF_BLOCK_HANDLE";
10434   default:
10435     return "Unknown";
10436   }
10437 }
10438 
10439 static
getNFBitNames(char * buff,Uint32 buffLen,const Uint32 bits)10440 void getNFBitNames(char* buff, Uint32 buffLen, const Uint32 bits)
10441 {
10442   Uint32 index = 1;
10443   while (index < Dbtc::HostRecord::NF_NODE_FAIL_BITS)
10444   {
10445     if (bits & index)
10446     {
10447       Uint32 chars = BaseString::snprintf(buff,
10448                                           buffLen,
10449                                           "%s",
10450                                           getNFBitName(index));
10451       buff+= chars;
10452       buffLen-= chars;
10453       if (bits > (index << 1))
10454       {
10455         chars = BaseString::snprintf(buff,
10456                                      buffLen,
10457                                      ", ");
10458         buff+= chars;
10459         buffLen-= chars;
10460       }
10461     }
10462 
10463     index = index << 1;
10464   }
10465 }
10466 
10467 
10468 void
checkNodeFailComplete(Signal * signal,Uint32 failedNodeId,Uint32 bit)10469 Dbtc::checkNodeFailComplete(Signal* signal,
10470 			    Uint32 failedNodeId,
10471 			    Uint32 bit)
10472 {
10473   hostptr.i = failedNodeId;
10474   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
10475   hostptr.p->m_nf_bits &= ~bit;
10476 
10477   if (hostptr.p->m_nf_bits == 0)
10478   {
10479     g_eventLogger->info("DBTC %u: Step %s completed, failure handling for "
10480                         "node %u complete.",
10481                         instance(),
10482                         getNFBitName(bit),
10483                         failedNodeId);
10484 
10485     NFCompleteRep * const nfRep = (NFCompleteRep *)&signal->theData[0];
10486     nfRep->blockNo      = DBTC;
10487     nfRep->nodeId       = cownNodeid;
10488     nfRep->failedNodeId = hostptr.i;
10489 
10490     if (instance() == 0)
10491     {
10492       jam();
10493       sendSignal(cdihblockref, GSN_NF_COMPLETEREP, signal,
10494                  NFCompleteRep::SignalLength, JBB);
10495       sendSignal(QMGR_REF, GSN_NF_COMPLETEREP, signal,
10496                  NFCompleteRep::SignalLength, JBB);
10497     }
10498     else
10499     {
10500       /**
10501        * Send to proxy
10502        */
10503       sendSignal(DBTC_REF, GSN_NF_COMPLETEREP, signal,
10504                  NFCompleteRep::SignalLength, JBB);
10505     }
10506   }
10507   else
10508   {
10509     char buffer[100];
10510     getNFBitNames(buffer,
10511                   sizeof(buffer),
10512                   hostptr.p->m_nf_bits);
10513 
10514     g_eventLogger->info("DBTC %u: Step %s completed, failure handling "
10515                         "for node %u waiting for %s.",
10516                         instance(),
10517                         getNFBitName(bit),
10518                         failedNodeId,
10519                         buffer);
10520   }
10521 
10522   CRASH_INSERTION(8058);
10523   if (ERROR_INSERTED(8059))
10524   {
10525     signal->theData[0] = 9999;
10526     sendSignalWithDelay(numberToRef(CMVMI, hostptr.i),
10527                         GSN_NDB_TAMPER, signal, 100, 1);
10528   }
10529 }
10530 
checkScanActiveInFailedLqh(Signal * signal,Uint32 scanPtrI,Uint32 failedNodeId)10531 void Dbtc::checkScanActiveInFailedLqh(Signal* signal,
10532                                       Uint32 scanPtrI,
10533                                       Uint32 failedNodeId)
10534 {
10535   ScanRecordPtr scanptr;
10536   while (scanPtrI != RNIL)
10537   {
10538     jam();
10539     if (unlikely(scanRecordPool.getUncheckedPtrs(&scanPtrI, &scanptr, 1) == 0))
10540     {
10541       continue;
10542     }
10543     if (!Magic::match(scanptr.p->m_magic, ScanRecord::TYPE_ID))
10544     {
10545       continue;
10546     }
10547     bool found = false;
10548     if (scanptr.p->scanState != ScanRecord::IDLE)
10549     {
10550       jam();
10551       ScanFragRecPtr ptr;
10552       Local_ScanFragRec_dllist run(c_scan_frag_pool,
10553                                    scanptr.p->m_running_scan_frags);
10554 
10555       for(run.first(ptr); !ptr.isNull(); )
10556       {
10557 	jam();
10558 	ScanFragRecPtr curr = ptr;
10559 	run.next(ptr);
10560 	if (curr.p->scanFragState == ScanFragRec::LQH_ACTIVE &&
10561 	    refToNode(curr.p->lqhBlockref) == failedNodeId)
10562         {
10563 	  jam();
10564 	  curr.p->scanFragState = ScanFragRec::COMPLETED;
10565 	  curr.p->stopFragTimer();
10566           run.remove(curr);
10567           c_scan_frag_pool.release(curr);
10568 	  found = true;
10569 	}
10570       }
10571       if (found)
10572       {
10573         checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
10574                             c_scan_frag_pool);
10575       }
10576       if (!found)
10577       {
10578         Local_ScanFragRec_dllist deliv(c_scan_frag_pool,
10579                                        scanptr.p->m_delivered_scan_frags);
10580         for(deliv.first(ptr); !ptr.isNull(); deliv.next(ptr))
10581         {
10582           jam();
10583           if (refToNode(ptr.p->lqhBlockref) == failedNodeId)
10584           {
10585             jam();
10586             found = true;
10587             break;
10588           }
10589         }
10590       }
10591       if (!found)
10592       {
10593         ScanFragLocationPtr ptr;
10594         Local_ScanFragLocation_list frags(m_fragLocationPool,
10595                                           scanptr.p->m_fragLocations);
10596         for (frags.first(ptr); !found && !ptr.isNull(); frags.next(ptr))
10597         {
10598           for (Uint32 j = ptr.p->m_first_index; j < ptr.p->m_next_index; j++)
10599           {
10600             const BlockReference blockRef =
10601               ptr.p->m_frag_location_array[j].preferredBlockRef;
10602             const NodeId nodeId = refToNode(blockRef);
10603             if (nodeId == failedNodeId)
10604             {
10605               jam();
10606               found = true;
10607               break;
10608             }
10609           }
10610         }
10611       }
10612     }
10613     if(found)
10614     {
10615       jam();
10616       scanError(signal, scanptr, ZSCAN_LQH_ERROR);
10617     }
10618 
10619     // Send CONTINUEB to continue later
10620     signal->theData[0] = TcContinueB::ZCHECK_SCAN_ACTIVE_FAILED_LQH;
10621     signal->theData[1] = scanPtrI; // Check next scanptr
10622     signal->theData[2] = failedNodeId;
10623     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10624     return;
10625   }//for
10626   checkNodeFailComplete(signal, failedNodeId, HostRecord::NF_CHECK_SCAN);
10627 }
10628 
10629 void
nodeFailCheckTransactions(Signal * signal,Uint32 transPtrI,Uint32 failedNodeId)10630 Dbtc::nodeFailCheckTransactions(Signal* signal,
10631 				Uint32 transPtrI,
10632 				Uint32 failedNodeId)
10633 {
10634   jam();
10635   Uint32 TtcTimer = ctcTimer;
10636   Uint32 TapplTimeout = c_appl_timeout_value;
10637 
10638   const Uint32 RT_BREAK = 64;
10639   Uint32 loop_count = 0;
10640   Uint32 api_ptr = transPtrI;
10641   bool found = false;
10642   while (!found &&
10643          api_ptr != RNIL &&
10644          loop_count < RT_BREAK)
10645   {
10646     jam();
10647     ApiConnectRecordPtr ptrs[8];
10648     Uint32 ptr_cnt =
10649         c_apiConnectRecordPool.getUncheckedPtrs(&api_ptr,
10650                                                 ptrs,
10651                                                 NDB_ARRAY_SIZE(ptrs));
10652     loop_count += NDB_ARRAY_SIZE(ptrs);
10653     for (Uint32 i = 0; i < ptr_cnt; i++)
10654     {
10655       jam();
10656       if (!Magic::match(ptrs[i].p->m_magic, ApiConnectRecord::TYPE_ID))
10657       {
10658         continue;
10659       }
10660       ApiConnectRecordPtr const& transPtr = ptrs[i];
10661       if (transPtr.p->m_transaction_nodes.get(failedNodeId))
10662       {
10663         jam();
10664 
10665         // Force timeout regardless of state
10666         c_appl_timeout_value = 1;
10667           setApiConTimer(transPtr, TtcTimer - 2, __LINE__);
10668         timeOutFoundLab(signal, transPtr.i, ZNODEFAIL_BEFORE_COMMIT);
10669         c_appl_timeout_value = TapplTimeout;
10670 
10671         if (i + 1 < ptr_cnt)
10672         {
10673           api_ptr = ptrs[i + 1].i;
10674         }
10675         found = true;
10676         break;
10677       }
10678     }
10679   }
10680   if (api_ptr == RNIL)
10681   {
10682     jam();
10683     checkNodeFailComplete(signal, failedNodeId,
10684                           HostRecord::NF_CHECK_TRANSACTION);
10685   }
10686   else
10687   {
10688     signal->theData[0] = TcContinueB::ZNF_CHECK_TRANSACTIONS;
10689     signal->theData[1] = api_ptr;
10690     signal->theData[2] = failedNodeId;
10691     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
10692   }
10693 }
10694 
10695 void
ndbdFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)10696 Dbtc::ndbdFailBlockCleanupCallback(Signal* signal,
10697                                    Uint32 failedNodeId,
10698                                    Uint32 ignoredRc)
10699 {
10700   jamEntry();
10701 
10702   checkNodeFailComplete(signal, failedNodeId,
10703                         HostRecord::NF_BLOCK_HANDLE);
10704 }
10705 
10706 void
apiFailBlockCleanupCallback(Signal * signal,Uint32 failedNodeId,Uint32 ignoredRc)10707 Dbtc::apiFailBlockCleanupCallback(Signal* signal,
10708                                   Uint32 failedNodeId,
10709                                   Uint32 ignoredRc)
10710 {
10711   jamEntry();
10712 
10713   signal->theData[0] = failedNodeId;
10714   signal->theData[1] = reference();
10715   sendSignal(capiFailRef, GSN_API_FAILCONF, signal, 2, JBB);
10716 }
10717 
10718 void
checkScanFragList(Signal * signal,Uint32 failedNodeId,ScanRecord * scanP,Local_ScanFragRec_dllist::Head & head)10719 Dbtc::checkScanFragList(Signal* signal,
10720                         Uint32 failedNodeId,
10721                         ScanRecord * scanP,
10722                         Local_ScanFragRec_dllist::Head & head)
10723 {
10724   DEBUG("checkScanActiveInFailedLqh: scanFragError");
10725 }
10726 
execTAKE_OVERTCCONF(Signal * signal)10727 void Dbtc::execTAKE_OVERTCCONF(Signal* signal)
10728 {
10729   jamEntry();
10730 
10731   const Uint32 sig_len = signal->getLength();
10732 
10733   const TakeOverTcConf* const conf = (const TakeOverTcConf*) &signal->theData;
10734 
10735   const Uint32 failedNodeId = conf->failedNode;
10736   hostptr.i = failedNodeId;
10737   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
10738 
10739   const Uint32 senderRef = conf->senderRef;
10740 
10741   if (senderRef != reference())
10742   {
10743     jam();
10744 
10745     tcNodeFailptr.i = 0;
10746     ptrAss(tcNodeFailptr, tcFailRecord);
10747 
10748     /**
10749      * Node should be in queue
10750      */
10751     Uint32 i = 0;
10752     Uint32 end = tcNodeFailptr.p->queueIndex;
10753     for (; i<end; i++)
10754     {
10755       jam();
10756       if (tcNodeFailptr.p->queueList[i] == hostptr.i)
10757       {
10758         g_eventLogger->info("DBTC %u: Removed node %u"
10759           " from takeover queue, %u failed nodes remaining",
10760                             instance(),
10761                             hostptr.i,
10762                             end - 1);
10763 
10764         jam();
10765         break;
10766       }
10767     }
10768 
10769     if (i == end)
10770     {
10771       if (sig_len <= TakeOverTcConf::SignalLength_v8_0_17)
10772       {
10773         jam();
10774         if (!checkNodeFailSequence(signal))
10775         {
10776           jam();
10777           return;
10778         }
10779         /*
10780          * Fallthrough to resend signal for later retry.
10781          */
10782       }
10783       else
10784       {
10785         jam();
10786         const Uint32 senderTcFailNo = conf->tcFailNo;
10787         const Uint32 tcFailNo = cfailure_nr;
10788         /*
10789          * If we have seen the failure number that sender have seen, we really
10790          * should have queued the node failed for handling.
10791          */
10792         ndbrequire(tcFailNo < senderTcFailNo);
10793       }
10794       /*
10795        * If we have not yet seen all failures that sender has, delay this
10796        * signal for retry later.
10797        */
10798       sendSignalWithDelay(reference(), GSN_TAKE_OVERTCCONF, signal,
10799                           10, signal->getLength());
10800       return;
10801     }
10802     tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[end-1];
10803     tcNodeFailptr.p->queueIndex = end - 1;
10804   }
10805 
10806   Uint32 cnt = c_ongoing_take_over_cnt;
10807   ndbrequire(cnt);
10808   c_ongoing_take_over_cnt = cnt - 1;
10809   checkNodeFailComplete(signal, hostptr.i, HostRecord::NF_TAKEOVER);
10810 
10811   GcpRecordPtr tmpGcpPointer;
10812   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
10813   if (cnt == 1 && gcp_list.first(tmpGcpPointer))
10814   {
10815     /**
10816      * Check if there are any hanging GCP_NOMORETRANS
10817      */
10818     if (tmpGcpPointer.p->gcpNomoretransRec)
10819     {
10820       if (tmpGcpPointer.p->apiConnectList.isEmpty())
10821       {
10822         jam();
10823         g_eventLogger->info("DBTC %u: Completing GCP %u/%u "
10824                             "on node failure takeover completion.",
10825                             instance(),
10826                             Uint32(tmpGcpPointer.p->gcpId >> 32),
10827                             Uint32(tmpGcpPointer.p->gcpId));
10828         gcpTcfinished(signal, tmpGcpPointer.p->gcpId);
10829         unlinkAndReleaseGcp(tmpGcpPointer);
10830       }
10831       else
10832       {
10833         jam();
10834         /**
10835          * GCP completion underway, but not all transactions
10836          * completed.  Completion will be normal.
10837          * Log now for symmetry in NF handling logging
10838          */
10839         g_eventLogger->info("DBTC %u: GCP completion %u/%u waiting "
10840                             "for all included transactions to complete.",
10841                             instance(),
10842                             Uint32(tmpGcpPointer.p->gcpId >> 32),
10843                             Uint32(tmpGcpPointer.p->gcpId));
10844       }
10845     }
10846   }
10847 }//Dbtc::execTAKE_OVERTCCONF()
10848 
insert_take_over_failed_node(Signal * signal,Uint32 failedNodeId)10849 void Dbtc::insert_take_over_failed_node(Signal* signal, Uint32 failedNodeId)
10850 {
10851   tcNodeFailptr.i = 0;
10852   ptrAss(tcNodeFailptr, tcFailRecord);
10853   if (tcNodeFailptr.p->failStatus != FS_IDLE ||
10854       cmasterNodeId != getOwnNodeId() ||
10855       (! (instance() == 0 /* single TC */ ||
10856           instance() == TAKE_OVER_INSTANCE))) /* in mt-TC case let 1 instance
10857                                                  do take-over */
10858   {
10859     jam();
10860     /*------------------------------------------------------------*/
10861     /*       WE CAN CURRENTLY ONLY HANDLE ONE TAKE OVER AT A TIME */
10862     /*------------------------------------------------------------*/
10863     /*       IF MORE THAN ONE TAKE OVER IS REQUESTED WE WILL      */
10864     /*       QUEUE THE TAKE OVER AND START IT AS SOON AS THE      */
10865     /*       PREVIOUS ARE COMPLETED.                              */
10866     /*------------------------------------------------------------*/
10867     g_eventLogger->info("DBTC %u: Inserting failed node %u into"
10868                         " takeover queue, length %u",
10869                         instance(),
10870                         failedNodeId,
10871                         tcNodeFailptr.p->queueIndex + 1);
10872     arrGuard(tcNodeFailptr.p->queueIndex, MAX_NDB_NODES);
10873     tcNodeFailptr.p->queueList[tcNodeFailptr.p->queueIndex] = failedNodeId;
10874     tcNodeFailptr.p->queueIndex++;
10875     return;
10876   }//if
10877   g_eventLogger->info("DBTC %u: Starting take over of node %u",
10878                       instance(),
10879                       failedNodeId);
10880   ndbrequire(cmasterNodeId == getOwnNodeId());
10881   ndbrequire(instance() == 0 || instance() == TAKE_OVER_INSTANCE);
10882   startTakeOverLab(signal, 0, failedNodeId);
10883 }
10884 
10885 /**
10886   TC Takeover protocol
10887   --------------------
10888   When a node fails it has a set of transactions ongoing in many cases. In
10889   order to complete those transactions we have implemented a take over
10890   protocol.
10891 
10892   The failed node was transaction controller for a set of transactions.
10893   The transaction controller has failed, so we cannot ask it for the
10894   state of the transactions. This means that we need to rebuild the
10895   transaction state of all transactions that was controlled by the failed
10896   node. If there are several node failures at the same time, then we'll
10897   take over one node at a time. The TC take over is only handled by the
10898   first TC instance, most of the work of the take over is handled by the
10899   LQH instances that need to scan all ongoing operations to send the
10900   operations to the TC instance that takes over. For the ndbd it is handled
10901   by the TC instance simply.
10902 
10903   With the introduction of multiple TC instances we have also seen it fit
10904   to handle also the take over of one TC instance in multiple steps. We use
10905   one step per TC instance we take over. If the TC take over fails due to
10906   not having sufficient amount of transaction records or operations records,
10907   we will also run several steps for each TC instance we take over.
10908 
10909   The TC take over process will eventually complete as long as there isn't
10910   any transaction that is bigger than the number of operation records
10911   available for TC take over.
10912 
10913   The protocol works as follows:
10914 
10915   Master TC (take over TC instance, starting at instance 0):
10916   Sends:
10917   LQH_TRANSREQ (Take over data reference,
10918                 Master TC block reference,
10919                 TC Take over node id,
10920                 TC Take over instance id)
10921 
10922   This signal is sent to the LQH proxy block in each of the alive nodes.
10923   From the proxy block it is sent to each LQH instance. For ndbd's we
10924   send it directly to the LQH block.
10925 
10926   Each LQH instance scans the operations for any operations that has a
10927   TC reference that comes from the TC node and TC instance that has failed.
10928   For each such operation it sends a LQH_TRANSCONF signal that contains a
10929   lot of data about the transaction operation.
10930 
10931   When the LQH instance have completed the scan of its operations then it
10932   will send a special LQH_TRANSCONF with a last operation flag set. All
10933   LQH_TRANSCONF is sent through the LQH proxy such that we can check when
10934   all LQH instances have completed their scans. We will only send one
10935   LQH_TRANSCONF signal from each node.
10936 
10937   The Master TC that performs the take over builds the state of each
10938   transaction such that it can decide whether the transaction was
10939   committed or not, if it wasn't committed we will abort it.
10940 
10941   The design is certain that each step will at least handle one transaction
10942   for each take over step. Normally it will complete all transactions in
10943   one instance in each step, we can though handle also other uncommon cases.
10944 */
10945 
10946 /*------------------------------------------------------------*/
10947 /*       INITIALISE THE HASH TABLES FOR STORING TRANSACTIONS  */
10948 /*       AND OPERATIONS DURING TC TAKE OVER.                  */
10949 /*------------------------------------------------------------*/
startTakeOverLab(Signal * signal,Uint32 instanceId,Uint32 failedNodeId)10950 void Dbtc::startTakeOverLab(Signal* signal,
10951                             Uint32 instanceId,
10952                             Uint32 failedNodeId)
10953 {
10954   for (Uint32 i = 0; i < TRANSID_FAIL_HASH_SIZE; i++) {
10955     ctransidFailHash[i] = RNIL;
10956   }//for
10957   for (Uint32 i = 0; i < TC_FAIL_HASH_SIZE; i++) {
10958     ctcConnectFailHash[i] = RNIL;
10959   }//for
10960   tcNodeFailptr.p->failStatus = FS_LISTENING;
10961   tcNodeFailptr.p->takeOverNode = failedNodeId;
10962   tcNodeFailptr.p->takeOverInstanceId = instanceId;
10963   tcNodeFailptr.p->takeOverFailed = false;
10964   tcNodeFailptr.p->maxInstanceId = 0;
10965   tcNodeFailptr.p->handledOneTransaction = false;
10966   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
10967     jam();
10968     ptrAss(hostptr, hostRecord);
10969     if (hostptr.p->hostStatus == HS_ALIVE)
10970     {
10971       LqhTransReq * const lqhTransReq  = (LqhTransReq *)&signal->theData[0];
10972       Uint32 sig_len;
10973       jam();
10974       tblockref = calcLqhBlockRef(hostptr.i);
10975       hostptr.p->lqhTransStatus = LTS_ACTIVE;
10976       lqhTransReq->senderData = tcNodeFailptr.i;
10977       lqhTransReq->senderRef = cownref;
10978       lqhTransReq->failedNodeId = failedNodeId;
10979       lqhTransReq->instanceId = instanceId;
10980       sig_len = LqhTransReq::SignalLength;
10981       if (ERROR_INSERTED(8064) && hostptr.i == getOwnNodeId())
10982       {
10983         ndbout_c("sending delayed GSN_LQH_TRANSREQ to self");
10984         sendSignalWithDelay(tblockref, GSN_LQH_TRANSREQ, signal, 100, sig_len);
10985         CLEAR_ERROR_INSERT_VALUE;
10986       }
10987       else
10988       {
10989         sendSignal(tblockref, GSN_LQH_TRANSREQ, signal, sig_len, JBB);
10990       }
10991     }//if
10992   }//for
10993 }//Dbtc::startTakeOverLab()
10994 
10995 Uint32
get_transid_fail_bucket(Uint32 transid1)10996 Dbtc::get_transid_fail_bucket(Uint32 transid1)
10997 {
10998   return transid1 & (TRANSID_FAIL_HASH_SIZE - 1);
10999 }
11000 
11001 void
insert_transid_fail_hash(Uint32 transid1,ApiConnectRecordPtr const apiConnectptr)11002 Dbtc::insert_transid_fail_hash(Uint32 transid1, ApiConnectRecordPtr const apiConnectptr)
11003 {
11004   Uint32 bucket = get_transid_fail_bucket(transid1);
11005   ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_FAIL);
11006   apiConnectptr.p->nextApiConnect = ctransidFailHash[bucket];
11007   ctransidFailHash[bucket] = apiConnectptr.i;
11008   return;
11009 }
11010 
11011 bool
findApiConnectFail(Signal * signal,Uint32 transid1,Uint32 transid2,ApiConnectRecordPtr & apiConnectptr)11012 Dbtc::findApiConnectFail(Signal *signal, Uint32 transid1, Uint32 transid2, ApiConnectRecordPtr& apiConnectptr)
11013 {
11014   Uint32 bucket = get_transid_fail_bucket(transid1);
11015   apiConnectptr.i = ctransidFailHash[bucket];
11016 
11017   while (apiConnectptr.i != RNIL)
11018   {
11019     jam();
11020     c_apiConnectRecordPool.getPtr(apiConnectptr);
11021     ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_FAIL);
11022     if (apiConnectptr.p->transid[0] == transid1 &&
11023         apiConnectptr.p->transid[1] == transid2)
11024     {
11025       jam();
11026       return true;
11027     }
11028     apiConnectptr.i = apiConnectptr.p->nextApiConnect;
11029   }
11030   jam();
11031   return false;
11032 }
11033 
releaseMarker(ApiConnectRecord * const regApiPtr)11034 void Dbtc::releaseMarker(ApiConnectRecord * const regApiPtr)
11035 {
11036   Ptr<CommitAckMarker> marker;
11037   marker.i = regApiPtr->commitAckMarker;
11038   if (marker.i != RNIL)
11039   {
11040     regApiPtr->commitAckMarker = RNIL;
11041     m_commitAckMarkerPool.getPtr(marker);
11042     CommitAckMarkerBuffer::DataBufferPool & pool =
11043       c_theCommitAckMarkerBufferPool;
11044     {
11045       LocalCommitAckMarkerBuffer commitAckMarkers(pool, marker.p->theDataBuffer);
11046       commitAckMarkers.release();
11047     }
11048     m_commitAckMarkerHash.remove(marker);
11049     m_commitAckMarkerPool.release(marker);
11050 
11051     checkPoolShrinkNeed(DBTC_COMMIT_ACK_MARKER_BUFFER_TRANSIENT_POOL_INDEX,
11052                         c_theCommitAckMarkerBufferPool);
11053     checkPoolShrinkNeed(DBTC_COMMIT_ACK_MARKER_TRANSIENT_POOL_INDEX,
11054                         m_commitAckMarkerPool);
11055   }
11056 }
11057 
remove_from_transid_fail_hash(Signal * signal,Uint32 transid1,ApiConnectRecordPtr const apiConnectptr)11058 void Dbtc::remove_from_transid_fail_hash(Signal *signal, Uint32 transid1, ApiConnectRecordPtr const apiConnectptr)
11059 {
11060   ApiConnectRecordPtr locApiConnectptr;
11061   ApiConnectRecordPtr prevApiConptr;
11062 
11063   ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_FAIL);
11064   prevApiConptr.i = RNIL;
11065   Uint32 bucket = get_transid_fail_bucket(transid1);
11066   locApiConnectptr.i = ctransidFailHash[bucket];
11067   ndbrequire(locApiConnectptr.i != RNIL);
11068   do
11069   {
11070     c_apiConnectRecordPool.getPtr(locApiConnectptr);
11071     if (locApiConnectptr.i == apiConnectptr.i)
11072     {
11073       if (prevApiConptr.i == RNIL)
11074       {
11075         jam();
11076         /* We were first in the hash linked list */
11077         ndbassert(ctransidFailHash[bucket] == apiConnectptr.i);
11078         ctransidFailHash[bucket] = apiConnectptr.p->nextApiConnect;
11079       }
11080       else
11081       {
11082         /* Link past our record in the hash list */
11083         jam();
11084         c_apiConnectRecordPool.getPtr(prevApiConptr);
11085         prevApiConptr.p->nextApiConnect = apiConnectptr.p->nextApiConnect;
11086       }
11087       apiConnectptr.p->nextApiConnect = RNIL;
11088       return;
11089     }
11090     else
11091     {
11092       jam();
11093       prevApiConptr.i = locApiConnectptr.i;
11094       locApiConnectptr.i = locApiConnectptr.p->nextApiConnect;
11095     }
11096   } while (locApiConnectptr.i != RNIL);
11097   ndbabort();
11098 }
11099 
11100 Uint32
get_tc_fail_bucket(Uint32 transid1,Uint32 opRec)11101 Dbtc::get_tc_fail_bucket(Uint32 transid1, Uint32 opRec)
11102 {
11103   return (transid1 ^ opRec) & (TC_FAIL_HASH_SIZE - 1);
11104 }
11105 
11106 void
insert_tc_fail_hash(Uint32 transid1,Uint32 tcOprec)11107 Dbtc::insert_tc_fail_hash(Uint32 transid1, Uint32 tcOprec)
11108 {
11109   Uint32 bucket = get_tc_fail_bucket(transid1, tcOprec);
11110   tcConnectptr.p->nextTcFailHash = ctcConnectFailHash[bucket];
11111   ctcConnectFailHash[bucket] = tcConnectptr.i;
11112 }
11113 
11114 bool
findTcConnectFail(Signal * signal,Uint32 transid1,Uint32 transid2,Uint32 tcOprec,ApiConnectRecordPtr const apiConnectptr)11115 Dbtc::findTcConnectFail(Signal* signal,
11116                         Uint32 transid1,
11117                         Uint32 transid2,
11118                         Uint32 tcOprec,
11119                         ApiConnectRecordPtr const apiConnectptr)
11120 {
11121   Uint32 bucket = get_tc_fail_bucket(transid1, tcOprec);
11122 
11123   tcConnectptr.i = ctcConnectFailHash[bucket];
11124   while (tcConnectptr.i != RNIL)
11125   {
11126     tcConnectRecord.getPtr(tcConnectptr);
11127     if (tcConnectptr.p->tcOprec == tcOprec &&
11128         tcConnectptr.p->apiConnect == apiConnectptr.i &&
11129         apiConnectptr.p->transid[0] == transid1 &&
11130         apiConnectptr.p->transid[1] == transid2)
11131     {
11132       jam();
11133       return true;
11134     }
11135     else
11136     {
11137       jam();
11138       tcConnectptr.i = tcConnectptr.p->nextTcFailHash;
11139     }
11140   }
11141   jam();
11142   return false;
11143 }
11144 
remove_transaction_from_tc_fail_hash(Signal * signal,ApiConnectRecord * const regApiPtr)11145 void Dbtc::remove_transaction_from_tc_fail_hash(Signal *signal, ApiConnectRecord* const regApiPtr)
11146 {
11147   TcConnectRecordPtr remTcConnectptr;
11148 
11149   remTcConnectptr.i = regApiPtr->tcConnect.getFirst();
11150   while (remTcConnectptr.i != RNIL)
11151   {
11152     jam();
11153     TcConnectRecordPtr loopTcConnectptr;
11154     TcConnectRecordPtr prevListptr;
11155     tcConnectRecord.getPtr(remTcConnectptr);
11156     bool found = false;
11157     Uint32 bucket = get_tc_fail_bucket(regApiPtr->transid[0],
11158                                        remTcConnectptr.p->tcOprec);
11159     prevListptr.i = RNIL;
11160     loopTcConnectptr.i = ctcConnectFailHash[bucket];
11161     while (loopTcConnectptr.i != RNIL)
11162     {
11163       if (loopTcConnectptr.i == remTcConnectptr.i)
11164       {
11165         found = true;
11166         if (prevListptr.i == RNIL)
11167         {
11168           jam();
11169           /* We were first in the hash linked list */
11170           ndbassert(ctcConnectFailHash[bucket] == remTcConnectptr.i);
11171           ctcConnectFailHash[bucket] = remTcConnectptr.p->nextTcFailHash;
11172         }
11173         else
11174         {
11175           /* Link past our record in the hash list */
11176           jam();
11177           tcConnectRecord.getPtr(prevListptr);
11178           prevListptr.p->nextTcFailHash =
11179             remTcConnectptr.p->nextTcFailHash;
11180         }
11181         remTcConnectptr.p->nextTcFailHash = RNIL;
11182         break;
11183       }
11184       else
11185       {
11186         jam();
11187         tcConnectRecord.getPtr(loopTcConnectptr);
11188         prevListptr.i = loopTcConnectptr.i;
11189         loopTcConnectptr.i = loopTcConnectptr.p->nextTcFailHash;
11190       }
11191     }
11192     ndbrequire(found);
11193     remTcConnectptr.i = remTcConnectptr.p->nextList;
11194   }
11195 }
11196 
11197 /*------------------------------------------------------------*/
11198 /*       A REPORT OF AN OPERATION WHERE TC FAILED HAS ARRIVED.*/
11199 /*------------------------------------------------------------*/
execLQH_TRANSCONF(Signal * signal)11200 void Dbtc::execLQH_TRANSCONF(Signal* signal)
11201 {
11202   jamEntry();
11203   LqhTransConf * const lqhTransConf = (LqhTransConf *)&signal->theData[0];
11204 
11205   if (ERROR_INSERTED(8102) ||
11206       ERROR_INSERTED(8118))
11207   {
11208     jam();
11209     if ((((LqhTransConf::OperationStatus)lqhTransConf->operationStatus) ==
11210          LqhTransConf::LastTransConf) &&
11211         ((signal->getSendersBlockRef() != reference()) ||
11212          ERROR_INSERTED(8118)))
11213     {
11214       jam();
11215       ndbout_c("Delaying final LQH_TRANSCONF from Lqh @ node %u",
11216                refToNode(signal->getSendersBlockRef()));
11217       // Force multi-tc takeover
11218       ((LqhTransConf*)lqhTransConf)->maxInstanceId = 4;
11219       sendSignalWithDelay(reference(),
11220                           GSN_LQH_TRANSCONF,
11221                           signal,
11222                           5000,
11223                           signal->getLength());
11224       return;
11225     }
11226   }
11227 
11228   CRASH_INSERTION(8060);
11229 
11230   tcNodeFailptr.i = lqhTransConf->tcRef;
11231   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
11232   NodeId nodeId = lqhTransConf->lqhNodeId;
11233   LqhTransConf::OperationStatus transStatus =
11234     (LqhTransConf::OperationStatus)lqhTransConf->operationStatus;
11235   Uint32 transid1    = lqhTransConf->transId1;
11236   Uint32 transid2    = lqhTransConf->transId2;
11237   Uint32 tcOprec     = lqhTransConf->oldTcOpRec;
11238   Uint32 reqinfo     = lqhTransConf->requestInfo;
11239   Uint64 gci         = Uint64(lqhTransConf->gci_hi) << 32;
11240   cnodes[0]    = lqhTransConf->nextNodeId1;
11241   cnodes[1]    = lqhTransConf->nextNodeId2;
11242   cnodes[2]    = lqhTransConf->nextNodeId3;
11243   const BlockReference ref = lqhTransConf->apiRef;
11244   BlockReference applRef = lqhTransConf->apiRef;
11245   Uint32 applOprec   = lqhTransConf->apiOpRec;
11246   const Uint32 tableId = lqhTransConf->tableId;
11247   Uint32 gci_lo = lqhTransConf->gci_lo;
11248   Uint32 fragId = lqhTransConf->fragId;
11249 
11250   ndbrequire(transStatus != LqhTransConf::Committed ||
11251              (signal->getLength() >= LqhTransConf::SignalLength_GCI_LO));
11252   gci |= gci_lo;
11253 
11254   if (transStatus == LqhTransConf::LastTransConf){
11255     jam();
11256     Uint32 maxInstanceId = lqhTransConf->maxInstanceId;
11257     if (unlikely(signal->getLength() < LqhTransConf::SignalLength_INST_ID))
11258     {
11259       maxInstanceId = 0;
11260     }
11261     ndbassert(maxInstanceId < NDBMT_MAX_BLOCK_INSTANCES);
11262     /* A node has reported one phase of take over handling as completed. */
11263     DEB_NODE_FAILURE(("Node %u report completion of a phase, maxInstance: %u",
11264                       nodeId,
11265                       maxInstanceId));
11266     nodeTakeOverCompletedLab(signal, nodeId, maxInstanceId);
11267     return;
11268   }//if
11269   if (transStatus == LqhTransConf::Marker){
11270     jam();
11271     reqinfo = 0;
11272     LqhTransConf::setMarkerFlag(reqinfo, 1);
11273   } else {
11274     TableRecordPtr tabPtr;
11275     tabPtr.i = tableId;
11276     ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
11277     switch((DictTabInfo::TableType)tabPtr.p->tableType){
11278     case DictTabInfo::SystemTable:
11279     case DictTabInfo::UserTable:
11280       break;
11281     default:
11282       applRef = 0;
11283       applOprec = 0;
11284     }
11285   }
11286 
11287   ApiConnectRecordPtr apiConnectptr;
11288   if (findApiConnectFail(signal, transid1, transid2, apiConnectptr))
11289   {
11290     /**
11291      * Found a transaction record, record the added info about this
11292      * transaction as received in this message
11293      */
11294     updateApiStateFail(signal,
11295                        transid1,
11296                        transid2,
11297                        transStatus,
11298                        reqinfo,
11299                        applRef,
11300                        gci,
11301                        nodeId,
11302                        apiConnectptr);
11303   }
11304   else
11305   {
11306     if (tcNodeFailptr.p->takeOverFailed)
11307     {
11308       jam();
11309       /**
11310        * After we failed to allocate a transaction record we won't
11311        * try to allocate any new ones since it might mean that we
11312        * miss operations of a transaction.
11313        */
11314       return;
11315     }
11316     if (unlikely(!seizeApiConnectFail(signal, apiConnectptr)))
11317     {
11318       jam();
11319       /**
11320        * We failed to allocate a transaction record, we will record that
11321        * we failed to handle all transactions and we will not allocate
11322        * any more transaction records as part of taking over this instance
11323        * of the failed TC. The failed transactions will be taken over in
11324        * a second step of the TC take over of this instance and possibly
11325        * even more than two steps will be performed.
11326        *
11327        * This could happen if the master node has less transaction records
11328        * than the failed node which is possible but not recommended.
11329        */
11330       g_eventLogger->info("Need to do another round of TC takeover handling."
11331                           " The failed node had a higher setting of "
11332                           "MaxNoOfConcurrentTransactions than this node has, "
11333                           "this node has MaxNoOfConcurrentTransactions = %u",
11334                           capiConnectFailCount);
11335       tcNodeFailptr.p->takeOverFailed = true;
11336       return;
11337     }
11338     /**
11339      * A new transaction was found, allocate a record for it and fill
11340      * it with info as received in LQH_TRANSCONF message. Also insert
11341      * it in hash table for transaction records in TC take over.
11342      */
11343     insert_transid_fail_hash(transid1, apiConnectptr);
11344     initApiConnectFail(signal,
11345                        transid1,
11346                        transid2,
11347                        transStatus,
11348                        reqinfo,
11349                        applRef,
11350                        gci,
11351                        nodeId,
11352                        apiConnectptr);
11353   }
11354 
11355   if(apiConnectptr.p->ndbapiBlockref == 0 && applRef != 0)
11356   {
11357     jam();
11358     apiConnectptr.p->ndbapiBlockref = ref;
11359     apiConnectptr.p->ndbapiConnect = applOprec;
11360   }
11361 
11362   if (transStatus != LqhTransConf::Marker)
11363   {
11364     Uint32 instanceKey;
11365 
11366     if (unlikely(signal->getLength() < LqhTransConf::SignalLength_FRAG_ID))
11367     {
11368       jam();
11369       instanceKey = 0;
11370     }
11371     else
11372     {
11373       jam();
11374       instanceKey = getInstanceKey(tableId, fragId);
11375     }
11376     if (findTcConnectFail(signal, transid1, transid2, tcOprec, apiConnectptr))
11377     {
11378       jam();
11379       updateTcStateFail(signal,
11380                         instanceKey,
11381                         tcOprec,
11382                         reqinfo,
11383                         transStatus,
11384                         nodeId,
11385                         apiConnectptr);
11386     }
11387     else
11388     {
11389       if (cfreeTcConnectFail.isEmpty())
11390       {
11391         /**
11392          * We failed to allocate a TC record, given that we can no longer
11393          * complete take over of this transaction we must handle the failed
11394          * transaction take over. We also set takeOverFailed to true to
11395          * ensure that we cannot start any new transaction take over after
11396          * this one. This is imperative to do since otherwise a new operation
11397          * on the failed transaction can come along and find free resources.
11398          * This would not be a correct behavior so we need to protect against
11399          * it by not starting any transactions after any seize failure.
11400          *
11401          * As long as we don't have transactions that are bigger than the
11402          * available number of TC records we should make progress at each
11403          * step and the algorithm should eventually complete.
11404          *
11405          * This could happen if the master node have fewer operation records
11406          * than the failed node had. This could happen but isn't
11407          * recommended.
11408          */
11409         jam();
11410         g_eventLogger->info("Need to do another round of TC takeover handling."
11411                             " The failed node had a higher setting of "
11412                             "MaxNoOfConcurrentOperations than this node has, "
11413                             "this node has MaxNoOfConcurrentOperations = %u",
11414                             ctcConnectFailCount);
11415         tcNodeFailptr.p->takeOverFailed = true;
11416         remove_transaction_from_tc_fail_hash(signal, apiConnectptr.p);
11417         releaseMarker(apiConnectptr.p);
11418         remove_from_transid_fail_hash(signal, transid1, apiConnectptr);
11419         releaseTakeOver(signal, apiConnectptr);
11420       }
11421       else
11422       {
11423         jam();
11424         seizeTcConnectFail(signal);
11425         linkTcInConnectionlist(signal, apiConnectptr.p);
11426         insert_tc_fail_hash(transid1, tcOprec);
11427         initTcConnectFail(signal,
11428                           instanceKey,
11429                           tcOprec,
11430                           reqinfo,
11431                           transStatus,
11432                           nodeId,
11433                           apiConnectptr.i);
11434       }
11435     }
11436   }
11437 }//Dbtc::execLQH_TRANSCONF()
11438 
11439 /*------------------------------------------------------------*/
11440 /*       A NODE HAS REPORTED COMPLETION OF TAKE OVER REPORTING*/
11441 /*------------------------------------------------------------*/
nodeTakeOverCompletedLab(Signal * signal,NodeId nodeId,Uint32 maxInstanceId)11442 void Dbtc::nodeTakeOverCompletedLab(Signal* signal,
11443                                     NodeId nodeId,
11444                                     Uint32 maxInstanceId)
11445 {
11446   Uint32 guard0;
11447 
11448   CRASH_INSERTION(8061);
11449 
11450   if (unlikely(maxInstanceId >= NDBMT_MAX_BLOCK_INSTANCES))
11451   {
11452     /**
11453      * bug# 19193927 : LQH sends junk max instance id
11454      * Bug is fixed, but handle upgrade
11455      */
11456     maxInstanceId = NDBMT_MAX_BLOCK_INSTANCES - 1;
11457   }
11458   if (tcNodeFailptr.p->maxInstanceId < maxInstanceId)
11459   {
11460     jam();
11461     tcNodeFailptr.p->maxInstanceId = maxInstanceId;
11462   }
11463   hostptr.i = nodeId;
11464   ptrCheckGuard(hostptr, chostFilesize, hostRecord);
11465   hostptr.p->lqhTransStatus = LTS_IDLE;
11466   for (hostptr.i = 1; hostptr.i < MAX_NDB_NODES; hostptr.i++) {
11467     jam();
11468     ptrAss(hostptr, hostRecord);
11469     if (hostptr.p->hostStatus == HS_ALIVE) {
11470       if (hostptr.p->lqhTransStatus == LTS_ACTIVE) {
11471         jam();
11472         /*------------------------------------------------------------*/
11473         /*       NOT ALL NODES ARE COMPLETED WITH REPORTING IN THE    */
11474         /*       TAKE OVER.                                           */
11475         /*------------------------------------------------------------*/
11476         DEB_NODE_FAILURE(("Not all nodes completed take over"));
11477         return;
11478       }//if
11479     }//if
11480   }//for
11481   /*------------------------------------------------------------*/
11482   /*       ALL NODES HAVE REPORTED ON THE STATUS OF THE VARIOUS */
11483   /*       OPERATIONS THAT WAS CONTROLLED BY THE FAILED TC. WE  */
11484   /*       ARE NOW IN A POSITION TO COMPLETE ALL OF THOSE       */
11485   /*       TRANSACTIONS EITHER IN A SUCCESSFUL WAY OR IN AN     */
11486   /*       UNSUCCESSFUL WAY. WE WILL ALSO REPORT THIS CONCLUSION*/
11487   /*       TO THE APPLICATION IF THAT IS STILL ALIVE.           */
11488   /*------------------------------------------------------------*/
11489   tcNodeFailptr.p->currentHashIndexTakeOver = 0;
11490   tcNodeFailptr.p->completedTakeOver = 0;
11491   tcNodeFailptr.p->failStatus = FS_COMPLETING;
11492   guard0 = cnoParallelTakeOver - 1;
11493   /*------------------------------------------------------------*/
11494   /*       WE WILL COMPLETE THE TRANSACTIONS BY STARTING A      */
11495   /*       NUMBER OF PARALLEL ACTIVITIES. EACH ACTIVITY WILL    */
11496   /*       COMPLETE ONE TRANSACTION AT A TIME AND IN THAT       */
11497   /*       TRANSACTION IT WILL COMPLETE ONE OPERATION AT A TIME.*/
11498   /*       WHEN ALL ACTIVITIES ARE COMPLETED THEN THE TAKE OVER */
11499   /*       IS COMPLETED.                                        */
11500   /*------------------------------------------------------------*/
11501   arrGuard(guard0, MAX_NDB_NODES);
11502   for (tindex = 0; tindex <= guard0; tindex++) {
11503     jam();
11504     tcNodeFailptr.p->takeOverProcState[tindex] = ZTAKE_OVER_ACTIVE;
11505     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
11506     signal->theData[1] = tcNodeFailptr.i;
11507     signal->theData[2] = tindex;
11508     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
11509   }//for
11510 }//Dbtc::nodeTakeOverCompletedLab()
11511 
11512 /*------------------------------------------------------------*/
11513 /*       COMPLETE A NEW TRANSACTION FROM THE HASH TABLE OF    */
11514 /*       TRANSACTIONS TO COMPLETE.                            */
11515 /*------------------------------------------------------------*/
completeTransAtTakeOverLab(Signal * signal,UintR TtakeOverInd)11516 void Dbtc::completeTransAtTakeOverLab(Signal* signal, UintR TtakeOverInd)
11517 {
11518   jam();
11519   while (tcNodeFailptr.p->currentHashIndexTakeOver < TRANSID_FAIL_HASH_SIZE)
11520   {
11521     jam();
11522     ApiConnectRecordPtr apiConnectptr;
11523     apiConnectptr.i =
11524         ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver];
11525     if (apiConnectptr.i != RNIL) {
11526       jam();
11527       /*------------------------------------------------------------*/
11528       /*       WE HAVE FOUND A TRANSACTION THAT NEEDS TO BE         */
11529       /*       COMPLETED. REMOVE IT FROM THE HASH TABLE SUCH THAT   */
11530       /*       NOT ANOTHER ACTIVITY ALSO TRIES TO COMPLETE THIS     */
11531       /*       TRANSACTION.                                         */
11532       /*------------------------------------------------------------*/
11533       c_apiConnectRecordPool.getPtr(apiConnectptr);
11534       ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_FAIL);
11535       ctransidFailHash[tcNodeFailptr.p->currentHashIndexTakeOver] =
11536         apiConnectptr.p->nextApiConnect;
11537       tcNodeFailptr.p->handledOneTransaction = true;
11538       DEB_NODE_FAILURE(("Handle apiConnect: %u in hash index: %u",
11539                         apiConnectptr.i,
11540                         tcNodeFailptr.p->currentHashIndexTakeOver));
11541       completeTransAtTakeOverDoOne(signal, TtakeOverInd, apiConnectptr);
11542       // One transaction taken care of, return from this function
11543       // and wait for the next CONTINUEB to continue processing
11544       break;
11545 
11546     } else {
11547       if (tcNodeFailptr.p->currentHashIndexTakeOver <
11548           (TRANSID_FAIL_HASH_SIZE -1)){
11549         jam();
11550         tcNodeFailptr.p->currentHashIndexTakeOver++;
11551       } else {
11552         jam();
11553         DEB_NODE_FAILURE(("completeTransAtTakeOverDoLast"));
11554         completeTransAtTakeOverDoLast(signal, TtakeOverInd);
11555         tcNodeFailptr.p->currentHashIndexTakeOver++;
11556       }//if
11557     }//if
11558   }//while
11559 }//Dbtc::completeTransAtTakeOverLab()
11560 
11561 
completeTransAtTakeOverDoLast(Signal * signal,UintR TtakeOverInd)11562 void Dbtc::completeTransAtTakeOverDoLast(Signal* signal, UintR TtakeOverInd)
11563 {
11564   Uint32 guard0;
11565   /*------------------------------------------------------------*/
11566   /*       THERE ARE NO MORE TRANSACTIONS TO COMPLETE. THIS     */
11567   /*       ACTIVITY IS COMPLETED.                               */
11568   /*------------------------------------------------------------*/
11569   arrGuard(TtakeOverInd, MAX_NDB_NODES);
11570   if (tcNodeFailptr.p->takeOverProcState[TtakeOverInd] != ZTAKE_OVER_ACTIVE) {
11571     jam();
11572     systemErrorLab(signal, __LINE__);
11573     return;
11574   }//if
11575   /**
11576    * If we need to continue with take over processing it will still be with
11577    * the same node.
11578    */
11579   if (tcNodeFailptr.p->takeOverFailed == ZTRUE)
11580   {
11581     /**
11582      * We performed a take over and it didn't complete, we will try
11583      * again. The reason it failed was due to this TC instance
11584      * not having sufficient resources to handle all transactions,
11585      * we should however make progress and thus eventually we should
11586      * be able to complete it. The only reason that it could completely
11587      * fail is if there is one transaction which is so big that we
11588      * cannot calculate its outcome.
11589      *
11590      * Given that we haven't completed this round, we continue with
11591      * one more attempt on the same TC instance.
11592      */
11593     jam();
11594     g_eventLogger->info("DBTC %u: Continuing take over of "
11595                         "DBTC instance %u in node %u",
11596                         instance(),
11597                         tcNodeFailptr.p->takeOverInstanceId,
11598                         tcNodeFailptr.p->takeOverNode);
11599     ndbrequire(tcNodeFailptr.p->handledOneTransaction);
11600     startTakeOverLab(signal,
11601                      tcNodeFailptr.p->takeOverInstanceId,
11602                      tcNodeFailptr.p->takeOverNode);
11603     return;
11604   }
11605   if (tcNodeFailptr.p->takeOverInstanceId < tcNodeFailptr.p->maxInstanceId)
11606   {
11607     /**
11608      * We deal with one TC instance at a time, we have completed one
11609      * instance and there are more instances to handle. Let's continue
11610      * with the next instance.
11611      */
11612     jam();
11613     g_eventLogger->info("DBTC %u: Completed take over of "
11614                         "DBTC instance %u in failed node %u,"
11615                         " continuing with the next instance",
11616                         instance(),
11617                         tcNodeFailptr.p->takeOverInstanceId,
11618                         tcNodeFailptr.p->takeOverNode);
11619     startTakeOverLab(signal,
11620                      tcNodeFailptr.p->takeOverInstanceId + 1,
11621                      tcNodeFailptr.p->takeOverNode);
11622     return;
11623   }
11624   /**
11625    * We have completed take over of this node for all its TC instances.
11626    * We will continue taking over other nodes if there are any more
11627    * nodes to take over.
11628    */
11629   tcNodeFailptr.p->takeOverProcState[TtakeOverInd] = ZTAKE_OVER_IDLE;
11630   tcNodeFailptr.p->completedTakeOver++;
11631 
11632   g_eventLogger->info("DBTC %u: Completed take over"
11633                       " of failed node %u",
11634                       instance(),
11635                       tcNodeFailptr.p->takeOverNode);
11636   CRASH_INSERTION(8062);
11637 
11638   if (tcNodeFailptr.p->completedTakeOver == cnoParallelTakeOver) {
11639     jam();
11640     /*------------------------------------------------------------*/
11641     /*       WE WERE THE LAST ACTIVITY THAT WAS COMPLETED. WE NEED*/
11642     /*       TO REPORT THE COMPLETION OF THE TAKE OVER TO ALL     */
11643     /*       NODES THAT ARE ALIVE.                                */
11644     /*------------------------------------------------------------*/
11645     NodeReceiverGroup rg(DBTC, c_alive_nodes);
11646     TakeOverTcConf* const conf = (TakeOverTcConf*) &signal->theData;
11647     conf->failedNode = tcNodeFailptr.p->takeOverNode;
11648     conf->senderRef = reference();
11649     conf->tcFailNo = cfailure_nr;
11650     // It is ok to send too long signal to old nodes (<8.0.18).
11651     sendSignal(rg, GSN_TAKE_OVERTCCONF, signal,
11652                TakeOverTcConf::SignalLength,
11653                JBB);
11654 
11655     if (tcNodeFailptr.p->queueIndex > 0) {
11656       jam();
11657       /*------------------------------------------------------------*/
11658       /*       THERE ARE MORE NODES TO TAKE OVER. WE NEED TO START  */
11659       /*       THE TAKE OVER.                                       */
11660       /*------------------------------------------------------------*/
11661       Uint32 failedNodeId = tcNodeFailptr.p->queueList[0];
11662       guard0 = tcNodeFailptr.p->queueIndex - 1;
11663       arrGuard(guard0 + 1, MAX_NDB_NODES);
11664       for (Uint32 i = 0; i <= guard0; i++) {
11665         jam();
11666         tcNodeFailptr.p->queueList[i] = tcNodeFailptr.p->queueList[i+1];
11667       }//for
11668       tcNodeFailptr.p->queueIndex--;
11669       g_eventLogger->info("DBTC %u: Starting next DBTC node"
11670                           " take over for failed node %u,"
11671                           " %u failed nodes remaining in takeover queue",
11672                           instance(),
11673                           failedNodeId,
11674                           tcNodeFailptr.p->queueIndex);
11675       startTakeOverLab(signal, 0, failedNodeId);
11676       return;
11677     } else {
11678       jam();
11679       tcNodeFailptr.p->failStatus = FS_IDLE;
11680     }//if
11681   }//if
11682   return;
11683 }//Dbtc::completeTransAtTakeOverDoLast()
11684 
completeTransAtTakeOverDoOne(Signal * signal,UintR TtakeOverInd,ApiConnectRecordPtr const apiConnectptr)11685 void Dbtc::completeTransAtTakeOverDoOne(Signal* signal, UintR TtakeOverInd, ApiConnectRecordPtr const apiConnectptr)
11686 {
11687   apiConnectptr.p->takeOverRec = (Uint8)tcNodeFailptr.i;
11688   apiConnectptr.p->takeOverInd = TtakeOverInd;
11689 
11690   switch (apiConnectptr.p->apiConnectstate) {
11691   case CS_FAIL_COMMITTED:
11692     jam();
11693     /*------------------------------------------------------------*/
11694     /*       ALL PARTS OF THE TRANSACTIONS REPORTED COMMITTED. WE */
11695     /*       HAVE THUS COMPLETED THE COMMIT PHASE. WE CAN REPORT  */
11696     /*       COMMITTED TO THE APPLICATION AND CONTINUE WITH THE   */
11697     /*       COMPLETE PHASE.                                      */
11698     /*------------------------------------------------------------*/
11699     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
11700     tcConnectptr.i = apiConnectptr.p->tcConnect.getFirst();
11701     tcConnectRecord.getPtr(tcConnectptr);
11702     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
11703     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
11704     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
11705     commitGciHandling(signal, apiConnectptr.p->globalcheckpointid, apiConnectptr);
11706     DEB_NODE_FAILURE(("toCompleteHandling"));
11707     toCompleteHandlingLab(signal, apiConnectptr);
11708     return;
11709   case CS_FAIL_COMMITTING:
11710     jam();
11711     /*------------------------------------------------------------*/
11712     /*       AT LEAST ONE PART WAS ONLY PREPARED AND AT LEAST ONE */
11713     /*       PART WAS COMMITTED. COMPLETE THE COMMIT PHASE FIRST. */
11714     /*       THEN CONTINUE AS AFTER COMMITTED.                    */
11715     /*------------------------------------------------------------*/
11716     tcConnectptr.i = apiConnectptr.p->tcConnect.getFirst();
11717     tcConnectRecord.getPtr(tcConnectptr);
11718     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
11719     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
11720     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
11721     commitGciHandling(signal, apiConnectptr.p->globalcheckpointid, apiConnectptr);
11722     DEB_NODE_FAILURE(("toCommitHandling"));
11723     toCommitHandlingLab(signal, apiConnectptr);
11724     return;
11725   case CS_FAIL_ABORTING:
11726   case CS_FAIL_PREPARED:
11727     jam();
11728     /*------------------------------------------------------------*/
11729     /*       WE WILL ABORT THE TRANSACTION IF IT IS IN A PREPARED */
11730     /*       STATE IN THIS VERSION. IN LATER VERSIONS WE WILL     */
11731     /*       HAVE TO ADD CODE FOR HANDLING OF PREPARED-TO-COMMIT  */
11732     /*       TRANSACTIONS. THESE ARE NOT ALLOWED TO ABORT UNTIL WE*/
11733     /*       HAVE HEARD FROM THE TRANSACTION COORDINATOR.         */
11734     /*                                                            */
11735     /*       IT IS POSSIBLE TO COMMIT TRANSACTIONS THAT ARE       */
11736     /*       PREPARED ACTUALLY. WE WILL LEAVE THIS PROBLEM UNTIL  */
11737     /*       LATER VERSIONS.                                      */
11738     /*------------------------------------------------------------*/
11739     tcConnectptr.i = apiConnectptr.p->tcConnect.getFirst();
11740     tcConnectRecord.getPtr(tcConnectptr);
11741     apiConnectptr.p->currentTcConnect = tcConnectptr.i;
11742     apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
11743     tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
11744     DEB_NODE_FAILURE(("toAbortHandling"));
11745     toAbortHandlingLab(signal, apiConnectptr);
11746     return;
11747   case CS_FAIL_ABORTED:
11748     jam();
11749     sendTCKEY_FAILREF(signal, apiConnectptr.p);
11750 
11751     DEB_NODE_FAILURE(("sendTCKEY_FAILREF"));
11752     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
11753     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
11754     signal->theData[2] = apiConnectptr.p->takeOverInd;
11755     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
11756     releaseTakeOver(signal, apiConnectptr);
11757     break;
11758   case CS_FAIL_COMPLETED:
11759     jam();
11760     sendTCKEY_FAILCONF(signal, apiConnectptr.p);
11761 
11762     DEB_NODE_FAILURE(("sendTCKEY_FAILCONF"));
11763     signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
11764     signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
11765     signal->theData[2] = apiConnectptr.p->takeOverInd;
11766     sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
11767     releaseApiConnectFail(signal, apiConnectptr);
11768     break;
11769   default:
11770     jam();
11771     systemErrorLab(signal, __LINE__);
11772     return;
11773   }//switch
11774 }//Dbtc::completeTransAtTakeOverDoOne()
11775 
11776 void
sendTCKEY_FAILREF(Signal * signal,ApiConnectRecord * regApiPtr)11777 Dbtc::sendTCKEY_FAILREF(Signal* signal, ApiConnectRecord * regApiPtr){
11778   jam();
11779 
11780   const Uint32 ref = regApiPtr->ndbapiBlockref;
11781   const NodeId nodeId = refToNode(ref);
11782   if(ref != 0)
11783   {
11784     jam();
11785     bool connectedToNode = getNodeInfo(nodeId).m_connected;
11786     signal->theData[0] = regApiPtr->ndbapiConnect;
11787     signal->theData[1] = regApiPtr->transid[0];
11788     signal->theData[2] = regApiPtr->transid[1];
11789 
11790     if (likely(connectedToNode))
11791     {
11792       jam();
11793       sendSignal(ref, GSN_TCKEY_FAILREF, signal, 3, JBB);
11794     }
11795     else
11796     {
11797       routeTCKEY_FAILREFCONF(signal, regApiPtr, GSN_TCKEY_FAILREF, 3);
11798     }
11799   }
11800   releaseMarker(regApiPtr);
11801 }
11802 
11803 void
sendTCKEY_FAILCONF(Signal * signal,ApiConnectRecord * regApiPtr)11804 Dbtc::sendTCKEY_FAILCONF(Signal* signal, ApiConnectRecord * regApiPtr){
11805   jam();
11806   TcKeyFailConf * const failConf = (TcKeyFailConf *)&signal->theData[0];
11807 
11808   const Uint32 ref = regApiPtr->ndbapiBlockref;
11809   const Uint32 marker = regApiPtr->commitAckMarker;
11810   const NodeId nodeId = refToNode(ref);
11811   if(ref != 0)
11812   {
11813     jam();
11814     failConf->apiConnectPtr = regApiPtr->ndbapiConnect | (marker != RNIL);
11815     failConf->transId1 = regApiPtr->transid[0];
11816     failConf->transId2 = regApiPtr->transid[1];
11817 
11818     bool connectedToNode = getNodeInfo(nodeId).m_connected;
11819     if (likely(connectedToNode))
11820     {
11821       jam();
11822       sendSignal(ref, GSN_TCKEY_FAILCONF, signal,
11823 		 TcKeyFailConf::SignalLength, JBB);
11824     }
11825     else
11826     {
11827       routeTCKEY_FAILREFCONF(signal, regApiPtr,
11828 			     GSN_TCKEY_FAILCONF, TcKeyFailConf::SignalLength);
11829     }
11830   }
11831   regApiPtr->commitAckMarker = RNIL;
11832 }
11833 
11834 void
routeTCKEY_FAILREFCONF(Signal * signal,const ApiConnectRecord * regApiPtr,Uint32 gsn,Uint32 len)11835 Dbtc::routeTCKEY_FAILREFCONF(Signal* signal, const ApiConnectRecord* regApiPtr,
11836 			     Uint32 gsn, Uint32 len)
11837 {
11838   jam();
11839 
11840   Uint32 ref = regApiPtr->ndbapiBlockref;
11841 
11842   /**
11843    * We're not connected
11844    *   so we find another node in same node group as died node
11845    *   and send to it, so that it can forward
11846    */
11847   tcNodeFailptr.i = regApiPtr->takeOverRec;
11848   ptrCheckGuard(tcNodeFailptr, 1, tcFailRecord);
11849 
11850   /**
11851    * Save signal
11852    */
11853   Uint32 save[25];
11854   ndbrequire(len <= 25);
11855   memcpy(save, signal->theData, 4*len);
11856 
11857   Uint32 node = tcNodeFailptr.p->takeOverNode;
11858 
11859   CheckNodeGroups * sd = (CheckNodeGroups*)signal->getDataPtrSend();
11860   sd->blockRef = reference();
11861   sd->requestType =
11862     CheckNodeGroups::Direct |
11863     CheckNodeGroups::GetNodeGroupMembers;
11864   sd->nodeId = node;
11865   EXECUTE_DIRECT_MT(DBDIH, GSN_CHECKNODEGROUPSREQ, signal,
11866 		    CheckNodeGroups::SignalLength, 0);
11867   jamEntry();
11868 
11869   NdbNodeBitmask mask;
11870   mask.assign(sd->mask);
11871   mask.clear(getOwnNodeId());
11872   memcpy(signal->theData, save, 4*len);
11873 
11874   Uint32 i = 0;
11875   while((i = mask.find(i + 1)) != NdbNodeBitmask::NotFound)
11876   {
11877     jam();
11878     HostRecordPtr localHostptr;
11879     localHostptr.i = i;
11880     ptrCheckGuard(localHostptr, chostFilesize, hostRecord);
11881     if (localHostptr.p->hostStatus == HS_ALIVE)
11882     {
11883       jam();
11884       signal->theData[len] = gsn;
11885       signal->theData[len+1] = ref;
11886       sendSignal(calcTcBlockRef(i), GSN_TCKEY_FAILREFCONF_R,
11887 		 signal, len+2, JBB);
11888       return;
11889     }
11890   }
11891 
11892 
11893    /**
11894     * This code was 'unfinished' code for partially connected API's
11895     *   it does however not really work...
11896     *   and we seriously need to think about semantics for API connect
11897     */
11898 #if 0
11899   ndbrequire(getNodeInfo(refToNode(ref)).m_type == NodeInfo::DB);
11900 #endif
11901 }
11902 
11903 void
execTCKEY_FAILREFCONF_R(Signal * signal)11904 Dbtc::execTCKEY_FAILREFCONF_R(Signal* signal)
11905 {
11906   jamEntry();
11907   Uint32 len = signal->getLength();
11908   Uint32 gsn = signal->theData[len-2];
11909   Uint32 ref = signal->theData[len-1];
11910   sendSignal(ref, gsn, signal, len-2, JBB);
11911 }
11912 
11913 /*------------------------------------------------------------*/
11914 /*       THIS PART HANDLES THE ABORT PHASE IN THE CASE OF A   */
11915 /*       NODE FAILURE BEFORE THE COMMIT DECISION.             */
11916 /*------------------------------------------------------------*/
11917 /*       ABORT REQUEST SUCCESSFULLY COMPLETED ON TNODEID      */
11918 /*------------------------------------------------------------*/
execABORTCONF(Signal * signal)11919 void Dbtc::execABORTCONF(Signal* signal)
11920 {
11921   UintR compare_transid1, compare_transid2;
11922 
11923   jamEntry();
11924   tcConnectptr.i = signal->theData[0];
11925   NodeId nodeId = signal->theData[2];
11926   if (ERROR_INSERTED(8045)) {
11927     CLEAR_ERROR_INSERT_VALUE;
11928     sendSignalWithDelay(cownref, GSN_ABORTCONF, signal, 2000, 5);
11929     return;
11930   }//if
11931   if (unlikely(!tcConnectRecord.getValidPtr(tcConnectptr) ||
11932                tcConnectptr.p->tcConnectstate != OS_WAIT_ABORT_CONF))
11933   {
11934     jam();
11935     warningReport(signal, 16);
11936     return;
11937   }
11938   ApiConnectRecordPtr apiConnectptr;
11939   apiConnectptr.i = tcConnectptr.p->apiConnect;
11940   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr) ||
11941                apiConnectptr.p->apiConnectstate != CS_WAIT_ABORT_CONF))
11942   {
11943     jam();
11944     warningReport(signal, 17);
11945     return;
11946   }//if
11947   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[3];
11948   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[4];
11949   if (unlikely(compare_transid1 != 0 || compare_transid2 != 0))
11950   {
11951     jam();
11952     warningReport(signal, 18);
11953     return;
11954   }//if
11955   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
11956   if (unlikely(
11957     tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
11958     nodeId))
11959   {
11960     jam();
11961     warningReport(signal, 19);
11962     return;
11963   }//if
11964   tcurrentReplicaNo = (Uint8)Z8NIL;
11965   tcConnectptr.p->tcConnectstate = OS_ABORTING;
11966   toAbortHandlingLab(signal, apiConnectptr);
11967 }//Dbtc::execABORTCONF()
11968 
toAbortHandlingLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)11969 void Dbtc::toAbortHandlingLab(Signal* signal,
11970                               ApiConnectRecordPtr const apiConnectptr)
11971 {
11972   do {
11973     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
11974       jam();
11975       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
11976       const LqhTransConf::OperationStatus stat =
11977 	(LqhTransConf::OperationStatus)
11978 	tcConnectptr.p->failData[tcurrentReplicaNo];
11979       switch(stat){
11980       case LqhTransConf::InvalidStatus:
11981       case LqhTransConf::Aborted:
11982         jam();
11983         /*empty*/;
11984         break;
11985       case LqhTransConf::Prepared:
11986         jam();
11987         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
11988         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
11989         if (hostptr.p->hostStatus == HS_ALIVE) {
11990           jam();
11991           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
11992           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
11993           setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
11994           tcConnectptr.p->tcConnectstate = OS_WAIT_ABORT_CONF;
11995           apiConnectptr.p->apiConnectstate = CS_WAIT_ABORT_CONF;
11996           apiConnectptr.p->timeOutCounter = 0;
11997           signal->theData[0] = tcConnectptr.i;
11998           signal->theData[1] = cownref;
11999           signal->theData[2] = apiConnectptr.p->transid[0];
12000           signal->theData[3] = apiConnectptr.p->transid[1];
12001           signal->theData[4] = apiConnectptr.p->tcBlockref;
12002           signal->theData[5] = tcConnectptr.p->tcOprec;
12003           sendSignal(tblockref, GSN_ABORTREQ, signal, 6, JBB);
12004           return;
12005         }//if
12006         break;
12007       default:
12008         jam();
12009         systemErrorLab(signal, __LINE__);
12010         return;
12011       }//switch
12012     }//if
12013     if (apiConnectptr.p->currentReplicaNo > 0) {
12014       jam();
12015       /*------------------------------------------------------------*/
12016       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
12017       /*       ABORTED.                                             */
12018       /*------------------------------------------------------------*/
12019       apiConnectptr.p->currentReplicaNo--;
12020       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
12021     } else {
12022       /*------------------------------------------------------------*/
12023       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
12024       /*------------------------------------------------------------*/
12025       tcConnectptr.i = tcConnectptr.p->nextList;
12026       if (tcConnectptr.i == RNIL) {
12027 	/*------------------------------------------------------------*/
12028 	/*       WE HAVE COMPLETED THE ABORT PHASE. WE CAN NOW REPORT */
12029 	/*       THE ABORT STATUS TO THE APPLICATION AND CONTINUE     */
12030 	/*       WITH THE NEXT TRANSACTION.                           */
12031 	/*------------------------------------------------------------*/
12032         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
12033           jam();
12034 	  sendTCKEY_FAILREF(signal, apiConnectptr.p);
12035 
12036 	  /*------------------------------------------------------------*/
12037 	  /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
12038 	  /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
12039 	  /*------------------------------------------------------------*/
12040           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
12041           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
12042           signal->theData[2] = apiConnectptr.p->takeOverInd;
12043           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
12044           releaseTakeOver(signal, apiConnectptr);
12045         } else {
12046           jam();
12047           releaseAbortResources(signal, apiConnectptr);
12048         }//if
12049         return;
12050       }//if
12051       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
12052       tcConnectRecord.getPtr(tcConnectptr);
12053       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
12054       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
12055     }//if
12056   } while (1);
12057 }//Dbtc::toAbortHandlingLab()
12058 
12059 /*------------------------------------------------------------*/
12060 /*       THIS PART HANDLES THE COMMIT PHASE IN THE CASE OF A  */
12061 /*       NODE FAILURE IN THE MIDDLE OF THE COMMIT PHASE.      */
12062 /*------------------------------------------------------------*/
12063 /*       COMMIT REQUEST SUCCESSFULLY COMPLETED ON TNODEID     */
12064 /*------------------------------------------------------------*/
execCOMMITCONF(Signal * signal)12065 void Dbtc::execCOMMITCONF(Signal* signal)
12066 {
12067   UintR compare_transid1, compare_transid2;
12068 
12069   jamEntry();
12070   tcConnectptr.i = signal->theData[0];
12071   NodeId nodeId = signal->theData[1];
12072   if (ERROR_INSERTED(8046)) {
12073     CLEAR_ERROR_INSERT_VALUE;
12074     sendSignalWithDelay(cownref, GSN_COMMITCONF, signal, 2000, 4);
12075     return;
12076   }//if
12077   if (unlikely(!tcConnectRecord.getValidPtr(tcConnectptr) ||
12078                tcConnectptr.p->tcConnectstate != OS_WAIT_COMMIT_CONF))
12079   {
12080     jam();
12081     warningReport(signal, 8);
12082     return;
12083   }//if
12084   ApiConnectRecordPtr apiConnectptr;
12085   apiConnectptr.i = tcConnectptr.p->apiConnect;
12086   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr) ||
12087                apiConnectptr.p->apiConnectstate != CS_WAIT_COMMIT_CONF))
12088   {
12089     jam();
12090     warningReport(signal, 9);
12091     return;
12092   }//if
12093   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
12094   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
12095   if (unlikely(compare_transid1 != 0 || compare_transid2 != 0))
12096   {
12097     jam();
12098     warningReport(signal, 10);
12099     return;
12100   }//if
12101   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
12102   if (unlikely(
12103     tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
12104     nodeId))
12105   {
12106     jam();
12107     warningReport(signal, 11);
12108     return;
12109   }//if
12110   CRASH_INSERTION(8026);
12111   if (ERROR_INSERTED(8026)) {
12112     jam();
12113     systemErrorLab(signal, __LINE__);
12114   }//if
12115   tcurrentReplicaNo = (Uint8)Z8NIL;
12116   tcConnectptr.p->tcConnectstate = OS_COMMITTED;
12117   toCommitHandlingLab(signal, apiConnectptr);
12118 }//Dbtc::execCOMMITCONF()
12119 
toCommitHandlingLab(Signal * signal,ApiConnectRecordPtr apiConnectptr)12120 void Dbtc::toCommitHandlingLab(Signal* signal,
12121                                ApiConnectRecordPtr apiConnectptr)
12122 {
12123   do {
12124     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
12125       jam();
12126       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
12127       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
12128       case LqhTransConf::InvalidStatus:
12129         jam();
12130         /*empty*/;
12131         break;
12132       case LqhTransConf::Committed:
12133         jam();
12134         /*empty*/;
12135         break;
12136       case LqhTransConf::Prepared:
12137         jam();
12138         /*------------------------------------------------------------*/
12139         /*       THE NODE WAS PREPARED AND IS WAITING FOR ABORT OR    */
12140         /*       COMMIT REQUEST FROM TC.                              */
12141         /*------------------------------------------------------------*/
12142         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
12143         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
12144         if (hostptr.p->hostStatus == HS_ALIVE) {
12145           jam();
12146           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
12147           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
12148           setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
12149           apiConnectptr.p->apiConnectstate = CS_WAIT_COMMIT_CONF;
12150           apiConnectptr.p->timeOutCounter = 0;
12151           tcConnectptr.p->tcConnectstate = OS_WAIT_COMMIT_CONF;
12152           Uint64 gci = apiConnectptr.p->globalcheckpointid;
12153           signal->theData[0] = tcConnectptr.i;
12154           signal->theData[1] = cownref;
12155           signal->theData[2] = Uint32(gci >> 32); // XXX JON
12156           signal->theData[3] = apiConnectptr.p->transid[0];
12157           signal->theData[4] = apiConnectptr.p->transid[1];
12158           signal->theData[5] = apiConnectptr.p->tcBlockref;
12159           signal->theData[6] = tcConnectptr.p->tcOprec;
12160           signal->theData[7] = Uint32(gci);
12161           sendSignal(tblockref, GSN_COMMITREQ, signal, 8, JBB);
12162           return;
12163         }//if
12164         break;
12165       default:
12166         jam();
12167         systemErrorLab(signal, __LINE__);
12168         return;
12169         break;
12170       }//switch
12171     }//if
12172     if (apiConnectptr.p->currentReplicaNo > 0) {
12173       jam();
12174       /*------------------------------------------------------------*/
12175       /*       THERE IS STILL ANOTHER REPLICA THAT NEEDS TO BE      */
12176       /*       COMMITTED.                                           */
12177       /*------------------------------------------------------------*/
12178       apiConnectptr.p->currentReplicaNo--;
12179       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
12180     } else {
12181       /*------------------------------------------------------------*/
12182       /*       THE LAST REPLICA IN THIS OPERATION HAVE COMMITTED.   */
12183       /*------------------------------------------------------------*/
12184       tcConnectptr.i = tcConnectptr.p->nextList;
12185       if (tcConnectptr.i == RNIL) {
12186 	/*------------------------------------------------------------*/
12187 	/*       WE HAVE COMPLETED THE COMMIT PHASE. WE CAN NOW REPORT*/
12188 	/*       THE COMMIT STATUS TO THE APPLICATION AND CONTINUE    */
12189 	/*       WITH THE COMPLETE PHASE.                             */
12190 	/*------------------------------------------------------------*/
12191         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
12192           jam();
12193 	  sendTCKEY_FAILCONF(signal, apiConnectptr.p);
12194 	} else {
12195           jam();
12196           apiConnectptr = sendApiCommitAndCopy(signal, apiConnectptr);
12197         }//if
12198         apiConnectptr.p->currentTcConnect = apiConnectptr.p->tcConnect.getFirst();
12199         tcConnectptr.i = apiConnectptr.p->tcConnect.getFirst();
12200         tcConnectRecord.getPtr(tcConnectptr);
12201         tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
12202         apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
12203         toCompleteHandlingLab(signal, apiConnectptr);
12204         return;
12205       }//if
12206       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
12207       tcConnectRecord.getPtr(tcConnectptr);
12208       apiConnectptr.p->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
12209       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
12210     }//if
12211   } while (1);
12212 }//Dbtc::toCommitHandlingLab()
12213 
12214 /*------------------------------------------------------------*/
12215 /*       COMMON PART TO HANDLE COMPLETE PHASE WHEN ANY NODE   */
12216 /*       HAVE FAILED.                                         */
12217 /*------------------------------------------------------------*/
12218 /*       THE NODE WITH TNODEID HAVE COMPLETED THE OPERATION   */
12219 /*------------------------------------------------------------*/
execCOMPLETECONF(Signal * signal)12220 void Dbtc::execCOMPLETECONF(Signal* signal)
12221 {
12222   UintR compare_transid1, compare_transid2;
12223 
12224   jamEntry();
12225   tcConnectptr.i = signal->theData[0];
12226   NodeId nodeId = signal->theData[1];
12227   if (ERROR_INSERTED(8047)) {
12228     CLEAR_ERROR_INSERT_VALUE;
12229     sendSignalWithDelay(cownref, GSN_COMPLETECONF, signal, 2000, 4);
12230     return;
12231   }//if
12232   if (unlikely(!tcConnectRecord.getValidPtr(tcConnectptr) ||
12233                tcConnectptr.p->tcConnectstate != OS_WAIT_COMPLETE_CONF))
12234   {
12235     jam();
12236     warningReport(signal, 12);
12237     return;
12238   }//if
12239   ApiConnectRecordPtr apiConnectptr;
12240   apiConnectptr.i = tcConnectptr.p->apiConnect;
12241   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr) ||
12242                apiConnectptr.p->apiConnectstate != CS_WAIT_COMPLETE_CONF))
12243   {
12244     jam();
12245     warningReport(signal, 13);
12246     return;
12247   }//if
12248   compare_transid1 = apiConnectptr.p->transid[0] ^ signal->theData[2];
12249   compare_transid2 = apiConnectptr.p->transid[1] ^ signal->theData[3];
12250   if (unlikely(compare_transid1 != 0 || compare_transid2 != 0))
12251   {
12252     jam();
12253     warningReport(signal, 14);
12254     return;
12255   }//if
12256   arrGuard(apiConnectptr.p->currentReplicaNo, MAX_REPLICAS);
12257   if (unlikely(
12258     tcConnectptr.p->tcNodedata[apiConnectptr.p->currentReplicaNo] !=
12259     nodeId))
12260   {
12261     jam();
12262     warningReport(signal, 15);
12263     return;
12264   }//if
12265   if (ERROR_INSERTED(8028)) {
12266     jam();
12267     systemErrorLab(signal, __LINE__);
12268   }//if
12269   tcConnectptr.p->tcConnectstate = OS_COMPLETED;
12270   tcurrentReplicaNo = (Uint8)Z8NIL;
12271   toCompleteHandlingLab(signal, apiConnectptr);
12272 }//Dbtc::execCOMPLETECONF()
12273 
toCompleteHandlingLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12274 void Dbtc::toCompleteHandlingLab(Signal* signal,
12275                                  ApiConnectRecordPtr const apiConnectptr)
12276 {
12277   do {
12278     if (tcurrentReplicaNo != (Uint8)Z8NIL) {
12279       jam();
12280       arrGuard(tcurrentReplicaNo, MAX_REPLICAS);
12281       switch (tcConnectptr.p->failData[tcurrentReplicaNo]) {
12282       case LqhTransConf::InvalidStatus:
12283         jam();
12284         /*empty*/;
12285         break;
12286       default:
12287         jam();
12288         /*------------------------------------------------------------*/
12289         /*       THIS NODE DID NOT REPORT ANYTHING FOR THIS OPERATION */
12290         /*       IT MUST HAVE FAILED.                                 */
12291         /*------------------------------------------------------------*/
12292         /*------------------------------------------------------------*/
12293         /*       SEND COMPLETEREQ TO THE NEXT REPLICA.                */
12294         /*------------------------------------------------------------*/
12295         hostptr.i = tcConnectptr.p->tcNodedata[tcurrentReplicaNo];
12296         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
12297         if (hostptr.p->hostStatus == HS_ALIVE) {
12298           jam();
12299           Uint32 instanceKey = tcConnectptr.p->lqhInstanceKey;
12300           tblockref = numberToRef(DBLQH, instanceKey, hostptr.i);
12301           setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
12302           tcConnectptr.p->tcConnectstate = OS_WAIT_COMPLETE_CONF;
12303           apiConnectptr.p->apiConnectstate = CS_WAIT_COMPLETE_CONF;
12304           apiConnectptr.p->timeOutCounter = 0;
12305           tcConnectptr.p->apiConnect = apiConnectptr.i;
12306           signal->theData[0] = tcConnectptr.i;
12307           signal->theData[1] = cownref;
12308           signal->theData[2] = apiConnectptr.p->transid[0];
12309           signal->theData[3] = apiConnectptr.p->transid[1];
12310           signal->theData[4] = apiConnectptr.p->tcBlockref;
12311           signal->theData[5] = tcConnectptr.p->tcOprec;
12312           sendSignal(tblockref, GSN_COMPLETEREQ, signal, 6, JBB);
12313           return;
12314         }//if
12315         break;
12316       }//switch
12317     }//if
12318     if (apiConnectptr.p->currentReplicaNo != 0) {
12319       jam();
12320       /*------------------------------------------------------------*/
12321       /*       THERE ARE STILL MORE REPLICAS IN THIS OPERATION. WE  */
12322       /*       NEED TO CONTINUE WITH THOSE REPLICAS.                */
12323       /*------------------------------------------------------------*/
12324       apiConnectptr.p->currentReplicaNo--;
12325       tcurrentReplicaNo = apiConnectptr.p->currentReplicaNo;
12326     } else {
12327       tcConnectptr.i = tcConnectptr.p->nextList;
12328       if (tcConnectptr.i == RNIL) {
12329         /*------------------------------------------------------------*/
12330         /*       WE HAVE COMPLETED THIS TRANSACTION NOW AND CAN       */
12331         /*       CONTINUE THE PROCESS WITH THE NEXT TRANSACTION.      */
12332         /*------------------------------------------------------------*/
12333         if (apiConnectptr.p->takeOverRec != (Uint8)Z8NIL) {
12334           jam();
12335           signal->theData[0] = TcContinueB::ZCOMPLETE_TRANS_AT_TAKE_OVER;
12336           signal->theData[1] = (UintR)apiConnectptr.p->takeOverRec;
12337           signal->theData[2] = apiConnectptr.p->takeOverInd;
12338           sendSignal(cownref, GSN_CONTINUEB, signal, 3, JBB);
12339           handleGcp(signal, apiConnectptr);
12340           releaseTakeOver(signal, apiConnectptr);
12341         } else {
12342           jam();
12343 
12344           if (tc_testbit(apiConnectptr.p->m_flags,
12345                          ApiConnectRecord::TF_LATE_COMMIT))
12346           {
12347             jam();
12348 
12349             ApiConnectRecordPtr apiCopy = apiConnectptr;
12350 
12351             sendApiLateCommitSignal(signal, apiCopy);
12352           }
12353 
12354           releaseTransResources(signal, apiConnectptr);
12355 jam();
12356         }//if
12357         return;
12358       }//if
12359       /*------------------------------------------------------------*/
12360       /*       WE HAVE COMPLETED AN OPERATION AND THERE ARE MORE TO */
12361       /*       COMPLETE. TAKE THE NEXT OPERATION AND START WITH THE */
12362       /*       FIRST REPLICA SINCE IT IS THE COMPLETE PHASE.        */
12363       /*------------------------------------------------------------*/
12364       apiConnectptr.p->currentTcConnect = tcConnectptr.i;
12365       tcConnectRecord.getPtr(tcConnectptr);
12366       tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
12367       apiConnectptr.p->currentReplicaNo = tcurrentReplicaNo;
12368     }//if
12369   } while (1);
12370 }//Dbtc::toCompleteHandlingLab()
12371 
12372 /*----------------------------------------------------------*/
12373 /*       INITIALISE AN API CONNECT FAIL RECORD              */
12374 /*----------------------------------------------------------*/
initApiConnectFail(Signal * signal,Uint32 transid1,Uint32 transid2,LqhTransConf::OperationStatus transStatus,Uint32 reqinfo,BlockReference applRef,Uint64 gci,NodeId nodeId,ApiConnectRecordPtr const apiConnectptr)12375 void Dbtc::initApiConnectFail(Signal* signal,
12376                               Uint32 transid1,
12377                               Uint32 transid2,
12378                               LqhTransConf::OperationStatus transStatus,
12379                               Uint32 reqinfo,
12380                               BlockReference applRef,
12381                               Uint64 gci,
12382                               NodeId nodeId,
12383                               ApiConnectRecordPtr const apiConnectptr)
12384 {
12385   apiConnectptr.p->transid[0] = transid1;
12386   apiConnectptr.p->transid[1] = transid2;
12387   apiConnectptr.p->tcConnect.init();
12388   apiConnectptr.p->currSavePointId = 0;
12389   BlockReference blockRef = calcTcBlockRef(tcNodeFailptr.p->takeOverNode);
12390 
12391   apiConnectptr.p->tcBlockref = blockRef;
12392   apiConnectptr.p->ndbapiBlockref = 0;
12393   apiConnectptr.p->ndbapiConnect = 0;
12394   apiConnectptr.p->buddyPtr = RNIL;
12395   apiConnectptr.p->m_transaction_nodes.clear();
12396   apiConnectptr.p->singleUserMode = 0;
12397   setApiConTimer(apiConnectptr, 0, __LINE__);
12398   switch(transStatus){
12399   case LqhTransConf::Committed:
12400     jam();
12401     apiConnectptr.p->globalcheckpointid = gci;
12402     apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
12403     break;
12404   case LqhTransConf::Prepared:
12405     jam();
12406     apiConnectptr.p->apiConnectstate = CS_FAIL_PREPARED;
12407     break;
12408   case LqhTransConf::Aborted:
12409     jam();
12410     apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTED;
12411     break;
12412   case LqhTransConf::Marker:
12413     jam();
12414     apiConnectptr.p->apiConnectstate = CS_FAIL_COMPLETED;
12415     break;
12416   default:
12417     jam();
12418     systemErrorLab(signal, __LINE__);
12419   }//if
12420   apiConnectptr.p->commitAckMarker = RNIL;
12421   if(LqhTransConf::getMarkerFlag(reqinfo)){
12422     jam();
12423     CommitAckMarkerPtr tmp;
12424 
12425     {
12426       CommitAckMarker key;
12427       key.transid1 = transid1;
12428       key.transid2 = transid2;
12429       if (m_commitAckMarkerHash.find(tmp, key))
12430       {
12431         /**
12432          * We found a "lingering" marker...
12433          *   most probably from earlier node failure
12434          *   check consistency using lots of it-statements
12435          */
12436         jam();
12437         if (tmp.p->apiConnectPtr == RNIL)
12438         {
12439           jam();
12440           // ok - marker had no transaction, use it...
12441         }
12442         else
12443         {
12444           ApiConnectRecordPtr transPtr;
12445           transPtr.i = tmp.p->apiConnectPtr;
12446           c_apiConnectRecordPool.getPtr(transPtr);
12447           if (transPtr.p->commitAckMarker == RNIL)
12448           {
12449             jam();
12450             // ok - marker had a transaction that had moved on, use it...
12451           }
12452           else if (transPtr.p->commitAckMarker != tmp.i)
12453           {
12454             jam();
12455             // ok - marker had a transaction that had moved on, use it...
12456           }
12457           else
12458           {
12459             jam();
12460             /**
12461              * marker pointed to a transaction that was pointing to marker...
12462              *   i.e both transaction + marker lingering...
12463              *   treat this as an updateApiStateFail and release already seize trans
12464              */
12465             releaseApiConnectFail(signal, apiConnectptr);
12466             updateApiStateFail(signal,
12467                                transid1,
12468                                transid2,
12469                                transStatus,
12470                                reqinfo,
12471                                applRef,
12472                                gci,
12473                                nodeId,
12474                                transPtr);
12475             return;
12476           }
12477         }
12478       }
12479       else
12480       {
12481         jam();
12482         m_commitAckMarkerPool.seize(tmp);
12483         ndbrequire(tmp.i != RNIL);
12484         tmp.p->transid1      = transid1;
12485         tmp.p->transid2      = transid2;
12486         m_commitAckMarkerHash.add(tmp);
12487       }
12488     }
12489 
12490     apiConnectptr.p->commitAckMarker = tmp.i;
12491     tmp.p->apiNodeId     = refToNode(applRef);
12492     tmp.p->apiConnectPtr = apiConnectptr.i;
12493     ndbrequire(tmp.p->insert_in_commit_ack_marker_all(this, nodeId));
12494   }
12495 }//Dbtc::initApiConnectFail()
12496 
12497 /*------------------------------------------------------------*/
12498 /*       INITIALISE AT TC CONNECT AT TAKE OVER WHEN ALLOCATING*/
12499 /*       THE TC CONNECT RECORD.                               */
12500 /*------------------------------------------------------------*/
initTcConnectFail(Signal * signal,Uint32 instanceKey,Uint32 tcOprec,Uint32 reqinfo,LqhTransConf::OperationStatus transStatus,NodeId nodeId,Uint32 apiConnectPtr)12501 void Dbtc::initTcConnectFail(Signal* signal,
12502                              Uint32 instanceKey,
12503                              Uint32 tcOprec,
12504                              Uint32 reqinfo,
12505                              LqhTransConf::OperationStatus transStatus,
12506                              NodeId nodeId,
12507                              Uint32 apiConnectPtr)
12508 {
12509   TcConnectRecord * regTcPtr = tcConnectptr.p;
12510   regTcPtr->apiConnect = apiConnectPtr;
12511   regTcPtr->tcOprec = tcOprec;
12512   Uint32 replicaNo = LqhTransConf::getReplicaNo(reqinfo);
12513   for (Uint32 i = 0; i < MAX_REPLICAS; i++) {
12514     regTcPtr->failData[i] = LqhTransConf::InvalidStatus;
12515   }//for
12516   regTcPtr->tcNodedata[replicaNo] = nodeId;
12517   regTcPtr->failData[replicaNo] = transStatus;
12518   regTcPtr->lastReplicaNo = LqhTransConf::getLastReplicaNo(reqinfo);
12519   regTcPtr->dirtyOp = LqhTransConf::getDirtyFlag(reqinfo);
12520   regTcPtr->lqhInstanceKey = instanceKey;
12521 }//Dbtc::initTcConnectFail()
12522 
12523 /*----------------------------------------------------------*/
12524 /*       INITIALISE TC NODE FAIL RECORD.                    */
12525 /*----------------------------------------------------------*/
initTcFail(Signal * signal)12526 void Dbtc::initTcFail(Signal* signal)
12527 {
12528   tcNodeFailptr.i = 0;
12529   ptrAss(tcNodeFailptr, tcFailRecord);
12530   tcNodeFailptr.p->queueIndex = 0;
12531   tcNodeFailptr.p->failStatus = FS_IDLE;
12532 }//Dbtc::initTcFail()
12533 
12534 /*----------------------------------------------------------*/
12535 /*               RELEASE_TAKE_OVER                          */
12536 /*----------------------------------------------------------*/
releaseTakeOver(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12537 void Dbtc::releaseTakeOver(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12538 {
12539 
12540   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, apiConnectptr.p->tcConnect);
12541   while (tcConList.removeFirst(tcConnectptr))
12542   {
12543     jam();
12544     releaseTcConnectFail(signal);
12545   }
12546   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
12547                       tcConnectRecord);
12548   releaseApiConnectFail(signal, apiConnectptr);
12549 }//Dbtc::releaseTakeOver()
12550 
12551 /*---------------------------------------------------------------------------*/
12552 /*                               SETUP_FAIL_DATA                             */
12553 /* SETUP DATA TO REUSE TAKE OVER CODE FOR HANDLING ABORT/COMMIT IN NODE      */
12554 /* FAILURE SITUATIONS.                                                       */
12555 /*---------------------------------------------------------------------------*/
setupFailData(Signal * signal,ApiConnectRecord * const regApiPtr)12556 void Dbtc::setupFailData(Signal* signal, ApiConnectRecord* const regApiPtr)
12557 {
12558   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
12559   ndbrequire(tcConList.first(tcConnectptr));
12560   do {
12561     switch (tcConnectptr.p->tcConnectstate) {
12562     case OS_PREPARED:
12563     case OS_COMMITTING:
12564       jam();
12565       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
12566       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
12567 	jam();
12568 	/*-------------------------------------------------------------------
12569 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
12570 	 * IN THIS CASE ALL LQH'S ARE PREPARED AND WAITING FOR
12571 	 * COMMIT/ABORT DECISION.
12572 	 *------------------------------------------------------------------*/
12573 	tcConnectptr.p->failData[tindex] = LqhTransConf::Prepared;
12574       }//for
12575       break;
12576     case OS_COMMITTED:
12577     case OS_COMPLETING:
12578       jam();
12579       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
12580       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
12581 	jam();
12582 	/*-------------------------------------------------------------------
12583 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
12584 	 * IN THIS CASE ALL LQH'S ARE COMMITTED AND WAITING FOR
12585 	 * COMPLETE MESSAGE.
12586 	 *------------------------------------------------------------------*/
12587 	tcConnectptr.p->failData[tindex] = LqhTransConf::Committed;
12588       }//for
12589       break;
12590     case OS_COMPLETED:
12591       jam();
12592       arrGuard(tcConnectptr.p->lastReplicaNo, MAX_REPLICAS);
12593       for (tindex = 0; tindex <= tcConnectptr.p->lastReplicaNo; tindex++) {
12594 	jam();
12595 	/*-------------------------------------------------------------------
12596 	 * KEYDATA IS USED TO KEEP AN INDICATION OF STATE IN LQH.
12597 	 * IN THIS CASE ALL LQH'S ARE COMPLETED.
12598 	 *-------------------------------------------------------------------*/
12599 	tcConnectptr.p->failData[tindex] = LqhTransConf::InvalidStatus;
12600       }//for
12601       break;
12602     default:
12603       jam();
12604       sendSystemError(signal, __LINE__);
12605       break;
12606     }//switch
12607     if (tabortInd != ZCOMMIT_SETUP) {
12608       jam();
12609       for (UintR Ti = 0; Ti <= tcConnectptr.p->lastReplicaNo; Ti++) {
12610         hostptr.i = tcConnectptr.p->tcNodedata[Ti];
12611         ptrCheckGuard(hostptr, chostFilesize, hostRecord);
12612         if (hostptr.p->hostStatus != HS_ALIVE) {
12613           jam();
12614 	  /*-----------------------------------------------------------------
12615 	   * FAILURE OF ANY INVOLVED NODE ALWAYS INVOKES AN ABORT DECISION.
12616 	   *-----------------------------------------------------------------*/
12617           tabortInd = ZTRUE;
12618         }//if
12619       }//for
12620     }//if
12621     tcConnectptr.p->tcConnectstate = OS_TAKE_OVER;
12622     tcConnectptr.p->tcOprec = tcConnectptr.i;
12623   } while (tcConList.next(tcConnectptr));
12624   regApiPtr->tcBlockref = cownref;
12625   regApiPtr->currentTcConnect = regApiPtr->tcConnect.getFirst();
12626   tcConnectptr.i = regApiPtr->tcConnect.getFirst();
12627   tcConnectRecord.getPtr(tcConnectptr);
12628   regApiPtr->currentReplicaNo = tcConnectptr.p->lastReplicaNo;
12629   tcurrentReplicaNo = tcConnectptr.p->lastReplicaNo;
12630 }//Dbtc::setupFailData()
12631 
12632 /*----------------------------------------------------------*/
12633 /*       UPDATE THE STATE OF THE API CONNECT FOR THIS PART.   */
12634 /*----------------------------------------------------------*/
updateApiStateFail(Signal * signal,Uint32 transid1,Uint32 transid2,LqhTransConf::OperationStatus transStatus,Uint32 reqinfo,BlockReference applRef,Uint64 gci,NodeId nodeId,ApiConnectRecordPtr const apiConnectptr)12635 void Dbtc::updateApiStateFail(Signal* signal,
12636                               Uint32 transid1,
12637                               Uint32 transid2,
12638                               LqhTransConf::OperationStatus transStatus,
12639                               Uint32 reqinfo,
12640                               BlockReference applRef,
12641                               Uint64 gci,
12642                               NodeId nodeId,
12643                               ApiConnectRecordPtr const apiConnectptr)
12644 {
12645   if(LqhTransConf::getMarkerFlag(reqinfo))
12646   {
12647     CommitAckMarkerPtr tmp;
12648     const Uint32 marker = apiConnectptr.p->commitAckMarker;
12649     if (marker == RNIL)
12650     {
12651       jam();
12652 
12653       m_commitAckMarkerPool.seize(tmp);
12654       ndbrequire(tmp.i != RNIL);
12655 
12656       apiConnectptr.p->commitAckMarker = tmp.i;
12657       tmp.p->transid1      = transid1;
12658       tmp.p->transid2      = transid2;
12659       tmp.p->apiNodeId     = refToNode(applRef);
12660       tmp.p->apiConnectPtr = apiConnectptr.i;
12661 #if defined VM_TRACE || defined ERROR_INSERT
12662       {
12663 	CommitAckMarkerPtr check;
12664 	ndbrequire(!m_commitAckMarkerHash.find(check, *tmp.p));
12665       }
12666 #endif
12667       m_commitAckMarkerHash.add(tmp);
12668     } else {
12669       jam();
12670       tmp.i = marker;
12671       tmp.p = m_commitAckMarkerHash.getPtr(marker);
12672 
12673       ndbrequire(tmp.p->transid1 == transid1);
12674       ndbrequire(tmp.p->transid2 == transid2);
12675     }
12676     ndbrequire(tmp.p->insert_in_commit_ack_marker_all(this, nodeId));
12677   }
12678 
12679   switch (transStatus) {
12680   case LqhTransConf::Committed:
12681     jam();
12682     switch (apiConnectptr.p->apiConnectstate) {
12683     case CS_FAIL_COMMITTING:
12684     case CS_FAIL_COMMITTED:
12685       jam();
12686       ndbrequire(gci == apiConnectptr.p->globalcheckpointid);
12687       break;
12688     case CS_FAIL_PREPARED:
12689       jam();
12690       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
12691       apiConnectptr.p->globalcheckpointid = gci;
12692       break;
12693     case CS_FAIL_COMPLETED:
12694       jam();
12695       apiConnectptr.p->globalcheckpointid = gci;
12696       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTED;
12697       break;
12698     default:
12699       jam();
12700       systemErrorLab(signal, __LINE__);
12701       break;
12702     }//switch
12703     break;
12704   case LqhTransConf::Prepared:
12705     jam();
12706     switch (apiConnectptr.p->apiConnectstate) {
12707     case CS_FAIL_COMMITTED:
12708       jam();
12709       apiConnectptr.p->apiConnectstate = CS_FAIL_COMMITTING;
12710       break;
12711     case CS_FAIL_ABORTED:
12712       jam();
12713       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
12714       break;
12715     case CS_FAIL_COMMITTING:
12716     case CS_FAIL_PREPARED:
12717     case CS_FAIL_ABORTING:
12718       jam();
12719       /*empty*/;
12720       break;
12721     default:
12722       jam();
12723       systemErrorLab(signal, __LINE__);
12724       break;
12725     }//switch
12726     break;
12727   case LqhTransConf::Aborted:
12728     jam();
12729     switch (apiConnectptr.p->apiConnectstate) {
12730     case CS_FAIL_COMMITTING:
12731     case CS_FAIL_COMMITTED:
12732       jam();
12733       systemErrorLab(signal, __LINE__);
12734       break;
12735     case CS_FAIL_PREPARED:
12736       jam();
12737       apiConnectptr.p->apiConnectstate = CS_FAIL_ABORTING;
12738       break;
12739     case CS_FAIL_ABORTING:
12740     case CS_FAIL_ABORTED:
12741       jam();
12742       /*empty*/;
12743       break;
12744     default:
12745       jam();
12746       systemErrorLab(signal, __LINE__);
12747       break;
12748     }//switch
12749     break;
12750   case LqhTransConf::Marker:
12751     jam();
12752     break;
12753   default:
12754     jam();
12755     systemErrorLab(signal, __LINE__);
12756     break;
12757   }//switch
12758 }//Dbtc::updateApiStateFail()
12759 
12760 /*------------------------------------------------------------*/
12761 /*               UPDATE_TC_STATE_FAIL                         */
12762 /*                                                            */
12763 /*       WE NEED TO UPDATE THE STATUS OF TC_CONNECT RECORD AND*/
12764 /*       WE ALSO NEED TO CHECK THAT THERE IS CONSISTENCY      */
12765 /*       BETWEEN THE DIFFERENT REPLICAS.                      */
12766 /*------------------------------------------------------------*/
updateTcStateFail(Signal * signal,Uint32 instanceKey,Uint32 tcOprec,Uint32 reqinfo,LqhTransConf::OperationStatus transStatus,NodeId nodeId,ApiConnectRecordPtr const apiConnectptr)12767 void Dbtc::updateTcStateFail(Signal* signal,
12768                              Uint32 instanceKey,
12769                              Uint32 tcOprec,
12770                              Uint32 reqinfo,
12771                              LqhTransConf::OperationStatus transStatus,
12772                              NodeId nodeId,
12773                              ApiConnectRecordPtr const apiConnectptr)
12774 {
12775   const Uint8 replicaNo     = LqhTransConf::getReplicaNo(reqinfo);
12776   const Uint8 lastReplicaNo = LqhTransConf::getLastReplicaNo(reqinfo);
12777   const Uint8 dirtyOp       = LqhTransConf::getDirtyFlag(reqinfo);
12778 
12779   TcConnectRecord * regTcPtr = tcConnectptr.p;
12780 
12781   ndbrequire(regTcPtr->apiConnect == apiConnectptr.i);
12782   ndbrequire(regTcPtr->failData[replicaNo] == LqhTransConf::InvalidStatus);
12783   ndbrequire(regTcPtr->lastReplicaNo == lastReplicaNo);
12784   ndbrequire(regTcPtr->dirtyOp == dirtyOp);
12785 
12786   regTcPtr->tcNodedata[replicaNo] = nodeId;
12787   regTcPtr->failData[replicaNo] = transStatus;
12788   ndbrequire(regTcPtr->tcOprec == tcOprec);
12789   ndbrequire(regTcPtr->lqhInstanceKey == instanceKey)
12790 }//Dbtc::updateTcStateFail()
12791 
execTCGETOPSIZEREQ(Signal * signal)12792 void Dbtc::execTCGETOPSIZEREQ(Signal* signal)
12793 {
12794   jamEntry();
12795   CRASH_INSERTION(8000);
12796 
12797   UintR Tuserpointer = signal->theData[0];         /* DBDIH POINTER         */
12798   BlockReference Tusersblkref = signal->theData[1];/* DBDIH BLOCK REFERENCE */
12799   signal->theData[0] = Tuserpointer;
12800   signal->theData[1] = coperationsize;
12801   if (refToNode(Tusersblkref) == getOwnNodeId())
12802   {
12803     /**
12804      * The message goes to the DBTC proxy before being processed by
12805      * DBDIH.
12806      */
12807     sendSignal(Tusersblkref, GSN_TCGETOPSIZECONF, signal, 2, JBB);
12808   }
12809   else
12810   {
12811     /**
12812      * No proxy used, so this is the only DBTC instance.
12813      * Thus we go directly to the DBDIH to ensure that we have
12814      * completed the LCP locally before allowing a new one to
12815      * start.
12816      */
12817     signal->theData[2] = Tusersblkref;
12818     sendSignal(DBDIH_REF, GSN_CHECK_LCP_IDLE_ORD, signal, 3, JBB);
12819   }
12820 }//Dbtc::execTCGETOPSIZEREQ()
12821 
execTC_CLOPSIZEREQ(Signal * signal)12822 void Dbtc::execTC_CLOPSIZEREQ(Signal* signal)
12823 {
12824   jamEntry();
12825   CRASH_INSERTION(8001);
12826 
12827   tuserpointer = signal->theData[0];
12828   tusersblkref = signal->theData[1];
12829                                             /* DBDIH BLOCK REFERENCE         */
12830   coperationsize = 0;
12831   signal->theData[0] = tuserpointer;
12832   sendSignal(tusersblkref, GSN_TC_CLOPSIZECONF, signal, 1, JBB);
12833 }//Dbtc::execTC_CLOPSIZEREQ()
12834 
12835 /* ######################################################################### */
12836 /* #######                        ERROR MODULE                       ####### */
12837 /* ######################################################################### */
tabStateErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12838 void Dbtc::tabStateErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12839 {
12840   terrorCode = ZSTATE_ERROR;
12841   releaseAtErrorLab(signal, apiConnectptr);
12842 }//Dbtc::tabStateErrorLab()
12843 
wrongSchemaVersionErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12844 void Dbtc::wrongSchemaVersionErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12845 {
12846   const TcKeyReq * const tcKeyReq = (TcKeyReq *)&signal->theData[0];
12847 
12848   TableRecordPtr tabPtr;
12849   tabPtr.i = tcKeyReq->tableId;
12850   const Uint32 schemVer = tcKeyReq->tableSchemaVersion;
12851   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
12852 
12853   terrorCode = tabPtr.p->getErrorCode(schemVer);
12854 
12855   abortErrorLab(signal, apiConnectptr);
12856 }//Dbtc::wrongSchemaVersionErrorLab()
12857 
noFreeConnectionErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12858 void Dbtc::noFreeConnectionErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12859 {
12860   terrorCode = ZNO_FREE_TC_CONNECTION;
12861   abortErrorLab(signal, apiConnectptr);        /* RECORD. OTHERWISE GOTO ERRORHANDLING  */
12862 }//Dbtc::noFreeConnectionErrorLab()
12863 
aiErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12864 void Dbtc::aiErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12865 {
12866   terrorCode = ZLENGTH_ERROR;
12867   abortErrorLab(signal, apiConnectptr);
12868 }//Dbtc::aiErrorLab()
12869 
appendToSectionErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12870 void Dbtc::appendToSectionErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12871 {
12872   terrorCode = ZGET_DATAREC_ERROR;
12873   releaseAtErrorLab(signal, apiConnectptr);
12874 }//Dbtc::appendToSectionErrorLab
12875 
releaseAtErrorLab(Signal * signal,ApiConnectRecordPtr const apiConnectptr)12876 void Dbtc::releaseAtErrorLab(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
12877 {
12878   ptrGuard(tcConnectptr);
12879   tcConnectptr.p->tcConnectstate = OS_ABORTING;
12880   /*-------------------------------------------------------------------------*
12881    * A FAILURE OF THIS OPERATION HAS OCCURRED. THIS FAILURE WAS EITHER A
12882    * FAULTY PARAMETER OR A RESOURCE THAT WAS NOT AVAILABLE.
12883    * WE WILL ABORT THE ENTIRE TRANSACTION SINCE THIS IS THE SAFEST PATH
12884    * TO HANDLE THIS PROBLEM.
12885    * SINCE WE HAVE NOT YET CONTACTED ANY LQH WE SET NUMBER OF NODES TO ZERO
12886    * WE ALSO SET THE STATE TO ABORTING TO INDICATE THAT WE ARE NOT EXPECTING
12887    * ANY SIGNALS.
12888    *-------------------------------------------------------------------------*/
12889   tcConnectptr.p->noOfNodes = 0;
12890   abortErrorLab(signal, apiConnectptr);
12891 }//Dbtc::releaseAtErrorLab()
12892 
warningHandlerLab(Signal * signal,int line)12893 void Dbtc::warningHandlerLab(Signal* signal, int line)
12894 {
12895 #if defined VM_TRACE || defined ERROR_INSERT
12896   ndbout_c("warningHandler: line %d", line);
12897 #endif
12898 }//Dbtc::warningHandlerLab()
12899 
systemErrorLab(Signal * signal,int line)12900 void Dbtc::systemErrorLab(Signal* signal, int line)
12901 {
12902   progError(line, NDBD_EXIT_NDBREQUIRE);
12903 }//Dbtc::systemErrorLab()
12904 
12905 
12906 #ifdef ERROR_INSERT
testFragmentDrop(Signal * signal)12907 bool Dbtc::testFragmentDrop(Signal* signal)
12908 {
12909   Uint32 fragIdToDrop= ~0;
12910   /* Drop some fragments to test the dropped fragment handling code */
12911   if (ERROR_INSERTED(8074))
12912     fragIdToDrop= 1;
12913   else if (ERROR_INSERTED(8075))
12914     fragIdToDrop= 2;
12915   else if (ERROR_INSERTED(8076))
12916     fragIdToDrop= 3;
12917 
12918   if ((signal->header.m_fragmentInfo == fragIdToDrop) ||
12919       ERROR_INSERTED(8077)) // Drop all fragments
12920   {
12921     /* This signal fragment should be dropped
12922      * Let's throw away the sections, and call the
12923      * signal dropped report handler
12924      * This code is replicating the effect of the code in
12925      * TransporterCallback::deliver_signal()
12926      */
12927     SectionHandle handle(this, signal);
12928     Uint32 secCount= handle.m_cnt;
12929     releaseSections(handle);
12930     SignalDroppedRep* rep = (SignalDroppedRep*)signal->theData;
12931     Uint32 gsn = signal->header.theVerId_signalNumber;
12932     Uint32 len = signal->header.theLength;
12933     Uint32 newLen= (len > 22 ? 22 : len);
12934     memmove(rep->originalData, signal->theData, (4 * newLen));
12935     rep->originalGsn = gsn;
12936     rep->originalLength = len;
12937     rep->originalSectionCount = secCount;
12938     signal->header.theVerId_signalNumber = GSN_SIGNAL_DROPPED_REP;
12939     signal->header.theLength = newLen + 3;
12940     signal->header.m_noOfSections = 0;
12941 
12942     executeFunction(GSN_SIGNAL_DROPPED_REP, signal);
12943     return true;
12944   }
12945   return false;
12946 }
12947 #endif
12948 
12949 /* ######################################################################### *
12950  * #######                        SCAN MODULE                        ####### *
12951  * ######################################################################### *
12952 
12953   The application orders a scan of a table.  We divide the scan into a scan on
12954   each fragment.  The scan uses the primary replicas since the scan might be
12955   used for an update in a separate transaction.
12956 
12957   Scans are always done as a separate transaction.  Locks from the scan
12958   can be overtaken by another transaction.  Scans can never lock the entire
12959   table.  Locks are released immediately after the read has been verified
12960   by the application. There is not even an option to leave the locks.
12961   The reason is that this would hurt real-time behaviour too much.
12962 
12963   -#  The first step in handling a scan of a table is to receive all signals
12964       defining the scan. If failures occur during this step we release all
12965       resource and reply with SCAN_TABREF providing the error code.
12966       If system load is too high, the request will not be allowed.
12967 
12968   -#  The second step retrieves the number of fragments that exist in the
12969       table. It also ensures that the table actually exist.  After this,
12970       the scan is ready to be parallelised.  The idea is that the receiving
12971       process (hereafter called delivery process) will start up a number
12972       of scan processes.  Each of these scan processes will
12973       independently scan one fragment at a time.  The delivery
12974       process object is the scan record and the scan process object is
12975       the scan fragment record plus the scan operation record.
12976 
12977   -#  The third step is thus performed in parallel. In the third step each
12978       scan process retrieves the primary replica of the fragment it will
12979       scan.  Then it starts the scan as soon as the load on that node permits.
12980 
12981   The LQH returns either when it retrieved the maximum number of tuples or
12982   when it has retrived at least one tuple and is hindered by a lock to
12983   retrieve the next tuple.  This is to ensure that a scan process never
12984   can be involved in a deadlock situation.
12985 
12986   Tuples from each fragment scan are sent directly to API from TUP, and tuples
12987   from different fragments are delivered in parallel (so will be interleaved
12988   when received).
12989 
12990   When a batch of tuples from one fragment has been fully fetched, the scan of
12991   that fragment will not continue until the previous batch has been
12992   acknowledged by API with a SCAN_NEXTREQ signal.
12993 
12994 
12995   ERROR HANDLING
12996 
12997   As already mentioned it is rather easy to handle errors before the scan
12998   processes have started.  In this case it is enough to release the resources
12999   and send SCAN_TAB_REF.
13000 
13001   If an error occurs in any of the scan processes then we have to stop all
13002   scan processes. We do however only stop the delivery process and ask
13003   the api to order us to close the scan.  The reason is that we can easily
13004   enter into difficult timing problems since the application and this
13005   block is out of synch we will thus always start by report the error to
13006   the application and wait for a close request. This error report uses the
13007   SCAN_TABREF signal with a special error code that the api must check for.
13008 
13009 
13010   CLOSING AN ACTIVE SCAN
13011 
13012   The application can close a scan for several reasons before it is completed.
13013   One reason was mentioned above where an error in a scan process led to a
13014   request to close the scan. Another reason could simply be that the
13015   application found what it looked for and is thus not interested in the
13016   rest of the scan.
13017 
13018   IT COULD ALSO BE DEPENDENT ON INTERNAL ERRORS IN THE API.
13019 
13020   When a close scan request is received, all scan processes are stopped and all
13021   resources belonging to those scan processes are released. Stopping the scan
13022   processes most often includes communication with an LQH where the local scan
13023   is controlled. Finally all resources belonging to the scan is released and
13024   the SCAN_TABCONF is sent with an indication of that the scan is closed.
13025 
13026 
13027   CLOSING A COMPLETED SCAN
13028 
13029   When all scan processes are completed then a report is sent to the
13030   application which indicates that no more tuples can be fetched.
13031   The application will send a close scan and the same action as when
13032   closing an active scan is performed.
13033   In this case it will of course not find any active scan processes.
13034   It will even find all scan processes already released.
13035 
13036   The reason for requiring the api to close the scan is the same as above.
13037   It is to avoid any timing problems due to that the api and this block
13038   is out of synch.
13039 
13040   * ######################################################################## */
execSCAN_TABREQ(Signal * signal)13041 void Dbtc::execSCAN_TABREQ(Signal* signal)
13042 {
13043   jamEntry();
13044 
13045 #ifdef ERROR_INSERT
13046   /* Test fragmented + dropped signal handling */
13047   if (ERROR_INSERTED(8074) ||
13048       ERROR_INSERTED(8075) ||
13049       ERROR_INSERTED(8076) ||
13050       ERROR_INSERTED(8077))
13051   {
13052     jam();
13053     if (testFragmentDrop(signal)) {
13054       jam();
13055       return;
13056     }
13057   } /* End of test fragmented + dropped signal handling */
13058 #endif
13059 
13060   /* Reassemble if the request was fragmented */
13061   if (!assembleFragments(signal)){
13062     jam();
13063     return;
13064   }
13065 
13066   const BlockReference apiBlockRef = signal->getSendersBlockRef();
13067   const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
13068   const Uint32 ri = scanTabReq->requestInfo;
13069   const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
13070   const Uint32 transid1 = scanTabReq->transId1;
13071   const Uint32 transid2 = scanTabReq->transId2;
13072   const Uint32 tmpXX = scanTabReq->buddyConPtr;
13073   const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
13074   Uint32 currSavePointId = 0;
13075 
13076   Uint32 errCode;
13077   ScanRecordPtr scanptr;
13078 
13079   /* Short SCANTABREQ has 1 section, Long has 2 or 3.
13080    * Section 0 : NDBAPI receiver ids (Mandatory)
13081    * Section 1 : ATTRINFO section (Mandatory for long SCAN_TABREQ
13082    * Section 2 : KEYINFO section (Optional for long SCAN_TABREQ
13083    */
13084   Uint32 numSections= signal->getNoOfSections();
13085   ndbassert( numSections >= 1 );
13086   bool isLongReq= numSections >= 2;
13087 
13088   SectionHandle handle(this, signal);
13089   SegmentedSectionPtr api_op_ptr;
13090   handle.getSection(api_op_ptr, ScanTabReq::ReceiverIdSectionNum);
13091 
13092   // Scan parallelism is determined by the number of receiver ids sent
13093   Uint32 scanParallel = api_op_ptr.sz;
13094   Uint32 scanConcurrency = scanParallel;
13095   Uint32 * apiPtr = signal->theData+25; // temp storage
13096   copy(apiPtr, api_op_ptr);
13097 
13098   Uint32 aiLength= 0;
13099   Uint32 keyLen= 0;
13100 
13101   if (likely(isLongReq))
13102   {
13103     SegmentedSectionPtr attrInfoPtr, keyInfoPtr;
13104     /* Long SCANTABREQ, determine Ai and Key length from sections */
13105     handle.getSection(attrInfoPtr, ScanTabReq::AttrInfoSectionNum);
13106     aiLength= attrInfoPtr.sz;
13107     if (numSections == 3)
13108     {
13109       handle.getSection(keyInfoPtr, ScanTabReq::KeyInfoSectionNum);
13110       keyLen= keyInfoPtr.sz;
13111     }
13112   }
13113   else
13114   {
13115     /* Short SCANTABREQ, get Ai and Key length from signal */
13116     aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
13117     keyLen = scanTabReq->attrLenKeyLen >> 16;
13118   }
13119 
13120   ApiConnectRecordPtr apiConnectptr;
13121   apiConnectptr.i = scanTabReq->apiConnectPtr;
13122   tabptr.i = scanTabReq->tableId;
13123 
13124   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
13125   {
13126     jam();
13127     releaseSections(handle);
13128     warningHandlerLab(signal, __LINE__);
13129     return;
13130   }//if
13131 
13132   ApiConnectRecord * transP = apiConnectptr.p;
13133   if (unlikely(tabptr.i >= ctabrecFilesize))
13134   {
13135     errCode = ZUNKNOWN_TABLE_ERROR;
13136     goto SCAN_TAB_error;
13137   }
13138 
13139   if (transP->apiConnectstate != CS_CONNECTED)
13140   {
13141     jam();
13142     // could be left over from TCKEYREQ rollback
13143     if (transP->apiConnectstate == CS_ABORTING &&
13144 	transP->abortState == AS_IDLE) {
13145       jam();
13146     } else if(transP->apiConnectstate == CS_STARTED &&
13147               transP->tcConnect.isEmpty())
13148     {
13149       jam();
13150       // left over from simple/dirty read
13151     } else {
13152       jam();
13153       jamLine(transP->apiConnectstate);
13154       errCode = ZSTATE_ERROR;
13155       goto SCAN_TAB_error_no_state_change;
13156     }
13157   }
13158   ndbassert(transP->ndbapiBlockref == apiBlockRef);
13159 
13160   if (unlikely(tabptr.i >= ctabrecFilesize))
13161   {
13162     errCode = ZUNKNOWN_TABLE_ERROR;
13163     goto SCAN_TAB_error;
13164   }
13165 
13166   if (unlikely(ScanTabReq::getMultiFragFlag(ri) &&
13167                !ScanTabReq::getViaSPJFlag(ri)))
13168   {
13169     jam();
13170     errCode = 4003; // Function not implemented
13171     goto SCAN_TAB_error;
13172   }
13173 
13174   ptrAss(tabptr, tableRecord);
13175   if ((aiLength == 0) ||
13176       (!tabptr.p->checkTable(schemaVersion)) ||
13177       (scanConcurrency == 0) ||
13178       (cConcScanCount >= cscanrecFileSize))
13179   {
13180     goto SCAN_error_check;
13181   }
13182   if (buddyPtr != RNIL) {
13183     ApiConnectRecordPtr buddyApiPtr;
13184     buddyApiPtr.i = buddyPtr;
13185     if (likely(c_apiConnectRecordPool.getValidPtr(buddyApiPtr)) &&
13186         likely((transid1 == buddyApiPtr.p->transid[0]) &&
13187 	       (transid2 == buddyApiPtr.p->transid[1])))
13188     {
13189       jam();
13190 
13191       if (unlikely(buddyApiPtr.p->apiConnectstate == CS_ABORTING))
13192       {
13193 	// transaction has been aborted
13194 	jam();
13195 	errCode = buddyApiPtr.p->returncode;
13196 	goto SCAN_TAB_error;
13197       }//if
13198       currSavePointId = buddyApiPtr.p->currSavePointId;
13199       buddyApiPtr.p->currSavePointId++;
13200     }
13201     else
13202     {
13203       jam();
13204     }
13205   }
13206 
13207   if (unlikely(getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
13208                getNodeState().getSingleUserApi() !=
13209                refToNode(apiConnectptr.p->ndbapiBlockref) &&
13210                /* Don't refuse scan to start on table marked as
13211                   NDB_SUM_READONLY or NDB_SUM_READWRITE */
13212                tabptr.p->singleUserMode == NDB_SUM_LOCKED))
13213   {
13214     errCode = ZCLUSTER_IN_SINGLEUSER_MODE;
13215     goto SCAN_TAB_error;
13216   }
13217 
13218   scanptr = seizeScanrec(signal);
13219   ndbrequire(transP->apiScanRec == RNIL);
13220   ndbrequire(scanptr.p->scanApiRec == RNIL);
13221 
13222   errCode = initScanrec(scanptr, scanTabReq, scanParallel,
13223                         apiPtr, apiConnectptr.i);
13224   if (unlikely(errCode))
13225   {
13226     jam();
13227     transP->apiScanRec = scanptr.i;
13228     releaseScanResources(signal, scanptr, apiConnectptr, true /* NotStarted */);
13229     goto SCAN_TAB_error;
13230   }
13231 
13232   releaseSection(handle.m_ptr[ScanTabReq::ReceiverIdSectionNum].i);
13233   if (likely(isLongReq))
13234   {
13235     jamDebug();
13236     /* We keep the AttrInfo and KeyInfo sections */
13237     scanptr.p->scanAttrInfoPtr = handle.m_ptr[ScanTabReq::AttrInfoSectionNum].i;
13238     if (keyLen)
13239     {
13240       jamDebug();
13241       scanptr.p->scanKeyInfoPtr = handle.m_ptr[ScanTabReq::KeyInfoSectionNum].i;
13242     }
13243   }
13244   else
13245   {
13246     jam();
13247     CacheRecordPtr cachePtr;
13248     if (seizeCacheRecord(signal, cachePtr, apiConnectptr.p) != 0)
13249     {
13250       transP->apiScanRec = scanptr.i;
13251       releaseScanResources(signal, scanptr, apiConnectptr, true /* NotStarted */);
13252       goto SCAN_TAB_error;
13253     }
13254     cachePtr.p->attrlength = aiLength;
13255     cachePtr.p->keylen = keyLen;
13256     cachePtr.p->save1 = 0;
13257   }
13258   handle.clear();
13259 
13260   scanptr.p->m_scan_dist_key = scanTabReq->distributionKey;
13261   scanptr.p->m_scan_dist_key_flag = ScanTabReq::getDistributionKeyFlag(ri);
13262 
13263   if (ERROR_INSERTED(8119))
13264   {
13265     jam();
13266     if (scanptr.p->m_scan_dist_key_flag)
13267     {
13268       jam();
13269       ndbout_c("Forcing scan distribution key to 0xffffffff");
13270       scanptr.p->m_scan_dist_key = 0xffffffff;
13271     }
13272   }
13273 
13274   transP->apiScanRec = scanptr.i;
13275   transP->returncode = 0;
13276   transP->transid[0] = transid1;
13277   transP->transid[1] = transid2;
13278   transP->buddyPtr   = buddyPtr;
13279 
13280   // The scan is started
13281   transP->apiConnectstate = CS_START_SCAN;
13282   transP->currSavePointId = currSavePointId;
13283 
13284   /**********************************************************
13285   * We start the timer on scanRec to be able to discover a
13286   * timeout in the API the API now is in charge!
13287   ***********************************************************/
13288   setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
13289   updateBuddyTimer(apiConnectptr);
13290 
13291   /***********************************************************
13292    * WE HAVE NOW RECEIVED ALL REFERENCES TO SCAN OBJECTS IN
13293    * THE API. WE ARE NOW READY TO RECEIVE THE ATTRIBUTE INFO
13294    * IF ANY TO RECEIVE.
13295    **********************************************************/
13296   scanptr.p->scanState = ScanRecord::WAIT_AI;
13297 
13298   if (ERROR_INSERTED(8038))
13299   {
13300     /**
13301      * Force API_FAILREQ
13302      */
13303     signal->theData[0] = refToNode(apiConnectptr.p->ndbapiBlockref);
13304     sendSignal(QMGR_REF, GSN_API_FAILREQ, signal, 1, JBA);
13305     CLEAR_ERROR_INSERT_VALUE;
13306   }
13307 
13308   if (likely(isLongReq))
13309   {
13310     /* All AttrInfo (and KeyInfo) has been received, continue
13311      * processing
13312      */
13313     diFcountReqLab(signal, scanptr, apiConnectptr);
13314   }
13315 
13316   return;
13317 
13318  SCAN_error_check:
13319   if (aiLength == 0) {
13320     jam();
13321     errCode = ZSCAN_AI_LEN_ERROR;
13322     goto SCAN_TAB_error;
13323   }//if
13324   if (!tabptr.p->checkTable(schemaVersion)){
13325     jam();
13326     errCode = tabptr.p->getErrorCode(schemaVersion);
13327     goto SCAN_TAB_error;
13328   }//if
13329   if (scanConcurrency == 0) {
13330     jam();
13331     errCode = ZNO_CONCURRENCY_ERROR;
13332     goto SCAN_TAB_error;
13333   }//if
13334 #if defined(VM_TRACE) || defined(ERROR_INSERT)
13335   ndbrequire(cConcScanCount >= cscanrecFileSize);
13336 #else
13337   ndbrequire(cConcScanCount == cscanrecFileSize);
13338 #endif
13339   jam();
13340   errCode = ZNO_SCANREC_ERROR;
13341   goto SCAN_TAB_error;
13342 
13343 SCAN_TAB_error:
13344   jam();
13345   /**
13346    * Prepare for up coming ATTRINFO/KEYINFO
13347    */
13348   transP->apiConnectstate = CS_ABORTING;
13349   transP->abortState = AS_IDLE;
13350   transP->transid[0] = transid1;
13351   transP->transid[1] = transid2;
13352 
13353 SCAN_TAB_error_no_state_change:
13354 
13355   releaseSections(handle);
13356 
13357   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
13358   ref->apiConnectPtr = transP->ndbapiConnect;
13359   ref->transId1 = transid1;
13360   ref->transId2 = transid2;
13361   ref->errorCode  = errCode;
13362   ref->closeNeeded = 0;
13363   sendSignal(apiBlockRef, GSN_SCAN_TABREF,
13364 	     signal, ScanTabRef::SignalLength, JBB);
13365 
13366   /**
13367    * If we are DISCONNECTED, an API_FAILREQ signals had
13368    * already arrived when we got the SCAN_TABREQ. Those
13369    * are required to arrive as the last signal from a failed
13370    * API-node. We want to detect that if it should happen.
13371    */
13372   ndbassert(transP->apiConnectstate != CS_DISCONNECTED);
13373   return;
13374 }//Dbtc::execSCAN_TABREQ()
13375 
ScanFragRec()13376 Dbtc::ScanFragRec::ScanFragRec()
13377 : m_magic(Magic::make(TYPE_ID)),
13378   lqhScanFragId(RNIL),
13379   lqhBlockref(0),
13380   m_connectCount(0),
13381   scanFragState(ScanFragRec::IDLE),
13382   scanRec(RNIL),
13383   m_scan_frag_conf_status(0),
13384   m_ops(0),
13385   m_apiPtr(RNIL),
13386   m_totalLen(0),
13387   m_hasMore(0),
13388   nextList(RNIL),
13389   prevList(RNIL)
13390 {
13391   stopFragTimer();
13392   NdbTick_Invalidate(&m_start_ticks);
13393 }
13394 
13395 Uint32
initScanrec(ScanRecordPtr scanptr,const ScanTabReq * scanTabReq,UintR scanParallel,const Uint32 apiPtr[],Uint32 apiConnectPtr)13396 Dbtc::initScanrec(ScanRecordPtr scanptr,
13397 		  const ScanTabReq * scanTabReq,
13398 		  UintR scanParallel,
13399                   const Uint32 apiPtr[],
13400                   Uint32 apiConnectPtr)
13401 {
13402   const UintR ri = scanTabReq->requestInfo;
13403   const Uint32 batchSizeRows = ScanTabReq::getScanBatch(ri);
13404   scanptr.p->scanApiRec = apiConnectPtr;
13405   scanptr.p->scanTableref = tabptr.i;
13406   scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
13407   scanptr.p->scanNoFrag = 0;
13408   scanptr.p->scanParallel = scanParallel;
13409   scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
13410   scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
13411   scanptr.p->batch_size_rows = batchSizeRows;
13412   scanptr.p->m_scan_block_no = DBLQH;
13413   scanptr.p->m_scan_dist_key_flag = 0;
13414   scanptr.p->m_start_ticks = getHighResTimer();
13415 
13416   scanptr.p->m_running_scan_frags.init();
13417 
13418   Uint32 tmp = 0;
13419   ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
13420   ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
13421   ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
13422   ScanFragReq::setReadCommittedFlag(tmp,ScanTabReq::getReadCommittedFlag(ri));
13423   ScanFragReq::setRangeScanFlag(tmp, ScanTabReq::getRangeScanFlag(ri));
13424   ScanFragReq::setDescendingFlag(tmp, ScanTabReq::getDescendingFlag(ri));
13425   ScanFragReq::setTupScanFlag(tmp, ScanTabReq::getTupScanFlag(ri));
13426   ScanFragReq::setNoDiskFlag(tmp, ScanTabReq::getNoDiskFlag(ri));
13427   ScanFragReq::setMultiFragFlag(tmp, ScanTabReq::getMultiFragFlag(ri));
13428   if (ScanTabReq::getViaSPJFlag(ri))
13429   {
13430     jam();
13431     scanptr.p->m_scan_block_no = DBSPJ;
13432   }
13433 
13434   scanptr.p->scanRequestInfo = tmp;
13435   scanptr.p->m_read_committed_base = ScanTabReq::getReadCommittedBaseFlag(ri);
13436   scanptr.p->scanStoredProcId = scanTabReq->storedProcId;
13437   scanptr.p->scanState = ScanRecord::RUNNING;
13438   scanptr.p->m_queued_count = 0;
13439   scanptr.p->m_booked_fragments_count = 0;
13440   scanptr.p->m_scan_cookie = DihScanTabConf::InvalidCookie;
13441   scanptr.p->m_close_scan_req = false;
13442   scanptr.p->m_pass_all_confs =  ScanTabReq::getPassAllConfsFlag(ri);
13443   scanptr.p->m_extended_conf = ScanTabReq::getExtendedConf(ri);
13444   scanptr.p->scanKeyInfoPtr = RNIL;
13445   scanptr.p->scanAttrInfoPtr = RNIL;
13446 
13447   Local_ScanFragRec_dllist list(c_scan_frag_pool,
13448 		    scanptr.p->m_running_scan_frags);
13449   for (Uint32 i = 0; i < scanParallel; i++) {
13450     jamDebug();
13451     ScanFragRecPtr ptr;
13452     if (ERROR_INSERTED(8093) ||
13453         unlikely(!c_scan_frag_pool.seize(ptr)))
13454     {
13455       jam();
13456       goto errout;
13457     }
13458     list.addFirst(ptr);
13459     ptr.p->scanRec = scanptr.i;
13460     ptr.p->lqhScanFragId = 0;
13461     ptr.p->m_apiPtr = apiPtr[i];
13462   }//for
13463   scanptr.p->m_booked_fragments_count = scanParallel;
13464 
13465   (* (ScanTabReq::getRangeScanFlag(ri) ?
13466       &c_counters.c_range_scan_count :
13467       &c_counters.c_scan_count))++;
13468   return 0;
13469 errout:
13470   {
13471     ScanFragRecPtr ptr;
13472     while (list.removeFirst(ptr))
13473     {
13474       c_scan_frag_pool.release(ptr);
13475     }
13476   }
13477   checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
13478                       c_scan_frag_pool);
13479   return ZSCAN_FRAGREC_ERROR;
13480 }//Dbtc::initScanrec()
13481 
scanTabRefLab(Signal * signal,Uint32 errCode,ApiConnectRecord * const regApiPtr)13482 void Dbtc::scanTabRefLab(Signal* signal, Uint32 errCode, ApiConnectRecord* const regApiPtr)
13483 {
13484   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
13485   ref->apiConnectPtr = regApiPtr->ndbapiConnect;
13486   ref->transId1 = regApiPtr->transid[0];
13487   ref->transId2 = regApiPtr->transid[1];
13488   ref->errorCode  = errCode;
13489   ref->closeNeeded = 0;
13490   sendSignal(regApiPtr->ndbapiBlockref, GSN_SCAN_TABREF,
13491              signal, ScanTabRef::SignalLength, JBB);
13492 }//Dbtc::scanTabRefLab()
13493 
13494 /**
13495  * scanKeyinfoLab
13496  * Handle reception of KeyInfo for a Scan
13497  */
scanKeyinfoLab(Signal * signal,CacheRecord * const regCachePtr,ApiConnectRecordPtr const apiConnectptr)13498 void Dbtc::scanKeyinfoLab(Signal* signal,
13499                           CacheRecord * const regCachePtr,
13500                           ApiConnectRecordPtr const apiConnectptr)
13501 {
13502   /* Receive KEYINFO for a SCAN operation
13503    * Note that old NDBAPI nodes sometimes send header-only KEYINFO signals
13504    */
13505   UintR TkeyLen = regCachePtr->keylen;
13506   UintR Tlen = regCachePtr->save1;
13507 
13508   Uint32 wordsInSignal= MIN(KeyInfo::DataLength,
13509                             (TkeyLen - Tlen));
13510 
13511   ndbassert( signal->getLength() ==
13512              (KeyInfo::HeaderLength + wordsInSignal) );
13513 
13514   if (unlikely ((! appendToSection(regCachePtr->keyInfoSectionI,
13515                                    &signal->theData[KeyInfo::HeaderLength],
13516                                    wordsInSignal)) ||
13517                  ERROR_INSERTED(8094)))
13518   {
13519     jam();
13520     Uint32 transid0 = apiConnectptr.p->transid[0];
13521     Uint32 transid1 = apiConnectptr.p->transid[1];
13522     ndbrequire(apiConnectptr.p->apiScanRec != RNIL);
13523     ScanRecordPtr scanPtr;
13524     scanPtr.i = apiConnectptr.p->apiScanRec;
13525     if (likely(scanRecordPool.getValidPtr(scanPtr)))
13526     {
13527       abortScanLab(signal,
13528                    scanPtr,
13529                    ZGET_DATAREC_ERROR,
13530                    true /* Not started */,
13531                    apiConnectptr);
13532 
13533       /* Prepare for up coming ATTRINFO/KEYINFO */
13534       apiConnectptr.p->apiConnectstate = CS_ABORTING;
13535       apiConnectptr.p->abortState = AS_IDLE;
13536       apiConnectptr.p->transid[0] = transid0;
13537       apiConnectptr.p->transid[1] = transid1;
13538     }
13539     return;
13540   }
13541 
13542   Tlen+= wordsInSignal;
13543   regCachePtr->save1 = Tlen;
13544 
13545   if (Tlen < TkeyLen)
13546   {
13547     jam();
13548     /* More KeyInfo still to come - continue waiting */
13549     setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
13550     return;
13551   }
13552 
13553   /* All KeyInfo has been received, we will now start receiving
13554    * ATTRINFO
13555    */
13556   jam();
13557   ndbassert(Tlen == TkeyLen);
13558   return;
13559 } // scanKeyinfoLab
13560 
13561 /*---------------------------------------------------------------------------*/
13562 /*                                                                           */
13563 /*       RECEPTION OF ATTRINFO FOR SCAN TABLE REQUEST.                       */
13564 /*---------------------------------------------------------------------------*/
scanAttrinfoLab(Signal * signal,UintR Tlen,ApiConnectRecordPtr const apiConnectptr)13565 void Dbtc::scanAttrinfoLab(Signal* signal, UintR Tlen, ApiConnectRecordPtr const apiConnectptr)
13566 {
13567   ScanRecordPtr scanptr;
13568   scanptr.i = apiConnectptr.p->apiScanRec;
13569   scanRecordPool.getPtr(scanptr);
13570   CacheRecordPtr cachePtr;
13571   cachePtr.i = apiConnectptr.p->cachePtr;
13572   ndbassert(cachePtr.i != Uint32(~0));
13573   c_cacheRecordPool.getPtr(cachePtr);
13574   CacheRecord * const regCachePtr = cachePtr.p;
13575   ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_AI);
13576 
13577   regCachePtr->currReclenAi = regCachePtr->currReclenAi + Tlen;
13578 
13579   if (unlikely(! appendToSection(regCachePtr->attrInfoSectionI,
13580                                  &signal->theData[AttrInfo::HeaderLength],
13581                                  Tlen)))
13582   {
13583     jam();
13584     abortScanLab(signal, scanptr, ZGET_ATTRBUF_ERROR, true, apiConnectptr);
13585     return;
13586   }
13587 
13588   if (regCachePtr->currReclenAi == regCachePtr->attrlength)
13589   {
13590     jam();
13591     /* We have now received all the signals defining this
13592      * scan.  We are ready to start executing the scan
13593      */
13594     scanptr.p->scanAttrInfoPtr = regCachePtr->attrInfoSectionI;
13595     scanptr.p->scanKeyInfoPtr = regCachePtr->keyInfoSectionI;
13596     releaseCacheRecord(apiConnectptr, regCachePtr);
13597     diFcountReqLab(signal, scanptr, apiConnectptr);
13598     return;
13599   }
13600   else if (unlikely (regCachePtr->currReclenAi > regCachePtr->attrlength))
13601   {
13602     jam();
13603     abortScanLab(signal, scanptr, ZLENGTH_ERROR, true, apiConnectptr);
13604     return;
13605   }
13606 
13607   /* Still some ATTRINFO to arrive...*/
13608   return;
13609 }//Dbtc::scanAttrinfoLab()
13610 
diFcountReqLab(Signal * signal,ScanRecordPtr scanptr,ApiConnectRecordPtr const apiConnectptr)13611 void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr, ApiConnectRecordPtr const apiConnectptr)
13612 {
13613   /**
13614    * Check so that the table is not being dropped
13615    */
13616   TableRecordPtr tabPtr;
13617   tabPtr.i = scanptr.p->scanTableref;
13618   tabPtr.p = &tableRecord[tabPtr.i];
13619   if (likely(tabPtr.p->checkTable(scanptr.p->scanSchemaVersion)))
13620   {
13621     ;
13622   } else {
13623     abortScanLab(signal, scanptr,
13624 		 tabPtr.p->getErrorCode(scanptr.p->scanSchemaVersion),
13625                  true,
13626                  apiConnectptr);
13627     return;
13628   }
13629 
13630   scanptr.p->scanNextFragId = 0;
13631   ndbassert(scanptr.p->m_booked_fragments_count == scanptr.p->scanParallel);
13632   scanptr.p->m_read_any_node =
13633     (ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo) ||
13634        scanptr.p->m_read_committed_base) &&
13635     ((tabPtr.p->m_flags & TableRecord::TR_FULLY_REPLICATED) != 0);
13636 
13637   /*************************************************
13638    * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
13639    ***************************************************/
13640   ndbassert(scanptr.p->m_scan_cookie == DihScanTabConf::InvalidCookie);
13641   DihScanTabReq * req = (DihScanTabReq*)signal->getDataPtrSend();
13642   req->tableId = scanptr.p->scanTableref;
13643   req->schemaTransId = 0;
13644   req->jamBufferPtr = jamBuffer();
13645 
13646   EXECUTE_DIRECT_MT(DBDIH, GSN_DIH_SCAN_TAB_REQ, signal,
13647                     DihScanTabReq::SignalLength, 0);
13648 
13649   DihScanTabConf * conf = (DihScanTabConf*)signal->getDataPtr();
13650   if (likely(conf->senderData == 0))
13651   {
13652     execDIH_SCAN_TAB_CONF(signal, scanptr, tabPtr, apiConnectptr);
13653     return;
13654   }
13655   else
13656   {
13657     execDIH_SCAN_TAB_REF(signal, scanptr, apiConnectptr);
13658     return;
13659   }
13660 }//Dbtc::diFcountReqLab()
13661 
13662 /********************************************************************
13663  * execDIH_SCAN_TAB_CONF
13664  *
13665  * WE HAVE ASKED DIH ABOUT THE NUMBER OF FRAGMENTS IN THIS TABLE.
13666  * WE WILL NOW GET THE LOCATION (NODE,INSTANCE) OF EACH OF THE
13667  * FRAGMENTS AS A PREPARATION FOR STARTING THE SCAN.
13668  ********************************************************************/
execDIH_SCAN_TAB_CONF(Signal * signal,ScanRecordPtr scanptr,TableRecordPtr tabPtr,ApiConnectRecordPtr const apiConnectptr)13669 void Dbtc::execDIH_SCAN_TAB_CONF(Signal* signal,
13670                                  ScanRecordPtr scanptr,
13671                                  TableRecordPtr tabPtr,
13672                                  ApiConnectRecordPtr const apiConnectptr)
13673 {
13674   DihScanTabConf * conf = (DihScanTabConf*)signal->getDataPtr();
13675   jamEntryDebug();
13676   Uint32 tfragCount = conf->fragmentCount;
13677   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
13678   scanptr.p->m_scan_cookie = conf->scanCookie;
13679   ndbrequire(scanptr.p->m_scan_cookie != DihScanTabConf::InvalidCookie);
13680 
13681   if (unlikely(conf->reorgFlag))
13682   {
13683     jam();
13684     ScanFragReq::setReorgFlag(scanptr.p->scanRequestInfo, ScanFragReq::REORG_NOT_MOVED);
13685   }
13686   if (unlikely(regApiPtr->apiFailState != ApiConnectRecord::AFS_API_OK))
13687   {
13688     jam();
13689     releaseScanResources(signal, scanptr, apiConnectptr, true);
13690     handleApiFailState(signal, apiConnectptr.i);
13691     return;
13692   }//if
13693   if (unlikely(tfragCount == 0))
13694   {
13695     jam();
13696     abortScanLab(signal, scanptr, ZNO_FRAGMENT_ERROR, true, apiConnectptr);
13697     return;
13698   }//if
13699 
13700   /* We are in a EXECUTE_DIRECT reply from diFcountReqLab()
13701    * where checkTable() already succeeded
13702    */
13703   ndbassert(tabptr.p->checkTable(scanptr.p->scanSchemaVersion));
13704 
13705   if (scanptr.p->m_scan_dist_key_flag)   //Pruned scan
13706   {
13707     jamDebug();
13708     ndbrequire(DictTabInfo::isOrderedIndex(tabPtr.p->tableType) ||
13709                tabPtr.p->get_user_defined_partitioning());
13710 
13711     /**
13712      * Prepare for sendDihGetNodeReq to request DBDIH info for
13713      * the single pruned-to fragId we got from NDB API.
13714      */
13715     tfragCount = 1;
13716   }
13717   ndbassert(scanptr.p->scanNextFragId == 0);
13718 
13719   scanptr.p->scanParallel = tfragCount;
13720   scanptr.p->scanNoFrag = tfragCount;
13721   scanptr.p->scanState = ScanRecord::RUNNING;
13722 
13723   setApiConTimer(apiConnectptr, 0, __LINE__);
13724   updateBuddyTimer(apiConnectptr);
13725 
13726   /**
13727    * Request fragment info from DIH.
13728    */
13729   jam();
13730   sendDihGetNodesLab(signal, scanptr, apiConnectptr);
13731 }//Dbtc::execDIH_SCAN_TAB_CONF()
13732 
13733 
13734 static
compareFragLocation(const void * a,const void * b)13735 int compareFragLocation(const void * a, const void * b)
13736 {
13737   return (((Dbtc::ScanFragLocation*)a)->primaryBlockRef -
13738           ((Dbtc::ScanFragLocation*)b)->primaryBlockRef);
13739 }
13740 
13741 /********************************************************************
13742  * sendDihGetNodesLab
13743  *
13744  * Will request DBDIH for the LQH fragment location of all 'scanNoFrag'
13745  * fragments. Insert a fragment location record in the list
13746  * 'ScanRecord::m_fragLocations' for each fragment to be scanned.
13747  *
13748  * As the DBDIH signaling is direct executed, we can execute for quite
13749  * a while here. To avoid too much work in one request we send CONTINUEB
13750  * every MAX_DIGETNODESREQS'th signal to space out the signals a bit.
13751  ********************************************************************/
sendDihGetNodesLab(Signal * signal,ScanRecordPtr scanptr,ApiConnectRecordPtr const apiConnectptr)13752 void Dbtc::sendDihGetNodesLab(Signal* signal, ScanRecordPtr scanptr, ApiConnectRecordPtr const apiConnectptr)
13753 {
13754   jam();
13755   Uint32 fragCnt = 0;
13756   ScanRecord* const scanP = scanptr.p;
13757 
13758   if (scanP->scanState == ScanRecord::CLOSING_SCAN)
13759   {
13760     jam();
13761     updateBuddyTimer(apiConnectptr);
13762     close_scan_req_send_conf(signal, scanptr, apiConnectptr);
13763     return;
13764   }
13765 
13766   TableRecordPtr tabPtr;
13767   tabPtr.i = scanP->scanTableref;
13768   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
13769 
13770   /**
13771    * Check table, ERROR_INSERT verify scanError() failure handling.
13772    */
13773   const Uint32 schemaVersion = scanP->scanSchemaVersion;
13774   if (ERROR_INSERTED_CLEAR(8081))
13775   {
13776     jam();
13777     scanError(signal, scanptr, ZTIME_OUT_ERROR);
13778     return;
13779   }
13780   if (unlikely(!tabPtr.p->checkTable(schemaVersion)))
13781   {
13782     jam();
13783     scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
13784     return;
13785   }
13786 
13787   /**
13788    * Note that the above checkTable() and scanState checking is
13789    * sufficient for all sendDihGetNodeReq's below: As EXECUTE_DIRECT
13790    * is used, there cant be any other signals processed inbetween
13791    * which close the scan, or drop the table.
13792    */
13793   bool is_multi_spj_scan =
13794     ScanFragReq::getMultiFragFlag(scanP->scanRequestInfo);
13795   ScanFragLocationPtr fragLocationPtr;
13796   {
13797     Local_ScanFragLocation_list list(m_fragLocationPool,
13798                                      scanptr.p->m_fragLocations);
13799     if (unlikely(!m_fragLocationPool.seize(fragLocationPtr)))
13800     {
13801       jam();
13802       scanError(signal, scanptr, ZNO_FRAG_LOCATION_RECORD_ERROR);
13803       return;
13804     }
13805     list.addLast(fragLocationPtr);
13806     fragLocationPtr.p->m_first_index = 0;
13807     fragLocationPtr.p->m_next_index = 0;
13808   }
13809   do
13810   {
13811     ndbassert(scanP->scanState == ScanRecord::RUNNING);
13812     ndbassert(tabPtr.p->checkTable(schemaVersion) == true);
13813 
13814     /**
13815      * We check for CONTINUEB sending here to limits how many
13816      * direct executed 'GSN_DIGETNODESREQ' we can do in
13817      * one signal to ensure we keep the rules of not executing
13818      * for more than 5-10 microseconds per signal.
13819      */
13820     if (fragCnt >= DiGetNodesReq::MAX_DIGETNODESREQS)
13821     {
13822       jam();
13823       signal->theData[0] = TcContinueB::ZSTART_FRAG_SCANS;
13824       signal->theData[1] = scanptr.i;
13825       sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
13826       return;
13827     }
13828 
13829     const bool success = sendDihGetNodeReq(signal,
13830                                            scanptr,
13831                                            fragLocationPtr,
13832                                            scanP->scanNextFragId,
13833                                            is_multi_spj_scan);
13834     if (unlikely(!success))
13835     {
13836       jam();
13837       return;  //sendDihGetNodeReq called scanError() upon failure.
13838     }
13839     fragCnt++;
13840     scanP->scanNextFragId++;
13841 
13842   } while (scanP->scanNextFragId < scanP->scanNoFrag);
13843 
13844   /**
13845    * We got the 'fragLocations' for all fragments to be scanned.
13846    * For MultiFrag' scans the SPJ-instance has not been filled
13847    * in yet. All frag scans in this REQ is now set up to use the
13848    * same SPJ instance.
13849    *
13850    * Then sort the fragLocations[] on blockRef such that possible
13851    * multiFrag scans could easily find fragId's to be included in
13852    * the same multiFragment SCAN_FRAGREQ
13853    */
13854   if (is_multi_spj_scan)
13855   {
13856     jam();
13857     Uint32 i;
13858     ScanFragLocationPtr ptr;
13859     Local_ScanFragLocation_list frags(m_fragLocationPool, scanP->m_fragLocations);
13860     const Uint32 spjInstance = (cspjInstanceRR++ % 120) + 1;
13861 
13862     ScanFragLocation fragLocations[MAX_NDB_PARTITIONS];
13863 
13864     /* Construct SPJ blockRefs, fill in fragment locations into a temporary array */
13865     i = 0;
13866     for (frags.first(ptr); !ptr.isNull(); frags.next(ptr))
13867     {
13868       for (Uint32 j = ptr.p->m_first_index; j < ptr.p->m_next_index; j++)
13869       {
13870         const BlockReference primaryBlockRef =
13871           ptr.p->m_frag_location_array[j].primaryBlockRef;
13872         const BlockReference preferredBlockRef =
13873           ptr.p->m_frag_location_array[j].preferredBlockRef;
13874 
13875         const NodeId primaryNodeId = refToNode(primaryBlockRef);
13876         const NodeId preferredNodeId = refToNode(preferredBlockRef);
13877         ndbassert(refToMain(primaryBlockRef) == DBSPJ);
13878         ndbassert(refToMain(preferredBlockRef) == DBSPJ);
13879 
13880         ndbassert(i < MAX_NDB_PARTITIONS);
13881         fragLocations[i].fragId = ptr.p->m_frag_location_array[j].fragId;
13882         fragLocations[i].primaryBlockRef =
13883           numberToRef(DBSPJ, spjInstance, primaryNodeId);
13884         fragLocations[i].preferredBlockRef =
13885           numberToRef(DBSPJ, spjInstance, preferredNodeId);
13886         i++;
13887       }
13888     }
13889     ndbassert(i == scanP->scanNoFrag);
13890     /* Sort fragment locations on 'blockRef' */
13891     qsort(fragLocations, scanP->scanNoFrag,
13892           sizeof(ScanFragLocation), compareFragLocation);
13893 
13894     /* Write back the blockRef-sorted fragment locations */
13895     i = 0;
13896     for (frags.first(ptr); !ptr.isNull(); frags.next(ptr))
13897     {
13898       for (Uint32 j = ptr.p->m_first_index; j < ptr.p->m_next_index; j++)
13899       {
13900         ndbassert(i < MAX_NDB_PARTITIONS);
13901         ptr.p->m_frag_location_array[j].fragId   = fragLocations[i].fragId;
13902         ptr.p->m_frag_location_array[j].primaryBlockRef =
13903           fragLocations[i].primaryBlockRef;
13904         ptr.p->m_frag_location_array[j].preferredBlockRef =
13905           fragLocations[i].preferredBlockRef;
13906         i++;
13907       }
13908     }
13909     ndbassert(i == scanP->scanNoFrag);
13910   }
13911 
13912   /* Start sending SCAN_FRAGREQ's, possibly interrupted with CONTINUEB */
13913   scanP->scanNextFragId = 0;
13914   sendFragScansLab(signal, scanptr, apiConnectptr);
13915 }//Dbtc::sendDihGetNodesLab
13916 
13917 /******************************************************
13918  * execDIH_SCAN_TAB_REF
13919  ******************************************************/
execDIH_SCAN_TAB_REF(Signal * signal,ScanRecordPtr scanptr,ApiConnectRecordPtr const apiConnectptr)13920 void Dbtc::execDIH_SCAN_TAB_REF(Signal* signal,
13921                                 ScanRecordPtr scanptr,
13922                                 ApiConnectRecordPtr const apiConnectptr)
13923 {
13924   jamEntry();
13925   DihScanTabRef * ref = (DihScanTabRef*)signal->getDataPtr();
13926   const Uint32 errCode = ref->error;
13927   if (apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK)
13928   {
13929     jam();
13930     releaseScanResources(signal, scanptr, apiConnectptr, true);
13931     handleApiFailState(signal, apiConnectptr.i);
13932     return;
13933   }//if
13934   abortScanLab(signal, scanptr, errCode, true, apiConnectptr);
13935 }//Dbtc::execDIH_SCAN_TAB_REF()
13936 
13937 /**
13938  * Abort a scan not yet 'RUNNING' on any LDM's.
13939  *
13940  * Use ::scanError() instead for failing a scan which
13941  * is in 'RUNNING' or in 'CLOSING_SCAN' state.
13942  */
abortScanLab(Signal * signal,ScanRecordPtr scanptr,Uint32 errCode,bool not_started,ApiConnectRecordPtr const apiConnectptr)13943 void Dbtc::abortScanLab(Signal* signal, ScanRecordPtr scanptr, Uint32 errCode,
13944                         bool not_started, ApiConnectRecordPtr const apiConnectptr)
13945 {
13946   ndbassert(scanptr.p->scanState != ScanRecord::RUNNING);
13947   ndbassert(scanptr.p->scanState != ScanRecord::CLOSING_SCAN);
13948 
13949   time_track_complete_scan_error(scanptr.p,
13950                                  refToNode(apiConnectptr.p->ndbapiBlockref));
13951   scanTabRefLab(signal, errCode, apiConnectptr.p);
13952   releaseScanResources(signal, scanptr, apiConnectptr, not_started);
13953 }//Dbtc::abortScanLab()
13954 
releaseScanResources(Signal * signal,ScanRecordPtr scanPtr,ApiConnectRecordPtr const apiConnectptr,bool not_started)13955 void Dbtc::releaseScanResources(Signal* signal,
13956                                 ScanRecordPtr scanPtr,
13957                                 ApiConnectRecordPtr const apiConnectptr,
13958 				bool not_started)
13959 {
13960   if (apiConnectptr.p->cachePtr != RNIL)
13961   {
13962     CacheRecordPtr cachePtr;
13963     cachePtr.i = apiConnectptr.p->cachePtr;
13964     ndbrequire(cachePtr.i != Uint32(~0));
13965     c_cacheRecordPool.getPtr(cachePtr);
13966     releaseKeys(cachePtr.p);
13967     releaseAttrinfo(cachePtr, apiConnectptr.p);
13968   }//if
13969 
13970   if (not_started)
13971   {
13972     jam();
13973     Local_ScanFragRec_dllist run(c_scan_frag_pool, scanPtr.p->m_running_scan_frags);
13974     Local_ScanFragRec_dllist queue(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
13975     ScanFragRecPtr ptr;
13976     while (run.removeFirst(ptr))
13977     {
13978       c_scan_frag_pool.release(ptr);
13979     }
13980     while (queue.removeFirst(ptr))
13981     {
13982       c_scan_frag_pool.release(ptr);
13983     }
13984     checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
13985                         c_scan_frag_pool);
13986   }
13987 
13988   {
13989     ScanFragLocationPtr ptr;
13990     Local_ScanFragLocation_list frags(m_fragLocationPool,
13991                                       scanPtr.p->m_fragLocations);
13992     while (frags.removeFirst(ptr))
13993     {
13994       m_fragLocationPool.release(ptr);
13995     }
13996     checkPoolShrinkNeed(DBTC_FRAG_LOCATION_TRANSIENT_POOL_INDEX,
13997                         m_fragLocationPool);
13998   }
13999 
14000   if (scanPtr.p->scanKeyInfoPtr != RNIL)
14001   {
14002     releaseSection(scanPtr.p->scanKeyInfoPtr);
14003     scanPtr.p->scanKeyInfoPtr = RNIL;
14004   }
14005 
14006   if (scanPtr.p->scanAttrInfoPtr != RNIL)
14007   {
14008     releaseSection(scanPtr.p->scanAttrInfoPtr);
14009     scanPtr.p->scanAttrInfoPtr = RNIL;
14010   }
14011 
14012   ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
14013   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
14014   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
14015 
14016   ndbassert(scanPtr.p->scanApiRec == apiConnectptr.i);
14017   ndbassert(apiConnectptr.p->apiScanRec == scanPtr.i);
14018 
14019   if (scanPtr.p->m_scan_cookie != DihScanTabConf::InvalidCookie)
14020   {
14021     jam();
14022     /* Cookie was requested, 'return' it */
14023     DihScanTabCompleteRep* rep = (DihScanTabCompleteRep*)signal->getDataPtrSend();
14024     rep->tableId = scanPtr.p->scanTableref;
14025     rep->scanCookie = scanPtr.p->m_scan_cookie;
14026     rep->jamBufferPtr = jamBuffer();
14027 
14028     EXECUTE_DIRECT_MT(DBDIH, GSN_DIH_SCAN_TAB_COMPLETE_REP, signal,
14029                       DihScanTabCompleteRep::SignalLength, 0);
14030     jamEntryDebug();
14031     /* No return code, it will always succeed. */
14032     scanPtr.p->m_scan_cookie = DihScanTabConf::InvalidCookie;
14033   }
14034 
14035   // link into free list
14036   scanRecordPool.release(scanPtr);
14037   checkPoolShrinkNeed(DBTC_SCAN_RECORD_TRANSIENT_POOL_INDEX,
14038                       scanRecordPool);
14039   ndbassert(cConcScanCount > 0);
14040   cConcScanCount--;
14041 
14042   apiConnectptr.p->apiScanRec = RNIL;
14043   apiConnectptr.p->apiConnectstate = CS_CONNECTED;
14044   setApiConTimer(apiConnectptr, 0, __LINE__);
14045 }//Dbtc::releaseScanResources()
14046 
sendDihGetNodeReq(Signal * signal,ScanRecordPtr scanptr,ScanFragLocationPtr & fragLocationPtr,Uint32 scanFragId,bool is_multi_spj_scan)14047 bool Dbtc::sendDihGetNodeReq(Signal* signal,
14048                              ScanRecordPtr scanptr,
14049                              ScanFragLocationPtr & fragLocationPtr,
14050                              Uint32 scanFragId,
14051                              bool is_multi_spj_scan)
14052 {
14053   jamDebug();
14054   DiGetNodesReq * const req = (DiGetNodesReq *)&signal->theData[0];
14055 
14056   req->tableId = scanptr.p->scanTableref;
14057   req->hashValue = scanFragId;
14058   req->distr_key_indicator = ZTRUE;
14059   req->scan_indicator = ZTRUE;
14060   req->anyNode = scanptr.p->m_read_any_node;
14061   req->jamBufferPtr = jamBuffer();
14062   req->get_next_fragid_indicator = 0;
14063 
14064   if (scanptr.p->m_scan_dist_key_flag) //Scan pruned to specific fragment
14065   {
14066     jamDebug();
14067     ndbassert(scanFragId == 0); /* Pruned to 1 fragment */
14068     req->hashValue = scanptr.p->m_scan_dist_key;
14069 
14070     TableRecordPtr tabPtr;
14071     tabPtr.i = scanptr.p->scanTableref;
14072     ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
14073 
14074     req->distr_key_indicator = tabPtr.p->get_user_defined_partitioning();
14075   }
14076 
14077   EXECUTE_DIRECT_MT(DBDIH, GSN_DIGETNODESREQ, signal,
14078                     DiGetNodesReq::SignalLength, 0);
14079 
14080   jamEntryDebug();
14081   /**
14082    * theData[0] is always '0' in a DiGetNodesCONF,
14083    * else it is a REF, with errorCode in theData[1]
14084    */
14085   const Uint32 errorCode =
14086     (signal->theData[0] != 0)    ? signal->theData[1] : //DIH error
14087     (ERROR_INSERTED_CLEAR(8095)) ? ZGET_DATAREC_ERROR : //Fake error
14088     0;
14089 
14090   if (errorCode != 0)
14091   {
14092     scanError(signal, scanptr, errorCode);
14093     return false;
14094   }
14095 
14096   const DiGetNodesConf * conf = (DiGetNodesConf *)&signal->theData[0];
14097   const Uint32 lqhScanFragId = conf->fragId;
14098   NodeId nodeId = conf->nodes[0];
14099   const NodeId ownNodeId = getOwnNodeId();
14100 
14101   arrGuard(nodeId, MAX_NDB_NODES);
14102   {
14103     if (ERROR_INSERTED(8050) &&
14104         nodeId != ownNodeId)
14105     {
14106       /* Asked to scan a fragment which is not on the same node as the
14107        * TC - transaction hinting / scan partition pruning has failed
14108        * Used by testPartitioning.cpp
14109        */
14110       CRASH_INSERTION(8050);
14111     }
14112   }
14113 
14114   TableRecordPtr tabPtr;
14115   tabPtr.i = scanptr.p->scanTableref;
14116   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
14117 
14118   /**
14119    * This must be false as select count(*) otherwise
14120    *   can "pass" committing on backup fragments and
14121    *   get incorrect row count
14122    *
14123    * The table property TR_READ_BACKUP guarantees that all commits will
14124    * release locks on all replicas before reporting the commit to the
14125    * application. This means that we are safe to also read from backups
14126    * for committed reads. We avoid doing it for locking reads to avoid
14127    * unnecessary deadlock scenarios. We do it however for those
14128    * operations that have flagged that the base is committed read.
14129    * Base operations on BLOB tables upgrade locks in this fashion and
14130    * they are safe to read from backup replicas without causing
14131    * more deadlocks than otherwise would happen.
14132    */
14133   NodeId primaryNodeId = nodeId;
14134   Uint32 TreadBackup = (tabPtr.p->m_flags & TableRecord::TR_READ_BACKUP);
14135   if (TreadBackup &&
14136       (ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo) ||
14137        scanptr.p->m_read_committed_base))
14138   {
14139     jam();
14140     /* Primary not counted in DIGETNODES signal */
14141     Uint32 count = (conf->reqinfo & 0xFFFF) + 1;
14142     for (Uint32 i = 1; i < count; i++)
14143     {
14144       if (conf->nodes[i] == ownNodeId)
14145       {
14146         jam();
14147         nodeId = ownNodeId;
14148         break;
14149       }
14150     }
14151     if (nodeId != ownNodeId)
14152     {
14153       Uint32 node;
14154       jam();
14155       Uint16 nodes[4];
14156       nodes[0] = (Uint16)conf->nodes[0];
14157       nodes[1] = (Uint16)conf->nodes[1];
14158       nodes[2] = (Uint16)conf->nodes[2];
14159       nodes[3] = (Uint16)conf->nodes[3];
14160       if ((node = check_own_location_domain(&nodes[0],
14161                                             count)) != 0)
14162       {
14163         nodeId = node;
14164       }
14165     }
14166   }
14167 
14168   if (ERROR_INSERTED(8083) &&
14169       nodeId != ownNodeId)
14170   {
14171     ndbabort();  // Only node-local reads
14172   }
14173 
14174   /* Send SCANFRAGREQ directly to LQH block, or 'viaSPJ'
14175    * In the later case we may do a Round-Robin load distribution
14176    * among the SPJ instances if multiple SPJ requests are needed.
14177    */
14178   Uint32 blockInstance;
14179   if (scanptr.p->m_scan_block_no == DBLQH)
14180   {
14181     /**
14182      * Get instance key from upper bits except most significant bit
14183      * which is used for reorg moving flag.
14184      */
14185     blockInstance = (conf->reqinfo >> 24) & 127;
14186   }
14187   // Else, it is a 'viaSPJ request':
14188   else if (is_multi_spj_scan)
14189   {
14190     //SPJ instance is set together with qsort'ing of m_fragLocations
14191     blockInstance = 0;
14192   }
14193   // Prefer own TC/SPJ intance if a single request to ownNodeId
14194   else if (nodeId == ownNodeId &&        //Request to ownNodeId
14195            scanptr.p->scanNoFrag == 1)   //Pruned to single fragment
14196   {
14197     blockInstance = instance();          //Choose SPJ-instance in own block-thread
14198   }
14199   else
14200   {
14201     //See comment for other usage of 'cspjInstanceRR'
14202     blockInstance = (cspjInstanceRR++ % 120) + 1;
14203   }
14204 
14205   /* SCANFRAGREQ with optional KEYINFO and mandatory ATTRINFO are
14206    * now sent to LQH / SPJ
14207    * This starts the scan on the given fragment(s).
14208    * If this is the last SCANFRAGREQ, sendScanFragReq will release
14209    * the KeyInfo and AttrInfo sections when sending.
14210    */
14211   NodeId preferredNodeId = nodeId;
14212   if (!is_multi_spj_scan)
14213   {
14214     primaryNodeId = nodeId;
14215   }
14216   else
14217   {
14218     jam();
14219   }
14220   const BlockReference primaryBlockRef = numberToRef(
14221                   scanptr.p->m_scan_block_no, blockInstance, primaryNodeId);
14222   const BlockReference preferredBlockRef = numberToRef(
14223                   scanptr.p->m_scan_block_no, blockInstance, preferredNodeId);
14224 
14225   //Build list of fragId locations.
14226   {
14227     jamDebug();
14228     Uint32 index = fragLocationPtr.p->m_next_index;
14229     if (unlikely((index + 1) == NUM_FRAG_LOCATIONS_IN_ARRAY))
14230     {
14231       jamDebug();
14232       Local_ScanFragLocation_list list(m_fragLocationPool,
14233                                        scanptr.p->m_fragLocations);
14234       if (unlikely(!m_fragLocationPool.seize(fragLocationPtr)))
14235       {
14236         jam();
14237         scanError(signal, scanptr, ZNO_FRAG_LOCATION_RECORD_ERROR);
14238         return false;
14239       }
14240       list.addLast(fragLocationPtr);
14241       index = 0;
14242       fragLocationPtr.p->m_first_index = 0;
14243     }
14244     fragLocationPtr.p->m_next_index = index + 1;
14245     fragLocationPtr.p->m_frag_location_array[index].fragId = lqhScanFragId;
14246     fragLocationPtr.p->m_frag_location_array[index].primaryBlockRef =
14247       primaryBlockRef;
14248     fragLocationPtr.p->m_frag_location_array[index].preferredBlockRef =
14249       preferredBlockRef;
14250   }
14251   return true;
14252 }//Dbtc::sendDihGetNodeReq
14253 
14254 /********************************************************************
14255  * ::sendFragScansLab()
14256  *
14257  * WE WILL NOW START A NUMBER OF PARALLEL SCAN PROCESSES. EACH OF
14258  * THESE WILL SCAN ONE FRAGMENT AT A TIME, OR A SET OF 'MULTI-FRAGMENTS'
14259  * LOCATED AT THE SAME NODE/INSTANCE. To avoid too much work in one
14260  * request we send CONTINUEB every 4th signal to space out the
14261  * signals a bit.
14262  ********************************************************************/
sendFragScansLab(Signal * signal,ScanRecordPtr scanptr,ApiConnectRecordPtr const apiConnectptr)14263 void Dbtc::sendFragScansLab(Signal* signal,
14264                             ScanRecordPtr scanptr,
14265                             ApiConnectRecordPtr const apiConnectptr)
14266 {
14267   jamDebug();
14268   ScanFragRecPtr scanFragP;
14269   Uint32 fragCnt = 0;
14270   Uint32 cntLocSignals = 0;
14271   const NodeId ownNodeId = getOwnNodeId();
14272 
14273   TableRecordPtr tabPtr;
14274   tabPtr.i = scanptr.p->scanTableref;
14275   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
14276 
14277   if (scanptr.p->scanState == ScanRecord::CLOSING_SCAN)
14278   {
14279     jam();
14280     updateBuddyTimer(apiConnectptr);
14281     close_scan_req_send_conf(signal, scanptr, apiConnectptr);
14282     return;
14283   }
14284 
14285   /**
14286    * Check table, ERROR_INSERT to verify scanError() failure handling.
14287    */
14288   const Uint32 schemaVersion = scanptr.p->scanSchemaVersion;
14289   if (ERROR_INSERTED_CLEAR(8115))
14290   {
14291     jam();
14292     scanError(signal, scanptr, ZTIME_OUT_ERROR);
14293     return;
14294   }
14295   if (unlikely(!tabPtr.p->checkTable(schemaVersion)))
14296   {
14297     jam();
14298     scanError(signal, scanptr, tabPtr.p->getErrorCode(schemaVersion));
14299     return;
14300   }
14301 
14302   /**
14303    * Note that the above checkTable() and scanState checking is
14304    * sufficient for all the sendScanFragReq's below:
14305    * Table or scanState can not change while we are in controll.
14306    * sendScanFragReq() itself can fail, possibly closing the scan.
14307    * However, that is caught by checking its return value.
14308    */
14309   scanFragP.i = RNIL;
14310   ScanFragLocationPtr fragLocationPtr;
14311   {
14312     Local_ScanFragLocation_list list(m_fragLocationPool,
14313                                      scanptr.p->m_fragLocations);
14314     list.first(fragLocationPtr);
14315   }
14316   while (fragLocationPtr.p != NULL)
14317   {
14318     ndbassert(tabPtr.p->checkTable(schemaVersion) == true);
14319     ndbassert(scanptr.p->scanState != ScanRecord::CLOSING_SCAN);
14320 
14321     { // running-list scope
14322       Local_ScanFragRec_dllist list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
14323 
14324       /**
14325        * Since we have to leave the running-list scope for the list while
14326        * calling sendScanFragReq we have to have the below logic to
14327        * restart the loop when coming back from sendScanFragReq.
14328        */
14329       if (scanFragP.i == RNIL)
14330       {
14331         jamDebug();
14332         list.first(scanFragP);
14333       }
14334       else
14335       {
14336         jamDebug();
14337         list.next(scanFragP);
14338       }
14339       for (; !scanFragP.isNull(); list.next(scanFragP))
14340       {
14341         if (scanFragP.p->scanFragState == ScanFragRec::IDLE) // Start it NOW!.
14342         {
14343           jam();
14344           /**
14345            * A max fanout of 1::4 of consumed::produced signals are allowed.
14346            * If we are about to produce more, we have to contine later.
14347            */
14348 	  if (cntLocSignals > 4)
14349           {
14350             jam();
14351             signal->theData[0] = TcContinueB::ZSEND_FRAG_SCANS;
14352             signal->theData[1] = scanptr.i;
14353             sendSignal(reference(), GSN_CONTINUEB, signal, 2, JBB);
14354             return;
14355           }
14356           if (fragCnt > 0 &&
14357               scanptr.p->scanNextFragId == scanptr.p->scanNoFrag-1 && //Last FragId
14358               ERROR_INSERTED_CLEAR(8097))
14359           {
14360             jam();
14361             signal->theData[0] = TcContinueB::ZSEND_FRAG_SCANS;
14362             signal->theData[1] = scanptr.i;
14363             sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 2, 10);
14364             return;
14365           }
14366 
14367           /**
14368            * Need to break out of running-list scope before calling
14369            * sendScanFragReq.
14370            */
14371           fragCnt++;
14372           break;
14373         } // if IDLE
14374       }
14375     }
14376     /**
14377      * We have to distinguish between exiting the loop due to end of loop or
14378      * to get out of running-list scope to call sendScanFragReq.
14379      */
14380     if (scanFragP.isNull())
14381     {
14382       jam();
14383       return;
14384     }
14385 
14386     ndbassert(scanptr.p->m_booked_fragments_count > 0);
14387     scanptr.p->m_booked_fragments_count--;
14388     const bool success = sendScanFragReq(signal,
14389                                          scanptr,
14390                                          scanFragP,
14391                                          fragLocationPtr,
14392                                          apiConnectptr);
14393     if (unlikely(!success))
14394     {
14395       jam();
14396       return;
14397     }
14398 
14399     const NodeId nodeId = refToNode(scanFragP.p->lqhBlockref);
14400     const bool local = (nodeId == ownNodeId);
14401     if (local)
14402       cntLocSignals++;
14403   } //while (!scanptr.p->m_fragLocations.isEmpty());
14404 
14405   /**
14406    * There could possibly be some leftover ScanFragRec's if the
14407    * API prepared for a larger 'parallelism' than needed to scan
14408    * all fragments. We finish of any excess ScanFragRec's by
14409    * letting them return an 'empty' result set.
14410    */
14411   {
14412     Local_ScanFragRec_dllist list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
14413     Local_ScanFragRec_dllist queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
14414 
14415     list.next(scanFragP);
14416     while (!scanFragP.isNull())
14417     {
14418       jam();
14419       ndbassert(scanFragP.p->scanFragState == ScanFragRec::IDLE);
14420 
14421       // Prepare an 'empty result' reply for this 'scanFragP'
14422       scanFragP.p->m_ops = 0;
14423       scanFragP.p->m_totalLen = 0;
14424       scanFragP.p->m_hasMore = 0;
14425       scanFragP.p->m_scan_frag_conf_status = 1;
14426       scanFragP.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
14427       scanFragP.p->stopFragTimer();
14428 
14429       // Insert into 'queued' reply messages
14430       ScanFragRecPtr tmp(scanFragP);
14431       list.next(scanFragP);
14432       list.remove(tmp);
14433       queued.addFirst(tmp);
14434       scanptr.p->m_queued_count++;
14435       ndbassert(scanptr.p->m_booked_fragments_count > 0);
14436       scanptr.p->m_booked_fragments_count--;
14437     }
14438   }
14439   /*********************************************
14440    * WE HAVE NOW STARTED A FRAGMENT SCAN. NOW
14441    * WAIT FOR THE FIRST SCANNED RECORDS
14442    *********************************************/
14443 }//Dbtc::sendFragScansLab
14444 
14445 
14446 /**
14447  * Dbtc::execSCAN_FRAGREF
14448  *  Our attempt to scan a fragment was refused
14449  *  set error code and close all other fragment
14450  *  scan's belonging to this scan
14451  */
execSCAN_FRAGREF(Signal * signal)14452 void Dbtc::execSCAN_FRAGREF(Signal* signal)
14453 {
14454   const ScanFragRef * const ref = (ScanFragRef *)&signal->theData[0];
14455 
14456   jamEntry();
14457   const Uint32 errCode = ref->errorCode;
14458 
14459   scanFragptr.i = ref->senderData;
14460   if (!c_scan_frag_pool.getValidPtr(scanFragptr))
14461   {
14462     jam();
14463     warningHandlerLab(signal, __LINE__);
14464     return;
14465   }
14466 
14467   ScanRecordPtr scanptr;
14468   scanptr.i = scanFragptr.p->scanRec;
14469   if (!scanRecordPool.getValidPtr(scanptr))
14470   {
14471     jam();
14472     systemErrorLab(signal, __LINE__);
14473   }
14474 
14475   ApiConnectRecordPtr apiConnectptr;
14476   apiConnectptr.i = scanptr.p->scanApiRec;
14477   if (!c_apiConnectRecordPool.getValidPtr(apiConnectptr))
14478   {
14479     jam();
14480     systemErrorLab(signal, __LINE__);
14481   }
14482 
14483   Uint32 transid1 = apiConnectptr.p->transid[0] ^ ref->transId1;
14484   Uint32 transid2 = apiConnectptr.p->transid[1] ^ ref->transId2;
14485   transid1 = transid1 | transid2;
14486   if (transid1 != 0) {
14487     jam();
14488     systemErrorLab(signal, __LINE__);
14489   }//if
14490 
14491   /**
14492    * Set errorcode, close connection to this lqh fragment,
14493    * stop fragment timer and call scanFragError to start
14494    * close of the other fragment scans
14495    */
14496   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
14497   scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
14498   scanFragptr.p->stopFragTimer();
14499   time_track_complete_scan_frag_error(scanFragptr.p);
14500   {
14501     Local_ScanFragRec_dllist run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
14502     run.remove(scanFragptr);
14503     c_scan_frag_pool.release(scanFragptr);
14504     checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
14505                         c_scan_frag_pool);
14506   }
14507   scanError(signal, scanptr, errCode);
14508 }//Dbtc::execSCAN_FRAGREF()
14509 
14510 /**
14511  * Dbtc::scanError
14512  *
14513  * Called when an error occurs during
14514  */
scanError(Signal * signal,ScanRecordPtr scanptr,Uint32 errorCode)14515 void Dbtc::scanError(Signal* signal, ScanRecordPtr scanptr, Uint32 errorCode)
14516 {
14517   jam();
14518   ScanRecord* scanP = scanptr.p;
14519 
14520   DEBUG("scanError, errorCode = "<< errorCode <<
14521 	", scanState = " << scanptr.p->scanState);
14522 
14523   ApiConnectRecordPtr apiConnectptr;
14524   apiConnectptr.i = scanP->scanApiRec;
14525   c_apiConnectRecordPool.getPtr(apiConnectptr);
14526   ndbrequire(apiConnectptr.p->apiScanRec == scanptr.i);
14527 
14528   if(scanP->scanState == ScanRecord::CLOSING_SCAN){
14529     jam();
14530     close_scan_req_send_conf(signal, scanptr, apiConnectptr);
14531     return;
14532   }
14533 
14534   ndbrequire(scanP->scanState == ScanRecord::RUNNING);
14535 
14536   /**
14537    * Close scan wo/ having received an order to do so
14538    */
14539   close_scan_req(signal, scanptr, false, apiConnectptr);
14540 
14541   if (apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK)
14542   {
14543     jam();
14544     return;
14545   }
14546 
14547   ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
14548   ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
14549   ref->transId1 = apiConnectptr.p->transid[0];
14550   ref->transId2 = apiConnectptr.p->transid[1];
14551   ref->errorCode  = errorCode;
14552   ref->closeNeeded = 1;
14553   sendSignal(apiConnectptr.p->ndbapiBlockref, GSN_SCAN_TABREF,
14554 	     signal, ScanTabRef::SignalLength, JBB);
14555 }//Dbtc::scanError()
14556 
14557 /************************************************************
14558  * execSCAN_FRAGCONF
14559  *
14560  * A NUMBER OF OPERATIONS HAVE BEEN COMPLETED IN THIS
14561  * FRAGMENT. TAKE CARE OF AND ISSUE FURTHER ACTIONS.
14562  ************************************************************/
execSCAN_FRAGCONF(Signal * signal)14563 void Dbtc::execSCAN_FRAGCONF(Signal* signal)
14564 {
14565   Uint32 transid1, transid2, total_len;
14566   jamEntry();
14567 
14568   const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
14569   const Uint32 noCompletedOps = conf->completedOps;
14570   const Uint32 status = conf->fragmentCompleted;
14571   const Uint32 activeMask =
14572     (signal->getLength() >= ScanFragConf::SignalLength_ext)
14573       ? conf->activeMask : 0;
14574 
14575   scanFragptr.i = conf->senderData;
14576   if (!c_scan_frag_pool.getValidPtr(scanFragptr))
14577   {
14578     jam();
14579     warningHandlerLab(signal, __LINE__);
14580     return;
14581   }
14582 
14583   ScanRecordPtr scanptr;
14584   scanptr.i = scanFragptr.p->scanRec;
14585   if (!scanRecordPool.getValidPtr(scanptr))
14586   {
14587     jam();
14588     systemErrorLab(signal, __LINE__);
14589     return;
14590   }
14591 
14592   ApiConnectRecordPtr apiConnectptr;
14593   apiConnectptr.i = scanptr.p->scanApiRec;
14594   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
14595   {
14596     jam();
14597     systemErrorLab(signal, __LINE__);
14598     return;
14599   }
14600 
14601   transid1 = apiConnectptr.p->transid[0] ^ conf->transId1;
14602   transid2 = apiConnectptr.p->transid[1] ^ conf->transId2;
14603   total_len= conf->total_len;
14604   transid1 = transid1 | transid2;
14605   if (unlikely(transid1 != 0))
14606   {
14607     jam();
14608     systemErrorLab(signal, __LINE__);
14609     return;
14610   }//if
14611 
14612   ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
14613   if (likely(refToMain(scanFragptr.p->lqhBlockref) == DBLQH))
14614   {
14615     jamDebug();
14616     time_track_complete_scan_frag(scanFragptr.p);
14617   }
14618 
14619   if (unlikely(scanptr.p->scanState == ScanRecord::CLOSING_SCAN))
14620   {
14621     if(status == 0)
14622     {
14623       jam();
14624       /**
14625        * We have started closing = we sent a close -> ignore this
14626        */
14627       return;
14628     } else {
14629       jam();
14630       scanFragptr.p->stopFragTimer();
14631       scanFragptr.p->scanFragState = ScanFragRec::COMPLETED;
14632       {
14633         Local_ScanFragRec_dllist run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
14634         run.remove(scanFragptr);
14635         c_scan_frag_pool.release(scanFragptr);
14636         checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
14637                             c_scan_frag_pool);
14638       }
14639     }
14640     close_scan_req_send_conf(signal, scanptr, apiConnectptr);
14641     return;
14642   }
14643 
14644   scanFragptr.p->stopFragTimer();
14645 
14646   if (noCompletedOps == 0 && status != 0 &&
14647       !scanptr.p->m_pass_all_confs &&
14648       scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count <
14649         scanptr.p->scanNoFrag)
14650   {
14651     /**
14652      * Start on next fragment. Don't do this if we scan via the SPJ block. In
14653      * that case, dropping the last SCAN_TABCONF message for a fragment would
14654      * mean dropping the 'nodeMask' (which is sent in ScanFragConf::total_len).
14655      * This would confuse the API with respect to which pushed operations that
14656      * would get new tuples in the next batch. If we use SPJ, we must thus
14657      * send SCAN_TABCONF and let the API ask for the next batch.
14658      */
14659     jam();
14660     scanFragptr.p->scanFragState = ScanFragRec::IDLE;
14661     ScanFragLocationPtr fragLocationPtr;
14662     {
14663       Local_ScanFragLocation_list list(m_fragLocationPool,
14664                                        scanptr.p->m_fragLocations);
14665       list.first(fragLocationPtr);
14666       ndbassert(fragLocationPtr.p != NULL);
14667     }
14668     const bool ok = sendScanFragReq(signal,
14669                                     scanptr,
14670                                     scanFragptr,
14671                                     fragLocationPtr,
14672                                     apiConnectptr);
14673     if (!ok)
14674     {
14675       jam();
14676     }
14677     return;
14678   }
14679   {
14680     Local_ScanFragRec_dllist run(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
14681     Local_ScanFragRec_dllist queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
14682 
14683     run.remove(scanFragptr);
14684     queued.addFirst(scanFragptr);
14685     scanptr.p->m_queued_count++;
14686   }
14687 
14688   if (status != 0 &&
14689       scanptr.p->m_pass_all_confs &&
14690       scanptr.p->scanNextFragId+scanptr.p->m_booked_fragments_count
14691       < scanptr.p->scanNoFrag){
14692     /**
14693      * nodeMask(=total_len) should be zero since there will be no more
14694      * rows from this fragment.
14695      */
14696     ndbrequire(total_len==0);
14697     /**
14698      * Now set it to one to tell the API that there may be more rows from
14699      * the next fragment.
14700      */
14701     total_len  = 1;
14702   }
14703 
14704   scanFragptr.p->m_scan_frag_conf_status = status;
14705   scanFragptr.p->m_ops = noCompletedOps;
14706   scanFragptr.p->m_totalLen = total_len;
14707   scanFragptr.p->m_hasMore = activeMask;
14708   scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
14709 
14710   if (scanptr.p->m_queued_count > /** Min */ 0)
14711   {
14712     jamDebug();
14713     sendScanTabConf(signal, scanptr, apiConnectptr);
14714   }
14715 }//Dbtc::execSCAN_FRAGCONF()
14716 
14717 /****************************************************************************
14718  * execSCAN_NEXTREQ
14719  *
14720  * THE APPLICATION HAS PROCESSED THE TUPLES TRANSFERRED AND IS NOW READY FOR
14721  * MORE. THIS SIGNAL IS ALSO USED TO CLOSE THE SCAN.
14722  ****************************************************************************/
execSCAN_NEXTREQ(Signal * signal)14723 void Dbtc::execSCAN_NEXTREQ(Signal* signal)
14724 {
14725   const ScanNextReq * const req = (ScanNextReq *)&signal->theData[0];
14726   const UintR transid1 = req->transId1;
14727   const UintR transid2 = req->transId2;
14728   const UintR stopScan = req->stopScan;
14729 
14730   jamEntry();
14731 
14732   SectionHandle handle(this, signal);
14733   ApiConnectRecordPtr apiConnectptr;
14734   apiConnectptr.i = req->apiConnectPtr;
14735   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr)))
14736   {
14737     jam();
14738     releaseSections(handle);
14739     warningHandlerLab(signal, __LINE__);
14740     return;
14741   }//if
14742 
14743   /**
14744    * Check transid
14745    */
14746   const UintR ctransid1 = apiConnectptr.p->transid[0] ^ transid1;
14747   const UintR ctransid2 = apiConnectptr.p->transid[1] ^ transid2;
14748   if (unlikely((ctransid1 | ctransid2) != 0))
14749   {
14750     jam();
14751     releaseSections(handle);
14752     ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
14753     ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
14754     ref->transId1 = transid1;
14755     ref->transId2 = transid2;
14756     ref->errorCode  = ZSTATE_ERROR;
14757     ref->closeNeeded = 0;
14758     sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
14759 	       signal, ScanTabRef::SignalLength, JBB);
14760     DEBUG("Wrong transid");
14761     return;
14762   }
14763 
14764   /**
14765    * Check state of API connection
14766    */
14767   if (unlikely(apiConnectptr.p->apiConnectstate != CS_START_SCAN))
14768   {
14769     jam();
14770     releaseSections(handle);
14771     if (apiConnectptr.p->apiConnectstate == CS_CONNECTED) {
14772       jam();
14773       /*********************************************************************
14774        * The application sends a SCAN_NEXTREQ after experiencing a time-out.
14775        *  We will send a SCAN_TABREF to indicate a time-out occurred.
14776        *********************************************************************/
14777       DEBUG("scanTabRefLab: ZSCANTIME_OUT_ERROR2");
14778       ndbout_c("apiConnectptr(%d) -> abort", apiConnectptr.i);
14779       ndbabort(); //B2 indication of strange things going on
14780       scanTabRefLab(signal, ZSCANTIME_OUT_ERROR2, apiConnectptr.p);
14781       return;
14782     }
14783     DEBUG("scanTabRefLab: ZSTATE_ERROR");
14784     DEBUG("  apiConnectstate="<<apiConnectptr.p->apiConnectstate);
14785     ndbabort(); //B2 indication of strange things going on
14786     scanTabRefLab(signal, ZSTATE_ERROR, apiConnectptr.p);
14787     return;
14788   }//if
14789 
14790   /*******************************************************
14791    * START THE ACTUAL LOGIC OF SCAN_NEXTREQ.
14792    ********************************************************/
14793   // Stop the timer that is used to check for timeout in the API
14794   setApiConTimer(apiConnectptr, 0, __LINE__);
14795   ScanRecordPtr scanptr;
14796   scanptr.i = apiConnectptr.p->apiScanRec;
14797   if (!scanRecordPool.getValidPtr(scanptr) || scanptr.i == RNIL)
14798   {
14799     // How can this happen?
14800     // Assert to catch if path is tested, remove if hit and analyzed.
14801     ndbassert(false);
14802     releaseSections(handle);
14803     ScanTabRef * ref = (ScanTabRef*)&signal->theData[0];
14804     ref->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
14805     ref->transId1 = transid1;
14806     ref->transId2 = transid2;
14807     ref->errorCode  = ZSTATE_ERROR;
14808     ref->closeNeeded = 0;
14809     sendSignal(signal->senderBlockRef(), GSN_SCAN_TABREF,
14810 	       signal, ScanTabRef::SignalLength, JBB);
14811     return;
14812   }
14813 
14814   ScanRecord* scanP = scanptr.p;
14815 
14816   /* Copy ReceiverIds to working space past end of signal
14817    * so that we don't overwrite them when sending signals
14818    */
14819   Uint32 len = 0;
14820   if (handle.m_cnt > 0)
14821   {
14822     jam();
14823     /* TODO : Add Dropped signal handling for SCAN_NEXTREQ */
14824     /* Receiver ids are in a long section */
14825     ndbrequire(signal->getLength() == ScanNextReq::SignalLength);
14826     ndbrequire(handle.m_cnt == 1);
14827     SegmentedSectionPtr receiverIdsSection;
14828     ndbrequire(handle.getSection(receiverIdsSection,
14829                                  ScanNextReq::ReceiverIdsSectionNum));
14830     len= receiverIdsSection.p->m_sz;
14831     ndbassert(len < (8192 - 25));
14832 
14833     copy(signal->getDataPtrSend()+25, receiverIdsSection);
14834     releaseSections(handle);
14835   }
14836   else
14837   {
14838     jam();
14839     len= signal->getLength() - ScanNextReq::SignalLength;
14840     memcpy(signal->getDataPtrSend()+25,
14841            signal->getDataPtr()+ ScanNextReq::SignalLength,
14842            4 * len);
14843   }
14844 
14845   if (stopScan == ZTRUE) {
14846     jam();
14847     /*********************************************************************
14848      * APPLICATION IS CLOSING THE SCAN.
14849      **********************************************************************/
14850     close_scan_req(signal, scanptr, true, apiConnectptr);
14851     return;
14852   }//if
14853 
14854   if (unlikely(scanP->scanState == ScanRecord::CLOSING_SCAN))
14855   {
14856     jam();
14857     /**
14858      * The scan is closing (typically due to error)
14859      *   but the API hasn't understood it yet
14860      *
14861      * Wait for API close request
14862      */
14863     return;
14864   }
14865 
14866   ScanFragNextReq tmp;
14867   tmp.requestInfo = 0;
14868   tmp.transId1 = apiConnectptr.p->transid[0];
14869   tmp.transId2 = apiConnectptr.p->transid[1];
14870   tmp.batch_size_rows = scanP->batch_size_rows;
14871   tmp.batch_size_bytes = scanP->batch_byte_size;
14872 
14873   for(Uint32 i = 0 ; i<len; i++)
14874   {
14875     jam();
14876     scanFragptr.i = signal->theData[i+25];
14877     c_scan_frag_pool.getPtr(scanFragptr);
14878     ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
14879 
14880     scanFragptr.p->startFragTimer(ctcTimer);
14881     scanFragptr.p->m_ops = 0;
14882 
14883     {
14884       Local_ScanFragRec_dllist running(c_scan_frag_pool, scanP->m_running_scan_frags);
14885       Local_ScanFragRec_dllist delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
14886       delivered.remove(scanFragptr);
14887       running.addFirst(scanFragptr);
14888     }
14889 
14890     if(scanFragptr.p->m_scan_frag_conf_status)
14891     {
14892       /**
14893        * Last scan was complete.
14894        * Reuse this ScanFragRec 'thread' for scanning 'scanNextFragId'
14895        */
14896       jam();
14897       ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
14898       ndbassert(scanptr.p->m_booked_fragments_count);
14899       scanptr.p->m_booked_fragments_count--;
14900 
14901       scanFragptr.p->scanFragState = ScanFragRec::IDLE;
14902       ScanFragLocationPtr fragLocationPtr;
14903       {
14904         Local_ScanFragLocation_list list(m_fragLocationPool,
14905                                          scanptr.p->m_fragLocations);
14906         list.first(fragLocationPtr);
14907         ndbassert(fragLocationPtr.p != NULL);
14908       }
14909       const bool ok = sendScanFragReq(signal,
14910                                       scanptr,
14911                                       scanFragptr,
14912                                       fragLocationPtr,
14913                                       apiConnectptr);
14914       if (unlikely(!ok))
14915       {
14916         jam();
14917         return; //scanError() has already been called
14918       }
14919     }
14920     else
14921     {
14922       jam();
14923       scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
14924       scanFragptr.p->m_start_ticks = getHighResTimer();
14925       ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
14926       * req = tmp;
14927       req->senderData = scanFragptr.i;
14928       sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
14929 		 ScanFragNextReq::SignalLength, JBB);
14930     }
14931   }//for
14932 
14933 }//Dbtc::execSCAN_NEXTREQ()
14934 
14935 void
close_scan_req(Signal * signal,ScanRecordPtr scanPtr,bool req_received,ApiConnectRecordPtr const apiConnectptr)14936 Dbtc::close_scan_req(Signal* signal,
14937                      ScanRecordPtr scanPtr,
14938                      bool req_received,
14939                      ApiConnectRecordPtr const apiConnectptr)
14940 {
14941   ScanRecord* scanP = scanPtr.p;
14942   ndbrequire(scanPtr.p->scanState != ScanRecord::IDLE);
14943   ScanRecord::ScanState old = scanPtr.p->scanState;
14944   scanPtr.p->scanState = ScanRecord::CLOSING_SCAN;
14945   scanPtr.p->m_close_scan_req = req_received;
14946 
14947   if (old == ScanRecord::WAIT_FRAGMENT_COUNT)  //Dead state due to direct-exec
14948   {
14949     jam();
14950     scanPtr.p->scanState = old;
14951     return; // Will continue on execDI_FCOUNTCONF
14952   }
14953 
14954   /**
14955    * Queue         : Action
14956    * ============= : =================
14957    * completed     : -
14958    * running       : close -> LQH
14959    * delivered w/  : close -> LQH
14960    * delivered wo/ : move to completed
14961    * queued w/     : close -> LQH
14962    * queued wo/    : move to completed
14963    */
14964 
14965   ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
14966   nextReq->requestInfo = 0;
14967   ScanFragNextReq::setCloseFlag(nextReq->requestInfo, 1);
14968   nextReq->transId1 = apiConnectptr.p->transid[0];
14969   nextReq->transId2 = apiConnectptr.p->transid[1];
14970 
14971   {
14972     ScanFragRecPtr ptr;
14973     Local_ScanFragRec_dllist running(c_scan_frag_pool, scanP->m_running_scan_frags);
14974     Local_ScanFragRec_dllist delivered(c_scan_frag_pool,
14975                                        scanP->m_delivered_scan_frags);
14976     Local_ScanFragRec_dllist queued(c_scan_frag_pool, scanP->m_queued_scan_frags);
14977 
14978     // Close running
14979     for(running.first(ptr); !ptr.isNull(); ){
14980       ScanFragRecPtr curr = ptr; // Remove while iterating...
14981       running.next(ptr);
14982 
14983       switch(curr.p->scanFragState){
14984       case ScanFragRec::IDLE:
14985 	jam(); // real early abort
14986 	ndbrequire(old == ScanRecord::WAIT_AI || old == ScanRecord::RUNNING);
14987         curr.p->scanFragState = ScanFragRec::COMPLETED;
14988         running.remove(curr);
14989         c_scan_frag_pool.release(curr);
14990 	continue;
14991       case ScanFragRec::WAIT_GET_PRIMCONF:
14992 	jam();
14993 	continue;
14994       case ScanFragRec::LQH_ACTIVE:
14995 	jam();
14996 	break;
14997       default:
14998 	jamLine(curr.p->scanFragState);
14999 	ndbabort();
15000       }
15001 
15002       curr.p->startFragTimer(ctcTimer);
15003       curr.p->m_start_ticks = getHighResTimer();
15004       curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
15005       nextReq->senderData = curr.i;
15006       sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
15007 		 ScanFragNextReq::SignalLength, JBB);
15008     }
15009 
15010     // Close delivered
15011     for(delivered.first(ptr); !ptr.isNull(); ){
15012       jam();
15013       ScanFragRecPtr curr = ptr; // Remove while iterating...
15014       delivered.next(ptr);
15015 
15016       ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
15017       delivered.remove(curr);
15018 
15019       if (curr.p->m_scan_frag_conf_status == 0)
15020       {
15021 	jam();
15022         running.addFirst(curr);
15023 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
15024         curr.p->m_start_ticks = getHighResTimer();
15025 	curr.p->startFragTimer(ctcTimer);
15026 	nextReq->senderData = curr.i;
15027 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
15028 		   ScanFragNextReq::SignalLength, JBB);
15029       }
15030       else
15031       {
15032 	jam();
15033 	curr.p->scanFragState = ScanFragRec::COMPLETED;
15034 	curr.p->stopFragTimer();
15035 	c_scan_frag_pool.release(curr);
15036       }
15037     }//for
15038 
15039     /**
15040      * All queued with data should be closed
15041      */
15042     for(queued.first(ptr); !ptr.isNull(); ){
15043       jam();
15044       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
15045       ScanFragRecPtr curr = ptr; // Remove while iterating...
15046       queued.next(ptr);
15047 
15048       queued.remove(curr);
15049       scanP->m_queued_count--;
15050 
15051       if (curr.p->m_scan_frag_conf_status == 0)
15052       {
15053 	jam();
15054         running.addFirst(curr);
15055 	curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
15056         curr.p->m_start_ticks = getHighResTimer();
15057 	curr.p->startFragTimer(ctcTimer);
15058 	nextReq->senderData = curr.i;
15059 	sendSignal(curr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
15060 		   ScanFragNextReq::SignalLength, JBB);
15061       }
15062       else
15063       {
15064 	jam();
15065 	curr.p->scanFragState = ScanFragRec::COMPLETED;
15066 	curr.p->stopFragTimer();
15067 	c_scan_frag_pool.release(curr);
15068       }
15069     }
15070     checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
15071                         c_scan_frag_pool);
15072   }
15073   close_scan_req_send_conf(signal, scanPtr, apiConnectptr);
15074 }
15075 
15076 void
close_scan_req_send_conf(Signal * signal,ScanRecordPtr scanPtr,ApiConnectRecordPtr const apiConnectptr)15077 Dbtc::close_scan_req_send_conf(Signal* signal, ScanRecordPtr scanPtr, ApiConnectRecordPtr const apiConnectptr)
15078 {
15079   jam();
15080 
15081   ndbrequire(scanPtr.p->m_queued_scan_frags.isEmpty());
15082   ndbrequire(scanPtr.p->m_delivered_scan_frags.isEmpty());
15083   //ndbrequire(scanPtr.p->m_running_scan_frags.isEmpty());
15084 
15085   if(!scanPtr.p->m_running_scan_frags.isEmpty()){
15086     jam();
15087     return;
15088   }
15089 
15090   const bool apiFail =
15091     (apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK);
15092 
15093   if(!scanPtr.p->m_close_scan_req){
15094     jam();
15095     /**
15096      * The API hasn't order closing yet
15097      */
15098     return;
15099   }
15100 
15101   Uint32 ref = apiConnectptr.p->ndbapiBlockref;
15102   if(!apiFail && ref){
15103     jam();
15104     ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
15105     conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
15106     conf->requestInfo = ScanTabConf::EndOfData;
15107     conf->transId1 = apiConnectptr.p->transid[0];
15108     conf->transId2 = apiConnectptr.p->transid[1];
15109     sendSignal(ref, GSN_SCAN_TABCONF, signal, ScanTabConf::SignalLength, JBB);
15110     time_track_complete_scan(scanPtr.p, refToNode(ref));
15111   }
15112 
15113   releaseScanResources(signal, scanPtr, apiConnectptr);
15114 
15115   if(apiFail){
15116     jam();
15117     /**
15118      * API has failed
15119      */
15120     handleApiFailState(signal, apiConnectptr.i);
15121   }
15122 }
15123 
15124 Dbtc::ScanRecordPtr
seizeScanrec(Signal * signal)15125 Dbtc::seizeScanrec(Signal* signal)
15126 {
15127   ScanRecordPtr scanptr;
15128   ndbrequire(cConcScanCount < cscanrecFileSize); // TODO(wl9756)
15129   ndbrequire(scanRecordPool.seize(scanptr));
15130   cConcScanCount++;
15131   ndbrequire(scanptr.p->scanState == ScanRecord::IDLE);
15132   return scanptr;
15133 }//Dbtc::seizeScanrec()
15134 
15135 void
get_next_frag_location(ScanFragLocationPtr fragLocationPtr,Uint32 & fragId,Uint32 & primaryBlockRef,Uint32 & preferredBlockRef)15136 Dbtc::get_next_frag_location(ScanFragLocationPtr fragLocationPtr,
15137                              Uint32 & fragId,
15138                              Uint32 & primaryBlockRef,
15139                              Uint32 & preferredBlockRef)
15140 {
15141   Uint32 index = fragLocationPtr.p->m_first_index;
15142   fragId = fragLocationPtr.p->m_frag_location_array[index].fragId;
15143   primaryBlockRef =
15144     fragLocationPtr.p->m_frag_location_array[index].primaryBlockRef;
15145   preferredBlockRef =
15146     fragLocationPtr.p->m_frag_location_array[index].preferredBlockRef;
15147 }
15148 
15149 void
get_and_step_next_frag_location(ScanFragLocationPtr & fragLocationPtr,ScanRecord * scanPtrP,Uint32 & fragId,Uint32 & primaryBlockRef,Uint32 & preferredBlockRef)15150 Dbtc::get_and_step_next_frag_location(ScanFragLocationPtr & fragLocationPtr,
15151                                       ScanRecord *scanPtrP,
15152                                       Uint32 & fragId,
15153                                       Uint32 & primaryBlockRef,
15154                                       Uint32 & preferredBlockRef)
15155 {
15156   Uint32 index = fragLocationPtr.p->m_first_index;
15157   fragId = fragLocationPtr.p->m_frag_location_array[index].fragId;
15158   primaryBlockRef =
15159     fragLocationPtr.p->m_frag_location_array[index].primaryBlockRef;
15160   preferredBlockRef =
15161     fragLocationPtr.p->m_frag_location_array[index].preferredBlockRef;
15162 
15163   index++;
15164   if (likely(index < fragLocationPtr.p->m_next_index))
15165   {
15166     fragLocationPtr.p->m_first_index = index;
15167   }
15168   else
15169   {
15170     ScanFragLocationPtr ptr;
15171     Local_ScanFragLocation_list list(m_fragLocationPool,
15172                                      scanPtrP->m_fragLocations);
15173     list.removeFirst(ptr);
15174     ndbassert(ptr.i == fragLocationPtr.i);
15175     m_fragLocationPool.release(fragLocationPtr);  //Consumed it
15176     list.first(fragLocationPtr);
15177     checkPoolShrinkNeed(DBTC_FRAG_LOCATION_TRANSIENT_POOL_INDEX,
15178                         m_fragLocationPool);
15179   }
15180 }
15181 
sendScanFragReq(Signal * signal,ScanRecordPtr scanptr,ScanFragRecPtr scanFragP,ScanFragLocationPtr & fragLocationPtr,ApiConnectRecordPtr const apiConnectptr)15182 bool Dbtc::sendScanFragReq(Signal* signal,
15183                            ScanRecordPtr scanptr,
15184                            ScanFragRecPtr scanFragP,
15185                            ScanFragLocationPtr & fragLocationPtr,
15186                            ApiConnectRecordPtr const apiConnectptr)
15187 {
15188   jam();
15189   ScanRecord* const scanP = scanptr.p;
15190 
15191   Uint32 fragId, primaryLqhBlockRef, preferredLqhBlockRef;
15192   get_and_step_next_frag_location(fragLocationPtr,
15193                                   scanptr.p,
15194                                   fragId,
15195                                   primaryLqhBlockRef,
15196                                   preferredLqhBlockRef);
15197 
15198   scanP->scanNextFragId++;
15199 
15200   const NodeId nodeId = refToNode(preferredLqhBlockRef);
15201   Uint32 requestInfo = scanP->scanRequestInfo;
15202 
15203   ndbassert(scanFragP.p->scanFragState == ScanFragRec::IDLE);
15204   scanFragP.p->lqhBlockref = preferredLqhBlockRef;
15205   scanFragP.p->lqhScanFragId = fragId;
15206   scanFragP.p->m_connectCount = getNodeInfo(nodeId).m_connectCount;
15207 
15208   SectionHandle sections(this);
15209   sections.m_ptr[0].i = scanP->scanAttrInfoPtr;
15210   sections.m_ptr[1].i = scanP->scanKeyInfoPtr;
15211 
15212   sections.m_cnt = 1; // there is always attrInfo
15213 
15214   if (scanP->scanKeyInfoPtr != RNIL)
15215   {
15216     jamDebug();
15217     sections.m_cnt = 2; // and sometimes keyinfo
15218   }
15219 
15220   if (ScanFragReq::getMultiFragFlag(scanP->scanRequestInfo))
15221   {
15222     jam();
15223     /**
15224      * Fragment locations use a bit more involved model for SPJ queries
15225      * that use multiple SPJ workers. We want as much execution of the
15226      * query done locally as possible and we want to ensure that the
15227      * query execution is done within one location domain if possible.
15228      *
15229      * At the same time we want to ensure that we use the correct amount
15230      * of SPJ workers for the query as prepared by the NDB API. The NDB
15231      * API has prepared one SPJ worker for each data node that owns a
15232      * primary partition in the cluster.
15233      *
15234      * What we do is that when we combine several SPJ workers into one
15235      * since it is handled locally within one SPJ node we will increase
15236      * the batch size of that SPJ worker accordingly to ensure that we
15237      * make use of all the available batch size that the NDB API provided
15238      * for us.
15239      *
15240      * What we do is that we select the SPJ worker to be set according to
15241      * the preferred node to execute the query. This means that with
15242      * READ_BACKUP and FULLY_REPLICATED tables we will pick this node to
15243      * execute the query.
15244      *
15245      * When we use location domains we will prefer to use the execute
15246      * the query in the location domain where we are residing. This will
15247      * avoid all network traffic between location domains for the SPJ
15248      * queries. This will help avoiding network bottlenecks and ensure
15249      * that we make proper use of the bandwidth between location domains
15250      * mainly for write requests that need to pass over location domain
15251      * borders to ensure all replicas are updated.
15252      *
15253      * TODO: More work and thought is required to consider the execution
15254      * of queries involving a mix of FULLY_REPLICATED tables and tables
15255      * with normal partitioning.
15256      */
15257     Uint32 *fragIds = &signal->theData[25]; // temp storage
15258     *(fragIds++) = scanFragP.p->lqhScanFragId;
15259 
15260     /**
15261      * The fragLocations are sorted on primaryBlockRef.
15262      * Append all fragIds at same block to this SCAN_FRAGREQ.
15263      * Use preferredBlockRef to decide which SPJ to place
15264      * this SCAN_FRAGREQ.
15265      */
15266 
15267     while (fragLocationPtr.p != NULL)
15268     {
15269       Uint32 thisPrimaryLqhBlockRef;
15270       Uint32 thisPreferredLqhBlockRef;
15271       get_next_frag_location(fragLocationPtr,
15272                              fragId,
15273                              thisPrimaryLqhBlockRef,
15274                              thisPreferredLqhBlockRef);
15275       jam();
15276       if (thisPrimaryLqhBlockRef != primaryLqhBlockRef)
15277       {
15278         jam();
15279         jamLine(Uint16(fragId));
15280         break;
15281       }
15282       ndbrequire(preferredLqhBlockRef == scanFragP.p->lqhBlockref);
15283       *(fragIds++) = fragId;
15284       scanP->scanNextFragId++;
15285       get_and_step_next_frag_location(fragLocationPtr,
15286                                       scanptr.p,
15287                                       fragId,
15288                                       thisPrimaryLqhBlockRef,
15289                                       thisPreferredLqhBlockRef);
15290     }
15291     jam();
15292 
15293     Ptr<SectionSegment> fragIdPtr;
15294     const Uint32 length = (fragIds-&signal->theData[25]);
15295 
15296     if ((ERROR_INSERTED(8116)) ||
15297         (ERROR_INSERTED(8117) && (rand() % 3) == 0) ||
15298 	 !import(fragIdPtr, &signal->theData[25], length))
15299     {
15300       jam();
15301       sections.clear();
15302       scanError(signal, scanptr, ZGET_DATAREC_ERROR);
15303       return false;
15304     }
15305     sections.m_ptr[sections.m_cnt++].i = fragIdPtr.i;
15306   } //MultiFrag
15307 
15308   /* Determine whether this is the last scanFragReq.
15309    * Handle normal scan-all-fragments and partition pruned
15310    * scan-one-fragment cases.
15311    */
15312   const bool isLastReq= (scanP->scanNextFragId >= scanP->scanNoFrag);
15313   if (isLastReq)
15314   {
15315     /* This send will release these sections, remove our
15316      * references to them
15317      */
15318     jamDebug();
15319     scanP->scanKeyInfoPtr = RNIL;
15320     scanP->scanAttrInfoPtr = RNIL;
15321   }
15322 
15323   getSections(sections.m_cnt, sections.m_ptr);
15324 
15325   ScanFragReq * const req = (ScanFragReq *)&signal->theData[0];
15326   ScanFragReq::setScanPrio(requestInfo, 1);
15327   req->tableId = scanP->scanTableref;
15328   req->schemaVersion = scanP->scanSchemaVersion;
15329   req->senderData = scanFragP.i;
15330   req->requestInfo = requestInfo;
15331   req->fragmentNoKeyLen = scanFragP.p->lqhScanFragId;
15332   req->resultRef = apiConnectptr.p->ndbapiBlockref;
15333   req->savePointId = apiConnectptr.p->currSavePointId;
15334   req->transId1 = apiConnectptr.p->transid[0];
15335   req->transId2 = apiConnectptr.p->transid[1];
15336   req->clientOpPtr = scanFragP.p->m_apiPtr;
15337   req->batch_size_rows= scanP->batch_size_rows;
15338   req->batch_size_bytes= scanP->batch_byte_size;
15339 
15340   // Encode variable part
15341   ndbassert(ScanFragReq::getCorrFactorFlag(requestInfo) == 0);
15342 
15343   HostRecordPtr host_ptr;
15344   host_ptr.i = nodeId;
15345   ptrCheckGuard(host_ptr, chostFilesize, hostRecord);
15346   ndbrequire(host_ptr.p->hostStatus == HS_ALIVE);
15347 
15348   const bool longFragReq= (true &&
15349                            (! ERROR_INSERTED(8070) &&
15350                             ! ERROR_INSERTED(8088)));
15351   if (likely(longFragReq))
15352   {
15353     jamDebug();
15354     /* Send long, possibly fragmented SCAN_FRAGREQ */
15355 
15356     // TODO :
15357     //   1) Consider whether to adjust fragmentation threshold
15358     //      a) When to fragment signal vs fragment size
15359     //      b) Fragment size
15360     /* To reduce the copy burden we want to keep hold of the
15361      * AttrInfo and KeyInfo sections after sending them to
15362      * LQH.  To do this we perform the fragmented send inline,
15363      * so that all fragments are sent *now*.  This avoids any
15364      * problems with the fragmented send CONTINUE 'thread' using
15365      * the section while we hold or even release it.  The
15366      * signal receiver can still take realtime breaks when
15367      * receiving.
15368      *
15369      * Indicate to sendBatchedFragmentedSignal that we want to
15370      * keep the fragments, so it must not free them, unless this
15371      * is the last request in which case they can be freed.  If
15372      * the last request is a local send then a copy is avoided.
15373      */
15374     sendBatchedFragmentedSignal(NodeReceiverGroup(scanFragP.p->lqhBlockref),
15375                                 GSN_SCAN_FRAGREQ,
15376                                 signal,
15377                                 ScanFragReq::SignalLength,
15378                                 JBB,
15379                                 &sections,
15380                                 !isLastReq); // Keep sent sections unless
15381                                              // last send
15382 
15383     if (!isLastReq && ScanFragReq::getMultiFragFlag(requestInfo))
15384     {
15385       jamDebug();
15386       release(sections.m_ptr[sections.m_cnt-1]);
15387     }
15388 
15389     /* Clear handle, section deallocation handled elsewhere. */
15390     sections.clear();
15391   }
15392   else
15393   {
15394     jam();
15395     ndbassert(!ScanFragReq::getMultiFragFlag(requestInfo)); //Need 'longFragReq'
15396 
15397     /* Short SCANFRAGREQ with separate KeyInfo and AttrInfo trains
15398      * Sent to older NDBD nodes during upgrade
15399      */
15400     Uint32 reqAttrLen = sections.m_ptr[0].sz;
15401     ScanFragReq::setAttrLen(req->requestInfo, reqAttrLen);
15402     if (sections.m_cnt > 1)
15403     {
15404       jam();
15405       /*
15406        * bug#13834481 missing shift, causing fragment not found
15407        * (error 1231) on 6.3 node.
15408        */
15409       req->fragmentNoKeyLen |= (sections.m_ptr[1].sz << 16);
15410     }
15411     sendSignal(scanFragP.p->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
15412                ScanFragReq::SignalLength, JBB);
15413     if (sections.m_cnt > 1)
15414     {
15415       jam();
15416       /* Build KeyInfo train from KeyInfo long signal section */
15417       sendKeyInfoTrain(signal,
15418                        scanFragP.p->lqhBlockref,
15419                        scanFragP.i,
15420                        0, // Offset 0
15421                        sections.m_ptr[1].i,
15422                        apiConnectptr.p);
15423     }
15424 
15425     if (ERROR_INSERTED(8035))
15426       globalTransporterRegistry.performSend();
15427 
15428     if (!ERROR_INSERTED(8088))
15429     {
15430       ndbrequire(sendAttrInfoTrain(signal,
15431                                    scanFragP.p->lqhBlockref,
15432                                    scanFragP.i,
15433                                    0, // Offset 0
15434                                    sections.m_ptr[0].i,
15435                                    apiConnectptr.p));
15436     }
15437 
15438     if (ERROR_INSERTED(8035))
15439       globalTransporterRegistry.performSend();
15440 
15441     if (isLastReq)
15442     {
15443       /* Free the sections here */
15444       releaseSections(sections);
15445     }
15446     else
15447     {
15448       sections.clear();
15449     }
15450   }
15451 
15452   if (ERROR_INSERTED(8088))
15453   {
15454     signal->theData[0] = 9999;
15455     sendSignalWithDelay(CMVMI_REF, GSN_NDB_TAMPER, signal, 100, 1);
15456   }
15457 
15458   scanFragP.p->scanFragState = ScanFragRec::LQH_ACTIVE;
15459   scanFragP.p->startFragTimer(ctcTimer);
15460   scanFragP.p->m_start_ticks = getHighResTimer();
15461   updateBuddyTimer(apiConnectptr);
15462   return true;
15463 }//Dbtc::sendScanFragReq()
15464 
15465 
sendScanTabConf(Signal * signal,const ScanRecordPtr scanPtr,const ApiConnectRecordPtr apiConnectptr)15466 void Dbtc::sendScanTabConf(Signal* signal,
15467                            const ScanRecordPtr scanPtr,
15468                            const ApiConnectRecordPtr apiConnectptr)
15469 {
15470   jamDebug();
15471   Uint32* ops = signal->getDataPtrSend()+4;
15472   const Uint32 op_count = scanPtr.p->m_queued_count;
15473   const Uint32 ref = apiConnectptr.p->ndbapiBlockref;
15474 
15475   Uint32 words_per_op = 3;
15476   if (scanPtr.p->m_extended_conf)
15477   {
15478     // Use 4 or 5 word extended conf signal?
15479     const Uint32 apiVersion = getNodeInfo(refToNode(ref)).m_version;
15480     ndbassert(apiVersion != 0);
15481     if (ndbd_send_active_bitmask(apiVersion))
15482     {
15483       jamDebug();
15484       words_per_op = 5;
15485     }
15486     else
15487     {
15488       jamDebug();
15489       words_per_op = 4;
15490     }
15491   }
15492   if (ScanTabConf::SignalLength + (words_per_op * op_count) > 25)
15493   {
15494     jamDebug();
15495     ops += 21;
15496   }
15497 
15498   int left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
15499   Uint32 booked = scanPtr.p->m_booked_fragments_count;
15500 
15501   ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
15502   conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
15503   conf->requestInfo = op_count;
15504   conf->transId1 = apiConnectptr.p->transid[0];
15505   conf->transId2 = apiConnectptr.p->transid[1];
15506   ScanFragRecPtr ptr;
15507   {
15508     Local_ScanFragRec_dllist queued(c_scan_frag_pool, scanPtr.p->m_queued_scan_frags);
15509     Local_ScanFragRec_dllist delivered(c_scan_frag_pool, scanPtr.p->m_delivered_scan_frags);
15510     for(queued.first(ptr); !ptr.isNull(); ){
15511       ndbrequire(ptr.p->scanFragState == ScanFragRec::QUEUED_FOR_DELIVERY);
15512       ScanFragRecPtr curr = ptr; // Remove while iterating...
15513       queued.next(ptr);
15514 
15515       bool done = curr.p->m_scan_frag_conf_status && (left <= (int)booked);
15516       if(curr.p->m_scan_frag_conf_status)
15517 	booked++;
15518 
15519       * ops++ = curr.p->m_apiPtr;
15520       * ops++ = done ? RNIL : curr.i;
15521       if (words_per_op == 5)
15522       {
15523         * ops++ = curr.p->m_ops;
15524         * ops++ = curr.p->m_totalLen;
15525         * ops++ = curr.p->m_hasMore;
15526       }
15527       else if (words_per_op == 4)
15528       {
15529         * ops++ = curr.p->m_ops;
15530         * ops++ = curr.p->m_totalLen;
15531       }
15532       else
15533       {
15534         * ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
15535       }
15536 
15537       curr.p->stopFragTimer();
15538       queued.remove(curr);
15539       if(!done){
15540         delivered.addFirst(curr);
15541 	curr.p->scanFragState = ScanFragRec::DELIVERED;
15542       } else {
15543 	curr.p->scanFragState = ScanFragRec::COMPLETED;
15544 	c_scan_frag_pool.release(curr);
15545       }
15546     }
15547   }
15548   checkPoolShrinkNeed(DBTC_SCAN_FRAGMENT_TRANSIENT_POOL_INDEX,
15549                       c_scan_frag_pool);
15550 
15551   bool release = false;
15552   scanPtr.p->m_booked_fragments_count = booked;
15553   if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
15554      scanPtr.p->m_running_scan_frags.isEmpty())
15555   {
15556     jam();
15557     release = true;
15558     conf->requestInfo = op_count | ScanTabConf::EndOfData;
15559   }
15560   else
15561   {
15562     if (scanPtr.p->m_running_scan_frags.isEmpty())
15563     {
15564       jam();
15565       /**
15566        * All scan frags delivered...waiting for API
15567        */
15568       setApiConTimer(apiConnectptr, ctcTimer, __LINE__);
15569     }
15570     else
15571     {
15572       jam();
15573     }
15574   }
15575 
15576   if (ScanTabConf::SignalLength + (words_per_op * op_count) > 25)
15577   {
15578     jamDebug();
15579     LinearSectionPtr ptr[3];
15580     ptr[0].p = signal->getDataPtrSend()+25;
15581     ptr[0].sz = words_per_op * op_count;
15582     sendSignal(ref, GSN_SCAN_TABCONF, signal,
15583                ScanTabConf::SignalLength, JBB, ptr, 1);
15584   }
15585   else
15586   {
15587     jamDebug();
15588     sendSignal(ref, GSN_SCAN_TABCONF, signal,
15589 	       ScanTabConf::SignalLength + (words_per_op * op_count), JBB);
15590   }
15591   scanPtr.p->m_queued_count = 0;
15592 
15593   if (release)
15594   {
15595     jamDebug();
15596     time_track_complete_scan(scanPtr.p, refToNode(ref));
15597     releaseScanResources(signal, scanPtr, apiConnectptr);
15598   }
15599 
15600 }//Dbtc::sendScanTabConf()
15601 
15602 
gcpTcfinished(Signal * signal,Uint64 gci)15603 void Dbtc::gcpTcfinished(Signal* signal, Uint64 gci)
15604 {
15605   if (ERROR_INSERTED(8098))
15606   {
15607     if (cmasterNodeId == getOwnNodeId())
15608     {
15609       bool multi = ((gci&1) == 1);
15610       bool kill_me = ((gci&3) == 1);
15611       /* Kill multi 'assumes' NoOfReplicas=2, and skipping one
15612        * live node at a time avoids taking out a nodegroup
15613        */
15614       ndbout_c("TC killing multi : %u  me : %u", multi, kill_me);
15615       Uint32 start = getOwnNodeId();
15616       bool skip = !kill_me;
15617       Uint32 pos = start;
15618       do
15619       {
15620         NodeInfo ni = getNodeInfo(pos);
15621         if ((ni.getType() == NODE_TYPE_DB) &&
15622             ni.m_connected)
15623         {
15624           /* Found a db node... */
15625           if (!skip)
15626           {
15627             ndbout_c("TC : Killing node %u", pos);
15628             signal->theData[0] = 9999;
15629             sendSignal(numberToRef(CMVMI, pos), GSN_DUMP_STATE_ORD, signal,
15630                        1, JBA);
15631             if (!multi)
15632               break;
15633             skip = true;
15634           }
15635           else
15636           {
15637             ndbout_c("TC : Skipping node %u", pos);
15638             skip = false;
15639           }
15640         }
15641 
15642         pos++;
15643         if (pos == MAX_NDB_NODES)
15644           pos = 1;
15645       } while (pos != start);
15646     }
15647 
15648     /* Keep delaying GCP_TCFINISHED, but don't kill anymore */
15649     SET_ERROR_INSERT_VALUE(8099);
15650   }
15651 
15652   GCPTCFinished* conf = (GCPTCFinished*)signal->getDataPtrSend();
15653   conf->senderData = c_gcp_data;
15654   conf->gci_hi = Uint32(gci >> 32);
15655   conf->gci_lo = Uint32(gci);
15656   conf->tcFailNo = cfailure_nr; /* Indicate highest handled failno in GCP */
15657 
15658   if (ERROR_INSERTED(8099))
15659   {
15660     /* Slow it down */
15661     ndbout_c("TC : Sending delayed GCP_TCFINISHED (%u/%u), failNo %u to local DIH(%x)",
15662              conf->gci_hi, conf->gci_lo, cfailure_nr, cdihblockref);
15663     sendSignalWithDelay(c_gcp_ref, GSN_GCP_TCFINISHED, signal,
15664                         2000, GCPTCFinished::SignalLength);
15665     return;
15666   }
15667 
15668   sendSignal(c_gcp_ref, GSN_GCP_TCFINISHED, signal,
15669              GCPTCFinished::SignalLength, JBB);
15670 }//Dbtc::gcpTcfinished()
15671 
initApiConnect(Signal * signal)15672 void Dbtc::initApiConnect(Signal* signal)
15673 {
15674   SLList<ApiConnectRecord_pool, IA_ApiConnect>
15675                             fast_record_list(c_apiConnectRecordPool);
15676   for (Uint32 i = 0; i < 1000; i++)
15677   {
15678     refresh_watch_dog();
15679     jam();
15680     ApiConnectRecordPtr apiConnectptr;
15681     ndbrequire(c_apiConnectRecordPool.seize(apiConnectptr));
15682     ndbrequire(seizeApiConTimer(apiConnectptr));
15683     setApiConTimer(apiConnectptr, 0, __LINE__);
15684     fast_record_list.addFirst(apiConnectptr);
15685   }
15686 
15687   c_apiConnectFailList.init();
15688   LocalApiConnectRecord_api_list apiConListFail(c_apiConnectRecordPool,
15689                                                 c_apiConnectFailList);
15690   for (Uint32 j = 0; j < capiConnectFailCount; j++)
15691   {
15692     refresh_watch_dog();
15693     jam();
15694     ApiConnectRecordPtr apiConnectptr;
15695     ndbrequire(c_apiConnectRecordPool.seize(apiConnectptr));
15696     ndbrequire(seizeApiConTimer(apiConnectptr));
15697     setApiConTimer(apiConnectptr, 0, __LINE__);
15698     apiConListFail.addFirst(apiConnectptr);
15699   }//for
15700 
15701   capiConnectPREPARE_TO_COMMITList.init();
15702 
15703   ApiConnectRecordPtr apiConnectptr;
15704   while (fast_record_list.removeFirst(apiConnectptr))
15705   {
15706     refresh_watch_dog();
15707     jam();
15708     releaseApiConTimer(apiConnectptr);
15709     c_apiConnectRecordPool.release(apiConnectptr);
15710   }
15711   c_apiConnectRecordPool.resetUsedHi();
15712   c_apiConTimersPool.resetUsedHi();
15713 }//Dbtc::initApiConnect()
15714 
inithost(Signal * signal)15715 void Dbtc::inithost(Signal* signal)
15716 {
15717   cpackedListIndex = 0;
15718   ndbrequire(chostFilesize > 0);
15719   for (hostptr.i = 0; hostptr.i < chostFilesize; hostptr.i++) {
15720     jam();
15721     ptrAss(hostptr, hostRecord);
15722     hostptr.p->hostStatus = HS_DEAD;
15723     hostptr.p->inPackedList = false;
15724     hostptr.p->lqhTransStatus = LTS_IDLE;
15725     struct PackedWordsContainer * containerTCKEYCONF =
15726       &hostptr.p->packTCKEYCONF;
15727     containerTCKEYCONF->noOfPackedWords = 0;
15728     for (Uint32 i = 0; i < NDB_ARRAY_SIZE(hostptr.p->lqh_pack); i++)
15729     {
15730       struct PackedWordsContainer * container = &hostptr.p->lqh_pack[i];
15731       container->noOfPackedWords = 0;
15732       container->hostBlockRef = numberToRef(DBLQH, i, hostptr.i);
15733     }
15734     hostptr.p->m_nf_bits = 0;
15735   }//for
15736   c_alive_nodes.clear();
15737 }//Dbtc::inithost()
15738 
initialiseRecordsLab(Signal * signal,UintR Tdata0,Uint32 retRef,Uint32 retData)15739 void Dbtc::initialiseRecordsLab(Signal* signal, UintR Tdata0,
15740 				Uint32 retRef, Uint32 retData)
15741 {
15742   switch (Tdata0) {
15743   case 0:
15744     jam();
15745     initApiConnect(signal);
15746     break;
15747   case 1:
15748     jam();
15749     // UNUSED Free to initialise something
15750     break;
15751   case 2:
15752     jam();
15753     // UNUSED Free to initialise something
15754     break;
15755   case 3:
15756     jam();
15757     // UNUSED Free to initialise something
15758     break;
15759   case 4:
15760     jam();
15761     inithost(signal);
15762     break;
15763   case 5:
15764     jam();
15765     // UNUSED Free to initialise something
15766     break;
15767   case 6:
15768     jam();
15769     initTable(signal);
15770     break;
15771   case 7:
15772     jam();
15773     initialiseScanrec(signal);
15774     break;
15775   case 8:
15776     jam();
15777     break;
15778   case 9:
15779     jam();
15780     break;
15781   case 10:
15782     jam();
15783     initialiseTcConnect(signal);
15784     break;
15785   case 11:
15786     jam();
15787     initTcFail(signal);
15788 
15789     {
15790       ReadConfigConf * conf = (ReadConfigConf*)signal->getDataPtrSend();
15791       conf->senderRef = reference();
15792       conf->senderData = retData;
15793       sendSignal(retRef, GSN_READ_CONFIG_CONF, signal,
15794 		 ReadConfigConf::SignalLength, JBB);
15795     }
15796     return;
15797     break;
15798   default:
15799     jam();
15800     systemErrorLab(signal, __LINE__);
15801     return;
15802     break;
15803   }//switch
15804 
15805   signal->theData[0] = TcContinueB::ZINITIALISE_RECORDS;
15806   signal->theData[1] = Tdata0 + 1;
15807   signal->theData[2] = 0;
15808   signal->theData[3] = retRef;
15809   signal->theData[4] = retData;
15810   sendSignal(reference(), GSN_CONTINUEB, signal, 5, JBB);
15811 }
15812 
15813 /* ========================================================================= */
15814 /* =======                       INITIALISE_SCANREC                  ======= */
15815 /*                                                                           */
15816 /* ========================================================================= */
initialiseScanrec(Signal * signal)15817 void Dbtc::initialiseScanrec(Signal* signal)
15818 {
15819   ndbrequire(cscanrecFileSize > 0);
15820   cConcScanCount = 0;
15821 }//Dbtc::initialiseScanrec()
15822 
initTable(Signal * signal)15823 void Dbtc::initTable(Signal* signal)
15824 {
15825 
15826   ndbrequire(ctabrecFilesize > 0);
15827   for (tabptr.i = 0; tabptr.i < ctabrecFilesize; tabptr.i++) {
15828     refresh_watch_dog();
15829     ptrAss(tabptr, tableRecord);
15830     tabptr.p->currentSchemaVersion = 0;
15831     tabptr.p->m_flags = 0;
15832     tabptr.p->set_storedTable(true);
15833     tabptr.p->tableType = 0;
15834     tabptr.p->set_enabled(false);
15835     tabptr.p->set_dropping(false);
15836     tabptr.p->noOfKeyAttr = 0;
15837     tabptr.p->hasCharAttr = 0;
15838     tabptr.p->noOfDistrKeys = 0;
15839     tabptr.p->hasVarKeys = 0;
15840   }//for
15841 }//Dbtc::initTable()
15842 
initialiseTcConnect(Signal * signal)15843 void Dbtc::initialiseTcConnect(Signal* signal)
15844 {
15845   jam();
15846   SLList<TcConnectRecord_pool> fast_record_list(tcConnectRecord);
15847   for (Uint32 i = 0; i < 10000; i++)
15848   {
15849     refresh_watch_dog();
15850     jam();
15851     TcConnectRecordPtr tcConptr;
15852     ndbrequire(tcConnectRecord.seize(tcConptr));
15853     fast_record_list.addFirst(tcConptr);
15854   }
15855 
15856   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, cfreeTcConnectFail);
15857   Uint32 tcConnectFailCount = 0;
15858 #ifdef VM_TRACE
15859   Uint32 prevptr = 0;
15860 #endif
15861   while (tcConnectFailCount < ctcConnectFailCount)
15862   {
15863     refresh_watch_dog();
15864     jam();
15865     TcConnectRecordPtr tcConptr;
15866     ndbrequire(tcConnectRecord.seize(tcConptr));
15867     tcConnectFailCount++;
15868 #ifdef VM_TRACE
15869     ndbassert((prevptr == 0) || (prevptr < tcConptr.i));
15870     prevptr = tcConptr.i;
15871 #endif
15872     tcConList.addLast(tcConptr);
15873   }
15874   c_counters.cconcurrentOp = 0;
15875   m_concurrent_overtakeable_operations = 0;
15876 
15877   TcConnectRecordPtr tcConptr;
15878   while (fast_record_list.removeFirst(tcConptr))
15879   {
15880     refresh_watch_dog();
15881     jam();
15882     tcConnectRecord.release(tcConptr);
15883   }
15884   tcConnectRecord.resetUsedHi();
15885 }//Dbtc::initialiseTcConnect()
15886 
15887 /* ------------------------------------------------------------------------- */
15888 /* ----     LINK A GLOBAL CHECKPOINT RECORD INTO THE LIST WITH TRANSACTIONS  */
15889 /*          WAITING FOR COMPLETION.                                          */
15890 /* ------------------------------------------------------------------------- */
linkGciInGcilist(Ptr<GcpRecord> gcpPtr)15891 void Dbtc::linkGciInGcilist(Ptr<GcpRecord> gcpPtr)
15892 {
15893   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
15894   gcp_list.addLast(gcpPtr);
15895 }//Dbtc::linkGciInGcilist()
15896 
15897 /* ------------------------------------------------------------------------- */
15898 /* ------- LINK A TC CONNECT RECORD INTO THE API LIST OF TC CONNECTIONS  --- */
15899 /* ------------------------------------------------------------------------- */
linkTcInConnectionlist(Signal * signal,ApiConnectRecord * const regApiPtr)15900 void Dbtc::linkTcInConnectionlist(Signal* signal, ApiConnectRecord* const regApiPtr)
15901 {
15902   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, regApiPtr->tcConnect);
15903   tcConList.addLast(tcConnectptr);
15904   ndbrequire(tcConnectptr.p->nextList == RNIL);
15905 }//Dbtc::linkTcInConnectionlist()
15906 
15907 /*---------------------------------------------------------------------------*/
15908 /*                    RELEASE_ABORT_RESOURCES                                */
15909 /* THIS CODE RELEASES ALL RESOURCES AFTER AN ABORT OF A TRANSACTION AND ALSO */
15910 /* SENDS THE ABORT DECISION TO THE APPLICATION.                              */
15911 /*---------------------------------------------------------------------------*/
releaseAbortResources(Signal * signal,ApiConnectRecordPtr const apiConnectptr)15912 void Dbtc::releaseAbortResources(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
15913 {
15914   TcConnectRecordPtr rarTcConnectptr;
15915 
15916   jamDebug();
15917   c_counters.cabortCount++;
15918   ndbrequire((apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_USER));
15919   if (apiConnectptr.p->apiCopyRecord != RNIL)
15920   {
15921     // Put apiCopyRecord back in free list.
15922     jam();
15923     ApiConnectRecordPtr copyPtr;
15924     copyPtr.i = apiConnectptr.p->apiCopyRecord;
15925     c_apiConnectRecordPool.getPtr(copyPtr);
15926     ndbassert(copyPtr.p->apiCopyRecord == RNIL);
15927     ndbassert(copyPtr.p->nextApiConnect == RNIL);
15928     ndbrequire(copyPtr.p->apiConnectkind == ApiConnectRecord::CK_COPY);
15929     copyPtr.p->apiConnectkind = ApiConnectRecord::CK_FREE;
15930     apiConnectptr.p->apiCopyRecord = RNIL;
15931     releaseApiConTimer(copyPtr);
15932     ndbrequire(copyPtr.p->theSeizedIndexOperations.isEmpty());
15933     ndbrequire(copyPtr.p->theFiredTriggers.isEmpty());
15934     ndbrequire(copyPtr.p->cachePtr == RNIL);
15935     ndbrequire(copyPtr.p->tcConnect.isEmpty());
15936     c_apiConnectRecordPool.release(copyPtr);
15937     checkPoolShrinkNeed(DBTC_API_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
15938                         c_apiConnectRecordPool);
15939   }
15940   if (apiConnectptr.p->cachePtr != RNIL)
15941   {
15942     CacheRecordPtr cachePtr;
15943     cachePtr.i = apiConnectptr.p->cachePtr;
15944     if (likely(cachePtr.i == Uint32(~0)))
15945     {
15946       jam();
15947       cachePtr.p = &m_local_cache_record;
15948     }
15949     else
15950     {
15951       jam();
15952       c_cacheRecordPool.getPtr(cachePtr);
15953     }
15954     releaseKeys(cachePtr.p);
15955     jamDebug();
15956     releaseAttrinfo(cachePtr, apiConnectptr.p);
15957     jamDebug();
15958   }//if
15959   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, apiConnectptr.p->tcConnect);
15960   while (tcConList.removeFirst(tcConnectptr))
15961   {
15962     jam();
15963     // Clear any markers that have not already been cleared
15964     clearCommitAckMarker(apiConnectptr.p, tcConnectptr.p);
15965     releaseTcCon();
15966   }//while
15967   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
15968                       tcConnectRecord);
15969 
15970   jamDebug();
15971   ndbrequire(apiConnectptr.p->num_commit_ack_markers == 0);
15972   releaseMarker(apiConnectptr.p);
15973 
15974   apiConnectptr.p->tcConnect.init();
15975   apiConnectptr.p->m_transaction_nodes.clear();
15976   apiConnectptr.p->singleUserMode = 0;
15977 
15978   // MASV let state be CS_ABORTING until all
15979   // signals in the "air" have been received. Reset to CS_CONNECTED
15980   // will be done when a TCKEYREQ with start flag is received
15981   // or releaseApiCon is called
15982   // apiConnectptr.p->apiConnectstate = CS_CONNECTED;
15983   apiConnectptr.p->apiConnectstate = CS_ABORTING;
15984   apiConnectptr.p->abortState = AS_IDLE;
15985   jamDebug();
15986   releaseAllSeizedIndexOperations(apiConnectptr.p);
15987   jamDebug();
15988   releaseFiredTriggerData(&apiConnectptr.p->theFiredTriggers);
15989   jamDebug();
15990 
15991   if (tc_testbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG) ||
15992       apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK)
15993   {
15994     jam();
15995     bool ok = false;
15996     Uint32 blockRef = apiConnectptr.p->ndbapiBlockref;
15997     ReturnSignal ret = apiConnectptr.p->returnsignal;
15998     apiConnectptr.p->returnsignal = RS_NO_RETURN;
15999     tc_clearbit(apiConnectptr.p->m_flags, ApiConnectRecord::TF_EXEC_FLAG);
16000     switch(ret){
16001     case RS_TCROLLBACKCONF:
16002       jam();
16003       ok = true;
16004       signal->theData[0] = apiConnectptr.p->ndbapiConnect;
16005       signal->theData[1] = apiConnectptr.p->transid[0];
16006       signal->theData[2] = apiConnectptr.p->transid[1];
16007       sendSignal(blockRef, GSN_TCROLLBACKCONF, signal, 3, JBB);
16008       break;
16009     case RS_TCROLLBACKREP:{
16010       jam();
16011       ok = true;
16012 #ifdef ERROR_INSERT
16013       if (ERROR_INSERTED(8101))
16014       {
16015         char buf[128];
16016         BaseString::snprintf(buf, sizeof(buf), "Sending CONTINUEB:ZDEBUG_DELAY_TCROLLBACKREP");
16017         warningEvent("%s", buf);
16018 
16019         jam();
16020         signal->theData[0] = TcContinueB::ZDEBUG_DELAY_TCROLLBACKREP;
16021         signal->theData[1] = apiConnectptr.p->ndbapiConnect;
16022         signal->theData[2] = apiConnectptr.p->transid[0];
16023         signal->theData[3] = apiConnectptr.p->transid[1];
16024         signal->theData[4] = apiConnectptr.p->returncode;
16025         signal->theData[5] = apiConnectptr.p->errorData;
16026         signal->theData[6] = blockRef;
16027 
16028         sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 7);
16029         break;
16030       }
16031 #endif
16032       TcRollbackRep * const tcRollbackRep =
16033 	(TcRollbackRep *) signal->getDataPtr();
16034 
16035       tcRollbackRep->connectPtr = apiConnectptr.p->ndbapiConnect;
16036       tcRollbackRep->transId[0] = apiConnectptr.p->transid[0];
16037       tcRollbackRep->transId[1] = apiConnectptr.p->transid[1];
16038       tcRollbackRep->returnCode = apiConnectptr.p->returncode;
16039       tcRollbackRep->errorData = apiConnectptr.p->errorData;
16040       sendSignal(blockRef, GSN_TCROLLBACKREP, signal,
16041 		 TcRollbackRep::SignalLength, JBB);
16042     }
16043       break;
16044     case RS_NO_RETURN:
16045       jam();
16046       ok = true;
16047       break;
16048     case RS_TCKEYCONF:
16049     case RS_TC_COMMITCONF:
16050       break;
16051     }
16052     if(!ok){
16053       jam();
16054       ndbout_c("returnsignal = %d", apiConnectptr.p->returnsignal);
16055       sendSystemError(signal, __LINE__);
16056     }//if
16057 
16058   }
16059   setApiConTimer(apiConnectptr, 0,
16060                  100000 + apiConnectptr.p->m_apiConTimer_line);
16061   time_track_complete_transaction_error(apiConnectptr.p);
16062   if (apiConnectptr.p->apiFailState != ApiConnectRecord::AFS_API_OK)
16063   {
16064     jam();
16065     handleApiFailState(signal, apiConnectptr.i);
16066     return;
16067   }//if
16068 }//Dbtc::releaseAbortResources()
16069 
releaseApiCon(Signal * signal,UintR TapiConnectPtr)16070 void Dbtc::releaseApiCon(Signal* signal, UintR TapiConnectPtr)
16071 {
16072   ApiConnectRecordPtr TlocalApiConnectptr;
16073 
16074   TlocalApiConnectptr.i = TapiConnectPtr;
16075   c_apiConnectRecordPool.getPtr(TlocalApiConnectptr);
16076   if (TlocalApiConnectptr.p->apiCopyRecord != RNIL)
16077   {
16078     ApiConnectRecordPtr copyPtr;
16079     copyPtr.i = TlocalApiConnectptr.p->apiCopyRecord;
16080     c_apiConnectRecordPool.getPtr(copyPtr);
16081     if (copyPtr.p->apiConnectstate == CS_RESTART)
16082     {
16083       releaseApiConCopy(signal, copyPtr);
16084     }
16085   }
16086   ndbassert(TlocalApiConnectptr.p->nextApiConnect == RNIL);
16087   ndbrequire(TlocalApiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_USER);
16088   TlocalApiConnectptr.p->apiConnectkind = ApiConnectRecord::CK_FREE;
16089   setApiConTimer(TlocalApiConnectptr, 0, __LINE__);
16090   TlocalApiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
16091   ndbassert(TlocalApiConnectptr.p->m_transaction_nodes.isclear());
16092   ndbassert(TlocalApiConnectptr.p->apiScanRec == RNIL);
16093   /* ndbassert(TlocalApiConnectptr.p->cascading_scans_count == 0);
16094    * Not a valid assert, as we can abort a transaction, and release a connection
16095    * while triggered cascading scans are still in-flight
16096    */
16097   TlocalApiConnectptr.p->cascading_scans_count = 0;
16098   TlocalApiConnectptr.p->m_executing_trigger_ops = 0;
16099   TlocalApiConnectptr.p->m_inExecuteTriggers = false;
16100   TlocalApiConnectptr.p->ndbapiBlockref = 0;
16101   TlocalApiConnectptr.p->transid[0] = 0;
16102   TlocalApiConnectptr.p->transid[1] = 0;
16103   releaseApiConTimer(TlocalApiConnectptr);
16104   c_apiConnectRecordPool.release(TlocalApiConnectptr);
16105   checkPoolShrinkNeed(DBTC_API_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
16106                       c_apiConnectRecordPool);
16107 }//Dbtc::releaseApiCon()
16108 
releaseApiConnectFail(Signal * signal,ApiConnectRecordPtr const apiConnectptr)16109 void Dbtc::releaseApiConnectFail(Signal* signal, ApiConnectRecordPtr const apiConnectptr)
16110 {
16111   apiConnectptr.p->apiConnectstate = CS_RESTART;
16112   apiConnectptr.p->takeOverRec = (Uint8)Z8NIL;
16113   setApiConTimer(apiConnectptr, 0, __LINE__);
16114   LocalApiConnectRecord_api_list apiConList(c_apiConnectRecordPool,
16115                                             c_apiConnectFailList);
16116   ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_FAIL);
16117   apiConnectptr.p->apiConnectkind = ApiConnectRecord::CK_FREE;
16118   apiConList.addFirst(apiConnectptr);
16119   ndbrequire(apiConnectptr.p->commitAckMarker == RNIL);
16120 }//Dbtc::releaseApiConnectFail()
16121 
releaseKeys(CacheRecord * regCachePtr)16122 void Dbtc::releaseKeys(CacheRecord* regCachePtr)
16123 {
16124   Uint32 keyInfoSectionI= regCachePtr->keyInfoSectionI;
16125 
16126   /* Release KeyInfo section if there is one */
16127   releaseSection(keyInfoSectionI);
16128   regCachePtr->keyInfoSectionI= RNIL;
16129 
16130 }//Dbtc::releaseKeys()
16131 
releaseTcConnectFail(Signal * signal)16132 void Dbtc::releaseTcConnectFail(Signal* signal)
16133 {
16134   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, cfreeTcConnectFail);
16135   tcConList.addFirst(tcConnectptr);
16136 }//Dbtc::releaseTcConnectFail()
16137 
seizeApiConnect(Signal * signal,ApiConnectRecordPtr & apiConnectptr)16138 bool Dbtc::seizeApiConnect(Signal* signal, ApiConnectRecordPtr& apiConnectptr)
16139 {
16140   if (likely(c_apiConnectRecordPool.seize(apiConnectptr)))
16141   {
16142     jam();
16143     if (!seizeApiConTimer(apiConnectptr))
16144     {
16145       c_apiConnectRecordPool.release(apiConnectptr);
16146       terrorCode = ZNO_FREE_API_CONNECTION;
16147       return false;
16148     }
16149     terrorCode = ZOK;
16150     apiConnectptr.p->apiConnectkind = ApiConnectRecord::CK_USER;
16151     apiConnectptr.p->apiConnectstate = CS_DISCONNECTED;
16152     setApiConTimer(apiConnectptr, 0, __LINE__);
16153     apiConnectptr.p->apiConnectstate = CS_CONNECTED; /* STATE OF CONNECTION */
16154     tc_clearbit(apiConnectptr.p->m_flags,
16155                 ApiConnectRecord::TF_TRIGGER_PENDING);
16156     return true;
16157   } else {
16158     jam();
16159     terrorCode = ZNO_FREE_API_CONNECTION;
16160     return false;
16161   }//if
16162 }//Dbtc::seizeApiConnect()
16163 
seizeApiConnectFail(Signal * signal,ApiConnectRecordPtr & apiConnectptr)16164 bool Dbtc::seizeApiConnectFail(Signal* signal,
16165                                ApiConnectRecordPtr& apiConnectptr)
16166 {
16167   LocalApiConnectRecord_api_list apiConList(c_apiConnectRecordPool,
16168                                             c_apiConnectFailList);
16169   if (unlikely(!apiConList.removeFirst(apiConnectptr)))
16170   {
16171     return false;
16172   }
16173   ndbrequire(apiConnectptr.p->apiConnectkind == ApiConnectRecord::CK_FREE);
16174   apiConnectptr.p->apiConnectkind = ApiConnectRecord::CK_FAIL;
16175   return true;
16176 }
16177 
seizeTcConnectFail(Signal * signal)16178 void Dbtc::seizeTcConnectFail(Signal* signal)
16179 {
16180   LocalTcConnectRecord_fifo tcConList(tcConnectRecord, cfreeTcConnectFail);
16181   ndbrequire(tcConList.removeFirst(tcConnectptr));
16182   tcConnectptr.p = new (tcConnectptr.p) TcConnectRecord();
16183 }//Dbtc::seizeTcConnectFail()
16184 
16185 /**
16186  * sendAttrInfoTrain
16187  * This method sends an ATTRINFO signal train using AttrInfo
16188  * from the section passed, starting at the supplied offset
16189  */
sendAttrInfoTrain(Signal * signal,UintR TBRef,Uint32 connectPtr,Uint32 offset,Uint32 attrInfoIVal,ApiConnectRecord * const regApiPtr)16190 bool Dbtc::sendAttrInfoTrain(Signal* signal,
16191                              UintR TBRef,
16192                              Uint32 connectPtr,
16193                              Uint32 offset,
16194                              Uint32 attrInfoIVal,
16195                              ApiConnectRecord* const regApiPtr)
16196 {
16197   ndbassert( attrInfoIVal != RNIL );
16198   SectionReader attrInfoReader(attrInfoIVal, getSectionSegmentPool());
16199   Uint32 attrInfoLength= attrInfoReader.getSize();
16200 
16201   ndbassert( offset < attrInfoLength );
16202   if (unlikely(! attrInfoReader.step( offset )))
16203     return false;
16204   attrInfoLength-= offset;
16205 
16206   signal->theData[0] = connectPtr;
16207   signal->theData[1] = regApiPtr->transid[0];
16208   signal->theData[2] = regApiPtr->transid[1];
16209 
16210   while (attrInfoLength != 0)
16211   {
16212     Uint32 dataInSignal= MIN(AttrInfo::DataLength, attrInfoLength);
16213 
16214     if (unlikely(! attrInfoReader.getWords(&signal->theData[3],
16215                                            dataInSignal)))
16216       return false;
16217 
16218     sendSignal(TBRef, GSN_ATTRINFO, signal,
16219                AttrInfo::HeaderLength + dataInSignal, JBB);
16220 
16221     attrInfoLength-= dataInSignal;
16222   }
16223   return true;
16224 } //Dbtc::sendAttrInfoTrain()
16225 
sendContinueTimeOutControl(Signal * signal,Uint32 TapiConPtr)16226 void Dbtc::sendContinueTimeOutControl(Signal* signal, Uint32 TapiConPtr)
16227 {
16228   signal->theData[0] = TcContinueB::ZCONTINUE_TIME_OUT_CONTROL;
16229   signal->theData[1] = TapiConPtr;
16230   sendSignal(cownref, GSN_CONTINUEB, signal, 2, JBB);
16231 }//Dbtc::sendContinueTimeOutControl()
16232 
sendSystemError(Signal * signal,int line)16233 void Dbtc::sendSystemError(Signal* signal, int line)
16234 {
16235   progError(line, NDBD_EXIT_NDBREQUIRE);
16236 }//Dbtc::sendSystemError()
16237 
16238 /* ========================================================================= */
16239 /* -------             LINK ACTUAL GCP OUT OF LIST                   ------- */
16240 /* ------------------------------------------------------------------------- */
unlinkAndReleaseGcp(Ptr<GcpRecord> tmpGcpPtr)16241 void Dbtc::unlinkAndReleaseGcp(Ptr<GcpRecord> tmpGcpPtr)
16242 {
16243   ndbrequire(c_gcpRecordList.getFirst() == tmpGcpPtr.i);
16244 
16245   LocalGcpRecord_list gcp_list(c_gcpRecordPool, c_gcpRecordList);
16246   gcp_list.removeFirst(tmpGcpPtr);
16247   c_gcpRecordPool.release(tmpGcpPtr);
16248   checkPoolShrinkNeed(DBTC_GCP_RECORD_TRANSIENT_POOL_INDEX,
16249                       c_gcpRecordPool);
16250 }
16251 
16252 void
execDUMP_STATE_ORD(Signal * signal)16253 Dbtc::execDUMP_STATE_ORD(Signal* signal)
16254 {
16255   const Uint32 MAX_RECORDS_AT_A_TIME = 16;
16256 
16257   jamEntry();
16258   DumpStateOrd * const dumpState = (DumpStateOrd *)&signal->theData[0];
16259   Uint32 arg = signal->theData[0];
16260 
16261   // Dump set of ScanFragRecs
16262   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfScanFragRec){
16263     /**
16264      * DUMP 2500 12 10 1 1
16265      * Prints ScanFrag records 12 through 21 in instance 1.
16266      * The last parameter indicates whether to only print active instances.
16267      * If the parameter is missing it is set to 1 indicating printing only
16268      * active instances.
16269      *
16270      * Output to cluster log.
16271      */
16272     jam();
16273     Uint32 recordNo = 0;
16274     Uint32 numRecords = 0;
16275     Uint32 instanceId = 0;
16276     Uint32 includeOnlyActive = 1;
16277 
16278     if (signal->getLength() >= 4)
16279     {
16280       recordNo = dumpState->args[1];
16281       numRecords = dumpState->args[2];
16282       instanceId = dumpState->args[3];
16283       if (signal->getLength() >= 5)
16284       {
16285         includeOnlyActive = dumpState->args[4];
16286       }
16287     }
16288     else
16289     {
16290       return;
16291     }
16292     if (instance() != instanceId)
16293     {
16294       return;
16295     }
16296     if (numRecords > MAX_RECORDS_AT_A_TIME)
16297     {
16298       numRecords = MAX_RECORDS_AT_A_TIME;
16299     }
16300     if (unlikely(recordNo >= RNIL))
16301     {
16302       return;
16303     }
16304 
16305     ScanFragRecPtr sfp;
16306     Uint32 found = c_scan_frag_pool.getUncheckedPtrs(&recordNo, &sfp, 1);
16307     if (found == 1 &&
16308         Magic::match(sfp.p->m_magic, ScanFragRec::TYPE_ID) &&
16309         (sfp.p->scanFragState != ScanFragRec::COMPLETED ||
16310          !includeOnlyActive))
16311     {
16312       dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec;
16313       dumpState->args[1] = sfp.i;
16314       dumpState->args[2] = instance();
16315       signal->setLength(3);
16316       execDUMP_STATE_ORD(signal);
16317     }
16318     numRecords--;
16319 
16320     if (recordNo != RNIL && numRecords > 0)
16321     {
16322       dumpState->args[0] = DumpStateOrd::TcDumpSetOfScanFragRec;
16323       dumpState->args[1] = recordNo;
16324       dumpState->args[2] = numRecords;
16325       dumpState->args[3] = instance();
16326       dumpState->args[4] = includeOnlyActive;
16327       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
16328     }
16329     return;
16330   }
16331 
16332   // Dump one ScanFragRec
16333   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanFragRec){
16334     /**
16335      * DUMP 2501 12 1
16336      * Print ScanFrag record 12 in instance 1
16337      *
16338      * Output to cluster log.
16339      */
16340     jam();
16341     Uint32 recordNo = RNIL;
16342     Uint32 instanceId = RNIL;
16343     if (signal->getLength() == 3)
16344     {
16345       recordNo = dumpState->args[1];
16346       instanceId = dumpState->args[2];
16347     }
16348     else
16349     {
16350       return;
16351     }
16352     if (instanceId != instance())
16353     {
16354       return;
16355     }
16356     if (unlikely(recordNo >= RNIL))
16357     {
16358       return;
16359     }
16360 
16361     ScanFragRecPtr sfp;
16362     sfp.i = recordNo;
16363     if (c_scan_frag_pool.getValidPtr(sfp))
16364     {
16365       infoEvent("Dbtc::ScanFragRec[%d]: state=%d, lqhFragId=%u",
16366                   sfp.i,
16367                 sfp.p->scanFragState,
16368                 sfp.p->lqhScanFragId);
16369       infoEvent(" nodeid=%d, timer=%d",
16370                 refToNode(sfp.p->lqhBlockref),
16371                 sfp.p->scanFragTimer);
16372     }
16373     return;
16374   }
16375 
16376   // Dump set of ScanRecords
16377   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfScanRec){
16378     /**
16379      * DUMP 2502 12 10 1 1
16380      * Print Scan records 12 through 21 in instance 1
16381      * Last parameter == 0 indicates that we will print all
16382      * records, otherwise we will only print active scan records.
16383      * Last parameter is defaulting to 1 if not provided
16384      *
16385      * Output to the cluster log
16386      */
16387     jam();
16388     Uint32 recordNo = 0;
16389     Uint32 numRecords = 0;
16390     Uint32 instanceId = 0;
16391     Uint32 includeOnlyActive = 1;
16392 
16393     if (signal->getLength() >= 4)
16394     {
16395       recordNo = dumpState->args[1];
16396       numRecords = dumpState->args[2];
16397       instanceId = dumpState->args[3];
16398       if (signal->getLength() >= 5)
16399       {
16400         includeOnlyActive = dumpState->args[4];
16401       }
16402     }
16403     else
16404     {
16405       return;
16406     }
16407     if (instance() != instanceId)
16408     {
16409       return;
16410     }
16411     if (numRecords > MAX_RECORDS_AT_A_TIME)
16412     {
16413       numRecords = MAX_RECORDS_AT_A_TIME;
16414     }
16415     if (recordNo >= cscanrecFileSize)
16416     {
16417       return;
16418     }
16419 
16420     for (; numRecords > 0 && recordNo != RNIL; numRecords--)
16421     {
16422       ScanRecordPtr sp;
16423       if (unlikely(scanRecordPool.getUncheckedPtrs(&recordNo, &sp, 1) != 1))
16424       {
16425         continue;
16426       }
16427       if (!Magic::match(sp.p->m_magic, ScanRecord::TYPE_ID))
16428       {
16429         continue;
16430       }
16431       if (sp.p->scanState != ScanRecord::IDLE ||
16432           !includeOnlyActive)
16433       {
16434         dumpState->args[0] = DumpStateOrd::TcDumpOneScanRec;
16435         dumpState->args[1] = recordNo;
16436         dumpState->args[2] = instance();
16437         signal->setLength(3);
16438         execDUMP_STATE_ORD(signal);
16439       }
16440     }
16441     if (recordNo != RNIL && numRecords > 0)
16442     {
16443       dumpState->args[0] = DumpStateOrd::TcDumpSetOfScanRec;
16444       dumpState->args[1] = recordNo;
16445       dumpState->args[2] = numRecords;
16446       dumpState->args[3] = instance();
16447       dumpState->args[4] = includeOnlyActive;
16448       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
16449     }
16450     return;
16451   }
16452 
16453   // Dump one ScanRecord
16454   // and associated ScanFragRec and ApiConnectRecord
16455   if (dumpState->args[0] == DumpStateOrd::TcDumpOneScanRec){
16456     /**
16457      * DUMP 2504 12 1
16458      * This will print ScanRecord 12 in instance 1 and all associated
16459      * ScanFrag records and ApiConnect records.
16460      *
16461      * It is necessary to provide both record number and instance id
16462      * to get anything printed using this dump command.
16463      */
16464     jam();
16465     Uint32 recordNo = RNIL;
16466     Uint32 instanceId = 0;
16467     if (signal->getLength() == 3)
16468     {
16469       recordNo = dumpState->args[1];
16470       instanceId = dumpState->args[2];
16471     }
16472     else
16473     {
16474       return;
16475     }
16476     if (instanceId != instance())
16477     {
16478       return;
16479     }
16480     if (recordNo == RNIL)
16481     {
16482       return;
16483     }
16484     ScanRecordPtr sp;
16485     if (unlikely(scanRecordPool.getUncheckedPtrs(&recordNo, &sp, 1) != 1))
16486     {
16487       return;
16488     }
16489 
16490     infoEvent("Dbtc::ScanRecord[%d]: state=%d, "
16491 	      "nextfrag=%d, nofrag=%d",
16492 	      sp.i,
16493 	      sp.p->scanState,
16494 	      sp.p->scanNextFragId,
16495 	      sp.p->scanNoFrag);
16496     infoEvent(" para=%d, receivedop=%d, noOprecPerFrag=%d",
16497 	      sp.p->scanParallel,
16498 	      sp.p->scanReceivedOperations,
16499 	      sp.p->batch_size_rows);
16500     infoEvent(" schv=%d, tab=%d, sproc=%d",
16501 	      sp.p->scanSchemaVersion,
16502 	      sp.p->scanTableref,
16503 	      sp.p->scanStoredProcId);
16504     infoEvent(" apiRec=%d",
16505               sp.p->scanApiRec);
16506 
16507     if (sp.p->scanState != ScanRecord::IDLE){
16508       // Request dump of ScanFragRec
16509       ScanFragRecPtr sfptr;
16510 #define DUMP_SFR(x){\
16511       Local_ScanFragRec_dllist list(c_scan_frag_pool, x);\
16512       for(list.first(sfptr); !sfptr.isNull(); list.next(sfptr)){\
16513 	dumpState->args[0] = DumpStateOrd::TcDumpOneScanFragRec; \
16514 	dumpState->args[1] = sfptr.i;\
16515         dumpState->args[2] = instance(); \
16516         signal->setLength(3); \
16517 	execDUMP_STATE_ORD(signal);\
16518       }}
16519 
16520       DUMP_SFR(sp.p->m_running_scan_frags);
16521       DUMP_SFR(sp.p->m_queued_scan_frags);
16522       DUMP_SFR(sp.p->m_delivered_scan_frags);
16523 
16524       // Request dump of ApiConnectRecord
16525       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
16526       dumpState->args[1] = sp.p->scanApiRec;
16527       dumpState->args[2] = instance();
16528       signal->setLength(3);
16529       execDUMP_STATE_ORD(signal);
16530     }
16531     return;
16532   }
16533 
16534   // Dump Set of TcConnectRecord(s)
16535   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfTcConnectRec)
16536   {
16537     /**
16538      * DUMP 2517 12 10 1 1
16539      * This will print recordNo from 12 to 21 in instance 1 (first
16540      * instance is number since instance 0 is the DBTC Proxy instance).
16541      * We will not print records that doesn't exist. The last parameter
16542      * indicates whether to include only active records or if we should
16543      * include all records. This last parameter defaults to 1 which means
16544      * we are only printing information about active records.
16545      *
16546      * It is necessary to specify record number, number of records
16547      * and instance id to get anything printed.
16548      *
16549      * Use this DUMP command with care and avoid printing more than
16550      * 10 records per dump command in production systems to avoid
16551      * overloading any parts of the system. Also print from instance
16552      * at a time since otherwise it will be almost impossible to know
16553      * which instance have generated what printout.
16554      *
16555      * The printouts will end up in the cluster log.
16556      */
16557     jam();
16558     Uint32 recordNo = RNIL;
16559     Uint32 instanceId = RNIL;
16560     Uint32 numRecords = 1;
16561     Uint32 includeOnlyActive = 1;
16562 
16563     if (signal->getLength() >= 4)
16564     {
16565       recordNo = dumpState->args[1];
16566       numRecords = dumpState->args[2];
16567       instanceId = dumpState->args[3];
16568       if (signal->getLength() >= 5)
16569       {
16570         includeOnlyActive = dumpState->args[4];
16571       }
16572     }
16573     else
16574     {
16575       return;
16576     }
16577     if (instanceId != instance())
16578     {
16579       return;
16580     }
16581     if (numRecords > MAX_RECORDS_AT_A_TIME)
16582     {
16583       numRecords = MAX_RECORDS_AT_A_TIME;
16584     }
16585 
16586     TcConnectRecordPtr tc;
16587     tc.i = recordNo;
16588     if (tcConnectRecord.getValidPtr(tc))
16589     {
16590       if (tc.p->tcConnectstate != OS_CONNECTED ||
16591           !includeOnlyActive)
16592       {
16593         dumpState->args[0] = DumpStateOrd::TcDumpOneTcConnectRec;
16594         dumpState->args[1] = recordNo;
16595         dumpState->args[2] = instanceId;
16596         signal->setLength(3);
16597         execDUMP_STATE_ORD(signal);
16598       }
16599     }
16600 
16601     numRecords--;
16602     recordNo++;
16603     if (numRecords > 0)
16604     {
16605       (void) tcConnectRecord.getUncheckedPtrs(&recordNo, &tc, 1);
16606       if (recordNo != RNIL)
16607       {
16608         dumpState->args[0] = DumpStateOrd::TcDumpSetOfTcConnectRec;
16609         dumpState->args[1] = recordNo;
16610         dumpState->args[2] = numRecords;
16611         dumpState->args[3] = instanceId;
16612         dumpState->args[4] = includeOnlyActive;
16613         sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
16614       }
16615     }
16616     return;
16617   }
16618 
16619   // Dump one TcConnectRecord
16620   if (dumpState->args[0] == DumpStateOrd::TcDumpOneTcConnectRec)
16621   {
16622     /**
16623      * This part is mostly used as an assistant function to dump a range
16624      * of TcConnect records. It can also be invoked directly in
16625      * the following manner.
16626      *
16627      * DUMP 2516 12 1
16628      * Record 12 will be printed in instance 1
16629      */
16630     jam();
16631     Uint32 recordNo = RNIL;
16632     Uint32 instanceId = RNIL;
16633     if (signal->getLength() == 3)
16634     {
16635       recordNo = dumpState->args[1];
16636       instanceId = dumpState->args[2];
16637     }
16638     else
16639     {
16640       return;
16641     }
16642     if (instanceId != instance())
16643     {
16644       return;
16645     }
16646 
16647     TcConnectRecordPtr tc;
16648     tc.i = recordNo;
16649     if (!tcConnectRecord.getValidPtr(tc))
16650     {
16651       return;
16652     }
16653     infoEvent("Dbtc::TcConnectRecord[%d]: state=%d, apiCon=%d, "
16654 	      "commitAckMarker=%d",
16655 	      tc.i,
16656 	      tc.p->tcConnectstate,
16657 	      tc.p->apiConnect,
16658 	      tc.p->commitAckMarker);
16659     infoEvent(" special flags=%x, noOfNodes=%d, operation=%d",
16660 	      tc.p->m_special_op_flags,
16661 	      tc.p->noOfNodes,
16662 	      tc.p->operation);
16663     infoEvent(" clientData=%d, savePointId=%d, nodes(%d,%d,%d,%d), ",
16664 	      tc.p->clientData,
16665 	      tc.p->savePointId,
16666               tc.p->tcNodedata[0],
16667               tc.p->tcNodedata[1],
16668               tc.p->tcNodedata[2],
16669               tc.p->tcNodedata[3]);
16670     infoEvent(" next=%d, instance=%u ",
16671               tc.p->nextList,
16672               instance());
16673     return;
16674   }
16675 
16676   // Dump Set of ApiConnectRecord(s)
16677   if (dumpState->args[0] == DumpStateOrd::TcDumpSetOfApiConnectRec)
16678   {
16679     /**
16680      * Print a range of ApiConnect records
16681      * This command is invoked by the following DUMP command:
16682      * DUMP 2515 12 2 1
16683      * Print ApiConnect record 12 through 13 in instance 1
16684      *
16685      * The output will end up in the cluster log.
16686      *
16687      * WARNING: Don't print more than at most 10 records at a time
16688      * in a production system.
16689      * Use the full set of parameters such that we also specify the
16690      * instance id. This is necessary to know what is actually printed
16691      * since the printout from instance 1 and instance 2 doesn't
16692      * differ.
16693      */
16694     jam();
16695     Uint32 recordNo = RNIL;
16696     Uint32 instanceId = RNIL;
16697     Uint32 numRecords = 1;
16698     Uint32 includeOnlyActive = 1;
16699 
16700     if (signal->getLength() >= 4)
16701     {
16702       recordNo = dumpState->args[1];
16703       numRecords = dumpState->args[2];
16704       instanceId = dumpState->args[3];
16705       if (signal->getLength() >= 5)
16706       {
16707         includeOnlyActive = dumpState->args[4];
16708       }
16709     }
16710     else
16711     {
16712       return;
16713     }
16714     if (instanceId != instance())
16715     {
16716       return;
16717     }
16718 
16719     ApiConnectRecordPtr ap;
16720     ap.i = recordNo;
16721     if (!c_apiConnectRecordPool.getValidPtr(ap))
16722     {
16723       return;
16724     }
16725 
16726     if (!includeOnlyActive ||
16727         ((ap.p->apiConnectstate != CS_CONNECTED) &&
16728            (ap.p->apiConnectstate != CS_ABORTING ||
16729             ap.p->abortState != AS_IDLE)))
16730     {
16731       dumpState->args[0] = DumpStateOrd::TcDumpOneApiConnectRec;
16732       dumpState->args[1] = recordNo;
16733       dumpState->args[2] = instanceId;
16734       signal->setLength(3);
16735       execDUMP_STATE_ORD(signal);
16736     }
16737 
16738     numRecords--;
16739     (void) c_apiConnectRecordPool.getUncheckedPtrs(&recordNo, &ap, 1);
16740     if (recordNo != RNIL && numRecords > 0)
16741     {
16742       dumpState->args[0] = DumpStateOrd::TcDumpSetOfApiConnectRec;
16743       dumpState->args[1] = recordNo;
16744       dumpState->args[2] = numRecords;
16745       dumpState->args[3] = instanceId;
16746       dumpState->args[4] = includeOnlyActive;
16747       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
16748     }
16749     return;
16750   }
16751 
16752   // Dump one ApiConnectRecord
16753   if (dumpState->args[0] == DumpStateOrd::TcDumpOneApiConnectRec){
16754     /**
16755      * Print one ApiConnect record.
16756      * This is a support function to DUMP 2515. It can also
16757      * be used directly using the following command.
16758      *
16759      * DUMP 2505 12 1
16760      * Print ApiConnect record 12 in instance 1
16761      *
16762      * The output will be printed to the cluster log.
16763      */
16764     jam();
16765     Uint32 recordNo = RNIL;
16766     Uint32 instanceId = RNIL;
16767     if (signal->getLength() == 3)
16768     {
16769       recordNo = dumpState->args[1];
16770       instanceId = dumpState->args[2];
16771     }
16772     else
16773     {
16774       return;
16775     }
16776 
16777     ApiConnectRecordPtr ap;
16778     ap.i = recordNo;
16779     if (!c_apiConnectRecordPool.getValidPtr(ap))
16780     {
16781       return;
16782     }
16783     if (instanceId != instance())
16784     {
16785       return;
16786     }
16787 
16788     infoEvent("Dbtc::c_apiConnectRecordPool.getPtr(%d): state=%d, abortState=%d, "
16789 	      "apiFailState=%d",
16790 	      ap.i,
16791 	      ap.p->apiConnectstate,
16792 	      ap.p->abortState,
16793 	      ap.p->apiFailState);
16794     infoEvent(" transid(0x%x, 0x%x), apiBref=0x%x, scanRec=%d",
16795 	      ap.p->transid[0],
16796 	      ap.p->transid[1],
16797 	      ap.p->ndbapiBlockref,
16798 	      ap.p->apiScanRec);
16799     infoEvent(" ctcTimer=%d, apiTimer=%d, counter=%d, retcode=%d, "
16800 	      "retsig=%d",
16801               ctcTimer, getApiConTimer(ap),
16802 	      ap.p->counter,
16803 	      ap.p->returncode,
16804 	      ap.p->returnsignal);
16805     infoEvent(" lqhkeyconfrec=%d, lqhkeyreqrec=%d, "
16806 	      "tckeyrec=%d",
16807 	      ap.p->lqhkeyconfrec,
16808 	      ap.p->lqhkeyreqrec,
16809 	      ap.p->tckeyrec);
16810     infoEvent(" next=%d, instance=%u, firstTc=%d ",
16811 	      ap.p->nextApiConnect,
16812               instance(),
16813               ap.p->tcConnect.getFirst());
16814     return;
16815   }
16816 
16817   if (dumpState->args[0] == DumpStateOrd::TcDumpApiConnectRecSummary)
16818   {
16819     /**
16820      * This DUMP command is used to print a summary of ApiConnect record
16821      * connected to API nodes.
16822      * The following use of it is allowed:
16823      * DUMP 2514 1
16824      * This will print a summary of all ApiConnect records in instance 1
16825      *
16826      * Output is to the node log.
16827      */
16828     jam();
16829     Uint32 apiNode = 1;
16830     Uint32 pos = 0;
16831 
16832     Uint32 seized_count = 0;      /* Number seized by an Api */
16833     Uint32 stateless_count = 0;   /* Number 'started' with no ops */
16834     Uint32 stateful_count = 0;    /* Number running */
16835     Uint32 scan_count = 0;        /* Number used for scans */
16836 
16837     if (signal->getLength() == 2)
16838     {
16839       if (instance() != dumpState->args[1])
16840       {
16841         return;
16842       }
16843       ndbout_c("Start of ApiConnectRec summary (%u total allocated)",
16844                c_apiConnectRecordPool.getSize());
16845       /*
16846        * total allocated = MaxNoOfConcurrentTransactions
16847        * total allocated = unseized + SUM_over_Api_nodes(seized)
16848        *   unseized can be seized by any Api node
16849        *   seized are 'owned' by a particular api node, can't be used
16850        *     by others until they are manually released.
16851        * seized = seized_unused + stateless + stateful + scan
16852        *   seized_unused are 'idle' connection objects owned by an
16853        *     api node.
16854        *   stateless are potentially idle connection objects, last
16855        *     used in a TC-stateless operation (e.g. read committed)
16856        *   stateful are in use, handling some transaction
16857        *   scan are in use, handling a table or index scan
16858        */
16859     }
16860     else if (signal->getLength() == 7)
16861     {
16862       apiNode = dumpState->args[1];
16863       pos = dumpState->args[2];
16864       seized_count = dumpState->args[3];
16865       stateless_count = dumpState->args[4];
16866       stateful_count = dumpState->args[5];
16867       scan_count = dumpState->args[6];
16868     }
16869     else
16870     {
16871       return;
16872     }
16873 
16874     if (apiNode == 0)
16875       return;
16876 
16877     while (apiNode < MAX_NODES)
16878     {
16879       if (getNodeInfo(apiNode).getType() == NODE_TYPE_API &&
16880           getNodeInfo(apiNode).m_version != 0)
16881       {
16882         break;
16883       }
16884       apiNode ++;
16885     }
16886 
16887     if (apiNode >= MAX_NODES)
16888     {
16889       ndbout_c("End of ApiConnectRec summary");
16890       return;
16891     }
16892 
16893     for (int laps = 0; laps < 16 && pos != RNIL; laps++)
16894     {
16895       ApiConnectRecordPtr apiConnectptr;
16896       if (c_apiConnectRecordPool.getUncheckedPtrs(&pos, &apiConnectptr, 1) == 0)
16897       {
16898         continue;
16899       }
16900       if (!Magic::match(apiConnectptr.p->m_magic, ApiConnectRecord::TYPE_ID))
16901       {
16902         continue;
16903       }
16904       if (apiConnectptr.p->apiConnectkind != ApiConnectRecord::CK_USER)
16905       {
16906         continue;
16907       }
16908       /* Following code mostly similar to that for NdbInfo transactions table */
16909       Uint32 conState = apiConnectptr.p->apiConnectstate;
16910 
16911       if (conState == CS_ABORTING && apiConnectptr.p->abortState == AS_IDLE)
16912       {
16913         /**
16914          * These is for all practical purposes equal
16915          */
16916         conState = CS_CONNECTED;
16917       }
16918 
16919       if ((refToNode(apiConnectptr.p->ndbapiBlockref) == apiNode) &&
16920           (conState != CS_DISCONNECTED))
16921       {
16922         seized_count++;
16923 
16924         if (conState == CS_STARTED &&
16925             apiConnectptr.p->lqhkeyreqrec == 0)
16926         {
16927           stateless_count++;
16928         }
16929         else if (conState == CS_START_SCAN)
16930         {
16931           scan_count++;
16932         }
16933         else if (conState != CS_CONNECTED)
16934         {
16935           stateful_count++;
16936         }
16937       }
16938     }
16939 
16940     if (pos == RNIL)
16941     {
16942       /* Finished with this apiNode, output info, if any */
16943 //      if (seized_count > 0)
16944       {
16945         ndbout_c("  Api node %u connect records seized : %u stateless : %u stateful : %u scan : %u",
16946                  apiNode, seized_count, stateless_count, stateful_count, scan_count);
16947         seized_count = 0;
16948         stateless_count = 0;
16949         stateful_count = 0;
16950         scan_count = 0;
16951       }
16952 
16953       apiNode++;
16954       pos = 0;
16955     }
16956 
16957     signal->theData[0] = DumpStateOrd::TcDumpApiConnectRecSummary;
16958     signal->theData[1] = apiNode;
16959     signal->theData[2] = pos;
16960     signal->theData[3] = seized_count;
16961     signal->theData[4] = stateless_count;
16962     signal->theData[5] = stateful_count;
16963     signal->theData[6] = scan_count;
16964 
16965     sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 7, JBB);
16966     return;
16967   }
16968 
16969   if (dumpState->args[0] == DumpStateOrd::TcSetTransactionTimeout){
16970     jam();
16971     if(signal->getLength() > 1){
16972       set_timeout_value(signal->theData[1]);
16973     }
16974     else
16975     {
16976       /* Reset to configured value */
16977       const ndb_mgm_configuration_iterator * p =
16978         m_ctx.m_config.getOwnConfigIterator();
16979       ndbrequire(p != 0);
16980 
16981       Uint32 val = 3000;
16982       ndb_mgm_get_int_parameter(p, CFG_DB_TRANSACTION_DEADLOCK_TIMEOUT, &val);
16983       set_timeout_value(val);
16984     }
16985   }
16986 
16987   if (dumpState->args[0] == DumpStateOrd::TcSetApplTransactionTimeout){
16988     jam();
16989     if(signal->getLength() > 1){
16990       set_appl_timeout_value(signal->theData[1]);
16991     }
16992   }
16993 
16994   if (dumpState->args[0] == DumpStateOrd::TcStartDumpIndexOpCount)
16995   {
16996     static int frequency = 1;
16997     if (signal->getLength() > 1)
16998       frequency = signal->theData[1];
16999     else
17000       if (refToBlock(signal->getSendersBlockRef()) != DBTC)
17001 	frequency = 1;
17002 
17003     if (frequency)
17004     {
17005       dumpState->args[0] = DumpStateOrd::TcDumpIndexOpCount;
17006       execDUMP_STATE_ORD(signal);
17007       dumpState->args[0] = DumpStateOrd::TcStartDumpIndexOpCount;
17008 
17009       Uint32 delay = 1000 * (frequency > 25 ? 25 : frequency);
17010       sendSignalWithDelay(cownref, GSN_DUMP_STATE_ORD, signal, delay, 1);
17011     }
17012   }
17013 
17014   if (dumpState->args[0] == DumpStateOrd::TcDumpIndexOpCount)
17015   {
17016     infoEvent("instance: %u, IndexOpCount: pool: %d free: %d",
17017               instance(),
17018 	      c_theIndexOperationPool.getSize(),
17019 	      c_theIndexOperationPool.getNoOfFree());
17020     return;
17021   }
17022 
17023   if (arg == 2550)
17024   {
17025     jam();
17026     Uint32 len = signal->getLength() - 1;
17027     if (len + 2 > 25)
17028     {
17029       jam();
17030       infoEvent("Too long filter");
17031       return;
17032     }
17033     if (validate_filter(signal))
17034     {
17035       jam();
17036       memmove(signal->theData + 2, signal->theData + 1, 4 * len);
17037       signal->theData[0] = 2551;
17038       signal->theData[1] = 0;    // record
17039       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len + 2, JBB);
17040 
17041       infoEvent("Starting dump of transactions");
17042     }
17043     return;
17044   }
17045   if (arg == 2551)
17046   {
17047     jam();
17048     Uint32 len = signal->getLength();
17049     ndbassert(len > 1);
17050     Uint32 record = signal->theData[1];
17051 
17052     bool print = false;
17053     for (Uint32 i = 0; i < 32 && record != RNIL; i++)
17054     {
17055       jam();
17056       ApiConnectRecordPtr ap;
17057       if (c_apiConnectRecordPool.getUncheckedPtrs(&record, &ap, 1) != 1)
17058       {
17059         continue;
17060       }
17061       if (!Magic::match(ap.p->m_magic, ApiConnectRecord::TYPE_ID))
17062       {
17063         continue;
17064       }
17065       print = match_and_print(signal, ap);
17066 
17067       if (print)
17068       {
17069 	jam();
17070 	break;
17071       }
17072     }
17073 
17074     if (record == RNIL)
17075     {
17076       jam();
17077       infoEvent("End of transaction dump");
17078       return;
17079     }
17080 
17081     signal->theData[1] = record;
17082     if (print)
17083     {
17084       jam();
17085       sendSignalWithDelay(reference(), GSN_DUMP_STATE_ORD, signal, 200, len);
17086     }
17087     else
17088     {
17089       jam();
17090       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, len, JBB);
17091     }
17092     return;
17093   }
17094 #ifdef ERROR_INSERT
17095   if (arg == 2552 || arg == 4002 || arg == 4003)
17096   {
17097     ndbrequire(m_commitAckMarkerPool.getNoOfFree() == m_commitAckMarkerPool.getSize());
17098     return;
17099   }
17100 #endif
17101   if (arg == DumpStateOrd::DihTcSumaNodeFailCompleted &&
17102       signal->getLength() == 2)
17103   {
17104     jam();
17105     NodeId nodeId = signal->theData[1];
17106     if (nodeId < MAX_NODES && nodeId < NDB_ARRAY_SIZE(capiConnectClosing))
17107     {
17108       warningEvent(" DBTC: capiConnectClosing[%u]: %u",
17109                    nodeId, capiConnectClosing[nodeId]);
17110     }
17111     else
17112     {
17113       warningEvent(" DBTC: dump-%u to unknown node: %u", arg, nodeId);
17114     }
17115   }
17116 
17117   if (arg == DumpStateOrd::TcResourceSnapshot)
17118   {
17119     RSS_OP_SNAPSHOT_SAVE(cConcScanCount);
17120     RSS_AP_SNAPSHOT_SAVE(c_scan_frag_pool);
17121     RSS_AP_SNAPSHOT_SAVE(c_theDefinedTriggerPool);
17122     RSS_AP_SNAPSHOT_SAVE(c_theFiredTriggerPool);
17123     RSS_AP_SNAPSHOT_SAVE(c_theIndexPool);
17124     RSS_AP_SNAPSHOT_SAVE(m_commitAckMarkerPool);
17125     RSS_AP_SNAPSHOT_SAVE(c_theIndexOperationPool);
17126 #ifdef ERROR_INSERT
17127     rss_cconcurrentOp = c_counters.cconcurrentOp;
17128 #endif
17129     // Below not tested in 7.6.6 and earlier
17130     // ApiConnectRecord and ApiConTimers excluded since API never releases
17131     // those while connected
17132     RSS_AP_SNAPSHOT_SAVE(c_theAttributeBufferPool);
17133     RSS_AP_SNAPSHOT_SAVE(c_theCommitAckMarkerBufferPool);
17134     RSS_AP_SNAPSHOT_SAVE(m_fragLocationPool);
17135     RSS_AP_SNAPSHOT_SAVE(c_cacheRecordPool);
17136   }
17137   if (arg == DumpStateOrd::TcResourceCheckLeak)
17138   {
17139     RSS_OP_SNAPSHOT_CHECK(cConcScanCount);
17140     RSS_AP_SNAPSHOT_CHECK(c_scan_frag_pool);
17141     RSS_AP_SNAPSHOT_CHECK(c_theDefinedTriggerPool);
17142     RSS_AP_SNAPSHOT_CHECK(c_theFiredTriggerPool);
17143     RSS_AP_SNAPSHOT_CHECK(c_theIndexPool);
17144     RSS_AP_SNAPSHOT_CHECK(m_commitAckMarkerPool);
17145     RSS_AP_SNAPSHOT_CHECK(c_theIndexOperationPool);
17146 #ifdef ERROR_INSERT
17147     ndbrequire(rss_cconcurrentOp == c_counters.cconcurrentOp);
17148 #endif
17149     RSS_AP_SNAPSHOT_CHECK(c_theAttributeBufferPool);
17150     RSS_AP_SNAPSHOT_CHECK(c_theCommitAckMarkerBufferPool);
17151     RSS_AP_SNAPSHOT_CHECK(m_fragLocationPool);
17152     RSS_AP_SNAPSHOT_CHECK(c_cacheRecordPool);
17153   }
17154 
17155   if (arg == DumpStateOrd::TcDumpPoolLevels)
17156   {
17157     /**
17158      * DUMP 2555 1
17159      * Prints pool levels for instance 1 to cluster log
17160      */
17161     if (signal->getLength() == 2)
17162     {
17163       if (signal->theData[1] != instance())
17164       {
17165         return;
17166       }
17167       infoEvent("TC: instance: %u, Print pool levels", instance());
17168       signal->theData[4] = signal->theData[1];
17169       signal->theData[1] = 1;
17170       signal->theData[2] = 0;
17171       signal->theData[3] = 0;
17172       sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
17173       return;
17174     }
17175     if (signal->getLength() != 5)
17176     {
17177       ndbout_c("DUMP TcDumpPoolLevels : Bad signal length : %u", signal->getLength());
17178       return;
17179     }
17180     if (signal->theData[4] != instance())
17181     {
17182       return;
17183     }
17184 
17185     Uint32 resource = signal->theData[1];
17186     Uint32 position = signal->theData[2];
17187     Uint32 sum = signal->theData[3];
17188     /* const Uint32 MAX_ITER = 200; */
17189 
17190     switch(resource)
17191     {
17192     case 1:
17193       infoEvent("TC : Concurrent operations in use/total : %u/%u (%u bytes each)",
17194                 c_counters.cconcurrentOp,
17195                 tcConnectRecord.getSize(),
17196                 (Uint32) sizeof(TcConnectRecord));
17197       resource++;
17198       position = 0;
17199       sum = 0;
17200       break;
17201     case 2:
17202       infoEvent("TC : Concurrent scans in use/total : %u/%u (%u bytes each)",
17203                 cConcScanCount,
17204                 cscanrecFileSize,
17205                 (Uint32) sizeof(ScanRecord));
17206       resource++;
17207       position = 0;
17208       sum = 0;
17209       break;
17210     case 3:
17211       infoEvent("TC : Scan Frag records in use/total : %u/%u (%u bytes each)",
17212                 c_scan_frag_pool.getSize() -
17213                 c_scan_frag_pool.getNoOfFree(),
17214                 c_scan_frag_pool.getSize(),
17215                 (Uint32) sizeof(ScanFragRec));
17216       resource++;
17217       position = 0;
17218       sum = 0;
17219       break;
17220     default:
17221       return;
17222     }
17223 
17224     signal->theData[0] = DumpStateOrd::TcDumpPoolLevels;
17225     signal->theData[1] = resource;
17226     signal->theData[2] = position;
17227     signal->theData[3] = sum;
17228     signal->theData[4] = instance();
17229     sendSignal(reference(), GSN_DUMP_STATE_ORD, signal, 5, JBB);
17230     return;
17231   }
17232 
17233 #if defined(VM_TRACE) || defined(ERROR_INSERT)
17234   if (arg == DumpStateOrd::TcSetTransientPoolMaxSize)
17235   {
17236     jam();
17237     if (signal->getLength() < 3)
17238       return;
17239     const Uint32 pool_index = signal->theData[1];
17240     const Uint32 new_size = signal->theData[2];
17241     if (pool_index >= c_transient_pool_count)
17242       return;
17243     c_transient_pools[pool_index]->setMaxSize(new_size);
17244     if (pool_index == DBTC_SCAN_RECORD_TRANSIENT_POOL_INDEX)
17245     {
17246       cscanrecFileSize = new_size;
17247     }
17248   }
17249   if (arg == DumpStateOrd::TcResetTransientPoolMaxSize)
17250   {
17251     jam();
17252     if(signal->getLength() < 2)
17253       return;
17254     const Uint32 pool_index = signal->theData[1];
17255     if (pool_index >= c_transient_pool_count)
17256       return;
17257     c_transient_pools[pool_index]->resetMaxSize();
17258     if (pool_index == DBTC_SCAN_RECORD_TRANSIENT_POOL_INDEX)
17259     {
17260       cscanrecFileSize = cscanrecFileSize_original;
17261     }
17262   }
17263 #endif
17264 }//Dbtc::execDUMP_STATE_ORD()
17265 
execDBINFO_SCANREQ(Signal * signal)17266 void Dbtc::execDBINFO_SCANREQ(Signal *signal)
17267 {
17268   DbinfoScanReq req= *(DbinfoScanReq*)signal->theData;
17269   const Ndbinfo::ScanCursor* cursor =
17270     CAST_CONSTPTR(Ndbinfo::ScanCursor, DbinfoScan::getCursorPtr(&req));
17271   Ndbinfo::Ratelimit rl;
17272 
17273   jamEntry();
17274 
17275   switch(req.tableId){
17276   case Ndbinfo::POOLS_TABLEID:
17277   {
17278     Ndbinfo::pool_entry pools[] =
17279     {
17280       { "API Connect",
17281         c_apiConnectRecordPool.getUsed(),
17282         c_apiConnectRecordPool.getSize(),
17283         c_apiConnectRecordPool.getEntrySize(),
17284         c_apiConnectRecordPool.getUsedHi(),
17285         { 0, 0, 0, 0},
17286         RT_DBTC_API_CONNECT_RECORD},
17287       { "API Connect Timer",
17288         c_apiConTimersPool.getUsed(),
17289         c_apiConTimersPool.getSize(),
17290         c_apiConTimersPool.getEntrySize(),
17291         c_apiConTimersPool.getUsedHi(),
17292         { 0, 0, 0, 0},
17293         RT_DBTC_API_CONNECT_TIMERS},
17294       { "Cache Record",
17295         c_cacheRecordPool.getUsed(),
17296         c_cacheRecordPool.getSize(),
17297         c_cacheRecordPool.getEntrySize(),
17298         c_cacheRecordPool.getUsedHi(),
17299         { 0, 0, 0, 0},
17300         RT_DBTC_CACHE_RECORD},
17301       { "Defined Trigger",
17302         c_theDefinedTriggerPool.getUsed(),
17303         c_theDefinedTriggerPool.getSize(),
17304         c_theDefinedTriggerPool.getEntrySize(),
17305         c_theDefinedTriggerPool.getUsedHi(),
17306         { CFG_DB_NO_TRIGGERS, 0, 0, 0 },
17307         0},
17308       { "Fired Trigger",
17309         c_theFiredTriggerPool.getUsed(),
17310         c_theFiredTriggerPool.getSize(),
17311         c_theFiredTriggerPool.getEntrySize(),
17312         c_theFiredTriggerPool.getUsedHi(),
17313         { CFG_DB_NO_TRIGGER_OPS, 0, 0, 0 },
17314         RT_DBTC_FIRED_TRIGGER_DATA},
17315       { "GCP Record",
17316         c_gcpRecordPool.getUsed(),
17317         c_gcpRecordPool.getSize(),
17318         c_gcpRecordPool.getEntrySize(),
17319         c_gcpRecordPool.getUsedHi(),
17320         { 0, 0, 0, 0},
17321         RT_DBTC_GCP_RECORD},
17322       { "Index",
17323         c_theIndexPool.getUsed(),
17324         c_theIndexPool.getSize(),
17325         c_theIndexPool.getEntrySize(),
17326         c_theIndexPool.getUsedHi(),
17327         { CFG_DB_NO_TABLES,
17328           CFG_DB_NO_ORDERED_INDEXES,
17329           CFG_DB_NO_UNIQUE_HASH_INDEXES, 0 },
17330         0},
17331       { "Scan Fragment",
17332         c_scan_frag_pool.getUsed(),
17333         c_scan_frag_pool.getSize(),
17334         c_scan_frag_pool.getEntrySize(),
17335         c_scan_frag_pool.getUsedHi(),
17336         { CFG_DB_NO_LOCAL_SCANS, 0, 0, 0 },
17337         RT_DBTC_SCAN_FRAGMENT},
17338       { "Scan Fragment Location",
17339         m_fragLocationPool.getUsed(),
17340         m_fragLocationPool.getSize(),
17341         m_fragLocationPool.getEntrySize(),
17342         m_fragLocationPool.getUsedHi(),
17343         { 0, 0, 0, 0 },
17344         RT_DBTC_FRAG_LOCATION},
17345       { "Commit ACK Marker",
17346         m_commitAckMarkerPool.getUsed(),
17347         m_commitAckMarkerPool.getSize(),
17348         m_commitAckMarkerPool.getEntrySize(),
17349         m_commitAckMarkerPool.getUsedHi(),
17350         { CFG_DB_NO_TRANSACTIONS, 0, 0, 0 },
17351         RT_DBTC_COMMIT_ACK_MARKER},
17352       { "Commit ACK Marker Buffer",
17353         c_theCommitAckMarkerBufferPool.getUsed(),
17354         c_theCommitAckMarkerBufferPool.getSize(),
17355         c_theCommitAckMarkerBufferPool.getEntrySize(),
17356         c_theCommitAckMarkerBufferPool.getUsedHi(),
17357         { 0, 0, 0, 0 },
17358         RT_DBTC_COMMIT_ACK_MARKER_BUFFER},
17359       { "Index Op",
17360         c_theIndexOperationPool.getUsed(),
17361         c_theIndexOperationPool.getSize(),
17362         c_theIndexOperationPool.getEntrySize(),
17363         c_theIndexOperationPool.getUsedHi(),
17364         { 0, 0, 0, 0 },
17365         RT_DBTC_INDEX_OPERATION},
17366       { "Operations",
17367         tcConnectRecord.getUsed(),
17368         tcConnectRecord.getSize(),
17369         tcConnectRecord.getEntrySize(),
17370         tcConnectRecord.getUsedHi(),
17371         { 0, 0, 0, 0 },
17372         RT_DBTC_CONNECT_RECORD},
17373       { "TC Scan Record",  /* TC redundantly included to improve readability */
17374         cConcScanCount,
17375         cscanrecFileSize,
17376         sizeof(ScanRecord),
17377         0, /* No HWM */
17378         {CFG_DB_NO_SCANS, 0, 0, 0},
17379         0},
17380       { NULL, 0, 0, 0, 0, {0, 0, 0, 0}, 0 }
17381     };
17382 
17383    const size_t num_config_params =
17384       sizeof(pools[0].config_params) / sizeof(pools[0].config_params[0]);
17385     Uint32 pool = cursor->data[0];
17386     BlockNumber bn = blockToMain(number());
17387     while(pools[pool].poolname)
17388     {
17389       jam();
17390       Ndbinfo::Row row(signal, req);
17391       row.write_uint32(getOwnNodeId());
17392       row.write_uint32(bn);           // block number
17393       row.write_uint32(instance());   // block instance
17394       row.write_string(pools[pool].poolname);
17395 
17396       row.write_uint64(pools[pool].used);
17397       row.write_uint64(pools[pool].total);
17398       row.write_uint64(pools[pool].used_hi);
17399       row.write_uint64(pools[pool].entry_size);
17400       for (size_t i = 0; i < num_config_params; i++)
17401         row.write_uint32(pools[pool].config_params[i]);
17402       row.write_uint32(GET_RG(pools[pool].record_type));
17403       row.write_uint32(GET_TID(pools[pool].record_type));
17404       ndbinfo_send_row(signal, req, row, rl);
17405       pool++;
17406       if (rl.need_break(req))
17407       {
17408         jam();
17409         ndbinfo_send_scan_break(signal, req, rl, pool);
17410         return;
17411       }
17412     }
17413     break;
17414   }
17415   case Ndbinfo::TC_TIME_TRACK_STATS_TABLEID:
17416   {
17417     Uint32 restore = cursor->data[0];
17418     HostRecordPtr hostPtr;
17419     Uint32 first_index = restore & 0xFFFF;
17420     hostPtr.i = restore >> 16;
17421     if (hostPtr.i == 0)
17422       hostPtr.i = 1;
17423     for ( ; hostPtr.i < MAX_NODES; hostPtr.i++)
17424     {
17425       ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
17426       if (hostPtr.p->time_tracked == FALSE)
17427         continue;
17428       for (Uint32 i = first_index; i < TIME_TRACK_HISTOGRAM_RANGES; i++)
17429       {
17430         Ndbinfo::Row row(signal, req);
17431         row.write_uint32(getOwnNodeId());
17432         row.write_uint32(DBTC);
17433         row.write_uint32(instance());
17434         row.write_uint32(hostPtr.i);
17435         row.write_uint64(c_time_track_histogram_boundary[i]);
17436         row.write_uint64(hostPtr.p->time_track_scan_histogram[i]);
17437         row.write_uint64(hostPtr.p->time_track_scan_error_histogram[i]);
17438         row.write_uint64(hostPtr.p->time_track_scan_frag_histogram[i]);
17439         row.write_uint64(hostPtr.p->time_track_scan_frag_error_histogram[i]);
17440         row.write_uint64(hostPtr.p->time_track_transaction_histogram[i]);
17441         row.write_uint64(hostPtr.p->time_track_transaction_error_histogram[i]);
17442         row.write_uint64(hostPtr.p->time_track_read_key_histogram[i]);
17443         row.write_uint64(hostPtr.p->time_track_write_key_histogram[i]);
17444         row.write_uint64(hostPtr.p->time_track_index_key_histogram[i]);
17445         row.write_uint64(hostPtr.p->time_track_key_error_histogram[i]);
17446         ndbinfo_send_row(signal, req, row, rl);
17447         if (rl.need_break(req))
17448         {
17449           Uint32 save = i + 1 + (hostPtr.i << 16);
17450           jam();
17451           ndbinfo_send_scan_break(signal, req, rl, save);
17452           return;
17453         }
17454       }
17455       first_index = 0;
17456     }
17457     break;
17458   }
17459   case Ndbinfo::COUNTERS_TABLEID:
17460   {
17461     Ndbinfo::counter_entry counters[] = {
17462       { Ndbinfo::ATTRINFO_COUNTER, c_counters.cattrinfoCount },
17463       { Ndbinfo::TRANSACTIONS_COUNTER, c_counters.ctransCount },
17464       { Ndbinfo::COMMITS_COUNTER, c_counters.ccommitCount },
17465       { Ndbinfo::READS_COUNTER, c_counters.creadCount },
17466       { Ndbinfo::SIMPLE_READS_COUNTER, c_counters.csimpleReadCount },
17467       { Ndbinfo::WRITES_COUNTER, c_counters.cwriteCount },
17468       { Ndbinfo::ABORTS_COUNTER, c_counters.cabortCount },
17469       { Ndbinfo::TABLE_SCANS_COUNTER, c_counters.c_scan_count },
17470       { Ndbinfo::RANGE_SCANS_COUNTER, c_counters.c_range_scan_count },
17471       { Ndbinfo::LOCAL_READ_COUNTER, c_counters.clocalReadCount },
17472       { Ndbinfo::LOCAL_WRITE_COUNTER, c_counters.clocalWriteCount }
17473     };
17474     const size_t num_counters = sizeof(counters) / sizeof(counters[0]);
17475 
17476     Uint32 i = cursor->data[0];
17477     BlockNumber bn = blockToMain(number());
17478     while(i < num_counters)
17479     {
17480       jam();
17481       Ndbinfo::Row row(signal, req);
17482       row.write_uint32(getOwnNodeId());
17483       row.write_uint32(bn);           // block number
17484       row.write_uint32(instance());   // block instance
17485       row.write_uint32(counters[i].id);
17486 
17487       row.write_uint64(counters[i].val);
17488       ndbinfo_send_row(signal, req, row, rl);
17489       i++;
17490       if (rl.need_break(req))
17491       {
17492         jam();
17493         ndbinfo_send_scan_break(signal, req, rl, i);
17494         return;
17495       }
17496     }
17497 
17498     break;
17499   }
17500   case Ndbinfo::TRANSACTIONS_TABLEID:
17501   {
17502     Uint32 loop_count = 0;
17503     Uint32 api_ptr = cursor->data[0];
17504     const Uint32 maxloop = 256;
17505     bool do_break = false;
17506     while (!do_break &&
17507            api_ptr != RNIL &&
17508            loop_count < maxloop)
17509     {
17510       ApiConnectRecordPtr ptrs[8];
17511       Uint32 ptr_cnt =
17512           c_apiConnectRecordPool.getUncheckedPtrs(&api_ptr,
17513                                                   ptrs,
17514                                                   NDB_ARRAY_SIZE(ptrs)); // TODO respect #loops left
17515       loop_count += NDB_ARRAY_SIZE(ptrs);
17516       for (Uint32 i = 0; i < ptr_cnt; i++)
17517       {
17518         if (!Magic::match(ptrs[i].p->m_magic, ApiConnectRecord::TYPE_ID))
17519         {
17520           continue;
17521         }
17522         ApiConnectRecordPtr const& ptr = ptrs[i];
17523         Ndbinfo::Row row(signal, req);
17524         if (ndbinfo_write_trans(row, ptr))
17525         {
17526           jam();
17527           ndbinfo_send_row(signal, req, row, rl);
17528         }
17529         if (rl.need_break(req))
17530         {
17531           if (i + 1 < ptr_cnt)
17532           {
17533             api_ptr = ptrs[i + 1].i;
17534           }
17535           do_break = true;
17536           break;
17537         }
17538       }
17539     }
17540     if (api_ptr == RNIL)
17541     {
17542       goto done;
17543     }
17544     ndbinfo_send_scan_break(signal, req, rl, api_ptr);
17545     return;
17546   }
17547   default:
17548     break;
17549   }
17550 
17551 done:
17552   ndbinfo_send_scan_conf(signal, req, rl);
17553 }
17554 
17555 bool
ndbinfo_write_trans(Ndbinfo::Row & row,ApiConnectRecordPtr transPtr)17556 Dbtc::ndbinfo_write_trans(Ndbinfo::Row & row, ApiConnectRecordPtr transPtr)
17557 {
17558   Uint32 conState = transPtr.p->apiConnectstate;
17559 
17560   if (conState == CS_ABORTING && transPtr.p->abortState == AS_IDLE)
17561   {
17562     /**
17563      * These is for all practical purposes equal
17564      */
17565     conState = CS_CONNECTED;
17566   }
17567 
17568   if (conState == CS_CONNECTED ||
17569       conState == CS_DISCONNECTED ||
17570       conState == CS_RESTART)
17571   {
17572     return false;
17573   }
17574 
17575   row.write_uint32(getOwnNodeId());
17576   row.write_uint32(instance());   // block instance
17577   row.write_uint32(transPtr.i);
17578   row.write_uint32(transPtr.p->ndbapiBlockref);
17579   row.write_uint32(transPtr.p->transid[0]);
17580   row.write_uint32(transPtr.p->transid[1]);
17581   row.write_uint32(conState);
17582   row.write_uint32(transPtr.p->m_flags);
17583   row.write_uint32(transPtr.p->lqhkeyreqrec);
17584   Uint32 outstanding = 0;
17585   switch((ConnectionState)conState) {
17586   case CS_CONNECTED:
17587   case CS_DISCONNECTED:
17588     break;
17589   case CS_STARTED:
17590   case CS_RECEIVING:
17591   case CS_REC_COMMITTING:
17592   case CS_START_COMMITTING:
17593   case CS_SEND_FIRE_TRIG_REQ:
17594   case CS_WAIT_FIRE_TRIG_REQ:
17595     outstanding = transPtr.p->lqhkeyreqrec - transPtr.p->lqhkeyconfrec;
17596     break;
17597   case CS_COMMITTING:
17598   case CS_COMPLETING:
17599   case CS_COMMIT_SENT:
17600   case CS_COMPLETE_SENT:
17601   case CS_ABORTING:
17602     outstanding = transPtr.p->counter;
17603     break;
17604   case CS_PREPARE_TO_COMMIT:
17605     break;
17606   case CS_START_SCAN:
17607     // TODO
17608     break;
17609   case CS_WAIT_ABORT_CONF:
17610   case CS_WAIT_COMMIT_CONF:
17611   case CS_WAIT_COMPLETE_CONF:
17612     // not easily computed :-(
17613     break;
17614   case CS_FAIL_PREPARED:
17615   case CS_FAIL_ABORTED:
17616     // we're assembling a state...
17617     break;
17618   case CS_FAIL_COMMITTING:
17619   case CS_FAIL_COMMITTED:
17620   case CS_FAIL_ABORTING:
17621   case CS_FAIL_COMPLETED:
17622     // not easily computed :_(
17623     break;
17624   case CS_RESTART:
17625     break;
17626   }
17627 
17628   row.write_uint32(outstanding);
17629 
17630   Uint32 apiTimer = getApiConTimer(transPtr);
17631   row.write_uint32(apiTimer ? (ctcTimer - apiTimer) / 100 : 0);
17632   return true;
17633 }
17634 
17635 bool
validate_filter(Signal * signal)17636 Dbtc::validate_filter(Signal* signal)
17637 {
17638   Uint32 * start = signal->theData + 1;
17639   Uint32 * end = signal->theData + signal->getLength();
17640   if (start == end)
17641   {
17642     infoEvent("No filter specified, not listing...");
17643     return false;
17644   }
17645 
17646   while(start < end)
17647   {
17648     switch(* start){
17649     case 1: // API Node
17650     case 4: // Inactive time
17651       start += 2;
17652       break;
17653     case 2: // Transid
17654       start += 3;
17655       break;
17656     default:
17657       infoEvent("Invalid filter op: 0x%x pos: %ld",
17658 		* start,
17659 		(long int)(start - (signal->theData + 1)));
17660       return false;
17661     }
17662   }
17663 
17664   if (start != end)
17665   {
17666     infoEvent("Invalid filter, unexpected end");
17667     return false;
17668   }
17669 
17670   return true;
17671 }
17672 
17673 bool
match_and_print(Signal * signal,ApiConnectRecordPtr apiPtr)17674 Dbtc::match_and_print(Signal* signal, ApiConnectRecordPtr apiPtr)
17675 {
17676   Uint32 conState = apiPtr.p->apiConnectstate;
17677   if (conState == CS_CONNECTED ||
17678       conState == CS_DISCONNECTED ||
17679       conState == CS_RESTART)
17680     return false;
17681 
17682   Uint32 len = signal->getLength();
17683   Uint32* start = signal->theData + 2;
17684   Uint32* end = signal->theData + len;
17685   Uint32 apiTimer = getApiConTimer(apiPtr);
17686   while (start < end)
17687   {
17688     jam();
17689     switch(* start){
17690     case 1:
17691       jam();
17692       if (refToNode(apiPtr.p->ndbapiBlockref) != * (start + 1))
17693 	return false;
17694       start += 2;
17695       break;
17696     case 2:
17697       jam();
17698       if (apiPtr.p->transid[0] != * (start + 1) ||
17699 	  apiPtr.p->transid[1] != * (start + 2))
17700 	return false;
17701       start += 3;
17702       break;
17703     case 4:{
17704       jam();
17705       if (apiTimer == 0 || ((ctcTimer - apiTimer) / 100) < * (start + 1))
17706 	return false;
17707       start += 2;
17708       break;
17709     }
17710     default:
17711       ndbassert(false);
17712       return false;
17713     }
17714   }
17715 
17716   if (start != end)
17717   {
17718     ndbassert(false);
17719     return false;
17720   }
17721 
17722   /**
17723    * Do print
17724    */
17725   Uint32 *temp = signal->theData + 25;
17726   memcpy(temp, signal->theData, 4 * len);
17727 
17728   char state[10];
17729   const char *stateptr = "";
17730 
17731   switch(apiPtr.p->apiConnectstate){
17732   case CS_STARTED:
17733     stateptr = "Prepared";
17734     break;
17735   case CS_RECEIVING:
17736   case CS_REC_COMMITTING:
17737   case CS_START_COMMITTING:
17738     stateptr = "Running";
17739     break;
17740   case CS_COMMITTING:
17741     stateptr = "Committing";
17742     break;
17743   case CS_COMPLETING:
17744     stateptr = "Completing";
17745     break;
17746   case CS_PREPARE_TO_COMMIT:
17747     stateptr = "Prepare to commit";
17748     break;
17749   case CS_COMMIT_SENT:
17750     stateptr = "Commit sent";
17751     break;
17752   case CS_COMPLETE_SENT:
17753     stateptr = "Complete sent";
17754     break;
17755   case CS_ABORTING:
17756     stateptr = "Aborting";
17757     break;
17758   case CS_START_SCAN:
17759     stateptr = "Scanning";
17760     break;
17761   case CS_WAIT_ABORT_CONF:
17762   case CS_WAIT_COMMIT_CONF:
17763   case CS_WAIT_COMPLETE_CONF:
17764   case CS_FAIL_PREPARED:
17765   case CS_FAIL_COMMITTING:
17766   case CS_FAIL_COMMITTED:
17767   case CS_RESTART:
17768   case CS_FAIL_ABORTED:
17769   case CS_DISCONNECTED:
17770   default:
17771     BaseString::snprintf(state, sizeof(state),
17772 			 "%u", apiPtr.p->apiConnectstate);
17773     stateptr = state;
17774     break;
17775   }
17776 
17777   char buf[100];
17778   BaseString::snprintf(buf, sizeof(buf),
17779 		       "TRX[%u]: API: %d(0x%x)"
17780 		       "transid: 0x%x 0x%x inactive: %u(%d) state: %s",
17781 		       apiPtr.i,
17782 		       refToNode(apiPtr.p->ndbapiBlockref),
17783 		       refToBlock(apiPtr.p->ndbapiBlockref),
17784 		       apiPtr.p->transid[0],
17785 		       apiPtr.p->transid[1],
17786 		       apiTimer ? (ctcTimer - apiTimer) / 100 : 0,
17787                        apiPtr.p->m_apiConTimer_line,
17788 		       stateptr);
17789   infoEvent("%s", buf);
17790 
17791   memcpy(signal->theData, temp, 4*len);
17792   return true;
17793 }
17794 
execABORT_ALL_REQ(Signal * signal)17795 void Dbtc::execABORT_ALL_REQ(Signal* signal)
17796 {
17797   jamEntry();
17798   AbortAllReq * req = (AbortAllReq*)&signal->theData[0];
17799   AbortAllRef * ref = (AbortAllRef*)&signal->theData[0];
17800 
17801   const Uint32 senderData = req->senderData;
17802   const BlockReference senderRef = req->senderRef;
17803 
17804   if (getAllowStartTransaction(refToNode(senderRef), 0) == true &&
17805       !getNodeState().getSingleUserMode())
17806   {
17807     jam();
17808 
17809     ref->senderData = senderData;
17810     ref->errorCode = AbortAllRef::InvalidState;
17811     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
17812 	       AbortAllRef::SignalLength, JBB);
17813     return;
17814   }
17815 
17816   if(c_abortRec.clientRef != 0){
17817     jam();
17818 
17819     ref->senderData = senderData;
17820     ref->errorCode = AbortAllRef::AbortAlreadyInProgress;
17821     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
17822 	       AbortAllRef::SignalLength, JBB);
17823     return;
17824   }
17825 
17826   if(refToNode(senderRef) != getOwnNodeId()){
17827     jam();
17828 
17829     ref->senderData = senderData;
17830     ref->errorCode = AbortAllRef::FunctionNotImplemented;
17831     sendSignal(senderRef, GSN_ABORT_ALL_REF, signal,
17832 	       AbortAllRef::SignalLength, JBB);
17833     return;
17834   }
17835 
17836   c_abortRec.clientRef = senderRef;
17837   c_abortRec.clientData = senderData;
17838   c_abortRec.oldTimeOutValue = ctimeOutValue;
17839 
17840   ctimeOutValue = 0;
17841   const Uint32 sleepTime = (2 * 10 * ctimeOutCheckDelay + 199) / 200;
17842 
17843   checkAbortAllTimeout(signal, (sleepTime == 0 ? 1 : sleepTime));
17844 }
17845 
checkAbortAllTimeout(Signal * signal,Uint32 sleepTime)17846 void Dbtc::checkAbortAllTimeout(Signal* signal, Uint32 sleepTime)
17847 {
17848 
17849   ndbrequire(c_abortRec.clientRef != 0);
17850 
17851   if(sleepTime > 0){
17852     jam();
17853 
17854     sleepTime -= 1;
17855     signal->theData[0] = TcContinueB::ZWAIT_ABORT_ALL;
17856     signal->theData[1] = sleepTime;
17857     sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 200, 2);
17858     return;
17859   }
17860 
17861   AbortAllConf * conf = (AbortAllConf*)&signal->theData[0];
17862   conf->senderData = c_abortRec.clientData;
17863   sendSignal(c_abortRec.clientRef, GSN_ABORT_ALL_CONF, signal,
17864 	     AbortAllConf::SignalLength, JBB);
17865 
17866   ctimeOutValue = c_abortRec.oldTimeOutValue;
17867   c_abortRec.clientRef = 0;
17868 }
17869 
17870 /* **************************************************************** */
17871 /* ---------------------------------------------------------------- */
17872 /* ------------------ TRIGGER AND INDEX HANDLING ------------------ */
17873 /* ---------------------------------------------------------------- */
17874 /* **************************************************************** */
17875 
execCREATE_TRIG_IMPL_REQ(Signal * signal)17876 void Dbtc::execCREATE_TRIG_IMPL_REQ(Signal* signal)
17877 {
17878   jamEntry();
17879   if (!assembleFragments(signal))
17880   {
17881     jam();
17882     return;
17883   }
17884 
17885   const CreateTrigImplReq* req = (const CreateTrigImplReq*)signal->getDataPtr();
17886   const Uint32 senderRef = req->senderRef;
17887   const Uint32 senderData = req->senderData;
17888 
17889   SectionHandle handle(this, signal);
17890   releaseSections(handle); // Not using mask
17891 
17892   TcDefinedTriggerData* triggerData;
17893   DefinedTriggerPtr triggerPtr;
17894 
17895   triggerPtr.i = req->triggerId;
17896   if (ERROR_INSERTED(8033) ||
17897       !c_theDefinedTriggers.getPool().seizeId(triggerPtr, req->triggerId)) {
17898     jam();
17899     CLEAR_ERROR_INSERT_VALUE;
17900     // Failed to allocate trigger record
17901 ref:
17902     CreateTrigImplRef* ref =  (CreateTrigImplRef*)signal->getDataPtrSend();
17903 
17904     ref->senderRef = reference();
17905     ref->senderData = senderData;
17906     ref->errorCode = CreateTrigImplRef::InconsistentTC;
17907     ref->errorLine = __LINE__;
17908     sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_REF,
17909                signal, CreateTrigImplRef::SignalLength, JBB);
17910     return;
17911   }
17912   c_theDefinedTriggers.addFirst(triggerPtr);
17913 
17914   triggerData = triggerPtr.p;
17915   triggerData->triggerId = req->triggerId;
17916   triggerData->triggerType = TriggerInfo::getTriggerType(req->triggerInfo);
17917   triggerData->triggerEvent = TriggerInfo::getTriggerEvent(req->triggerInfo);
17918   triggerData->oldTriggerIds[0] = RNIL;
17919   triggerData->oldTriggerIds[1] = RNIL;
17920   triggerData->refCount = 0;
17921 
17922   switch(triggerData->triggerType){
17923   case TriggerType::SECONDARY_INDEX:
17924     jam();
17925     triggerData->indexId = req->indexId;
17926     break;
17927   case TriggerType::REORG_TRIGGER:
17928   case TriggerType::FULLY_REPLICATED_TRIGGER:
17929     jam();
17930     triggerData->tableId = req->tableId;
17931     break;
17932   case TriggerType::FK_PARENT:
17933   case TriggerType::FK_CHILD:
17934     triggerData->fkId = req->indexId;
17935     break;
17936   default:
17937     c_theDefinedTriggers.release(triggerPtr);
17938     goto ref;
17939   }
17940 
17941   if (unlikely(req->triggerId != req->upgradeExtra[1]))
17942   {
17943     /**
17944      * This is nasty upgrade for unique indexes
17945      */
17946     jam();
17947     ndbrequire(req->triggerId == req->upgradeExtra[0]);
17948     ndbrequire(triggerData->triggerType == TriggerType::SECONDARY_INDEX);
17949 
17950     DefinedTriggerPtr insertPtr = triggerPtr;
17951     DefinedTriggerPtr updatePtr;
17952     DefinedTriggerPtr deletePtr;
17953     if (c_theDefinedTriggers.getPool().seizeId(updatePtr, req->upgradeExtra[1]) == false)
17954     {
17955       jam();
17956       c_theDefinedTriggers.release(insertPtr);
17957       goto ref;
17958     }
17959     c_theDefinedTriggers.addFirst(updatePtr);
17960 
17961     if (c_theDefinedTriggers.getPool().seizeId(deletePtr, req->upgradeExtra[2]) == false)
17962     {
17963       jam();
17964       c_theDefinedTriggers.release(insertPtr);
17965       c_theDefinedTriggers.release(updatePtr);
17966       goto ref;
17967     }
17968     c_theDefinedTriggers.addFirst(deletePtr);
17969 
17970     insertPtr.p->triggerEvent = TriggerEvent::TE_INSERT;
17971 
17972     updatePtr.p->triggerId = req->upgradeExtra[1];
17973     updatePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
17974     updatePtr.p->triggerEvent = TriggerEvent::TE_UPDATE;
17975     updatePtr.p->oldTriggerIds[0] = RNIL;
17976     updatePtr.p->oldTriggerIds[1] = RNIL;
17977     updatePtr.p->indexId = req->indexId;
17978     updatePtr.p->refCount = 0;
17979 
17980     deletePtr.p->triggerId = req->upgradeExtra[2];
17981     deletePtr.p->triggerType = TriggerType::SECONDARY_INDEX;
17982     deletePtr.p->triggerEvent = TriggerEvent::TE_DELETE;
17983     deletePtr.p->oldTriggerIds[0] = RNIL;
17984     deletePtr.p->oldTriggerIds[1] = RNIL;
17985     deletePtr.p->indexId = req->indexId;
17986     deletePtr.p->refCount = 0;
17987   }
17988 
17989   CreateTrigImplConf* conf = (CreateTrigImplConf*)signal->getDataPtrSend();
17990   conf->senderRef = reference();
17991   conf->senderData = senderData;
17992   sendSignal(senderRef, GSN_CREATE_TRIG_IMPL_CONF,
17993              signal, CreateTrigImplConf::SignalLength, JBB);
17994 }
17995 
execDROP_TRIG_IMPL_REQ(Signal * signal)17996 void Dbtc::execDROP_TRIG_IMPL_REQ(Signal* signal)
17997 {
17998   jamEntry();
17999   const DropTrigImplReq* req = (const DropTrigImplReq*)signal->getDataPtr();
18000   const Uint32 senderRef = req->senderRef;
18001   const Uint32 senderData = req->senderData;
18002 
18003   /* Using a IgnoreAlloc variant of getPtr to make the lookup safe.
18004    * The validity of the trigger should be checked subsequently.
18005    */
18006   DefinedTriggerPtr triggerPtr;
18007   triggerPtr.i = req->triggerId;
18008   c_theDefinedTriggers.getPool().getPtrIgnoreAlloc(triggerPtr);
18009 
18010   // If triggerIds don't match, the trigger has probably already been dropped.
18011   if (triggerPtr.p->triggerId != req->triggerId || ERROR_INSERTED(8035))
18012   {
18013     jam();
18014     CLEAR_ERROR_INSERT_VALUE;
18015     // Failed to find trigger record
18016     DropTrigImplRef* ref = (DropTrigImplRef*)signal->getDataPtrSend();
18017 
18018     ref->senderRef = reference();
18019     ref->senderData = senderData;
18020     ref->errorCode = DropTrigImplRef::InconsistentTC;
18021     ref->errorLine = __LINE__;
18022     sendSignal(senderRef, GSN_DROP_TRIG_IMPL_REF,
18023                signal, DropTrigImplRef::SignalLength, JBB);
18024     return;
18025   }
18026 
18027   if (triggerPtr.p->refCount > 0)
18028   {
18029     jam();
18030     sendSignalWithDelay(reference(), GSN_DROP_TRIG_IMPL_REQ,
18031                         signal, 100, signal->getLength());
18032     return;
18033   }
18034 
18035   if (unlikely(triggerPtr.p->oldTriggerIds[0] != RNIL))
18036   {
18037     jam();
18038 
18039     const Uint32 * oldId = triggerPtr.p->oldTriggerIds;
18040     if (c_theDefinedTriggers.getPtr(oldId[0])->refCount > 0 ||
18041         c_theDefinedTriggers.getPtr(oldId[1])->refCount > 0)
18042     {
18043       jam();
18044       sendSignalWithDelay(reference(), GSN_DROP_TRIG_IMPL_REQ,
18045                           signal, 100, signal->getLength());
18046       return;
18047     }
18048 
18049     c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[0]);
18050     c_theDefinedTriggers.release(triggerPtr.p->oldTriggerIds[1]);
18051   }
18052 
18053   // Mark trigger record as dropped/invalid and release it
18054   triggerPtr.p->triggerId = 0xffffffff;
18055   c_theDefinedTriggers.release(triggerPtr);
18056 
18057   DropTrigImplConf* conf = (DropTrigImplConf*)signal->getDataPtrSend();
18058 
18059   conf->senderRef = reference();
18060   conf->senderData = senderData;
18061 
18062   sendSignal(senderRef, GSN_DROP_TRIG_IMPL_CONF,
18063              signal, DropTrigImplConf::SignalLength, JBB);
18064 }
18065 
execCREATE_INDX_IMPL_REQ(Signal * signal)18066 void Dbtc::execCREATE_INDX_IMPL_REQ(Signal* signal)
18067 {
18068   jamEntry();
18069   const CreateIndxImplReq * const req =
18070     (const CreateIndxImplReq *)signal->getDataPtr();
18071   const Uint32 senderRef = req->senderRef;
18072   const Uint32 senderData = req->senderData;
18073   TcIndexData* indexData;
18074   TcIndexDataPtr indexPtr;
18075 
18076   SectionHandle handle(this, signal);
18077   if (ERROR_INSERTED(8034) ||
18078       !c_theIndexes.getPool().seizeId(indexPtr, req->indexId)) {
18079     jam();
18080     CLEAR_ERROR_INSERT_VALUE;
18081     // Failed to allocate index record
18082      CreateIndxImplRef * const ref =
18083        (CreateIndxImplRef *)signal->getDataPtrSend();
18084 
18085      ref->senderRef = reference();
18086      ref->senderData = senderData;
18087      ref->errorCode = CreateIndxImplRef::InconsistentTC;
18088      ref->errorLine = __LINE__;
18089      releaseSections(handle);
18090      sendSignal(senderRef, GSN_CREATE_INDX_IMPL_REF,
18091                 signal, CreateIndxImplRef::SignalLength, JBB);
18092      return;
18093   }
18094   c_theIndexes.addFirst(indexPtr);
18095   indexData = indexPtr.p;
18096   // Indexes always start in state IS_BUILDING
18097   // Will become IS_ONLINE in execALTER_INDX_IMPL_REQ
18098   indexData->indexState = IS_BUILDING;
18099   indexData->indexId = indexPtr.i;
18100   indexData->primaryTableId = req->tableId;
18101 
18102   // So far need only attribute count
18103   SegmentedSectionPtr ssPtr;
18104   handle.getSection(ssPtr, CreateIndxReq::ATTRIBUTE_LIST_SECTION);
18105   SimplePropertiesSectionReader r0(ssPtr, getSectionSegmentPool());
18106   r0.reset(); // undo implicit first()
18107   if (!r0.getWord(&indexData->attributeList.sz) ||
18108       !r0.getWords(indexData->attributeList.id, indexData->attributeList.sz)) {
18109     ndbabort();
18110   }
18111   indexData->primaryKeyPos = indexData->attributeList.sz;
18112 
18113   releaseSections(handle);
18114 
18115   CreateIndxImplConf * const conf =
18116     (CreateIndxImplConf *)signal->getDataPtrSend();
18117 
18118   conf->senderRef = reference();
18119   conf->senderData = senderData;
18120   sendSignal(senderRef, GSN_CREATE_INDX_IMPL_CONF,
18121              signal, CreateIndxImplConf::SignalLength, JBB);
18122 }
18123 
execALTER_INDX_IMPL_REQ(Signal * signal)18124 void Dbtc::execALTER_INDX_IMPL_REQ(Signal* signal)
18125 {
18126   jamEntry();
18127   const AlterIndxImplReq * const req =
18128     (const AlterIndxImplReq *)signal->getDataPtr();
18129   const Uint32 senderRef = req->senderRef;
18130   const Uint32 senderData = req->senderData;
18131   TcIndexData* indexData;
18132   const Uint32 requestType = req->requestType;
18133   const Uint32 indexId = req->indexId;
18134 
18135   if ((indexData = c_theIndexes.getPtr(indexId)) == NULL) {
18136     jam();
18137     // Failed to find index record
18138     AlterIndxImplRef * const ref =
18139       (AlterIndxImplRef *)signal->getDataPtrSend();
18140 
18141     ref->senderRef = reference();
18142     ref->senderData = senderData;
18143     ref->errorCode = AlterIndxImplRef::InconsistentTC;
18144     ref->errorLine = __LINE__;
18145 
18146     sendSignal(senderRef, GSN_ALTER_INDX_IMPL_REF,
18147 	       signal, AlterIndxImplRef::SignalLength, JBB);
18148     return;
18149   }
18150   // Found index record, alter it's state
18151   switch (requestType) {
18152   case AlterIndxImplReq::AlterIndexOnline:
18153     jam();
18154     indexData->indexState = IS_ONLINE;
18155     break;
18156   case AlterIndxImplReq::AlterIndexOffline:
18157     jam();
18158     indexData->indexState = IS_BUILDING; // wl3600_todo ??
18159     break;
18160   default:
18161     ndbabort();
18162   }
18163   AlterIndxImplConf * const conf =
18164     (AlterIndxImplConf *)signal->getDataPtrSend();
18165 
18166   conf->senderRef = reference();
18167   conf->senderData = senderData;
18168   sendSignal(senderRef, GSN_ALTER_INDX_IMPL_CONF,
18169 	     signal, AlterIndxImplConf::SignalLength, JBB);
18170 }
18171 
18172 void
execCREATE_FK_IMPL_REQ(Signal * signal)18173 Dbtc::execCREATE_FK_IMPL_REQ(Signal* signal)
18174 {
18175   jamEntry();
18176   CreateFKImplReq reqCopy = * CAST_CONSTPTR(CreateFKImplReq,
18177                                             signal->getDataPtr());
18178   CreateFKImplReq * req = &reqCopy;
18179 
18180   Uint32 errCode = 0;
18181   SectionHandle handle(this, signal);
18182 
18183   if (req->requestType == CreateFKImplReq::RT_PREPARE)
18184   {
18185     jam();
18186     Ptr<TcFKData> fkPtr;
18187     if (c_fk_hash.find(fkPtr, req->fkId))
18188     {
18189       jam();
18190       errCode = CreateFKImplRef::ObjectAlreadyExist;
18191       goto error;
18192     }
18193     if (!c_fk_pool.seize(fkPtr))
18194     {
18195       jam();
18196       errCode = CreateFKImplRef::NoMoreObjectRecords;
18197       goto error;
18198     }
18199 
18200     fkPtr.p->fkId = req->fkId;
18201     fkPtr.p->bits = req->bits;
18202     fkPtr.p->parentTableId = req->parentTableId;
18203     fkPtr.p->childTableId = req->childTableId;
18204     fkPtr.p->childIndexId = req->childIndexId;
18205 
18206     if (req->parentIndexId != RNIL)
18207     {
18208       /**
18209        * Ignore base-table here...we'll only use the index anyway
18210        */
18211       jam();
18212       fkPtr.p->parentTableId = req->parentIndexId;
18213     }
18214 
18215     if (req->childIndexId == RNIL)
18216     {
18217       jam();
18218       fkPtr.p->childIndexId = req->childTableId;
18219     }
18220 
18221     {
18222       SegmentedSectionPtr ssPtr;
18223       handle.getSection(ssPtr, CreateFKImplReq::PARENT_COLUMNS);
18224       fkPtr.p->parentTableColumns.sz = ssPtr.sz;
18225       if (ssPtr.sz > NDB_ARRAY_SIZE(fkPtr.p->parentTableColumns.id))
18226       {
18227         errCode = CreateFKImplRef::InvalidFormat;
18228         goto error;
18229       }
18230       copy(fkPtr.p->parentTableColumns.id, ssPtr);
18231     }
18232 
18233     {
18234       SegmentedSectionPtr ssPtr;
18235       handle.getSection(ssPtr, CreateFKImplReq::CHILD_COLUMNS);
18236       fkPtr.p->childTableColumns.sz = ssPtr.sz;
18237       if (ssPtr.sz > NDB_ARRAY_SIZE(fkPtr.p->childTableColumns.id))
18238       {
18239         errCode = CreateFKImplRef::InvalidFormat;
18240         goto error;
18241       }
18242       copy(fkPtr.p->childTableColumns.id, ssPtr);
18243     }
18244 
18245     c_fk_hash.add(fkPtr);
18246   }
18247   else if (req->requestType == CreateFKImplReq::RT_ABORT)
18248   {
18249     jam();
18250     Ptr<TcFKData> fkPtr;
18251     ndbassert(c_fk_hash.find(fkPtr, req->fkId));
18252     if (c_fk_hash.find(fkPtr, req->fkId))
18253     {
18254       jam();
18255       c_fk_hash.release(fkPtr);
18256     }
18257   }
18258   else
18259   {
18260     ndbabort(); // No other request should reach TC
18261   }
18262 
18263   releaseSections(handle);
18264   {
18265     CreateFKImplConf * conf = CAST_PTR(CreateFKImplConf,
18266                                        signal->getDataPtrSend());
18267     conf->senderRef = reference();
18268     conf->senderData = req->senderData;
18269     sendSignal(req->senderRef, GSN_CREATE_FK_IMPL_CONF,
18270                signal, CreateFKImplConf::SignalLength, JBB);
18271   }
18272   return;
18273 error:
18274   releaseSections(handle);
18275   CreateFKImplRef * ref = CAST_PTR(CreateFKImplRef,
18276                                    signal->getDataPtrSend());
18277   ref->senderRef = reference();
18278   ref->senderData = req->senderData;
18279   ref->errorCode = errCode;
18280   sendSignal(req->senderRef, GSN_CREATE_FK_IMPL_REF,
18281              signal, CreateFKImplRef::SignalLength, JBB);
18282 }
18283 
18284 void
execDROP_FK_IMPL_REQ(Signal * signal)18285 Dbtc::execDROP_FK_IMPL_REQ(Signal* signal)
18286 {
18287   jamEntry();
18288   DropFKImplReq reqCopy = * CAST_CONSTPTR(DropFKImplReq,
18289                                           signal->getDataPtr());
18290   DropFKImplReq * req = &reqCopy;
18291 
18292   SectionHandle handle(this, signal);
18293   releaseSections(handle);
18294 
18295   Ptr<TcFKData> fkPtr;
18296   ndbassert(c_fk_hash.find(fkPtr, req->fkId));
18297   if (c_fk_hash.find(fkPtr, req->fkId))
18298   {
18299     jam();
18300     c_fk_hash.release(fkPtr);
18301 
18302     DropFKImplConf * conf = CAST_PTR(DropFKImplConf,
18303                                      signal->getDataPtrSend());
18304     conf->senderRef = reference();
18305     conf->senderData = req->senderData;
18306     sendSignal(req->senderRef, GSN_DROP_FK_IMPL_CONF,
18307                signal, DropFKImplConf::SignalLength, JBB);
18308   }
18309   else
18310   {
18311     jam();
18312     DropFKImplRef * ref = CAST_PTR(DropFKImplRef,
18313                                    signal->getDataPtrSend());
18314     ref->senderRef = reference();
18315     ref->senderData = req->senderData;
18316     ref->errorCode = DropFKImplRef::NoSuchObject;
18317     sendSignal(req->senderRef, GSN_DROP_FK_IMPL_REF,
18318                signal, DropFKImplRef::SignalLength, JBB);
18319   }
18320 }
18321 
execFIRE_TRIG_ORD(Signal * signal)18322 void Dbtc::execFIRE_TRIG_ORD(Signal* signal)
18323 {
18324   jamEntry();
18325 
18326   if (!assembleFragments(signal))
18327   {
18328     jam();
18329     return;
18330   }
18331   FireTrigOrd * const fireOrd =  (FireTrigOrd *)signal->getDataPtr();
18332   SectionHandle handle(this, signal);
18333   const bool longsignal = handle.m_cnt > 0;
18334 
18335   ApiConnectRecordPtr transPtr;
18336   TcConnectRecordPtr opPtr;
18337   ndbrequire(signal->getLength() >= FireTrigOrd::SignalLength);
18338   bool transIdOk = true;
18339   /* Check the received transaction id */
18340 
18341   /* Get triggering operation record */
18342   opPtr.i = fireOrd->getConnectionPtr();
18343 
18344   /* Get transaction record */
18345   if (likely(tcConnectRecord.getValidPtr(opPtr)))
18346   {
18347     /* Get transaction record */
18348     transPtr.i = opPtr.p->apiConnect;
18349   }
18350   else
18351   {
18352     transPtr.i = RNIL;
18353     opPtr.setNull();
18354   }
18355 
18356   if (unlikely(transPtr.i == RNIL) ||
18357       unlikely(!c_apiConnectRecordPool.getValidPtr(transPtr)))
18358   {
18359     jam();
18360     /* Looks like the connect record was released
18361      * Treat as a bad transid
18362      */
18363     jam();
18364     transIdOk = false;
18365   }
18366   else
18367   {
18368     jam();
18369     /* Check if signal's trans id and operation's transid are aligned */
18370     transIdOk = !((fireOrd->m_transId1 ^ transPtr.p->transid[0]) |
18371                   (fireOrd->m_transId2 ^ transPtr.p->transid[1]));
18372   }
18373 
18374   TcFiredTriggerData key;
18375   key.fireingOperation = opPtr.i;
18376   key.nodeId = refToNode(signal->getSendersBlockRef());
18377   FiredTriggerPtr trigPtr;
18378   bool ok = transIdOk;
18379 
18380   if (likely(longsignal && transIdOk))
18381   {
18382     jam();
18383     if (likely(c_theFiredTriggerPool.seize(trigPtr)))
18384     {
18385       jam();
18386       trigPtr.p->nodeId = key.nodeId;
18387       trigPtr.p->fireingOperation = key.fireingOperation;
18388       trigPtr.p->triggerId = fireOrd->m_triggerId;
18389     }
18390     else
18391     {
18392       jam();
18393       ok = false;
18394     }
18395   }
18396 
18397   Uint32 errorCode = ZTOO_MANY_FIRED_TRIGGERS;
18398   if (likely((longsignal && ok) ||
18399              c_firedTriggerHash.find(trigPtr, key)))
18400   {
18401     jam();
18402     if (!longsignal)
18403     {
18404       jam();
18405       c_firedTriggerHash.remove(trigPtr);
18406     }
18407 
18408     trigPtr.p->triggerType = (TriggerType::Value)fireOrd->m_triggerType;
18409     trigPtr.p->triggerEvent = (TriggerEvent::Value)fireOrd->m_triggerEvent;
18410 
18411     trigPtr.p->fragId= fireOrd->fragId;
18412     if (longsignal)
18413     {
18414       jam();
18415       AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
18416       {
18417         //TODO: error insert to make e.g middle append fail
18418         LocalAttributeBuffer tmp1(pool, trigPtr.p->keyValues);
18419         LocalAttributeBuffer tmp2(pool, trigPtr.p->beforeValues);
18420         LocalAttributeBuffer tmp3(pool, trigPtr.p->afterValues);
18421         append(tmp1, handle.m_ptr[0], getSectionSegmentPool());
18422         append(tmp2, handle.m_ptr[1], getSectionSegmentPool());
18423         append(tmp3, handle.m_ptr[2], getSectionSegmentPool());
18424       }
18425       releaseSections(handle);
18426     }
18427 
18428     ok &= trigPtr.p->keyValues.getSize() == fireOrd->m_noPrimKeyWords;
18429     ok &= trigPtr.p->afterValues.getSize() == fireOrd->m_noAfterValueWords;
18430     ok &= trigPtr.p->beforeValues.getSize() == fireOrd->m_noBeforeValueWords;
18431 
18432     if (ERROR_INSERTED(8085))
18433     {
18434       ok = false;
18435     }
18436 
18437     if(likely( ok ))
18438     {
18439       jam();
18440       setApiConTimer(transPtr, ctcTimer, __LINE__);
18441       opPtr.p->numReceivedTriggers++;
18442 
18443       /**
18444        * Fully replicated trigger have a more complex scenario, so not
18445        * 1 LQHKEYREQ per trigger, rather one LQHKEYREQ per node group
18446        * the table is stored in. This is handled in
18447        * executeFullyReplicatedTrigger.
18448        *
18449        * We add one here also for fully replicated triggers, this
18450        * represents the operation to scan for fragments to update, so
18451        * if there are no triggers to fire then this will be decremented
18452        * even with no actual triggers being fired. In addition one will
18453        * be added for each fragment that the fully replicated trigger
18454        * will update.
18455        *
18456        * Foreign key child triggers will issue one read on the parent
18457        * table, so this will always be one operation.
18458        *
18459        * Foreign key parent triggers will either issue one operation
18460        * against a PK or UK index in which case this add is sufficient.
18461        * It can also issue an index scan in which case several rows might
18462        * be found. In this case the scan is the one represented by this
18463        * add of the triggerExecutionCount, in addition each resulting
18464        * PK UPDATE/DELETE will add one more to the triggerExecutionCount.
18465        *
18466        * Unique index triggers will issue one operation for DELETEs and
18467        * INSERTs which is represented by this add, for updates there will
18468        * be one INSERT and one DELETE issued which causes one more to be
18469        * added as part of trigger execution.
18470        *
18471        * Finally we also have REORG triggers that fires, in this case we
18472        * increment it here and if the TCKEYREQ execution decides that
18473        * the reorg trigger doesn't need to be executed it will call
18474        * trigger_op_finished before returning from execTCKEYREQ. Otherwise
18475        * it will be called as usual on receiving LQHKEYCONF for the
18476        * triggered operation.
18477        */
18478       opPtr.p->triggerExecutionCount++; // Default 1 LQHKEYREQ per trigger
18479       // Insert fired trigger in execution queue
18480       {
18481         Local_TcFiredTriggerData_fifo
18482           list(c_theFiredTriggerPool, opPtr.p->thePendingTriggers);
18483         list.addLast(trigPtr);
18484       }
18485 
18486       if (opPtr.p->numReceivedTriggers == opPtr.p->numFiredTriggers ||
18487           transPtr.p->isExecutingDeferredTriggers())
18488       {
18489         jam();
18490         Local_TcFiredTriggerData_fifo
18491           list(c_theFiredTriggerPool, transPtr.p->theFiredTriggers);
18492         list.appendList(opPtr.p->thePendingTriggers);
18493 	executeTriggers(signal, &transPtr);
18494       }
18495       return;
18496     }
18497 
18498     /* Trigger entry found but either :
18499      *   - Overload resulted in loss of Trig_Attrinfo
18500      *     : Release resources + Abort transaction
18501      *   - Bad transaction id due to concurrent abort?
18502      *     : Release resources
18503      */
18504     jam();
18505     errorCode = ZINCONSISTENT_TRIGGER_STATE;
18506     // Release trigger records
18507     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
18508     LocalAttributeBuffer tmp1(pool, trigPtr.p->keyValues);
18509     tmp1.release();
18510     LocalAttributeBuffer tmp2(pool, trigPtr.p->beforeValues);
18511     tmp2.release();
18512     LocalAttributeBuffer tmp3(pool, trigPtr.p->afterValues);
18513     tmp3.release();
18514     c_theFiredTriggerPool.release(trigPtr);
18515     checkPoolShrinkNeed(DBTC_ATTRIBUTE_BUFFER_TRANSIENT_POOL_INDEX,
18516                         c_theAttributeBufferPool);
18517     checkPoolShrinkNeed(DBTC_FIRED_TRIGGER_DATA_TRANSIENT_POOL_INDEX,
18518                         c_theFiredTriggerPool);
18519   }
18520 
18521   releaseSections(handle);
18522 
18523   /* Either no trigger entry found, or overload, or
18524    * bad transid
18525    * If transid is ok, abort the transaction.
18526    * else, return.
18527    * (Note small risk of 'abort of innocent' in upgrade
18528    *  scenario with no transid in FIRE_TRIG_ORD)
18529    */
18530   jam();
18531   if (transIdOk)
18532   {
18533     jam();
18534     abortTransFromTrigger(signal, transPtr, errorCode);
18535   }
18536 
18537   return;
18538 }
18539 
execTRIG_ATTRINFO(Signal * signal)18540 void Dbtc::execTRIG_ATTRINFO(Signal* signal)
18541 {
18542   jamEntry();
18543   TrigAttrInfo * const trigAttrInfo =  (TrigAttrInfo *)signal->getDataPtr();
18544   Uint32 attrInfoLength = signal->getLength() - TrigAttrInfo::StaticLength;
18545   const Uint32 *src = trigAttrInfo->getData();
18546   FiredTriggerPtr firedTrigPtr;
18547 
18548   TcFiredTriggerData key;
18549   key.fireingOperation = trigAttrInfo->getConnectionPtr();
18550   key.nodeId = refToNode(signal->getSendersBlockRef());
18551   if(!c_firedTriggerHash.find(firedTrigPtr, key)){
18552     jam();
18553     if(!c_theFiredTriggerPool.seize(firedTrigPtr))
18554     {
18555       jam();
18556       /**
18557        * Will be handled when FIRE_TRIG_ORD arrives
18558        */
18559       ndbout_c("op: %d node: %d failed to seize",
18560 	       key.fireingOperation, key.nodeId);
18561       return;
18562     }
18563     ndbrequire(firedTrigPtr.p->keyValues.getSize() == 0 &&
18564 	       firedTrigPtr.p->beforeValues.getSize() == 0 &&
18565 	       firedTrigPtr.p->afterValues.getSize() == 0);
18566 
18567     firedTrigPtr.p->nodeId = refToNode(signal->getSendersBlockRef());
18568     firedTrigPtr.p->fireingOperation = key.fireingOperation;
18569     firedTrigPtr.p->triggerId = trigAttrInfo->getTriggerId();
18570     c_firedTriggerHash.add(firedTrigPtr);
18571   }
18572 
18573   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
18574   switch (trigAttrInfo->getAttrInfoType()) {
18575   case(TrigAttrInfo::PRIMARY_KEY):
18576     jam();
18577     {
18578       LocalAttributeBuffer buf(pool, firedTrigPtr.p->keyValues);
18579       buf.append(src, attrInfoLength);
18580     }
18581     break;
18582   case(TrigAttrInfo::BEFORE_VALUES):
18583     jam();
18584     {
18585       LocalAttributeBuffer buf(pool, firedTrigPtr.p->beforeValues);
18586       buf.append(src, attrInfoLength);
18587     }
18588     break;
18589   case(TrigAttrInfo::AFTER_VALUES):
18590     jam();
18591     {
18592       LocalAttributeBuffer buf(pool, firedTrigPtr.p->afterValues);
18593       buf.append(src, attrInfoLength);
18594     }
18595     break;
18596   default:
18597     ndbabort();
18598   }
18599 }
18600 
execDROP_INDX_IMPL_REQ(Signal * signal)18601 void Dbtc::execDROP_INDX_IMPL_REQ(Signal* signal)
18602 {
18603   jamEntry();
18604   const DropIndxImplReq * const req =
18605     (const DropIndxImplReq *)signal->getDataPtr();
18606   const Uint32 senderRef = req->senderRef;
18607   const Uint32 senderData = req->senderData;
18608   TcIndexData* indexData;
18609 
18610   if (ERROR_INSERTED(8036) ||
18611       (indexData = c_theIndexes.getPtr(req->indexId)) == NULL) {
18612     jam();
18613     CLEAR_ERROR_INSERT_VALUE;
18614     // Failed to find index record
18615     DropIndxImplRef * const ref =
18616       (DropIndxImplRef *)signal->getDataPtrSend();
18617 
18618     ref->senderRef = reference();
18619     ref->senderData = senderData;
18620     ref->errorCode = DropIndxImplRef::InconsistentTC;
18621     ref->errorLine = __LINE__;
18622     sendSignal(senderRef, GSN_DROP_INDX_IMPL_REF,
18623                signal, DropIndxImplRef::SignalLength, JBB);
18624     return;
18625   }
18626   // Release index record
18627   indexData->indexState = IS_OFFLINE;
18628   c_theIndexes.release(req->indexId);
18629 
18630   DropIndxImplConf * const conf =
18631     (DropIndxImplConf *)signal->getDataPtrSend();
18632 
18633   conf->senderRef = reference();
18634   conf->senderData = senderData;
18635   sendSignal(senderRef, GSN_DROP_INDX_IMPL_CONF,
18636              signal, DropIndxImplConf::SignalLength, JBB);
18637 }
18638 
execTCINDXREQ(Signal * signal)18639 void Dbtc::execTCINDXREQ(Signal* signal)
18640 {
18641   jamEntry();
18642   if (!assembleFragments(signal))
18643   {
18644     jam();
18645     return;
18646   }
18647 
18648   TcKeyReq * const tcIndxReq =  (TcKeyReq *)signal->getDataPtr();
18649   const UintR TapiIndex = tcIndxReq->apiConnectPtr;
18650   Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
18651   Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
18652   ApiConnectRecordPtr transPtr;
18653   bool isLongTcIndxReq= (signal->getNoOfSections() != 0);
18654   SectionHandle handle(this, signal);
18655 
18656   transPtr.i = TapiIndex;
18657   if (unlikely(!c_apiConnectRecordPool.getValidPtr(transPtr)))
18658   {
18659     jam();
18660     warningHandlerLab(signal, __LINE__);
18661     releaseSections(handle);
18662     return;
18663   }//if
18664   ApiConnectRecord * const regApiPtr = transPtr.p;
18665   // Seize index operation
18666   TcIndexOperationPtr indexOpPtr;
18667 
18668 #ifdef ERROR_INSERT
18669   if (ERROR_INSERTED(8100))
18670   {
18671     char buf[128];
18672     BaseString::snprintf(buf, sizeof(buf), "Inserted 8100, startFlag %u, regApiPtr->apiConnectstate %u, regApiPtr->abortState %u", startFlag, regApiPtr->apiConnectstate, regApiPtr->abortState);
18673     warningEvent("%s", buf);
18674 
18675     if (startFlag == 1)
18676     {
18677       jam();
18678       /*
18679         Phase 1:
18680         Abort the transaction by simulating a fake node failure.
18681         Don't send any TCROLLBACKREP until in next TCINDXREQ call
18682         to simulate a slow signal still in the air.
18683       */
18684       Signal s = *signal;
18685       signal->theData[0] = TcContinueB::ZDEBUG_DELAYED_ABORT;
18686       signal->theData[1] = transPtr.i;
18687       signal->theData[2] = regApiPtr->transid[0];
18688       signal->theData[3] = regApiPtr->transid[1];
18689       signal->theData[4] = ZNODEFAIL_BEFORE_COMMIT;
18690       signal->theData[5] = RS_TCROLLBACKREP;
18691       signal->theData[6] = 8101;
18692       sendSignalWithDelay(reference(), GSN_CONTINUEB, signal, 100, 6);
18693       *signal = s;
18694     }
18695   }
18696   else if (ERROR_INSERTED(8101))
18697   {
18698     char buf[128];
18699     BaseString::snprintf(buf, sizeof(buf), "Inserted 8101, startFlag %u, regApiPtr->apiConnectstate %u, regApiPtr->abortState %u", startFlag, regApiPtr->apiConnectstate, regApiPtr->abortState);
18700     warningEvent("%s", buf);
18701 
18702     jam();
18703     /*
18704       Phase 2:
18705       Transaction has been aborted by a fake node failure,
18706       but the API hasn't been informed yet. Force the state
18707       into waiting for pending signals.
18708     */
18709     if (regApiPtr->returncode != ZNODEFAIL_BEFORE_COMMIT ||
18710         regApiPtr->apiConnectstate != CS_ABORTING ||
18711         regApiPtr->abortState != AS_IDLE)
18712     {
18713       /*
18714         We are waiting for abort to complete, but have not reached
18715         the transaction state we want to test. Try again.
18716       */
18717       jam();
18718       sendSignalWithDelay(reference(), GSN_TCINDXREQ, signal, 100,
18719                           TcKeyReq::StaticLength, &handle);
18720       return;
18721     }
18722     CLEAR_ERROR_INSERT_VALUE;
18723   }
18724 #endif
18725 
18726    ConnectionState conState = regApiPtr->apiConnectstate;
18727    if (startFlag == 1 &&
18728        (conState == CS_CONNECTED ||
18729         (conState == CS_STARTED &&
18730          regApiPtr->tcConnect.isEmpty()) ||
18731         (conState == CS_ABORTING &&
18732          regApiPtr->abortState == AS_IDLE)))
18733   {
18734     jam();
18735     // This is a newly started transaction, clean-up from any
18736     // previous transaction.
18737     initApiConnectRec(signal, regApiPtr, true);
18738     regApiPtr->apiConnectstate = CS_STARTED;
18739   }//if (startFlag == 1 && ...
18740   else if (regApiPtr->apiConnectstate == CS_ABORTING)
18741   {
18742     jam();
18743     /*
18744       Transaction has been aborted and we have to do error
18745       handling, but since when we read the index table
18746       the generated TCKEYREQ will do the proper error
18747       handling. Any received TCKEYREF will be forwarded
18748       to the original sender as a TCINDXREF.
18749      */
18750   }//if (regApiPtr->apiConnectstate == CS_ABORTING)
18751 
18752   if (getNodeState().startLevel == NodeState::SL_SINGLEUSER &&
18753       getNodeState().getSingleUserApi() !=
18754       refToNode(regApiPtr->ndbapiBlockref))
18755   {
18756     jam();
18757     releaseSections(handle);
18758     terrorCode = ZCLUSTER_IN_SINGLEUSER_MODE;
18759     regApiPtr->m_flags |=
18760       TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
18761       ApiConnectRecord::TF_EXEC_FLAG : 0;
18762     abortErrorLab(signal, transPtr);
18763     return;
18764   }
18765 
18766   if (regApiPtr->apiCopyRecord == RNIL)
18767   {
18768     jam();
18769     if (unlikely(!seizeApiConnectCopy(signal, transPtr.p)))
18770     {
18771       jam();
18772       releaseSections(handle);
18773       terrorCode = ZSEIZE_API_COPY_ERROR;
18774       regApiPtr->m_flags |=
18775         TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
18776         ApiConnectRecord::TF_EXEC_FLAG : 0;
18777       abortErrorLab(signal, transPtr);
18778       return;
18779     }
18780   }
18781 
18782   if (ERROR_INSERTED(8036) || !seizeIndexOperation(regApiPtr, indexOpPtr)) {
18783     jam();
18784     releaseSections(handle);
18785     // Failed to allocate index operation
18786     terrorCode = 288;
18787     regApiPtr->m_flags |=
18788       TcKeyReq::getExecuteFlag(tcIndxRequestInfo) ?
18789       ApiConnectRecord::TF_EXEC_FLAG : 0;
18790     abortErrorLab(signal, transPtr);
18791     return;
18792   }
18793   TcIndexOperation* indexOp = indexOpPtr.p;
18794   indexOp->indexOpId = indexOpPtr.i;
18795 
18796   // Save original signal
18797   indexOp->tcIndxReq = *tcIndxReq;
18798   indexOp->connectionIndex = TapiIndex;
18799   regApiPtr->accumulatingIndexOp = indexOp->indexOpId;
18800 
18801   if (isLongTcIndxReq)
18802   {
18803     jam();
18804     /* KeyInfo and AttrInfo already received into sections */
18805     SegmentedSectionPtr keyInfoSection, attrInfoSection;
18806 
18807     /* Store i value for first long section of KeyInfo
18808      * and AttrInfo in Index operation
18809      */
18810     handle.getSection(keyInfoSection,
18811                       TcKeyReq::KeyInfoSectionNum);
18812 
18813     indexOp->keyInfoSectionIVal= keyInfoSection.i;
18814 
18815     if (handle.m_cnt == 2)
18816     {
18817       handle.getSection(attrInfoSection,
18818                         TcKeyReq::AttrInfoSectionNum);
18819       indexOp->attrInfoSectionIVal= attrInfoSection.i;
18820     }
18821 
18822     if (TcKeyReq::getDeferredConstraints(tcIndxRequestInfo))
18823     {
18824       regApiPtr->m_flags |= ApiConnectRecord::TF_DEFERRED_CONSTRAINTS;
18825     }
18826 
18827     if (TcKeyReq::getDisableFkConstraints(tcIndxRequestInfo))
18828     {
18829       regApiPtr->m_flags |= ApiConnectRecord::TF_DISABLE_FK_CONSTRAINTS;
18830     }
18831     indexOp->savedFlags = regApiPtr->m_flags;
18832 
18833     /* Detach sections from the handle
18834      * Success path code, or index operation cleanup is
18835      * now responsible for freeing the sections
18836      */
18837     handle.clear();
18838 
18839     /* All data received, process */
18840     readIndexTable(signal, transPtr, indexOp, 0);
18841     return;
18842   }
18843   else
18844   {
18845     jam();
18846     /* Short TcIndxReq, build up KeyInfo and AttrInfo
18847      * sections from separate signals
18848      */
18849     Uint32 * dataPtr = &tcIndxReq->scanInfo;
18850     Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
18851     Uint32 attrLength = TcKeyReq::getAttrinfoLen(tcIndxReq->attrLen);
18852 
18853     indexOp->pendingKeyInfo = indexLength;
18854     indexOp->pendingAttrInfo = attrLength;
18855 
18856     /**
18857      * Clear lengths from requestInfo to avoid confusion processing
18858      * long TcKeyReqs with bits from short TcKeyReqs set in their
18859      * requestInfo
18860      */
18861     TcKeyReq::setAIInTcKeyReq(indexOp->tcIndxReq.requestInfo, 0);
18862     TcKeyReq::setKeyLength(indexOp->tcIndxReq.requestInfo, 0);
18863 
18864     const Uint32 includedIndexLength = MIN(indexLength, TcKeyReq::MaxKeyInfo);
18865     const Uint32 includedAttrLength = MIN(attrLength, TcKeyReq::MaxAttrInfo);
18866     int ret;
18867 
18868     if ((ret = saveINDXKEYINFO(signal,
18869                                indexOp,
18870                                dataPtr,
18871                                includedIndexLength)) == 0)
18872     {
18873       jam();
18874       /* All KI + no AI received, process */
18875       readIndexTable(signal, transPtr, indexOp, 0);
18876       return;
18877     }
18878     else if (ret == -1)
18879     {
18880       jam();
18881       return;
18882     }
18883 
18884     dataPtr += includedIndexLength;
18885 
18886     if (saveINDXATTRINFO(signal,
18887                          indexOp,
18888                          dataPtr,
18889                          includedAttrLength) == 0)
18890     {
18891       jam();
18892       /* All KI and AI received, process */
18893       readIndexTable(signal, transPtr, indexOp, 0);
18894       return;
18895     }
18896   }
18897 }
18898 
execINDXKEYINFO(Signal * signal)18899 void Dbtc::execINDXKEYINFO(Signal* signal)
18900 {
18901   jamEntry();
18902   Uint32 keyInfoLength = signal->getLength() - IndxKeyInfo::HeaderLength;
18903   IndxKeyInfo * const indxKeyInfo =  (IndxKeyInfo *)signal->getDataPtr();
18904   const Uint32 *src = indxKeyInfo->getData();
18905   const UintR TconnectIndex = indxKeyInfo->connectPtr;
18906   ApiConnectRecordPtr transPtr;
18907   transPtr.i = TconnectIndex;
18908   if (unlikely(!c_apiConnectRecordPool.getValidPtr(transPtr)))
18909   {
18910     jam();
18911     warningHandlerLab(signal, __LINE__);
18912     return;
18913   }//if
18914   ApiConnectRecord * const regApiPtr = transPtr.p;
18915   TcIndexOperationPtr indexOpPtr;
18916 
18917   if (compare_transid(regApiPtr->transid, indxKeyInfo->transId) == false)
18918   {
18919     jam();
18920     return;
18921   }
18922 
18923   if (regApiPtr->apiConnectstate == CS_ABORTING)
18924   {
18925     jam();
18926     return;
18927   }
18928 
18929   indexOpPtr.i = regApiPtr->accumulatingIndexOp;
18930   if (indexOpPtr.i != RNIL && c_theIndexOperationPool.getValidPtr(indexOpPtr))
18931   {
18932     TcIndexOperation* indexOp = indexOpPtr.p;
18933     ndbassert( indexOp->pendingKeyInfo > 0 );
18934 
18935     if (saveINDXKEYINFO(signal,
18936                         indexOp,
18937                         src,
18938                         keyInfoLength) == 0)
18939     {
18940       jam();
18941       /* All KI + AI received, process */
18942       readIndexTable(signal, transPtr, indexOp, 0);
18943     }
18944   }
18945 }
18946 
execINDXATTRINFO(Signal * signal)18947 void Dbtc::execINDXATTRINFO(Signal* signal)
18948 {
18949   jamEntry();
18950   Uint32 attrInfoLength = signal->getLength() - IndxAttrInfo::HeaderLength;
18951   IndxAttrInfo * const indxAttrInfo =  (IndxAttrInfo *)signal->getDataPtr();
18952   const Uint32 *src = indxAttrInfo->getData();
18953   const UintR TconnectIndex = indxAttrInfo->connectPtr;
18954   ApiConnectRecordPtr transPtr;
18955   transPtr.i = TconnectIndex;
18956   if (unlikely(!c_apiConnectRecordPool.getValidPtr(transPtr)))
18957   {
18958     jam();
18959     warningHandlerLab(signal, __LINE__);
18960     return;
18961   }//if
18962   ApiConnectRecord * const regApiPtr = transPtr.p;
18963   TcIndexOperationPtr indexOpPtr;
18964 
18965   if (compare_transid(regApiPtr->transid, indxAttrInfo->transId) == false)
18966   {
18967     jam();
18968     return;
18969   }
18970 
18971   if (regApiPtr->apiConnectstate == CS_ABORTING)
18972   {
18973     jam();
18974     return;
18975   }
18976 
18977   indexOpPtr.i = regApiPtr->accumulatingIndexOp;
18978   if (indexOpPtr.i != RNIL && c_theIndexOperationPool.getValidPtr(indexOpPtr))
18979   {
18980     TcIndexOperation* indexOp = indexOpPtr.p;
18981     ndbassert( indexOp->pendingAttrInfo > 0 );
18982 
18983     if (saveINDXATTRINFO(signal,
18984                          indexOp,
18985                          src,
18986                          attrInfoLength) == 0)
18987     {
18988       jam();
18989       /* All KI + AI received, process */
18990       readIndexTable(signal, transPtr, indexOp, 0);
18991     }
18992   }
18993 }
18994 
18995 /**
18996  * Save received KeyInfo
18997  * Return true if we have received all needed data
18998  */
18999 int
saveINDXKEYINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)19000 Dbtc::saveINDXKEYINFO(Signal* signal,
19001                       TcIndexOperation* indexOp,
19002                       const Uint32 *src,
19003                       Uint32 len)
19004 {
19005   if (ERROR_INSERTED(8052) ||
19006       ! appendToSection(indexOp->keyInfoSectionIVal,
19007                         src,
19008                         len))
19009   {
19010     jam();
19011     // Failed to seize keyInfo, abort transaction
19012 #ifdef VM_TRACE
19013     ndbout_c("Dbtc::saveINDXKEYINFO: Failed to seize buffer for KeyInfo\n");
19014 #endif
19015     // Abort transaction
19016     ApiConnectRecordPtr apiConnectptr;
19017     apiConnectptr.i = indexOp->connectionIndex;
19018     c_apiConnectRecordPool.getPtr(apiConnectptr);
19019     releaseIndexOperation(apiConnectptr.p, indexOp);
19020     terrorCode = 289;
19021     if (TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
19022       apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
19023     abortErrorLab(signal, apiConnectptr);
19024     return -1;
19025   }
19026   indexOp->pendingKeyInfo-= len;
19027 
19028   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp))
19029   {
19030     jam();
19031     return 0;
19032   }
19033   return 1;
19034 }
19035 
receivedAllINDXKEYINFO(TcIndexOperation * indexOp)19036 bool Dbtc::receivedAllINDXKEYINFO(TcIndexOperation* indexOp)
19037 {
19038   return (indexOp->pendingKeyInfo == 0);
19039 }
19040 
19041 /**
19042  * Save signal INDXATTRINFO
19043  * Return true if we have received all needed data
19044  */
19045 int
saveINDXATTRINFO(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)19046 Dbtc::saveINDXATTRINFO(Signal* signal,
19047                        TcIndexOperation* indexOp,
19048                        const Uint32 *src,
19049                        Uint32 len)
19050 {
19051   if (ERROR_INSERTED(8051) ||
19052       ! appendToSection(indexOp->attrInfoSectionIVal,
19053                         src,
19054                         len))
19055   {
19056     jam();
19057 #ifdef VM_TRACE
19058     ndbout_c("Dbtc::saveINDXATTRINFO: Failed to seize buffer for attrInfo\n");
19059 #endif
19060     ApiConnectRecordPtr apiConnectptr;
19061     apiConnectptr.i = indexOp->connectionIndex;
19062     c_apiConnectRecordPool.getPtr(apiConnectptr);
19063     releaseIndexOperation(apiConnectptr.p, indexOp);
19064     terrorCode = 289;
19065     if (TcKeyReq::getExecuteFlag(indexOp->tcIndxReq.requestInfo))
19066       apiConnectptr.p->m_flags |= ApiConnectRecord::TF_EXEC_FLAG;
19067     abortErrorLab(signal, apiConnectptr);
19068     return -1;
19069   }
19070 
19071   indexOp->pendingAttrInfo-= len;
19072 
19073   if (receivedAllINDXKEYINFO(indexOp) && receivedAllINDXATTRINFO(indexOp))
19074   {
19075     jam();
19076     return 0;
19077   }
19078   return 1;
19079 }
19080 
receivedAllINDXATTRINFO(TcIndexOperation * indexOp)19081 bool Dbtc::receivedAllINDXATTRINFO(TcIndexOperation* indexOp)
19082 {
19083   return (indexOp->pendingAttrInfo == 0);
19084 }
19085 
19086 #ifdef ERROR_INSERT
19087 extern bool ErrorImportActive;
19088 #endif
19089 
saveTRANSID_AI(Signal * signal,TcIndexOperation * indexOp,const Uint32 * src,Uint32 len)19090 Uint32 Dbtc::saveTRANSID_AI(Signal* signal,
19091                             TcIndexOperation* indexOp,
19092                             const Uint32 *src,
19093                             Uint32 len)
19094 {
19095   /* TransID_AI is received as a result of looking up a
19096    * unique index table
19097    * The unique index table is looked up using the index
19098    * key to receive a single attribute containing the
19099    * fragment holding the base table row and the base
19100    * table primary key.
19101    * This is later used to build a TCKEYREQ against the
19102    * base table.
19103    * In this method, we prepare a KEYINFO section for the
19104    * TCKEYREQ as we receive TRANSID_AI words.
19105    *
19106    * Expected TRANSID_AI words :
19107    *
19108    *   Word(s)  Description           States
19109    *
19110    *   0        Attribute header      ITAS_WAIT_HEADER
19111    *             containing length     -> ITAS_WAIT_FRAGID
19112    *
19113    *   1        Fragment Id           ITAS_WAIT_FRAGID
19114    *                                   -> ITAS_WAIT_KEY
19115    *
19116    *   [2..N]   Base table primary    ITAS_WAIT_KEY
19117    *            key info               -> [ ITAS_WAIT_KEY |
19118    *                                        ITAS_WAIT_KEY_FAIL ]
19119    *                                   -> ITAS_ALL_RECEIVED
19120    *
19121    * The outgoing KeyInfo section contains the base
19122    * table primary key info, with the fragment id passed
19123    * as the distribution key.
19124    * ITAS_WAIT_KEY_FAIL state is entered when there is no
19125    * space to store received TRANSID_AI information and
19126    * key collection must fail.  Transaction abort is performed
19127    * once all TRANSID_AI is received, and the system waits in
19128    * ITAS_WAIT_KEY_FAIL state until then.
19129    *
19130    */
19131   Uint32 remain= len;
19132 
19133   while (remain != 0)
19134   {
19135     switch(indexOp->transIdAIState) {
19136     case ITAS_WAIT_HEADER:
19137     {
19138       jam();
19139       ndbassert(indexOp->transIdAISectionIVal == RNIL);
19140       /* Look at the first AttributeHeader to get the
19141        * expected size of the primary key attribute
19142        */
19143       AttributeHeader* head = (AttributeHeader *) src;
19144       ndbassert(head->getHeaderSize() == 1);
19145       indexOp->pendingTransIdAI = 1 + head->getDataSize();
19146 
19147       src++;
19148       remain--;
19149       indexOp->transIdAIState = ITAS_WAIT_FRAGID;
19150       break;
19151     }
19152     case ITAS_WAIT_FRAGID:
19153     {
19154       jam();
19155       ndbassert(indexOp->transIdAISectionIVal == RNIL);
19156       /* Grab the fragment Id word */
19157       indexOp->fragmentId= *src;
19158 
19159       src++;
19160       remain--;
19161       indexOp->transIdAIState = ITAS_WAIT_KEY;
19162       break;
19163     }
19164     case ITAS_WAIT_KEY:
19165     {
19166       jam();
19167       /* Add key information to long section */
19168 #ifdef ERROR_INSERT
19169       if (ERROR_INSERTED(8066))
19170       {
19171         ErrorImportActive = true;
19172       }
19173 #endif
19174 
19175       bool res = appendToSection(indexOp->transIdAISectionIVal, src, remain);
19176 #ifdef ERROR_INSERT
19177       if (ERROR_INSERTED(8066))
19178       {
19179         ErrorImportActive = false;
19180       }
19181 #endif
19182 
19183       if (res)
19184       {
19185         jam();
19186         remain= 0;
19187         break;
19188       }
19189       else
19190       {
19191         jam();
19192 #ifdef VM_TRACE
19193         ndbout_c("Dbtc::saveTRANSID_AI: Failed to seize buffer for TRANSID_AI\n");
19194 #endif
19195         indexOp->transIdAIState= ITAS_WAIT_KEY_FAIL;
19196       }
19197     }
19198       // Fall through to ITAS_WAIT_KEY_FAIL state handling
19199 
19200     case ITAS_WAIT_KEY_FAIL:
19201     {
19202       /* Failed when collecting key previously - if we have all the
19203        * TRANSID_AI now then we abort
19204        */
19205       if (indexOp->pendingTransIdAI > len)
19206       {
19207         /* Still some TransIdAI to arrive, keep waiting as if we had
19208          * stored it
19209          */
19210         remain= 0;
19211         break;
19212       }
19213 
19214       /* All TransIdAI has arrived, abort */
19215       ApiConnectRecordPtr apiConnectptr;
19216       apiConnectptr.i = indexOp->connectionIndex;
19217       c_apiConnectRecordPool.getPtr(apiConnectptr);
19218       releaseIndexOperation(apiConnectptr.p, indexOp);
19219       terrorCode = ZGET_DATAREC_ERROR;
19220       abortErrorLab(signal, apiConnectptr);
19221       return ZGET_DATAREC_ERROR;
19222     }
19223 
19224     case ITAS_ALL_RECEIVED:
19225       jam();
19226       // Fall through
19227     default:
19228       jam();
19229       /* Bad state, or bad state to receive TransId_Ai in */
19230       // Todo : Check error handling here.
19231 #ifdef VM_TRACE
19232       ndbout_c("Dbtc::saveTRANSID_AI: Bad state when receiving\n");
19233 #endif
19234       ApiConnectRecordPtr apiConnectptr;
19235       apiConnectptr.i = indexOp->connectionIndex;
19236       c_apiConnectRecordPool.getPtr(apiConnectptr);
19237       releaseIndexOperation(apiConnectptr.p, indexOp);
19238       terrorCode = ZINCONSISTENT_INDEX_USE;
19239       abortErrorLab(signal, apiConnectptr);
19240       return ZINCONSISTENT_INDEX_USE;
19241     } // switch
19242   } // while
19243 
19244   if ((indexOp->pendingTransIdAI-= len) == 0)
19245     indexOp->transIdAIState = ITAS_ALL_RECEIVED;
19246 
19247   return ZOK;
19248 }
19249 
receivedAllTRANSID_AI(TcIndexOperation * indexOp)19250 bool Dbtc::receivedAllTRANSID_AI(TcIndexOperation* indexOp)
19251 {
19252   return (indexOp->transIdAIState == ITAS_ALL_RECEIVED);
19253 }
19254 
19255 /**
19256  * Receive signal TCINDXCONF
19257  * This can be either the return of reading an index table
19258  * or performing an index operation
19259  */
execTCKEYCONF(Signal * signal)19260 void Dbtc::execTCKEYCONF(Signal* signal)
19261 {
19262   TcKeyConf * const tcKeyConf =  (TcKeyConf *)signal->getDataPtr();
19263   TcIndexOperationPtr indexOpPtr;
19264 
19265   jamEntry();
19266   indexOpPtr.i = tcKeyConf->apiConnectPtr;
19267   if (unlikely(!c_theIndexOperationPool.getValidPtr(indexOpPtr) ||
19268                indexOpPtr.i == RNIL))
19269   {
19270     jam();
19271     // Missing or invalid index operation
19272     return;
19273   }
19274 
19275   TcIndexOperation* const indexOp = indexOpPtr.p;
19276 
19277   /**
19278    * Check on TCKEYCONF whether the the transaction was committed
19279    */
19280   ndbassert(TcKeyConf::getCommitFlag(tcKeyConf->confInfo) == false);
19281 
19282   ApiConnectRecordPtr apiConnectptr;
19283   apiConnectptr.i = indexOp->connectionIndex;
19284   if (unlikely(!c_apiConnectRecordPool.getValidPtr(apiConnectptr) ||
19285                apiConnectptr.i == RNIL))
19286   {
19287     jam();
19288     // Missing or invalid api connection for index operation
19289     return;
19290   }
19291   ApiConnectRecord * const regApiPtr = apiConnectptr.p;
19292 
19293   switch(indexOp->indexOpState) {
19294   case(IOS_NOOP): {
19295     jam();
19296     // Should never happen, abort
19297     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19298 
19299     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
19300     tcIndxRef->transId[0] = regApiPtr->transid[0];
19301     tcIndxRef->transId[1] = regApiPtr->transid[1];
19302     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
19303     tcIndxRef->errorData = 0;
19304     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
19305 	       TcKeyRef::SignalLength, JBB);
19306     return;
19307   }
19308   case(IOS_INDEX_ACCESS): {
19309     jam();
19310     // Just waiting for the TRANSID_AI now
19311     indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI;
19312     break;
19313   }
19314   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
19315     jam();
19316     // Double TCKEYCONF, should never happen, abort
19317     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19318 
19319     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
19320     tcIndxRef->transId[0] = regApiPtr->transid[0];
19321     tcIndxRef->transId[1] = regApiPtr->transid[1];
19322     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
19323     tcIndxRef->errorData = 0;
19324     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
19325 	       TcKeyRef::SignalLength, JBB);
19326     return;
19327   }
19328   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
19329     jam();
19330     // Continue with index operation
19331     executeIndexOperation(signal, regApiPtr, indexOp);
19332     break;
19333   }
19334   }
19335 }
19336 
execTCKEYREF(Signal * signal)19337 void Dbtc::execTCKEYREF(Signal* signal)
19338 {
19339   TcKeyRef * const tcKeyRef = (TcKeyRef *)signal->getDataPtr();
19340   TcIndexOperationPtr indexOpPtr;
19341 
19342   jamEntry();
19343   indexOpPtr.i = tcKeyRef->connectPtr;
19344   if (!c_theIndexOperationPool.getValidPtr(indexOpPtr) || indexOpPtr.i == RNIL)
19345   {
19346     jam();
19347     // Missing or invalid index operation
19348     return;
19349   }
19350   TcIndexOperation * const indexOp = indexOpPtr.p;
19351   switch(indexOp->indexOpState) {
19352   case(IOS_NOOP): {
19353     jam();
19354     // Should never happen, abort
19355     break;
19356   }
19357   case(IOS_INDEX_ACCESS):
19358   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI):
19359   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
19360     jam();
19361     // Send TCINDXREF
19362 
19363     ApiConnectRecordPtr apiConnectptr;
19364     apiConnectptr.i = indexOp->connectionIndex;
19365     if (!c_apiConnectRecordPool.getValidPtr(apiConnectptr) || apiConnectptr.i == RNIL)
19366     {
19367       jam();
19368       // Invalid index operation, no valid api connection.
19369       return;
19370     }
19371     ApiConnectRecord * const regApiPtr = apiConnectptr.p;
19372 
19373     TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
19374     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19375 
19376     tcIndxRef->connectPtr = tcIndxReq->senderData;
19377     tcIndxRef->transId[0] = tcKeyRef->transId[0];
19378     tcIndxRef->transId[1] = tcKeyRef->transId[1];
19379     tcIndxRef->errorCode = tcKeyRef->errorCode;
19380     tcIndxRef->errorData = 0;
19381 
19382     releaseIndexOperation(regApiPtr, indexOp);
19383 
19384     sendSignal(regApiPtr->ndbapiBlockref,
19385                GSN_TCINDXREF, signal, TcKeyRef::SignalLength, JBB);
19386     return;
19387   }
19388   }
19389 }
19390 
execTRANSID_AI_R(Signal * signal)19391 void Dbtc::execTRANSID_AI_R(Signal* signal){
19392   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
19393   Uint32 sigLen = signal->length();
19394   Uint32 dataLen = sigLen - TransIdAI::HeaderLength - 1;
19395   Uint32 recBlockref = transIdAI->attrData[dataLen];
19396 
19397   jamEntry();
19398 
19399   SectionHandle handle(this, signal);
19400 
19401   /**
19402    * Forward signal to final destination
19403    * Truncate last word since that was used to hold the final dest.
19404    */
19405   sendSignal(recBlockref, GSN_TRANSID_AI,
19406 	     signal, sigLen - 1, JBB,
19407 	     &handle);
19408 }
19409 
execKEYINFO20_R(Signal * signal)19410 void Dbtc::execKEYINFO20_R(Signal* signal){
19411   KeyInfo20 * const keyInfo =  (KeyInfo20 *)signal->getDataPtr();
19412   Uint32 sigLen = signal->length();
19413   Uint32 dataLen = sigLen - KeyInfo20::HeaderLength - 1;
19414   Uint32 recBlockref = keyInfo->keyData[dataLen];
19415 
19416   jamEntry();
19417 
19418   SectionHandle handle(this, signal);
19419 
19420   /**
19421    * Forward signal to final destination
19422    * Truncate last word since that was used to hold the final dest.
19423    */
19424   sendSignal(recBlockref, GSN_KEYINFO20,
19425 	     signal, sigLen - 1, JBB,
19426 	     &handle);
19427 }
19428 
19429 
19430 /**
19431  * execTRANSID_AI
19432  *
19433  * TRANSID_AI are received as a result of performing a read on
19434  * the index table as part of a (unique) index operation.
19435  * The data received is the primary key of the base table
19436  * which is then used to perform the index operation on the
19437  * base table.
19438  */
execTRANSID_AI(Signal * signal)19439 void Dbtc::execTRANSID_AI(Signal* signal)
19440 {
19441   TransIdAI * const transIdAI =  (TransIdAI *)signal->getDataPtr();
19442 
19443   jamEntry();
19444   TcIndexOperationPtr indexOpPtr;
19445   indexOpPtr.i = transIdAI->connectPtr;
19446   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
19447   indexOpPtr.p = indexOp;
19448   if (!indexOp) {
19449     jam();
19450     // Missing index operation
19451   }
19452   const UintR TconnectIndex = indexOp->connectionIndex;
19453   ApiConnectRecordPtr transPtr;
19454 
19455   transPtr.i = TconnectIndex;
19456   c_apiConnectRecordPool.getPtr(transPtr);
19457   ApiConnectRecord * const regApiPtr = transPtr.p;
19458 
19459   // Acccumulate attribute data
19460   SectionHandle handle(this, signal);
19461   bool longSignal = (handle.m_cnt == 1);
19462   Uint32 errorCode = ZOK;
19463   if (longSignal)
19464   {
19465     SegmentedSectionPtr dataPtr;
19466     Uint32 dataLen;
19467     ndbrequire(handle.getSection(dataPtr, 0));
19468     dataLen = dataPtr.sz;
19469 
19470     SectionSegment * ptrP = dataPtr.p;
19471     while (dataLen > NDB_SECTION_SEGMENT_SZ)
19472     {
19473       errorCode = saveTRANSID_AI(signal, indexOp, &ptrP->theData[0],
19474                                  NDB_SECTION_SEGMENT_SZ);
19475       if (errorCode != ZOK)
19476       {
19477         releaseSections(handle);
19478         goto save_error;
19479       }
19480       dataLen -= NDB_SECTION_SEGMENT_SZ;
19481       ptrP = g_sectionSegmentPool.getPtr(ptrP->m_nextSegment);
19482     }
19483     errorCode = saveTRANSID_AI(signal, indexOp, &ptrP->theData[0], dataLen);
19484     if (errorCode != ZOK)
19485     {
19486       releaseSections(handle);
19487       goto save_error;
19488     }
19489 
19490     releaseSections(handle);
19491   }
19492   else
19493   {
19494     /* Short TransId_AI signal */
19495     errorCode = saveTRANSID_AI(signal,
19496                                indexOp,
19497                                transIdAI->getData(),
19498                                signal->getLength() - TransIdAI::HeaderLength);
19499     if (errorCode != ZOK) {
19500     save_error:
19501       jam();
19502       // Failed to allocate space for TransIdAI
19503       // Todo : How will this behave when transaction already aborted
19504       // in saveTRANSID_AI call?
19505       TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19506 
19507       tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
19508       tcIndxRef->transId[0] = regApiPtr->transid[0];
19509       tcIndxRef->transId[1] = regApiPtr->transid[1];
19510       tcIndxRef->errorCode = errorCode;
19511       tcIndxRef->errorData = 0;
19512       sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
19513                  TcKeyRef::SignalLength, JBB);
19514       return;
19515     }
19516   }
19517 
19518   switch(indexOp->indexOpState) {
19519   case(IOS_NOOP): {
19520     jam();
19521     // Should never happen, abort
19522     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19523 
19524     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
19525     tcIndxRef->transId[0] = regApiPtr->transid[0];
19526     tcIndxRef->transId[1] = regApiPtr->transid[1];
19527     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
19528     tcIndxRef->errorData = 0;
19529     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
19530 	       TcKeyRef::SignalLength, JBB);
19531     return;
19532     break;
19533   }
19534   case(IOS_INDEX_ACCESS): {
19535     jam();
19536     // Check if all TRANSID_AI have been received
19537     if (receivedAllTRANSID_AI(indexOp)) {
19538       jam();
19539       // Just waiting for a TCKEYCONF now
19540       indexOp->indexOpState = IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF;
19541     }
19542     // else waiting for either TRANSID_AI or TCKEYCONF
19543     break;
19544     }
19545   case(IOS_INDEX_ACCESS_WAIT_FOR_TCKEYCONF): {
19546     jam();
19547 #ifdef VM_TRACE
19548     ndbout_c("Dbtc::execTRANSID_AI: Too many TRANSID_AI, ignore for now\n");
19549 #endif
19550     /*
19551     // Too many TRANSID_AI
19552     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19553 
19554     tcIndexRef->connectPtr = indexOp->tcIndxReq.senderData;
19555     tcIndxRef->transId[0] = regApiPtr->transid[0];
19556     tcIndxRef->transId[1] = regApiPtr->transid[1];
19557     tcIndxRef->errorCode = 4349;
19558     tcIndxRef->errorData = 0;
19559     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
19560                TcKeyRef::SignalLength, JBB);
19561     */
19562     break;
19563   }
19564   case(IOS_INDEX_ACCESS_WAIT_FOR_TRANSID_AI): {
19565     jam();
19566     // Check if all TRANSID_AI have been received
19567     if (receivedAllTRANSID_AI(indexOp)) {
19568       jam();
19569       // Continue with index operation
19570       executeIndexOperation(signal, regApiPtr, indexOp);
19571     }
19572     // else continue waiting for more TRANSID_AI
19573     break;
19574   }
19575   }
19576 }
19577 
execTCROLLBACKREP(Signal * signal)19578 void Dbtc::execTCROLLBACKREP(Signal* signal)
19579 {
19580   TcRollbackRep* tcRollbackRep =  (TcRollbackRep *)signal->getDataPtr();
19581   jamEntry();
19582   TcIndexOperationPtr indexOpPtr;
19583   indexOpPtr.i = tcRollbackRep->connectPtr;
19584   TcIndexOperation* indexOp = c_theIndexOperationPool.getPtr(indexOpPtr.i);
19585   indexOpPtr.p = indexOp;
19586   tcRollbackRep =  (TcRollbackRep *)signal->getDataPtrSend();
19587   tcRollbackRep->connectPtr = indexOp->tcIndxReq.senderData;
19588   ApiConnectRecordPtr apiConnectptr;
19589   apiConnectptr.i = indexOp->tcIndxReq.apiConnectPtr;
19590   c_apiConnectRecordPool.getPtr(apiConnectptr);
19591   sendSignal(apiConnectptr.p->ndbapiBlockref,
19592 	     GSN_TCROLLBACKREP, signal, TcRollbackRep::SignalLength, JBB);
19593 }
19594 
19595 /**
19596  * Read index table with the index attributes as PK
19597  */
readIndexTable(Signal * signal,ApiConnectRecordPtr transPtr,TcIndexOperation * indexOp,Uint32 special_op_flags)19598 void Dbtc::readIndexTable(Signal* signal,
19599                           ApiConnectRecordPtr transPtr,
19600                           TcIndexOperation* indexOp,
19601                           Uint32 special_op_flags)
19602 {
19603   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
19604   Uint32 tcKeyRequestInfo = indexOp->tcIndxReq.requestInfo;
19605   TcIndexDataPtr indexDataPtr;
19606   Uint32 transId1 = indexOp->tcIndxReq.transId1;
19607   Uint32 transId2 = indexOp->tcIndxReq.transId2;
19608   ApiConnectRecord* regApiPtr = transPtr.p;
19609 
19610   const Operation_t opType =
19611     (Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
19612 
19613   // Find index table
19614   indexDataPtr.i = indexOp->tcIndxReq.tableId;
19615   /* Using a IgnoreAlloc variant of getPtr to make the lookup safe.
19616    * The validity of the index is checked subsequently using indexState. */
19617   c_theIndexes.getPool().getPtrIgnoreAlloc(indexDataPtr);
19618   if (indexDataPtr.p == NULL ||
19619       indexDataPtr.p->indexState == IS_OFFLINE )
19620   {
19621     /* The index was either null or was already dropped.
19622      * Abort the operation and release the resources. */
19623     jam();
19624     terrorCode = ZNO_SUCH_TABLE;
19625     /* If the signal is last in the batch, don't wait for more
19626      * and enable sending the reply signal in abortErrorLab */
19627     regApiPtr->m_flags |=
19628       TcKeyReq::getExecuteFlag(tcKeyRequestInfo) ?
19629       ApiConnectRecord::TF_EXEC_FLAG : 0;
19630     abortErrorLab(signal, transPtr);
19631     return;
19632   }
19633   TcIndexData* indexData = indexDataPtr.p;
19634   tcKeyReq->transId1 = transId1;
19635   tcKeyReq->transId2 = transId2;
19636   tcKeyReq->tableId = indexData->indexId;
19637   tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
19638   TcKeyReq::setOperationType(tcKeyRequestInfo,
19639 			     opType == ZREAD ? ZREAD : ZREAD_EX);
19640   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0); // No AI in long TCKEYREQ
19641   TcKeyReq::setInterpretedFlag(tcKeyRequestInfo, 0);
19642   tcKeyReq->senderData = indexOp->indexOpId;
19643   indexOp->indexOpState = IOS_INDEX_ACCESS;
19644   regApiPtr->executingIndexOp = regApiPtr->accumulatingIndexOp;
19645   regApiPtr->accumulatingIndexOp = RNIL;
19646   regApiPtr->m_special_op_flags =
19647     TcConnectRecord::SOF_INDEX_TABLE_READ | special_op_flags;
19648 
19649   if (ERROR_INSERTED(8037))
19650   {
19651     ndbout_c("shifting index version");
19652     tcKeyReq->tableSchemaVersion = ~(Uint32)indexOp->tcIndxReq.tableSchemaVersion;
19653   }
19654   tcKeyReq->attrLen = 1; // Primary key is stored as one attribute
19655   tcKeyReq->requestInfo = tcKeyRequestInfo;
19656 
19657   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
19658   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
19659 
19660   /* Long TCKEYREQ Signal sections
19661    * We attach the KeyInfo section received from the user, and
19662    * create a new AttrInfo section with just one AttributeHeader
19663    * to retrieve the base table primary key
19664    */
19665   Ptr<SectionSegment> indexLookupAttrInfoSection;
19666   Uint32 singleAIWord;
19667 
19668   AttributeHeader::init(&singleAIWord, indexData->primaryKeyPos, 0);
19669   if (! import(indexLookupAttrInfoSection,
19670                &singleAIWord,
19671                1))
19672   {
19673     jam();
19674     /* Error creating AttrInfo section to request primary
19675      * key from index table.
19676      */
19677     // TODO - verify error handling
19678 #ifdef VM_TRACE
19679     ndbout_c("Dbtc::readIndexTable: Failed to create AttrInfo section");
19680 #endif
19681     ApiConnectRecordPtr apiConnectptr;
19682     apiConnectptr.i = indexOp->connectionIndex;
19683     c_apiConnectRecordPool.getPtr(apiConnectptr);
19684     releaseIndexOperation(apiConnectptr.p, indexOp);
19685     terrorCode = 4000;
19686     abortErrorLab(signal, apiConnectptr);
19687     return;
19688   }
19689 
19690   ndbassert(signal->header.m_noOfSections == 0);
19691 
19692   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
19693     = indexOp->keyInfoSectionIVal;
19694 
19695   /* We pass this section to TCKEYREQ next */
19696   indexOp->keyInfoSectionIVal= RNIL;
19697 
19698   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
19699     = indexLookupAttrInfoSection.i;
19700   signal->header.m_noOfSections= 2;
19701 
19702   /* Direct execute of long TCKEYREQ
19703    * TCKEYREQ is responsible for freeing the KeyInfo and
19704    * AttrInfo sections passed to it
19705    */
19706   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
19707   jamEntry();
19708 
19709   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
19710   {
19711     jam();
19712   }
19713   else
19714   {
19715     jam();
19716     /**
19717      * "Fool" TC not to start commiting transaction since it always will
19718      *   have one outstanding lqhkeyreq
19719      * This is later decreased when the index read is complete
19720      */
19721     regApiPtr->lqhkeyreqrec++;
19722 
19723     /**
19724      * Remember ptr to index read operation
19725      *   (used to set correct save point id on index operation later)
19726      */
19727     indexOp->indexReadTcConnect = regApiPtr->tcConnect.getLast();
19728   }
19729 
19730   return;
19731 }
19732 
19733 /**
19734  * Execute the index operation with the result from
19735  * the index table read as PK
19736  */
executeIndexOperation(Signal * signal,ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)19737 void Dbtc::executeIndexOperation(Signal* signal,
19738 				 ApiConnectRecord* regApiPtr,
19739 				 TcIndexOperation* indexOp) {
19740 
19741   TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
19742   TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
19743   Uint32 tcKeyRequestInfo = tcIndxReq->requestInfo;
19744   TcIndexData* indexData;
19745 
19746   // Find index table
19747   if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
19748     jam();
19749     // Failed to find index record
19750     // TODO : How is this operation cleaned up?
19751     TcKeyRef * const tcIndxRef = (TcKeyRef *)signal->getDataPtrSend();
19752 
19753     tcIndxRef->connectPtr = indexOp->tcIndxReq.senderData;
19754     tcIndxRef->transId[0] = regApiPtr->transid[0];
19755     tcIndxRef->transId[1] = regApiPtr->transid[1];
19756     tcIndxRef->errorCode = ZINCONSISTENT_INDEX_USE;
19757     tcIndxRef->errorData = 0;
19758     sendSignal(regApiPtr->ndbapiBlockref, GSN_TCINDXREF, signal,
19759 	       TcKeyRef::SignalLength, JBB);
19760     return;
19761   }
19762 
19763   // Find schema version of primary table
19764   TableRecordPtr tabPtr;
19765   tabPtr.i = indexData->primaryTableId;
19766   ptrCheckGuard(tabPtr, ctabrecFilesize, tableRecord);
19767 
19768   tcKeyReq->apiConnectPtr = tcIndxReq->apiConnectPtr;
19769   tcKeyReq->attrLen = tcIndxReq->attrLen;
19770   tcKeyReq->tableId = indexData->primaryTableId;
19771   tcKeyReq->tableSchemaVersion = tabPtr.p->currentSchemaVersion;
19772   tcKeyReq->transId1 = regApiPtr->transid[0];
19773   tcKeyReq->transId2 = regApiPtr->transid[1];
19774   tcKeyReq->senderData = tcIndxReq->senderData; // Needed for TRANSID_AI to API
19775 
19776   if (tabPtr.p->get_user_defined_partitioning())
19777   {
19778     jam();
19779     tcKeyReq->scanInfo = indexOp->fragmentId; // As read from Index table
19780     TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
19781   }
19782   regApiPtr->m_special_op_flags = 0;
19783   regApiPtr->executingIndexOp = 0;
19784 
19785   /* KeyInfo section
19786    * Get the KeyInfo we received from the index table lookup
19787    */
19788   SegmentedSectionPtr keyInfoFromTransIdAI;
19789 
19790   ndbassert( indexOp->transIdAISectionIVal != RNIL );
19791   getSection(keyInfoFromTransIdAI, indexOp->transIdAISectionIVal);
19792 
19793   ndbassert( signal->header.m_noOfSections == 0 );
19794   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ]
19795     = indexOp->transIdAISectionIVal;
19796   signal->header.m_noOfSections = 1;
19797 
19798   indexOp->transIdAISectionIVal = RNIL;
19799 
19800   /* AttrInfo section
19801    * Attach any AttrInfo section from original TCINDXREQ
19802    */
19803   if ( indexOp->attrInfoSectionIVal != RNIL )
19804   {
19805     jam();
19806     SegmentedSectionPtr attrInfoFromInitialReq;
19807 
19808     getSection(attrInfoFromInitialReq, indexOp->attrInfoSectionIVal);
19809     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ]
19810       = indexOp->attrInfoSectionIVal;
19811     signal->header.m_noOfSections = 2;
19812     indexOp->attrInfoSectionIVal = RNIL;
19813   }
19814 
19815 
19816   TcKeyReq::setCommitFlag(tcKeyRequestInfo, 0);
19817   TcKeyReq::setExecuteFlag(tcKeyRequestInfo, 0);
19818   tcKeyReq->requestInfo = tcKeyRequestInfo;
19819 
19820   ndbassert(TcKeyReq::getDirtyFlag(tcKeyRequestInfo) == 0);
19821   ndbassert(TcKeyReq::getSimpleFlag(tcKeyRequestInfo) == 0);
19822 
19823   /**
19824    * Decrease lqhkeyreqrec to compensate for addition
19825    *   during read of index table
19826    * I.e. let TC start committing when other operations has completed
19827    */
19828   regApiPtr->lqhkeyreqrec--;
19829 
19830   /**
19831    * Fix savepoint id -
19832    *   fix so that index operation has the same savepoint id
19833    *   as the read of the index table (TCINDXREQ)
19834    */
19835   TcConnectRecordPtr tmp;
19836   tmp.i = indexOp->indexReadTcConnect;
19837 
19838   tcConnectRecord.getPtr(tmp);
19839   const Uint32 currSavePointId = regApiPtr->currSavePointId;
19840   const Uint32 triggeringOp = tmp.p->triggeringOperation;
19841   const Uint32 triggerId = tmp.p->currentTriggerId;
19842   regApiPtr->currSavePointId = tmp.p->savePointId;
19843 
19844 #ifdef ERROR_INSERT
19845   bool err8072 = ERROR_INSERTED(8072);
19846   if (err8072)
19847   {
19848     CLEAR_ERROR_INSERT_VALUE;
19849   }
19850 #endif
19851 
19852   if (triggeringOp != RNIL)
19853   {
19854     jam();
19855     /**
19856      * Carry forward info that this was caused by trigger
19857      *   (used by FK)
19858      */
19859     ndbassert(triggerId != RNIL);
19860     ndbassert(tcIndxReq->senderData == triggeringOp);
19861     regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
19862     regApiPtr->immediateTriggerId = triggerId;
19863     regApiPtr->m_executing_trigger_ops++;
19864   }
19865   releaseIndexOperation(regApiPtr, indexOp);
19866 
19867   /* Execute TCKEYREQ now - it is now responsible for freeing
19868    * the KeyInfo and AttrInfo sections
19869    */
19870   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
19871   jamEntry();
19872 
19873 #ifdef ERROR_INSERT
19874   if (err8072)
19875   {
19876     SET_ERROR_INSERT_VALUE(8072);
19877   }
19878 #endif
19879 
19880   if (unlikely(regApiPtr->apiConnectstate == CS_ABORTING))
19881   {
19882     // TODO : Presumably the abort cleans up the operation
19883     jam();
19884     return;
19885   }
19886 
19887   /*
19888    * Restore ApiConnectRecord state
19889    */
19890   regApiPtr->currSavePointId = currSavePointId;
19891   regApiPtr->immediateTriggerId = RNIL;
19892 }
19893 
seizeIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperationPtr & indexOpPtr)19894 bool Dbtc::seizeIndexOperation(ApiConnectRecord* regApiPtr,
19895 			       TcIndexOperationPtr& indexOpPtr)
19896 {
19897   if (likely(c_theIndexOperationPool.seize(indexOpPtr)))
19898   {
19899     jam();
19900     ndbassert(indexOpPtr.p->pendingKeyInfo == 0);
19901     ndbassert(indexOpPtr.p->keyInfoSectionIVal == RNIL);
19902     ndbassert(indexOpPtr.p->pendingAttrInfo == 0);
19903     ndbassert(indexOpPtr.p->attrInfoSectionIVal == RNIL);
19904     ndbassert(indexOpPtr.p->transIdAIState == ITAS_WAIT_HEADER);
19905     ndbassert(indexOpPtr.p->pendingTransIdAI == 0);
19906     ndbassert(indexOpPtr.p->transIdAISectionIVal == RNIL);
19907     ndbassert(indexOpPtr.p->savedFlags == 0);
19908 
19909     LocalTcIndexOperation_dllist list(c_theIndexOperationPool,
19910                                       regApiPtr->theSeizedIndexOperations);
19911     list.addFirst(indexOpPtr);
19912     return true;
19913   }
19914   jam();
19915   return false;
19916 }
19917 
releaseIndexOperation(ApiConnectRecord * regApiPtr,TcIndexOperation * indexOp)19918 void Dbtc::releaseIndexOperation(ApiConnectRecord* regApiPtr,
19919 				 TcIndexOperation* indexOp)
19920 {
19921   indexOp->indexOpState = IOS_NOOP;
19922   indexOp->pendingKeyInfo = 0;
19923   releaseSection(indexOp->keyInfoSectionIVal);
19924   indexOp->keyInfoSectionIVal= RNIL;
19925   indexOp->pendingAttrInfo = 0;
19926   releaseSection(indexOp->attrInfoSectionIVal);
19927   indexOp->attrInfoSectionIVal= RNIL;
19928   indexOp->transIdAIState = ITAS_WAIT_HEADER;
19929   indexOp->pendingTransIdAI = 0;
19930   releaseSection(indexOp->transIdAISectionIVal);
19931   indexOp->transIdAISectionIVal= RNIL;
19932   indexOp->savedFlags= 0;
19933 
19934   TcIndexOperationPtr indexOpPtr; // TODO get it passed into function
19935   indexOpPtr.i = indexOp->indexOpId;
19936   c_theIndexOperationPool.getPtr(indexOpPtr);
19937   ndbrequire(indexOpPtr.p == indexOp);
19938 
19939   LocalTcIndexOperation_dllist list(c_theIndexOperationPool,
19940                                     regApiPtr->theSeizedIndexOperations);
19941   list.remove(indexOpPtr);
19942   c_theIndexOperationPool.release(indexOpPtr);
19943   checkPoolShrinkNeed(DBTC_INDEX_OPERATION_TRANSIENT_POOL_INDEX,
19944                       c_theIndexOperationPool);
19945 }
19946 
releaseAllSeizedIndexOperations(ApiConnectRecord * regApiPtr)19947 void Dbtc::releaseAllSeizedIndexOperations(ApiConnectRecord* regApiPtr)
19948 {
19949   LocalTcIndexOperation_dllist list(c_theIndexOperationPool,
19950                                     regApiPtr->theSeizedIndexOperations);
19951   TcIndexOperationPtr seizedIndexOpPtr;
19952 
19953   while (list.removeFirst(seizedIndexOpPtr))
19954   {
19955     jam();
19956     TcIndexOperation* indexOp = seizedIndexOpPtr.p;
19957 
19958     indexOp->indexOpState = IOS_NOOP;
19959     indexOp->pendingKeyInfo = 0;
19960     releaseSection(indexOp->keyInfoSectionIVal);
19961     indexOp->keyInfoSectionIVal = RNIL;
19962     indexOp->pendingAttrInfo = 0;
19963     releaseSection(indexOp->attrInfoSectionIVal);
19964     indexOp->attrInfoSectionIVal = RNIL;
19965     indexOp->transIdAIState = ITAS_WAIT_HEADER;
19966     indexOp->pendingTransIdAI = 0;
19967     releaseSection(indexOp->transIdAISectionIVal);
19968     indexOp->transIdAISectionIVal = RNIL;
19969     indexOp->savedFlags= 0;
19970 
19971     c_theIndexOperationPool.release(seizedIndexOpPtr);
19972   }
19973   checkPoolShrinkNeed(DBTC_INDEX_OPERATION_TRANSIENT_POOL_INDEX,
19974                       c_theIndexOperationPool);
19975   jam();
19976 }
19977 
saveTriggeringOpState(Signal * signal,TcConnectRecord * trigOp)19978 void Dbtc::saveTriggeringOpState(Signal* signal, TcConnectRecord* trigOp)
19979 {
19980   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
19981   copyFromToLen((UintR*)lqhKeyConf,
19982 		&trigOp->savedState[0],
19983                 LqhKeyConf::SignalLength);
19984 }
19985 
19986 void
trigger_op_finished(Signal * signal,ApiConnectRecordPtr apiConnectptr,Uint32 trigPtrI,TcConnectRecord * triggeringOp,Uint32 errCode)19987 Dbtc::trigger_op_finished(Signal* signal,
19988                           ApiConnectRecordPtr apiConnectptr,
19989                           Uint32 trigPtrI,
19990                           TcConnectRecord* triggeringOp,
19991                           Uint32 errCode)
19992 {
19993   if (trigPtrI != RNIL)
19994   {
19995     jam();
19996     Ptr<TcDefinedTriggerData> trigPtr;
19997     c_theDefinedTriggers.getPtr(trigPtr, trigPtrI);
19998     switch(trigPtr.p->triggerType){
19999     case TriggerType::FK_PARENT:
20000     {
20001       if (errCode == ZNOT_FOUND)
20002       {
20003         jam();
20004         break; // good!
20005       }
20006 
20007       Ptr<TcFKData> fkPtr;
20008       // TODO make it a pool.getPtr() instead
20009       // by also adding fk_ptr_i to definedTriggerData
20010       ndbrequire(c_fk_hash.find(fkPtr, trigPtr.p->fkId));
20011       if (errCode == 0 && ((fkPtr.p->bits&CreateFKImplReq::FK_ON_ACTION) == 0))
20012       {
20013         jam();
20014         // Only restrict
20015         terrorCode = ZFK_CHILD_ROW_EXISTS;
20016         apiConnectptr.p->errorData = trigPtr.p->fkId;
20017       }
20018       else if (errCode == 0)
20019       {
20020         /**
20021          * Check action performed against expected result...
20022          */
20023         if (triggeringOp->operation == ZDELETE &&
20024             (fkPtr.p->bits & CreateFKImplReq::FK_DELETE_ACTION))
20025         {
20026           jam();
20027           // the on action succeeded, good!
20028           break;
20029         }
20030         else if ((triggeringOp->operation == ZUPDATE || triggeringOp->operation == ZWRITE) &&
20031                  (fkPtr.p->bits & CreateFKImplReq::FK_UPDATE_ACTION))
20032         {
20033           jam();
20034           // the on action succeeded, good!
20035           break;
20036         }
20037         jam();
20038         terrorCode = ZFK_CHILD_ROW_EXISTS;
20039         apiConnectptr.p->errorData = trigPtr.p->fkId;
20040       }
20041       else
20042       {
20043         jam();
20044         jamLine(errCode);
20045         terrorCode = errCode;
20046       }
20047       abortErrorLab(signal, apiConnectptr);
20048       return;
20049     }
20050     default:
20051       (void)1;
20052     }
20053   }
20054   if (!apiConnectptr.p->isExecutingDeferredTriggers())
20055   {
20056     jam();
20057     if (unlikely((triggeringOp->triggerExecutionCount == 0)))
20058     {
20059       printf("%u : %p->triggerExecutionCount == 0\n",
20060              __LINE__,
20061              triggeringOp);
20062       dump_trans(apiConnectptr);
20063     }
20064     ndbrequire(triggeringOp->triggerExecutionCount > 0);
20065     triggeringOp->triggerExecutionCount--;
20066     if (triggeringOp->triggerExecutionCount == 0)
20067     {
20068       /**
20069        * We have completed current trigger execution
20070        * Continue triggering operation
20071        */
20072       jam();
20073       continueTriggeringOp(signal, triggeringOp, apiConnectptr);
20074     }
20075   }
20076   else
20077   {
20078     jam();
20079     lqhKeyConf_checkTransactionState(signal, apiConnectptr);
20080   }
20081 }
20082 
continueTriggeringOp(Signal * signal,TcConnectRecord * trigOp,ApiConnectRecordPtr regApiPtr)20083 void Dbtc::continueTriggeringOp(Signal* signal,
20084                                 TcConnectRecord* trigOp,
20085                                 ApiConnectRecordPtr regApiPtr)
20086 {
20087   LqhKeyConf * lqhKeyConf = (LqhKeyConf *)signal->getDataPtr();
20088   copyFromToLen(&trigOp->savedState[0],
20089                 (UintR*)lqhKeyConf,
20090 		LqhKeyConf::SignalLength);
20091 
20092   if (unlikely(trigOp->savedState[LqhKeyConf::SignalLength-1] == ~Uint32(0)))
20093   {
20094     g_eventLogger->info("%u : savedState not set\n", __LINE__);
20095     printLQHKEYCONF(stderr,signal->getDataPtr(),LqhKeyConf::SignalLength,DBTC);
20096     dump_trans(regApiPtr);
20097   }
20098   ndbrequire(trigOp->savedState[LqhKeyConf::SignalLength-1] != ~Uint32(0));
20099   trigOp->savedState[LqhKeyConf::SignalLength-1] = ~Uint32(0);
20100 
20101   lqhKeyConf->numFiredTriggers = 0;
20102   trigOp->numReceivedTriggers = 0;
20103 
20104   if (trigOp->triggeringOperation != RNIL)
20105   {
20106     jam();
20107 
20108     /**
20109      * Here we add 1 to the transaction's triggered operations count
20110      * as it will be decremented again in the reanimated execLQHKEYCONF
20111      */
20112     regApiPtr.p->m_executing_trigger_ops++;
20113   }
20114 
20115   /**
20116    * All triggers executed successfully, continue operation
20117    *
20118    * We have to be careful here not sending too many direct signals in a row.
20119    * This has two consequences, first we are breaking the coding rules if we
20120    * do and thus other signals have a hard time to get their piece of the
20121    * CPU.
20122    * Secondly we can easily run out of stack which can cause all sorts of
20123    * weird errors. We cannot allow any type of completely recursive behaviour
20124    * in the NDB code.
20125    */
20126   c_lqhkeyconf_direct_sent++;
20127   if (c_lqhkeyconf_direct_sent <= 5)
20128   {
20129     jam();
20130     execLQHKEYCONF(signal);
20131   }
20132   else
20133   {
20134     jam();
20135     c_lqhkeyconf_direct_sent = 0;
20136     sendSignal(reference(),
20137                GSN_LQHKEYCONF,
20138                signal,
20139                LqhKeyConf::SignalLength,
20140                JBB);
20141   }
20142 }
20143 
executeTriggers(Signal * signal,ApiConnectRecordPtr const * transPtr)20144 void Dbtc::executeTriggers(Signal* signal, ApiConnectRecordPtr const* transPtr)
20145 {
20146   ApiConnectRecord* regApiPtr = transPtr->p;
20147   TcConnectRecordPtr opPtr;
20148   FiredTriggerPtr trigPtr;
20149   jam();
20150 
20151   /* Are we already executing triggers in this transaction? */
20152   ApiConnectRecord::ExecTriggersGuard execGuard(regApiPtr);
20153   if (!execGuard.canExecNow())
20154   {
20155     jam();
20156     return;
20157   }
20158 
20159   if (!regApiPtr->theFiredTriggers.isEmpty()) {
20160     jam();
20161     if ((regApiPtr->apiConnectstate == CS_STARTED) ||
20162         (regApiPtr->apiConnectstate == CS_START_COMMITTING) ||
20163         (regApiPtr->apiConnectstate == CS_SEND_FIRE_TRIG_REQ) ||
20164         (regApiPtr->apiConnectstate == CS_WAIT_FIRE_TRIG_REQ))
20165     {
20166       jam();
20167       Local_TcFiredTriggerData_fifo
20168         list(c_theFiredTriggerPool, regApiPtr->theFiredTriggers);
20169       list.first(trigPtr);
20170       while (trigPtr.i != RNIL) {
20171         jam();
20172         if (regApiPtr->cascading_scans_count >=
20173             MaxCascadingScansPerTransaction)
20174         {
20175           jam();
20176           // Pause all trigger execution if a cascading scan is ongoing
20177           D("trans: cascading scans " << regApiPtr->cascading_scans_count);
20178           return;
20179         }
20180 
20181         // Pause trigger execution if the number of concurrent
20182         // trigger operations have exceeded the limit
20183         if (regApiPtr->m_executing_trigger_ops >=
20184             MaxExecutingTriggerOpsPerTrans)
20185         {
20186           jam();
20187           D("trans: too many triggering operations "
20188             << regApiPtr->m_executing_trigger_ops);
20189           return;
20190         }
20191 
20192         // Execute ready triggers in parallel
20193         opPtr.i = trigPtr.p->fireingOperation;
20194         tcConnectRecord.getPtr(opPtr);
20195 	FiredTriggerPtr nextTrigPtr = trigPtr;
20196         list.next(nextTrigPtr);
20197         ndbrequire(opPtr.p->apiConnect == transPtr->i);
20198 
20199         if (opPtr.p->numReceivedTriggers == opPtr.p->numFiredTriggers ||
20200             regApiPtr->isExecutingDeferredTriggers())
20201         {
20202           jam();
20203           // Fireing operation is ready to have a trigger executing
20204           while (executeTrigger(signal, trigPtr.p, transPtr, &opPtr) == false)
20205           {
20206             jam();
20207             /**
20208              * TODO: timeslice, e.g CONTINUE
20209              */
20210           }
20211 
20212           // Should allow for interleaving here by sending a CONTINUEB and
20213 	  // return
20214           // Release trigger records
20215 	  AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
20216 	  LocalAttributeBuffer tmp1(pool, trigPtr.p->keyValues);
20217 	  tmp1.release();
20218 	  LocalAttributeBuffer tmp2(pool, trigPtr.p->beforeValues);
20219 	  tmp2.release();
20220 	  LocalAttributeBuffer tmp3(pool, trigPtr.p->afterValues);
20221 	  tmp3.release();
20222           list.remove(trigPtr);
20223           c_theFiredTriggerPool.release(trigPtr);
20224           checkPoolShrinkNeed(DBTC_ATTRIBUTE_BUFFER_TRANSIENT_POOL_INDEX,
20225                               c_theAttributeBufferPool);
20226           checkPoolShrinkNeed(DBTC_FIRED_TRIGGER_DATA_TRANSIENT_POOL_INDEX,
20227                               c_theFiredTriggerPool);
20228         }
20229 	trigPtr = nextTrigPtr;
20230       }
20231       return;
20232       // No more triggers, continue transaction after last executed trigger has
20233       // returned (in execLQHKEYCONF or execLQHKEYREF)
20234     } else {
20235 
20236       jam();
20237       /* Not in correct state to fire triggers yet, need to wait
20238        * (or keep waiting)
20239        */
20240 
20241       if ((regApiPtr->apiConnectstate == CS_RECEIVING) ||
20242           (regApiPtr->apiConnectstate == CS_REC_COMMITTING))
20243       {
20244         // Wait until transaction is ready to execute a trigger
20245         jam();
20246         D("trans: apiConnectstate " << regApiPtr->apiConnectstate);
20247         waitToExecutePendingTrigger(signal, *transPtr);
20248       }
20249       else
20250       {
20251         /* Transaction has started aborting.
20252          * Forget about unprocessed triggers
20253          */
20254         ndbrequire(regApiPtr->apiConnectstate == CS_ABORTING);
20255       }
20256     }
20257   }
20258 }
20259 
20260 void
waitToExecutePendingTrigger(Signal * signal,ApiConnectRecordPtr transPtr)20261 Dbtc::waitToExecutePendingTrigger(Signal* signal, ApiConnectRecordPtr transPtr)
20262 {
20263   if (!tc_testbit(transPtr.p->m_flags,
20264                   ApiConnectRecord::TF_TRIGGER_PENDING))
20265   {
20266     jam();
20267     D("trans: send trigger pending");
20268     c_lqhkeyconf_direct_sent = 0;
20269     transPtr.p->m_flags |= ApiConnectRecord::TF_TRIGGER_PENDING;
20270     signal->theData[0] = TcContinueB::TRIGGER_PENDING;
20271     signal->theData[1] = transPtr.i;
20272     signal->theData[2] = transPtr.p->transid[0];
20273     signal->theData[3] = transPtr.p->transid[1];
20274     sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
20275   }
20276   else
20277   {
20278     // We are already waiting for a pending trigger (CONTINUEB)
20279     D("trans: trigger pending already");
20280   }
20281 }
20282 
executeTrigger(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr)20283 bool Dbtc::executeTrigger(Signal* signal,
20284                           TcFiredTriggerData* firedTriggerData,
20285                           ApiConnectRecordPtr const* transPtr,
20286                           TcConnectRecordPtr* opPtr)
20287 {
20288   /* Using a IgnoreAlloc variant of getPtr to make the lookup safe.
20289    * The validity of the trigger should be checked subsequently.
20290    */
20291   DefinedTriggerPtr definedTriggerPtr;
20292   definedTriggerPtr.i = firedTriggerData->triggerId;
20293   c_theDefinedTriggers.getPool().getPtrIgnoreAlloc(definedTriggerPtr);
20294 
20295   // If triggerIds don't match, the trigger has been dropped -> skip trigger exec.
20296   if (likely(definedTriggerPtr.p->triggerId == firedTriggerData->triggerId))
20297   {
20298     TcDefinedTriggerData* const definedTriggerData = definedTriggerPtr.p;
20299     transPtr->p->pendingTriggers--;
20300     switch(firedTriggerData->triggerType) {
20301     case(TriggerType::SECONDARY_INDEX):
20302       jam();
20303       executeIndexTrigger(signal, definedTriggerData, firedTriggerData,
20304                           transPtr, opPtr);
20305       break;
20306     case TriggerType::REORG_TRIGGER:
20307       jam();
20308       executeReorgTrigger(signal, definedTriggerData, firedTriggerData,
20309                           transPtr, opPtr);
20310       break;
20311     case TriggerType::FK_PARENT:
20312       jam();
20313       executeFKParentTrigger(signal, definedTriggerData, firedTriggerData,
20314                              transPtr, opPtr);
20315       break;
20316     case TriggerType::FK_CHILD:
20317       jam();
20318       executeFKChildTrigger(signal, definedTriggerData, firedTriggerData,
20319                             transPtr, opPtr);
20320       break;
20321     case TriggerType::FULLY_REPLICATED_TRIGGER:
20322       jam();
20323       return executeFullyReplicatedTrigger(signal,
20324                                            definedTriggerData, firedTriggerData,
20325                                            transPtr, opPtr);
20326       break;
20327     default:
20328       ndbabort();
20329     }
20330   }
20331   return true;
20332 }
20333 
executeIndexTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr)20334 void Dbtc::executeIndexTrigger(Signal* signal,
20335                                TcDefinedTriggerData* definedTriggerData,
20336                                TcFiredTriggerData* firedTriggerData,
20337                                ApiConnectRecordPtr const* transPtr,
20338                                TcConnectRecordPtr* opPtr)
20339 {
20340   TcIndexData* indexData = c_theIndexes.getPtr(definedTriggerData->indexId);
20341   ndbassert(indexData != NULL);
20342 
20343   switch (firedTriggerData->triggerEvent) {
20344   case(TriggerEvent::TE_INSERT): {
20345     jam();
20346     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
20347     break;
20348   }
20349   case(TriggerEvent::TE_DELETE): {
20350     jam();
20351     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
20352     break;
20353   }
20354   case(TriggerEvent::TE_UPDATE): {
20355     jam();
20356     opPtr->p->triggerExecutionCount++; // One is already added...and this is 2
20357     deleteFromIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
20358     insertIntoIndexTable(signal, firedTriggerData, transPtr, opPtr, indexData);
20359     break;
20360   }
20361   default:
20362     ndbabort();
20363   }
20364 }
20365 
20366 Uint32
fk_constructAttrInfoSetNull(const TcFKData * fkPtrP)20367 Dbtc::fk_constructAttrInfoSetNull(const TcFKData * fkPtrP)
20368 {
20369   Uint32 attrInfo[MAX_ATTRIBUTES_IN_INDEX];
20370   for (Uint32 i = 0; i<fkPtrP->childTableColumns.sz; i++)
20371   {
20372     AttributeHeader::init(attrInfo + i, fkPtrP->childTableColumns.id[i],
20373                           0 /* setNull */);
20374   }
20375 
20376   Uint32 tmp = RNIL;
20377   if (ERROR_INSERTED(8106))
20378   {
20379     return tmp;
20380   }
20381 
20382   appendToSection(tmp, attrInfo, fkPtrP->childTableColumns.sz);
20383   return tmp;
20384 }
20385 
20386 Uint32
fk_constructAttrInfoUpdateCascade(const TcFKData * fkPtrP,AttributeBuffer::Head & srchead)20387 Dbtc::fk_constructAttrInfoUpdateCascade(const TcFKData * fkPtrP,
20388                                         AttributeBuffer::Head & srchead)
20389 {
20390   Uint32 tmp = RNIL;
20391   if (ERROR_INSERTED(8103))
20392   {
20393     return tmp;
20394   }
20395 
20396   /**
20397    * Construct an update based on the src-data
20398    *
20399    * NOTE: this assumes same order...
20400    */
20401   Uint32 pos = 0;
20402   AttributeBuffer::DataBufferIterator iter;
20403   LocalAttributeBuffer src(c_theAttributeBufferPool, srchead);
20404   bool moreData= src.first(iter);
20405   const Uint32 segSize= src.getSegmentSize(); // 11
20406 
20407   while (moreData)
20408   {
20409     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
20410     Uint32 dataSize = attrHeader->getDataSize();
20411 
20412     AttributeHeader ah(*iter.data);
20413     ah.setAttributeId(fkPtrP->childTableColumns.id[pos++]);// Renumber AttrIds
20414     if (unlikely(!appendToSection(tmp, &ah.m_value, 1)))
20415     {
20416       releaseSection(tmp);
20417       return RNIL;
20418     }
20419 
20420     moreData = src.next(iter, 1);
20421     while (dataSize)
20422     {
20423       ndbrequire(moreData);
20424       /* Copy as many contiguous words as possible */
20425       Uint32 contigLeft = segSize - iter.ind;
20426       ndbassert(contigLeft);
20427       Uint32 contigValid = MIN(dataSize, contigLeft);
20428 
20429       if (unlikely(!appendToSection(tmp, iter.data, contigValid)))
20430       {
20431         releaseSection(tmp);
20432         return RNIL;
20433       }
20434       moreData = src.next(iter, contigValid);
20435       dataSize -= contigValid;
20436     }
20437   }
20438 
20439   return tmp;
20440 }
20441 
20442 void
executeFKParentTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr)20443 Dbtc::executeFKParentTrigger(Signal* signal,
20444                              TcDefinedTriggerData* definedTriggerData,
20445                              TcFiredTriggerData* firedTriggerData,
20446                              ApiConnectRecordPtr const* transPtr,
20447                              TcConnectRecordPtr* opPtr)
20448 {
20449   Ptr<TcFKData> fkPtr;
20450   // TODO make it a pool.getPtr() instead
20451   // by also adding fk_ptr_i to definedTriggerData
20452   ndbrequire(c_fk_hash.find(fkPtr, definedTriggerData->fkId));
20453 
20454   /**
20455    * The parent table (the referenced table in the foreign key definition
20456    * was updated or had a row (no parent trigger on insert) deleted. This
20457    * could lead to the action CASCADE or SET NULL.
20458    *
20459    * CASCADE means that in the case of an update we will update the
20460    * referenced row with the new updated reference attributes.
20461    * In the case of DELETE CASCADE a delete in the parent table will
20462    * also be followed by a DELETE in the referencing table (child
20463    * table).
20464    *
20465    * In the case of SET NULL for UPDATE and DELETE we will set the
20466    * referencing attributes in the child table to NULL as part of
20467    * trigger execution.
20468    *
20469    * SET DEFAULT isn't supported by MySQL at the moment, so no special
20470    * code is needed to handle that.
20471    *
20472    * RESTRICT and NO ACTION both leads to read operations of the child
20473    * table to ensure that the references are valid, if they are not
20474    * found then the transaction is aborted.
20475    */
20476   Uint32 op = ZREAD;
20477   Uint32 attrValuesPtrI = RNIL;
20478   switch(firedTriggerData->triggerEvent)
20479   {
20480   case TriggerEvent::TE_UPDATE:
20481     if (fkPtr.p->bits & CreateFKImplReq::FK_UPDATE_CASCADE)
20482     {
20483       jam();
20484       /**
20485        * Update child table with after values of parent
20486        */
20487       op = ZUPDATE;
20488       attrValuesPtrI =
20489         fk_constructAttrInfoUpdateCascade(fkPtr.p,
20490                                           firedTriggerData->afterValues);
20491 
20492       if (unlikely(attrValuesPtrI == RNIL))
20493         goto oom;
20494     }
20495     else if (fkPtr.p->bits & CreateFKImplReq::FK_UPDATE_SET_NULL)
20496     {
20497       jam();
20498       /**
20499        * Update child table set null
20500        */
20501       goto setnull;
20502     }
20503     break;
20504   case TriggerEvent::TE_DELETE:
20505     if (fkPtr.p->bits & CreateFKImplReq::FK_DELETE_CASCADE)
20506     {
20507       jam();
20508       /**
20509        * Delete from child table
20510        */
20511       op = ZDELETE;
20512     }
20513     else if (fkPtr.p->bits & CreateFKImplReq::FK_DELETE_SET_NULL)
20514     {
20515       jam();
20516       /**
20517        * Update child table set null
20518        */
20519       goto setnull;
20520     }
20521     break;
20522   default:
20523     ndbabort();
20524   setnull:
20525   {
20526     op = ZUPDATE;
20527     attrValuesPtrI = fk_constructAttrInfoSetNull(fkPtr.p);
20528     if (unlikely(attrValuesPtrI == RNIL))
20529       goto oom;
20530   }
20531   }
20532 
20533   /**
20534    * Foreign key parent triggers can only exist with indexes.
20535    * If no bit is set then the index is a primary key, if
20536    * no primary index exists for the reference then a unique
20537    * index is choosen in which case the bit FK_CHILD_UI is set.
20538    * If neither a primary index nor a unique index is present
20539    * then an ordered index is used in which case the
20540    * bit FK_CHILD_OI is set. If neither an ordered index is present
20541    * then the foreign key creation will fail, so here this cannot
20542    * happen.
20543    *
20544    * The index is on the foreign key child table, that is it is
20545    * required on the table that defines the foreign key.
20546    */
20547   if (! (fkPtr.p->bits & CreateFKImplReq::FK_CHILD_OI))
20548   {
20549     jam();
20550     fk_readFromChildTable(signal, firedTriggerData, transPtr, opPtr,
20551                           fkPtr.p, op, attrValuesPtrI);
20552   }
20553   else
20554   {
20555     jam();
20556     fk_scanFromChildTable(signal, firedTriggerData, transPtr, opPtr->i,
20557                           fkPtr.p, op, attrValuesPtrI);
20558   }
20559   return;
20560 oom:
20561   jam();
20562   abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
20563 }
20564 
20565 void
fk_readFromChildTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr,TcFKData * fkData,Uint32 op,Uint32 attrValuesPtrI)20566 Dbtc::fk_readFromChildTable(Signal* signal,
20567                             TcFiredTriggerData* firedTriggerData,
20568                             ApiConnectRecordPtr const* transPtr,
20569                             TcConnectRecordPtr* opPtr,
20570                             TcFKData* fkData,
20571                             Uint32 op,
20572                             Uint32 attrValuesPtrI)
20573 {
20574   ApiConnectRecord* regApiPtr = transPtr->p;
20575   TcConnectRecord* opRecord = opPtr->p;
20576   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
20577   Uint32 tcKeyRequestInfo = 0;
20578   TableRecordPtr childIndexPtr;
20579 
20580   childIndexPtr.i = fkData->childIndexId;
20581   ptrCheckGuard(childIndexPtr, ctabrecFilesize, tableRecord);
20582   tcKeyReq->apiConnectPtr = transPtr->i;
20583   tcKeyReq->senderData = opPtr->i;
20584 
20585   // Calculate key length and renumber attribute id:s
20586   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
20587   LocalAttributeBuffer beforeValues(pool, firedTriggerData->beforeValues);
20588 
20589   SegmentedSectionGuard guard(this, attrValuesPtrI);
20590   if (beforeValues.getSize() == 0)
20591   {
20592     jam();
20593     ndbrequire(tc_testbit(regApiPtr->m_flags,
20594                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
20595     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
20596     /* Already executing triggers */
20597     ndbassert(regApiPtr->m_inExecuteTriggers);
20598     return;
20599   }
20600 
20601   Uint32 keyIVal= RNIL;
20602   bool hasNull= false;
20603   Uint32 err = fk_buildKeyInfo(keyIVal, hasNull, beforeValues, fkData, false);
20604   guard.add(keyIVal);
20605   if (unlikely(err != 0))
20606   {
20607     jam();
20608     abortTransFromTrigger(signal, *transPtr, err);
20609     return;
20610   }
20611 
20612   /* If there's Nulls in the values that become the index table's
20613    * PK then we skip this delete
20614    */
20615   if (hasNull)
20616   {
20617     jam();
20618     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
20619     /* Already executing triggers */
20620     ndbassert(regApiPtr->m_inExecuteTriggers);
20621     return;
20622   }
20623 
20624   Uint16 flags = TcConnectRecord::SOF_TRIGGER;
20625   const Uint32 currSavePointId = regApiPtr->currSavePointId;
20626   Uint32 gsn = GSN_TCKEYREQ;
20627   if (op == ZREAD)
20628   {
20629     jam();
20630     /**
20631      * Fix savepoint id seen by READ:
20632      * - If it is a deferred trigger we will see the tuple content
20633      *   at commit time, as already available through
20634      *   the 'currSavePointId' set by commit.
20635      * - else, an immediate trigger should see the tuple as
20636      *   immediate after ('+1') the operation which updated it.
20637      */
20638     if (!transPtr->p->isExecutingDeferredTriggers())
20639       regApiPtr->currSavePointId = opRecord->savePointId+1;
20640 
20641    /*
20642     * Foreign key triggers =
20643     *     on DELETE/UPDATE(parent) -> READ/SCAN(child) with lock
20644     *     on INSERT/UPDATE(child)  -> READ(parent) with lock
20645     *
20646     * FK checks require a consistent read of 2 or more rows, which
20647     * require row locks in Ndb.  The most lightweight row locks available
20648     * are SimpleRead which takes a shared row lock for the duration of the
20649     * read at LDM.
20650     *
20651     * Minimal lock mode for correctness = SimpleRead(parent)+SimpleRead(child)
20652     */
20653     TcKeyReq::setSimpleFlag(tcKeyRequestInfo, 1);
20654     /* Read child row using SimpleRead lock */
20655     TcKeyReq::setDirtyFlag(tcKeyRequestInfo, 0);
20656   }
20657   else
20658   {
20659     jam();
20660     /**
20661      * Let an update/delete triggers be made with same save point
20662      *   as operation it orginated from.
20663      */
20664     regApiPtr->currSavePointId = opRecord->savePointId;
20665     if (fkData->childTableId != fkData->childIndexId)
20666     {
20667       jam();
20668       gsn = GSN_TCINDXREQ;
20669     }
20670   }
20671   regApiPtr->m_special_op_flags = flags;
20672 
20673   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
20674   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
20675   tcKeyReq->attrLen = 0;
20676   tcKeyReq->tableId = childIndexPtr.i;
20677   TcKeyReq::setOperationType(tcKeyRequestInfo, op);
20678   tcKeyReq->tableSchemaVersion = childIndexPtr.p->currentSchemaVersion;
20679   tcKeyReq->transId1 = regApiPtr->transid[0];
20680   tcKeyReq->transId2 = regApiPtr->transid[1];
20681   tcKeyReq->requestInfo = tcKeyRequestInfo;
20682 
20683   /* Attach KeyInfo section to signal */
20684   ndbrequire(signal->header.m_noOfSections == 0);
20685   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
20686   signal->header.m_noOfSections = 1;
20687 
20688   if (attrValuesPtrI != RNIL)
20689   {
20690     jam();
20691     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrValuesPtrI;
20692     signal->header.m_noOfSections = 2;
20693   }
20694 
20695   guard.clear(); // now sections will be handled...
20696 
20697   /* Pass trigger Id via ApiConnectRecord (nasty) */
20698   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
20699   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
20700   if (gsn == GSN_TCKEYREQ)
20701   {
20702     EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
20703   }
20704   else
20705   {
20706     fk_execTCINDXREQ(signal, * transPtr, * opPtr, op);
20707   }
20708   jamEntry();
20709 
20710   /*
20711    * Restore ApiConnectRecord state
20712    */
20713   regApiPtr->immediateTriggerId = RNIL;
20714   regApiPtr->currSavePointId = currSavePointId;
20715   regApiPtr->m_executing_trigger_ops++;
20716 }
20717 
20718 void
fk_execTCINDXREQ(Signal * signal,ApiConnectRecordPtr transPtr,TcConnectRecordPtr opPtr,Uint32 operation)20719 Dbtc::fk_execTCINDXREQ(Signal* signal,
20720                        ApiConnectRecordPtr transPtr,
20721                        TcConnectRecordPtr opPtr,
20722                        Uint32 operation)
20723 {
20724   jam();
20725   SectionHandle handle(this, signal);
20726   const TcKeyReq * tcIndxReq =  CAST_CONSTPTR(TcKeyReq,
20727                                               signal->getDataPtr());
20728 
20729   /**
20730    * this is a mockup of execTCINDXREQ...
20731    */
20732   TcIndexOperationPtr indexOpPtr;
20733   if (unlikely(!seizeIndexOperation(transPtr.p, indexOpPtr)))
20734   {
20735     jam();
20736     releaseSections(handle);
20737     abortTransFromTrigger(signal, transPtr, 288);
20738     return;
20739   }
20740 
20741   indexOpPtr.p->indexOpId = indexOpPtr.i;
20742 
20743   // Save original signal
20744   indexOpPtr.p->tcIndxReq = *tcIndxReq;
20745   indexOpPtr.p->connectionIndex = transPtr.i;
20746   transPtr.p->accumulatingIndexOp = indexOpPtr.i;
20747 
20748   /* KeyInfo and AttrInfo already received into sections */
20749   SegmentedSectionPtr keyInfoSection, attrInfoSection;
20750 
20751   /* Store i value for first long section of KeyInfo
20752    * and AttrInfo in Index operation
20753    */
20754   handle.getSection(keyInfoSection, TcKeyReq::KeyInfoSectionNum);
20755   indexOpPtr.p->keyInfoSectionIVal = keyInfoSection.i;
20756 
20757   if (handle.m_cnt == 2)
20758   {
20759     handle.getSection(attrInfoSection, TcKeyReq::AttrInfoSectionNum);
20760     indexOpPtr.p->attrInfoSectionIVal = attrInfoSection.i;
20761   }
20762 
20763   /* Detach sections from the handle
20764    * Success path code, or index operation cleanup is
20765    * now responsible for freeing the sections
20766    */
20767   handle.clear();
20768 
20769   /* All data received, process */
20770   readIndexTable(signal, transPtr, indexOpPtr.p,
20771                  transPtr.p->m_special_op_flags);
20772 
20773   if (unlikely(transPtr.p->apiConnectstate == CS_ABORTING))
20774   {
20775     jam();
20776   }
20777   else
20778   {
20779     /**
20780      * readIndexTable() sets senderData to indexOpPtr.i
20781      * and SOF_TRIGGER assumes triggerOperation is stored in senderData
20782      *   so set it correct afterwards...
20783      */
20784     jam();
20785     TcConnectRecordPtr tcPtr;
20786     tcPtr.i = indexOpPtr.p->indexReadTcConnect;
20787     tcConnectRecord.getPtr(tcPtr);
20788     tcPtr.p->triggeringOperation = opPtr.i;
20789     ndbrequire(hasOp(transPtr, opPtr.i));
20790   }
20791   return;
20792 }
20793 
20794 Uint32
fk_buildKeyInfo(Uint32 & keyIVal,bool & hasNull,LocalAttributeBuffer & values,TcFKData * fkPtrP,bool parent)20795 Dbtc::fk_buildKeyInfo(Uint32& keyIVal, bool& hasNull,
20796                       LocalAttributeBuffer & values,
20797                       TcFKData * fkPtrP,
20798                       bool parent)
20799 {
20800   if (ERROR_INSERTED(8104))
20801   {
20802     return ZGET_DATAREC_ERROR;
20803   }
20804 
20805   IndexAttributeList * list = 0;
20806   if (parent == true)
20807   {
20808     jam();
20809     list = &fkPtrP->childTableColumns;
20810   }
20811   else
20812   {
20813     jam();
20814     list = &fkPtrP->parentTableColumns;
20815   }
20816 
20817   AttributeBuffer::DataBufferIterator iter;
20818   bool eof = !values.first(iter);
20819   for (Uint32 i = 0; i < list->sz; i++)
20820   {
20821     Uint32 col = list->id[i];
20822     if (!eof && AttributeHeader(* iter.data).getAttributeId() == col)
20823     {
20824   found:
20825       Uint32 len = AttributeHeader(* iter.data).getDataSize();
20826       if (len == 0)
20827       {
20828         hasNull = true;
20829         return 0;
20830       }
20831       eof = !values.next(iter);
20832       Uint32 err = appendDataToSection(keyIVal, values, iter,
20833                                        len);
20834       if (unlikely(err != 0))
20835         return err;
20836 
20837       eof = iter.isNull();
20838     }
20839     else
20840     {
20841       /**
20842        * Search for column...
20843        */
20844       eof = !values.first(iter);
20845       while (!eof && AttributeHeader(* iter.data).getAttributeId() != col)
20846       {
20847         eof = !values.next(iter,
20848                            1 + AttributeHeader(* iter.data).getDataSize());
20849       }
20850       if (unlikely(eof))
20851       {
20852         return ZMISSING_TRIGGER_DATA;
20853       }
20854       ndbassert(AttributeHeader(* iter.data).getAttributeId() == col);
20855       goto found;
20856     }
20857   }
20858 
20859   return 0;
20860 }
20861 
20862 #define SCAN_FROM_CHILD_PARALLELISM 4
20863 
20864 void
fk_scanFromChildTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,const Uint32 opPtrI,TcFKData * fkData,Uint32 op,Uint32 attrValuesPtrI)20865 Dbtc::fk_scanFromChildTable(Signal* signal,
20866                             TcFiredTriggerData* firedTriggerData,
20867                             ApiConnectRecordPtr const* transPtr,
20868                             const Uint32 opPtrI,
20869                             TcFKData* fkData,
20870                             Uint32 op,
20871                             Uint32 attrValuesPtrI)
20872 {
20873   ApiConnectRecord* regApiPtr = transPtr->p;
20874 
20875   SegmentedSectionGuard guard(this, attrValuesPtrI);
20876 
20877   /*
20878    * cConcScanCount can be bigger than cscanrecFileSize if
20879    * DumpStateOrd::TcSetTransientPoolMaxSize have been used which is only
20880    * possible in debug build.
20881    * Otherwise it should be less than or equal to cscanrecFileSize.
20882    */
20883   if (unlikely(cConcScanCount >= cscanrecFileSize))
20884   {
20885     jam();
20886     abortTransFromTrigger(signal, *transPtr, ZNO_SCANREC_ERROR);
20887     return;
20888   }
20889 
20890   // TODO check against MaxDMLOperationsPerTransaction (not for failover?)
20891   if (unlikely(!tcConnectRecord.seize(tcConnectptr)))
20892   {
20893     jam();
20894     abortTransFromTrigger(signal, *transPtr, ZNO_FREE_TC_CONNECTION);
20895     return;
20896   }
20897   c_counters.cconcurrentOp++;
20898 
20899   ApiConnectRecordPtr apiConnectptr;
20900   if (unlikely(!seizeApiConnect(signal, apiConnectptr)))
20901   {
20902     jam();
20903     ndbrequire(terrorCode != ZOK);
20904     abortTransFromTrigger(signal, *transPtr, terrorCode);
20905     releaseTcCon();
20906     checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
20907                         tcConnectRecord);
20908     return;
20909   }
20910 
20911   // seize a TcConnectRecord to keep track of trigger stuff
20912   TcConnectRecordPtr tcPtr = tcConnectptr;
20913 
20914   // Reuse the ApiConnectRecordPtr, set this TC as (internal) 'API-client'
20915   ApiConnectRecordPtr scanApiConnectPtr = apiConnectptr;
20916   scanApiConnectPtr.p->ndbapiBlockref = reference();
20917   scanApiConnectPtr.p->ndbapiConnect = tcPtr.i;
20918 
20919   tcPtr.p->apiConnect = scanApiConnectPtr.i;
20920   ndbrequire(hasOp(* transPtr, opPtrI));
20921   tcPtr.p->triggeringOperation = opPtrI;
20922   tcPtr.p->currentTriggerId = firedTriggerData->triggerId;
20923   tcPtr.p->triggerErrorCode = ZNOT_FOUND;
20924   tcPtr.p->operation = op;
20925   tcPtr.p->indexOp = attrValuesPtrI;
20926   tcPtr.p->nextTcFailHash = transPtr->i;
20927 
20928   {
20929     Ptr<TcDefinedTriggerData> trigPtr;
20930     c_theDefinedTriggers.getPtr(trigPtr, tcPtr.p->currentTriggerId);
20931     trigPtr.p->refCount++;
20932   }
20933 
20934   TableRecordPtr childIndexPtr;
20935   childIndexPtr.i = fkData->childIndexId;
20936   ptrCheckGuard(childIndexPtr, ctabrecFilesize, tableRecord);
20937 
20938   /**
20939    * Construct an index-scan
20940    */
20941   const Uint32 parallelism = SCAN_FROM_CHILD_PARALLELISM;
20942   ScanTabReq * req = CAST_PTR(ScanTabReq, signal->getDataPtrSend());
20943   Uint32 ri = 0;
20944   ScanTabReq::setParallelism(ri, parallelism);
20945   ScanTabReq::setDescendingFlag(ri, 0);
20946   ScanTabReq::setRangeScanFlag(ri, 1);
20947   ScanTabReq::setTupScanFlag(ri, 0);
20948   ScanTabReq::setNoDiskFlag(ri, 1);
20949   if (op == ZREAD)
20950   {
20951     /* Scan child table using SimpleRead lock */
20952     ScanTabReq::setScanBatch(ri, 1);
20953     ScanTabReq::setLockMode(ri, 0);
20954     ScanTabReq::setHoldLockFlag(ri, 0);
20955     ScanTabReq::setKeyinfoFlag(ri, 0);
20956   }
20957   else
20958   {
20959     ScanTabReq::setScanBatch(ri, 16);
20960     ScanTabReq::setLockMode(ri, 1);
20961     ScanTabReq::setHoldLockFlag(ri, 1);
20962     ScanTabReq::setKeyinfoFlag(ri, 1);
20963   }
20964   ScanTabReq::setReadCommittedFlag(ri, 0);
20965   ScanTabReq::setDistributionKeyFlag(ri, 0);
20966   ScanTabReq::setViaSPJFlag(ri, 0);
20967   ScanTabReq::setPassAllConfsFlag(ri, 0);
20968   ScanTabReq::setExtendedConf(ri, 0);
20969   req->requestInfo = ri;
20970   req->transId1 = regApiPtr->transid[0];
20971   req->transId2 = regApiPtr->transid[1];
20972   req->buddyConPtr = transPtr->i;
20973   req->tableId = childIndexPtr.i;
20974   req->tableSchemaVersion = childIndexPtr.p->currentSchemaVersion;
20975   req->apiConnectPtr = scanApiConnectPtr.i;
20976   req->storedProcId = 0xFFFF;
20977   req->batch_byte_size = 0;
20978   req->first_batch_size = 0;
20979 
20980   SegmentedSectionPtr ptr[3];
20981   ptr[0].i = ptr[1].i = ptr[2].i = RNIL;
20982 
20983   Uint32 optrs[parallelism];
20984   for (Uint32 i = 0; i<parallelism; i++)
20985     optrs[i] = tcPtr.i;
20986 
20987   Uint32 program[] = {
20988     0, 1, 0, 0, 0, Interpreter::ExitLastOK()
20989   };
20990 
20991   if (op != ZREAD)
20992   {
20993     program[5] = Interpreter::ExitOK();
20994   }
20995 
20996   Uint32 errorCode = ZGET_DATAREC_ERROR;
20997   if (ERROR_INSERTED(8102))
20998   {
20999     goto oom;
21000   }
21001   if (unlikely( !import(ptr[0], optrs, NDB_ARRAY_SIZE(optrs))))
21002   {
21003     jam();
21004     goto oom;
21005   }
21006 
21007   if (unlikely( !import(ptr[1], program, NDB_ARRAY_SIZE(program))))
21008   {
21009     jam();
21010     goto oom;
21011   }
21012 
21013   {
21014     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
21015     LocalAttributeBuffer beforeValues(pool, firedTriggerData->beforeValues);
21016     if (unlikely((errorCode=fk_buildBounds(ptr[2], beforeValues, fkData)) != 0))
21017     {
21018       jam();
21019       goto oom;
21020     }
21021   }
21022 
21023   guard.clear(); // now sections will be handled...
21024 
21025   signal->header.m_noOfSections= 3;
21026   signal->m_sectionPtrI[0] = ptr[0].i;
21027   signal->m_sectionPtrI[1] = ptr[1].i;
21028   signal->m_sectionPtrI[2] = ptr[2].i;
21029 
21030   signal->header.theSendersBlockRef = reference();
21031   execSCAN_TABREQ(signal);
21032   if (scanApiConnectPtr.p->apiConnectstate == CS_ABORTING)
21033   {
21034     goto abort_trans;
21035   }
21036 
21037   transPtr->p->lqhkeyreqrec++; // Make sure that execution is stalled
21038   D("trans: cascading scans++ " << transPtr->p->cascading_scans_count);
21039   ndbrequire(transPtr->p->cascading_scans_count < MaxCascadingScansPerTransaction);
21040   transPtr->p->cascading_scans_count++;
21041   transPtr->p->m_executing_trigger_ops++;
21042   return;
21043 
21044 oom:
21045   jam();
21046   for (Uint32 i = 0; i < 3; i++)
21047   {
21048     if (ptr[i].i != RNIL)
21049     {
21050       release(ptr[i]);
21051     }
21052   }
21053 abort_trans:
21054   tcConnectptr = tcPtr;
21055   releaseTcCon();
21056   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
21057                       tcConnectRecord);
21058   releaseApiCon(signal, scanApiConnectPtr.i);
21059   abortTransFromTrigger(signal, *transPtr, errorCode);
21060   return;
21061 }
21062 
21063 /**
21064  * Receive a row with key information from a foreign key scan for
21065  * either an CASCADE DELETE/UPDATE or a SET NULL.
21066  * For each such row we will issue an UPDATE or DELETE and this is
21067  * part of the trigger execution of the foreign key parent trigger.
21068  * Therefore we increment the trigger execution count afterwards.
21069  */
21070 void
execKEYINFO20(Signal * signal)21071 Dbtc::execKEYINFO20(Signal* signal)
21072 {
21073   jamEntry();
21074   const KeyInfo20 * conf = CAST_CONSTPTR(KeyInfo20, signal->getDataPtr());
21075 
21076   Uint32 transId[] = {
21077     conf->transId1,
21078     conf->transId2
21079   };
21080 
21081   Uint32 keyLen = conf->keyLen;
21082   Uint32 scanInfo = conf->scanInfo_Node;
21083 
21084   TcConnectRecordPtr tcPtr;
21085   tcPtr.i = conf->clientOpPtr;
21086   if (unlikely(!tcConnectRecord.getValidPtr(tcPtr)))
21087   {
21088     jam();
21089     warningHandlerLab(signal, __LINE__);
21090     // Assert to catch code coverage, remove when reached and analysed
21091     ndbassert(false);
21092     return;
21093   }
21094 
21095   ApiConnectRecordPtr scanApiConnectPtr;
21096   scanApiConnectPtr.i = tcPtr.p->apiConnect;
21097   if (unlikely(!c_apiConnectRecordPool.getValidPtr(scanApiConnectPtr)))
21098   {
21099     jam();
21100     // Assert to catch code coverage, remove when reached and analysed
21101     ndbassert(false);
21102     return;
21103   }
21104 
21105   if (! (transId[0] == scanApiConnectPtr.p->transid[0] &&
21106          transId[1] == scanApiConnectPtr.p->transid[1]))
21107   {
21108     jam();
21109 
21110     /**
21111      * incorrect transid...no known scenario where this can happen
21112      */
21113     warningHandlerLab(signal, __LINE__);
21114     ndbassert(false);
21115     return;
21116   }
21117 
21118   /**
21119    * Validate base transaction
21120    */
21121   Uint32 orgTransPtrI = tcPtr.p->nextTcFailHash;
21122   ApiConnectRecordPtr transPtr;
21123   transPtr.i = orgTransPtrI;
21124   if (unlikely(!c_apiConnectRecordPool.getValidPtr(transPtr)) ||
21125       unlikely(! (transId[0] == transPtr.p->transid[0] &&
21126                   transId[1] == transPtr.p->transid[1] &&
21127                   transPtr.p->apiConnectstate != CS_ABORTING)))
21128   {
21129     jam();
21130 
21131     /**
21132      * The "base" transaction has been aborted...
21133      *   terminate scan directly
21134      */
21135     fk_scanFromChildTable_abort(signal,
21136                                 tcPtr,
21137                                 scanApiConnectPtr);
21138     return;
21139   }
21140 
21141   Ptr<TcDefinedTriggerData> trigPtr;
21142   c_theDefinedTriggers.getPtr(trigPtr, tcPtr.p->currentTriggerId);
21143 
21144   /* Extract KeyData */
21145   Uint32 keyInfoPtrI = RNIL;
21146   if (signal->header.m_noOfSections == 0)
21147   {
21148     jam();
21149     Ptr<SectionSegment> keyInfo;
21150     if (unlikely(! import(keyInfo, conf->keyData, keyLen)))
21151     {
21152       abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
21153       return;
21154     }
21155     keyInfoPtrI = keyInfo.i;
21156   }
21157   else
21158   {
21159     jam();
21160     ndbrequire(signal->header.m_noOfSections == 1); // key is already here...
21161     keyInfoPtrI = signal->m_sectionPtrI[0];
21162     signal->header.m_noOfSections = 0;
21163   }
21164 
21165   Ptr<TcFKData> fkPtr;
21166   // TODO make it a pool.getPtr() instead
21167   // by also adding fk_ptr_i to definedTriggerData
21168   ndbrequire(c_fk_hash.find(fkPtr, trigPtr.p->fkId));
21169 
21170   /**
21171    * Construct a DELETE/UPDATE
21172    * NOTE: on table...not index
21173    */
21174   Uint32 op = tcPtr.p->operation;
21175   TcKeyReq * const tcKeyReq =  CAST_PTR(TcKeyReq, signal->getDataPtrSend());
21176   TableRecordPtr childTabPtr;
21177 
21178   childTabPtr.i = fkPtr.p->childTableId;
21179   ptrCheckGuard(childTabPtr, ctabrecFilesize, tableRecord);
21180   tcKeyReq->apiConnectPtr = orgTransPtrI;
21181   tcKeyReq->senderData = tcPtr.p->triggeringOperation;
21182 
21183   tcKeyReq->attrLen = 0;
21184   tcKeyReq->tableId = childTabPtr.i;
21185   tcKeyReq->tableSchemaVersion = childTabPtr.p->currentSchemaVersion;
21186   tcKeyReq->transId1 = transPtr.p->transid[0];
21187   tcKeyReq->transId2 = transPtr.p->transid[1];
21188   Uint32 tcKeyRequestInfo = 0;
21189   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
21190   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
21191   TcKeyReq::setOperationType(tcKeyRequestInfo, op);
21192   const bool use_scan_takeover = false;
21193   if (use_scan_takeover)
21194   {
21195     TcKeyReq::setScanIndFlag(tcKeyRequestInfo, 1);
21196   }
21197   tcKeyReq->requestInfo = tcKeyRequestInfo;
21198   if (use_scan_takeover)
21199   {
21200     tcKeyReq->scanInfo = (scanInfo << 1) + 1; // TODO cleanup
21201   }
21202   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyInfoPtrI;
21203   signal->header.m_noOfSections= 1;
21204 
21205   if (tcPtr.p->indexOp != RNIL)
21206   {
21207     /**
21208      * attrValues save in indexOp
21209      */
21210     Uint32 tmp = RNIL;
21211     if (unlikely( !dupSection(tmp, tcPtr.p->indexOp)))
21212     {
21213       jam();
21214       releaseSection(keyInfoPtrI);
21215       signal->header.m_noOfSections = 0;
21216       abortTransFromTrigger(signal, transPtr, ZGET_DATAREC_ERROR);
21217       return;
21218     }
21219     signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = tmp;
21220     signal->header.m_noOfSections= 2;
21221   }
21222 
21223   TcConnectRecordPtr opPtr; // triggering operation
21224   opPtr.i = tcPtr.p->triggeringOperation;
21225   tcConnectRecord.getPtr(opPtr);
21226 
21227   /**
21228    * Fix savepoint id -
21229    *   fix so that op has same savepoint id as triggering operation
21230    */
21231   const Uint32 currSavePointId = transPtr.p->currSavePointId;
21232   transPtr.p->currSavePointId = opPtr.p->savePointId;
21233   transPtr.p->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
21234   /* Pass trigger Id via ApiConnectRecord (nasty) */
21235   ndbrequire(transPtr.p->immediateTriggerId == RNIL);
21236   transPtr.p->immediateTriggerId = tcPtr.p->currentTriggerId;
21237   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength +
21238                  (use_scan_takeover ? 1 : 0));
21239   jamEntry();
21240 
21241   /*
21242    * Restore ApiConnectRecord state
21243    */
21244   transPtr.p->immediateTriggerId = RNIL;
21245   transPtr.p->currSavePointId = currSavePointId;
21246 
21247   /**
21248    * Update counter of how many trigger executed...
21249    */
21250   opPtr.p->triggerExecutionCount++;
21251   transPtr.p->m_executing_trigger_ops++;
21252 }
21253 
21254 void
execSCAN_TABCONF(Signal * signal)21255 Dbtc::execSCAN_TABCONF(Signal* signal)
21256 {
21257   jamEntry();
21258 
21259   if (ERROR_INSERTED(8109))
21260   {
21261     jam();
21262     /* Hang around */
21263     sendSignalWithDelay(cownref, GSN_SCAN_TABCONF, signal, 100, signal->getLength());
21264     return;
21265   }
21266 
21267   const ScanTabConf * conf = CAST_CONSTPTR(ScanTabConf, signal->getDataPtr());
21268 
21269   Uint32 transId[] = {
21270     conf->transId1,
21271     conf->transId2
21272   };
21273 
21274   TcConnectRecordPtr tcPtr;
21275   tcPtr.i = conf->apiConnectPtr;
21276   if (unlikely(!tcConnectRecord.getValidPtr(tcPtr)))
21277   {
21278     jam();
21279     warningHandlerLab(signal, __LINE__);
21280     // Assert to catch code coverage, remove when reached and analysed
21281     ndbassert(false);
21282     return;
21283   }
21284 
21285   ApiConnectRecordPtr scanApiConnectPtr;
21286   scanApiConnectPtr.i = tcPtr.p->apiConnect;
21287   if (unlikely(!c_apiConnectRecordPool.getValidPtr(scanApiConnectPtr)))
21288   {
21289     jam();
21290     // Assert to catch code coverage, remove when reached and analysed
21291     ndbassert(false);
21292     return;
21293   }
21294 
21295   if (! (transId[0] == scanApiConnectPtr.p->transid[0] &&
21296          transId[1] == scanApiConnectPtr.p->transid[1]))
21297   {
21298     jam();
21299 
21300     /**
21301      * incorrect transid...no known scenario where this can happen
21302      */
21303     warningHandlerLab(signal, __LINE__);
21304     ndbassert(false);
21305     return;
21306   }
21307 
21308   /**
21309    * Validate base transaction
21310    */
21311   Uint32 orgTransPtrI = tcPtr.p->nextTcFailHash;
21312   ApiConnectRecordPtr orgApiConnectPtr;
21313   orgApiConnectPtr.i = orgTransPtrI;
21314   if (unlikely(!c_apiConnectRecordPool.getUncheckedPtrRW(orgApiConnectPtr)) ||
21315       unlikely(! (transId[0] == orgApiConnectPtr.p->transid[0] &&
21316                   transId[1] == orgApiConnectPtr.p->transid[1] &&
21317                   orgApiConnectPtr.p->apiConnectstate != CS_ABORTING)))
21318   {
21319     jam();
21320 
21321     /**
21322      * The "base" transaction has been aborted...
21323      *   terminate scan directly
21324      */
21325     if (conf->requestInfo & ScanTabConf::EndOfData)
21326     {
21327       jam();
21328       fk_scanFromChildTable_done(signal,
21329                                  tcPtr,
21330                                  scanApiConnectPtr);
21331     }
21332     else
21333     {
21334       jam();
21335       fk_scanFromChildTable_abort(signal,
21336                                   tcPtr,
21337                                   scanApiConnectPtr);
21338     }
21339     return;
21340   }
21341   ndbrequire(Magic::check_ptr(orgApiConnectPtr.p));
21342 
21343   Ptr<TcDefinedTriggerData> trigPtr;
21344   c_theDefinedTriggers.getPtr(trigPtr, tcPtr.p->currentTriggerId);
21345 
21346   Ptr<TcFKData> fkPtr;
21347   // TODO make it a pool.getPtr() instead
21348   // by also adding fk_ptr_i to definedTriggerData
21349   ndbrequire(c_fk_hash.find(fkPtr, trigPtr.p->fkId));
21350 
21351   Uint32 rows = 0;
21352   const Uint32 ops = (conf->requestInfo >> OPERATIONS_SHIFT) & OPERATIONS_MASK;
21353   for (Uint32 i = 0; i<ops; i++)
21354   {
21355     jam();
21356     ScanTabConf::OpData * op = (ScanTabConf::OpData*)
21357       (signal->getDataPtr() + ScanTabConf::SignalLength + 3 * i);
21358     rows += ScanTabConf::getRows(op->rows);
21359   }
21360 
21361   if (rows && tcPtr.p->operation != ZREAD)
21362   {
21363     jam();
21364     TcConnectRecordPtr opPtr; // triggering operation
21365     opPtr.i = tcPtr.p->triggeringOperation;
21366     tcConnectRecord.getPtr(opPtr);
21367     TcConnectRecord * triggeringOp = opPtr.p;
21368     if (triggeringOp->operation == ZDELETE &&
21369         (fkPtr.p->bits & (CreateFKImplReq::FK_DELETE_CASCADE | CreateFKImplReq::FK_DELETE_SET_NULL)))
21370     {
21371       /**
21372        * don't abort scan
21373        */
21374       jam();
21375       rows = 0;
21376     }
21377     else if ((triggeringOp->operation == ZUPDATE || triggeringOp->operation == ZWRITE) &&
21378              (fkPtr.p->bits & (CreateFKImplReq::FK_UPDATE_CASCADE | CreateFKImplReq::FK_UPDATE_SET_NULL)))
21379     {
21380       /**
21381        * don't abort scan
21382        */
21383       jam();
21384       rows = 0;
21385     }
21386   }
21387 
21388   if (rows)
21389   {
21390     jam();
21391     tcPtr.p->triggerErrorCode = ZFK_CHILD_ROW_EXISTS;
21392     orgApiConnectPtr.p->errorData = trigPtr.p->fkId;
21393   }
21394 
21395   if (conf->requestInfo & ScanTabConf::EndOfData)
21396   {
21397     jam();
21398     fk_scanFromChildTable_done(signal,
21399                                tcPtr,
21400                                scanApiConnectPtr);
21401   }
21402   else if (rows)
21403   {
21404     jam();
21405     /**
21406      * Abort scan...we already know that ZFK_CHILD_ROW_EXISTS
21407      */
21408     fk_scanFromChildTable_abort(signal,
21409                                 tcPtr,
21410                                 scanApiConnectPtr);
21411   }
21412   else
21413   {
21414     jam();
21415     /**
21416      * Continue scanning...
21417      */
21418     const Uint32 parallelism = SCAN_FROM_CHILD_PARALLELISM;
21419     Uint32 cnt = 0;
21420     Uint32 operations[parallelism];
21421     for (Uint32 i = 0; i<ops; i++)
21422     {
21423       jam();
21424       ScanTabConf::OpData * op = (ScanTabConf::OpData*)
21425         (signal->getDataPtr() + ScanTabConf::SignalLength + 3 * i);
21426       if (op->tcPtrI != RNIL)
21427       {
21428         ndbrequire(cnt < NDB_ARRAY_SIZE(operations));
21429         operations[cnt++] = op->tcPtrI;
21430       }
21431     }
21432     if (cnt)
21433     {
21434       jam();
21435       ScanNextReq* req = CAST_PTR(ScanNextReq, signal->getDataPtrSend());
21436       req->apiConnectPtr = scanApiConnectPtr.i;
21437       req->stopScan = 0;
21438       req->transId1 = scanApiConnectPtr.p->transid[0];
21439       req->transId2 = scanApiConnectPtr.p->transid[1];
21440       memcpy(signal->getDataPtrSend() + ScanNextReq::SignalLength,
21441              operations, 4 * cnt);
21442       sendSignal(reference(), GSN_SCAN_NEXTREQ, signal,
21443                  ScanNextReq::SignalLength + cnt, JBB);
21444     }
21445   }
21446 }
21447 
21448 void
fk_scanFromChildTable_abort(Signal * signal,TcConnectRecordPtr tcPtr,ApiConnectRecordPtr scanApiConnectPtr)21449 Dbtc::fk_scanFromChildTable_abort(Signal* signal,
21450                                   TcConnectRecordPtr tcPtr,
21451                                   ApiConnectRecordPtr scanApiConnectPtr)
21452 {
21453   ndbrequire(scanApiConnectPtr.p->ndbapiConnect == tcPtr.i);
21454   /**
21455    * Check that the scan has not already completed
21456    * - so we can abort aggresively
21457    */
21458   if (scanApiConnectPtr.p->apiConnectstate != CS_START_SCAN)
21459   {
21460     jam();
21461     /**
21462      * Scan has already completed...we just haven't received the EOD yet
21463      *
21464      *   wait for it...
21465      */
21466     return;
21467   }
21468 
21469   ScanNextReq* req = CAST_PTR(ScanNextReq, signal->getDataPtrSend());
21470   req->apiConnectPtr = scanApiConnectPtr.i;
21471   req->stopScan = 1;
21472   req->transId1 = scanApiConnectPtr.p->transid[0];
21473   req->transId2 = scanApiConnectPtr.p->transid[1];
21474 
21475   /**
21476    * Here we need to use EXECUTE_DIRECT
21477    *   or this signal will race with state-changes in scan-record
21478    *
21479    * NOTE: A better alternative would be to fix Dbtc/protocol to handle
21480    *       these races...
21481    */
21482   EXECUTE_DIRECT(DBTC, GSN_SCAN_NEXTREQ, signal, ScanNextReq::SignalLength);
21483 }
21484 
21485 void
fk_scanFromChildTable_done(Signal * signal,TcConnectRecordPtr tcPtr,ApiConnectRecordPtr scanApiConnectPtr)21486 Dbtc::fk_scanFromChildTable_done(Signal* signal,
21487                                  TcConnectRecordPtr tcPtr,
21488                                  ApiConnectRecordPtr scanApiConnectPtr)
21489 {
21490   ndbrequire(scanApiConnectPtr.p->ndbapiConnect == tcPtr.i);
21491   /**
21492    * save things needed to finish this trigger op
21493    */
21494   Uint32 transId[] = {
21495     scanApiConnectPtr.p->transid[0],
21496     scanApiConnectPtr.p->transid[1]
21497   };
21498 
21499   Uint32 errCode = tcPtr.p->triggerErrorCode;
21500   Uint32 triggerId = tcPtr.p->currentTriggerId;
21501   Uint32 orgTransPtrI = tcPtr.p->nextTcFailHash;
21502 
21503   TcConnectRecordPtr opPtr; // triggering operation
21504   opPtr.i = tcPtr.p->triggeringOperation;
21505 
21506   /**
21507    * release extra allocated resources
21508    */
21509   if (tcPtr.p->indexOp != RNIL)
21510   {
21511     releaseSection(tcPtr.p->indexOp);
21512   }
21513   tcConnectptr = tcPtr;
21514   releaseTcCon();
21515   checkPoolShrinkNeed(DBTC_CONNECT_RECORD_TRANSIENT_POOL_INDEX,
21516                       tcConnectRecord);
21517   releaseApiCon(signal, scanApiConnectPtr.i);
21518 
21519   ApiConnectRecordPtr orgApiConnectPtr;
21520   orgApiConnectPtr.i = orgTransPtrI;
21521 
21522   if (!c_apiConnectRecordPool.getValidPtr(orgApiConnectPtr) ||
21523       ! (transId[0] == orgApiConnectPtr.p->transid[0] &&
21524          transId[1] == orgApiConnectPtr.p->transid[1] &&
21525          orgApiConnectPtr.p->apiConnectstate != CS_ABORTING))
21526   {
21527     jam();
21528     /**
21529      * The "base" transaction has been aborted...
21530      *   we need just throw away our scan...
21531      *   any DML caused by it...is anyway put onto "real" transaction
21532      */
21533     return;
21534   }
21535 
21536   tcConnectRecord.getPtr(opPtr);
21537   if (opPtr.p->apiConnect != orgApiConnectPtr.i)
21538   {
21539     jam();
21540     ndbabort();
21541     /**
21542      * this should not happen :-)
21543      *
21544      * triggering operation has been moved to different transaction...
21545      * this should not happen since then the original trans should be aborted
21546      *   (or aborted and restarted) this is checked above...
21547      *
21548      */
21549     return;
21550   }
21551 
21552   ndbrequire(orgApiConnectPtr.p->lqhkeyreqrec > 0);
21553   ndbrequire(orgApiConnectPtr.p->lqhkeyreqrec > orgApiConnectPtr.p->lqhkeyconfrec);
21554   orgApiConnectPtr.p->lqhkeyreqrec--;
21555 
21556   D("trans: cascading scans-- " << orgApiConnectPtr.p->cascading_scans_count);
21557   ndbrequire(orgApiConnectPtr.p->cascading_scans_count > 0);
21558   orgApiConnectPtr.p->cascading_scans_count--;
21559   ndbrequire(orgApiConnectPtr.p->m_executing_trigger_ops > 0);
21560   orgApiConnectPtr.p->m_executing_trigger_ops--;
21561 
21562   trigger_op_finished(signal, orgApiConnectPtr, triggerId, opPtr.p, errCode);
21563   executeTriggers(signal, &orgApiConnectPtr);
21564 }
21565 
21566 void
execSCAN_TABREF(Signal * signal)21567 Dbtc::execSCAN_TABREF(Signal* signal)
21568 {
21569   jamEntry();
21570 
21571   if (ERROR_INSERTED(8109))
21572   {
21573     jam();
21574     /* Hang around */
21575     sendSignalWithDelay(cownref, GSN_SCAN_TABREF, signal, 100, signal->getLength());
21576     return;
21577   }
21578 
21579 
21580   const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, signal->getDataPtr());
21581 
21582   Uint32 transId[] = {
21583     ref->transId1,
21584     ref->transId2
21585   };
21586 
21587   TcConnectRecordPtr tcPtr;
21588   tcPtr.i = ref->apiConnectPtr;
21589   if (unlikely(!tcConnectRecord.getValidPtr(tcPtr)))
21590   {
21591     jam();
21592     warningHandlerLab(signal, __LINE__);
21593     // Assert to catch code coverage, remove when reached and analysed
21594     //ndbassert(false);
21595     return;
21596   }
21597 
21598   ApiConnectRecordPtr scanApiConnectPtr;
21599   scanApiConnectPtr.i = tcPtr.p->apiConnect;
21600   if (!c_apiConnectRecordPool.getValidPtr(scanApiConnectPtr) ||
21601       ! (transId[0] == scanApiConnectPtr.p->transid[0] &&
21602          transId[1] == scanApiConnectPtr.p->transid[1]))
21603   {
21604     jam();
21605 
21606     /**
21607      * incorrect transid...no known scenario where this can happen
21608      */
21609     warningHandlerLab(signal, __LINE__);
21610     ndbassert(false);
21611     return;
21612   }
21613 
21614   tcPtr.p->triggerErrorCode = ref->errorCode;
21615   if (ref->closeNeeded)
21616   {
21617     jam();
21618     fk_scanFromChildTable_abort(signal,
21619                                tcPtr,
21620                                scanApiConnectPtr);
21621   }
21622   else
21623   {
21624     jam();
21625     fk_scanFromChildTable_done(signal,
21626                                tcPtr,
21627                                scanApiConnectPtr);
21628   }
21629 }
21630 
21631 Uint32
fk_buildBounds(SegmentedSectionPtr & dst,LocalAttributeBuffer & src,TcFKData * fkData)21632 Dbtc::fk_buildBounds(SegmentedSectionPtr & dst,
21633                      LocalAttributeBuffer & src,
21634                      TcFKData* fkData)
21635 {
21636   dst.i = RNIL;
21637   Uint32 dstPtrI = RNIL;
21638 
21639   IndexAttributeList * list = &fkData->parentTableColumns;
21640 
21641   AttributeBuffer::DataBufferIterator iter;
21642   bool eof = !src.first(iter);
21643   for (Uint32 i = 0; i < list->sz; i++)
21644   {
21645     Uint32 col = list->id[i];
21646     if (!eof && AttributeHeader(* iter.data).getAttributeId() == col)
21647     {
21648   found:
21649       Uint32 byteSize = AttributeHeader(* iter.data).getByteSize();
21650       Uint32 len32 = (byteSize + 3) / 4;
21651       if (len32 == 0)
21652       {
21653         // ?? TODO what to do
21654       }
21655       eof = !src.next(iter);
21656 
21657       Uint32 data[2];
21658       data[0] = TuxBoundInfo::BoundEQ;
21659       AttributeHeader::init(data+1, i, byteSize);
21660       if (unlikely(!appendToSection(dstPtrI, data, NDB_ARRAY_SIZE(data))))
21661       {
21662         dst.i = dstPtrI;
21663         return ZGET_DATAREC_ERROR;
21664       }
21665 
21666       Uint32 err = appendDataToSection(dstPtrI, src, iter,
21667                                        len32);
21668       if (unlikely(err != 0))
21669       {
21670         dst.i = dstPtrI;
21671         return err;
21672       }
21673 
21674       eof = iter.isNull();
21675     }
21676     else
21677     {
21678       /**
21679        * Search for column...
21680        */
21681       eof = !src.first(iter);
21682       while (!eof && AttributeHeader(* iter.data).getAttributeId() != col)
21683       {
21684         eof = !src.next(iter,
21685                            1 + AttributeHeader(* iter.data).getDataSize());
21686       }
21687       if (unlikely(eof))
21688       {
21689         dst.i = dstPtrI;
21690         return ZMISSING_TRIGGER_DATA;
21691       }
21692       ndbassert(AttributeHeader(* iter.data).getAttributeId() == col);
21693       goto found;
21694     }
21695   }
21696 
21697   dst.i = dstPtrI;
21698   return 0;
21699 }
21700 
21701 void
executeFKChildTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr)21702 Dbtc::executeFKChildTrigger(Signal* signal,
21703                             TcDefinedTriggerData* definedTriggerData,
21704                             TcFiredTriggerData* firedTriggerData,
21705                             ApiConnectRecordPtr const* transPtr,
21706                             TcConnectRecordPtr* opPtr)
21707 {
21708   Ptr<TcFKData> fkPtr;
21709   // TODO make it a pool.getPtr() instead
21710   // by also adding fk_ptr_i to definedTriggerData
21711   ndbrequire(c_fk_hash.find(fkPtr, definedTriggerData->fkId));
21712 
21713   /**
21714    * We are performing an INSERT or an UPDATE on the child table
21715    * (the table where the foreign key is defined), we need to ensure that
21716    * the referenced table have the row we are referring to here.
21717    *
21718    * The parent table reference must be the primary key of the table,
21719    * so this is always a key lookup.
21720    */
21721   switch (firedTriggerData->triggerEvent) {
21722   case(TriggerEvent::TE_INSERT):
21723     jam();
21724     /**
21725      * Check that after values exists in parent table
21726      */
21727     fk_readFromParentTable(signal, firedTriggerData, transPtr, opPtr, fkPtr.p);
21728     break;
21729   case(TriggerEvent::TE_UPDATE):
21730     jam();
21731     /**
21732      * Check that after values exists in parent table
21733      */
21734     fk_readFromParentTable(signal, firedTriggerData, transPtr, opPtr, fkPtr.p);
21735     break;
21736   default:
21737     ndbabort();
21738   }
21739 }
21740 
21741 void
fk_readFromParentTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr,TcFKData * fkData)21742 Dbtc::fk_readFromParentTable(Signal* signal,
21743                              TcFiredTriggerData* firedTriggerData,
21744                              ApiConnectRecordPtr const* transPtr,
21745                              TcConnectRecordPtr* opPtr,
21746                              TcFKData* fkData)
21747 {
21748   ApiConnectRecord* regApiPtr = transPtr->p;
21749   TcConnectRecord* opRecord = opPtr->p;
21750   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
21751   Uint32 tcKeyRequestInfo = 0;
21752   TableRecordPtr parentTabPtr;
21753 
21754   parentTabPtr.i = fkData->parentTableId;
21755   ptrCheckGuard(parentTabPtr, ctabrecFilesize, tableRecord);
21756   tcKeyReq->apiConnectPtr = transPtr->i;
21757   tcKeyReq->senderData = opPtr->i;
21758 
21759   // Calculate key length and renumber attribute id:s
21760   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
21761   LocalAttributeBuffer afterValues(pool, firedTriggerData->afterValues);
21762 
21763   if (afterValues.getSize() == 0)
21764   {
21765     jam();
21766     ndbrequire(tc_testbit(regApiPtr->m_flags,
21767                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
21768     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
21769     /* Already executing triggers */
21770     ndbassert(regApiPtr->m_inExecuteTriggers);
21771     return;
21772   }
21773 
21774   Uint32 keyIVal= RNIL;
21775   bool hasNull= false;
21776   Uint32 err = fk_buildKeyInfo(keyIVal, hasNull, afterValues, fkData, true);
21777   SegmentedSectionGuard guard(this, keyIVal);
21778   if (unlikely(err != 0))
21779   {
21780     abortTransFromTrigger(signal, *transPtr, err);
21781     return;
21782   }
21783 
21784   /* If there's Nulls in the values that become the index table's
21785    * PK then we skip this delete
21786    */
21787   if (hasNull)
21788   {
21789     jam();
21790     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
21791     /* Already executing triggers */
21792     ndbassert(regApiPtr->m_inExecuteTriggers);
21793     return;
21794   }
21795 
21796   Uint16 flags = TcConnectRecord::SOF_TRIGGER;
21797   if (((fkData->bits & CreateFKImplReq::FK_ACTION_MASK) == 0) ||
21798       transPtr->p->isExecutingDeferredTriggers())
21799   {
21800     jam();
21801     /* Read parent row using SimpleRead locking */
21802     TcKeyReq::setSimpleFlag(tcKeyRequestInfo, 1);
21803     TcKeyReq::setDirtyFlag(tcKeyRequestInfo, 0);
21804   }
21805 
21806   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
21807   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
21808   tcKeyReq->attrLen = 0;
21809   tcKeyReq->tableId = parentTabPtr.i;
21810   TcKeyReq::setOperationType(tcKeyRequestInfo, ZREAD);
21811   tcKeyReq->tableSchemaVersion = parentTabPtr.p->currentSchemaVersion;
21812   tcKeyReq->transId1 = regApiPtr->transid[0];
21813   tcKeyReq->transId2 = regApiPtr->transid[1];
21814   tcKeyReq->requestInfo = tcKeyRequestInfo;
21815 
21816   guard.clear(); // now sections will be handled...
21817 
21818   /* Attach KeyInfo section to signal */
21819   ndbrequire(signal->header.m_noOfSections == 0);
21820   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
21821   signal->header.m_noOfSections = 1;
21822 
21823   /**
21824    * Fix savepoint id seen by READ:
21825    * - If it is a deferred trigger we will see the tuple content
21826    *   at commit time, as already available through the
21827    *   'currSavePointId' set by commit.
21828    * - else, an immediate trigger should see the tuple as
21829    *   immediate after ('+1') the operation which updated it.
21830    */
21831   const Uint32 currSavePointId = regApiPtr->currSavePointId;
21832   if (!transPtr->p->isExecutingDeferredTriggers())
21833     regApiPtr->currSavePointId = opRecord->savePointId+1;
21834 
21835   regApiPtr->m_special_op_flags = flags;
21836   /* Pass trigger Id via ApiConnectRecord (nasty) */
21837   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
21838   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
21839   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
21840   jamEntry();
21841 
21842   /*
21843    * Restore ApiConnectRecord state
21844    */
21845   regApiPtr->immediateTriggerId = RNIL;
21846   regApiPtr->currSavePointId = currSavePointId;
21847   regApiPtr->m_executing_trigger_ops++;
21848 }
21849 
releaseFiredTriggerData(Local_TcFiredTriggerData_fifo::Head * triggers_head)21850 void Dbtc::releaseFiredTriggerData(Local_TcFiredTriggerData_fifo::Head*
21851                                    triggers_head)
21852 {
21853   Local_TcFiredTriggerData_fifo triggers(c_theFiredTriggerPool, *triggers_head);
21854   FiredTriggerPtr trigPtr;
21855 
21856   while (triggers.removeFirst(trigPtr))
21857   {
21858     jam();
21859     // Release trigger records
21860 
21861     AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
21862     LocalAttributeBuffer tmp1(pool, trigPtr.p->keyValues);
21863     tmp1.release();
21864     LocalAttributeBuffer tmp2(pool, trigPtr.p->beforeValues);
21865     tmp2.release();
21866     LocalAttributeBuffer tmp3(pool, trigPtr.p->afterValues);
21867     tmp3.release();
21868     c_theFiredTriggerPool.release(trigPtr);
21869   }
21870   checkPoolShrinkNeed(DBTC_ATTRIBUTE_BUFFER_TRANSIENT_POOL_INDEX,
21871                       c_theAttributeBufferPool);
21872   checkPoolShrinkNeed(DBTC_FIRED_TRIGGER_DATA_TRANSIENT_POOL_INDEX,
21873                       c_theFiredTriggerPool);
21874 }
21875 
21876 /**
21877  * abortTransFromTrigger
21878  *
21879  * This method is called when there is a problem with trigger
21880  * handling and the transaction should be aborted with the
21881  * given error code
21882  */
abortTransFromTrigger(Signal * signal,ApiConnectRecordPtr const transPtr,Uint32 error)21883 void Dbtc::abortTransFromTrigger(Signal* signal,
21884                                  ApiConnectRecordPtr const transPtr,
21885                                  Uint32 error)
21886 {
21887   jam();
21888   terrorCode = error;
21889 
21890   abortErrorLab(signal, transPtr);
21891 }
21892 
21893 Uint32
appendDataToSection(Uint32 & sectionIVal,AttributeBuffer & src,AttributeBuffer::DataBufferIterator & iter,Uint32 len)21894 Dbtc::appendDataToSection(Uint32& sectionIVal,
21895                           AttributeBuffer & src,
21896                           AttributeBuffer::DataBufferIterator & iter,
21897                           Uint32 len)
21898 {
21899   const Uint32 segSize = src.getSegmentSize(); // 11
21900   while (len)
21901   {
21902     /* Copy as many contiguous words as possible */
21903     Uint32 contigLeft = segSize - iter.ind;
21904     ndbassert(contigLeft);
21905     Uint32 contigValid = MIN(len, contigLeft);
21906 
21907     if (unlikely(!appendToSection(sectionIVal,
21908                                   iter.data,
21909                                   contigValid)))
21910     {
21911       goto full;
21912     }
21913     len -= contigValid;
21914     bool hasMore = src.next(iter, contigValid);
21915 
21916     if (len == 0)
21917       break;
21918 
21919     if (unlikely(! hasMore))
21920     {
21921       ndbassert(false); // this is internal error...
21922       goto fail;
21923     }
21924   }
21925   return 0;
21926 
21927 full:
21928   jam();
21929   releaseSection(sectionIVal);
21930   sectionIVal= RNIL;
21931   return ZGET_DATAREC_ERROR;
21932 
21933 fail:
21934   jam();
21935   releaseSection(sectionIVal);
21936   sectionIVal= RNIL;
21937   return ZMISSING_TRIGGER_DATA;
21938 }
21939 
21940 /**
21941  * appendAttrDataToSection
21942  *
21943  * Copy data in AttrInfo form from the given databuffer
21944  * to the given section IVal (can be RNIL).
21945  * If attribute headers are to be copied they will be
21946  * renumbered consecutively, starting with the given
21947  * attrId.
21948  * hasNull is updated to indicate whether any Nulls
21949  * were encountered.
21950  */
appendAttrDataToSection(Uint32 & sectionIVal,AttributeBuffer & values,bool withHeaders,Uint32 & attrId,bool & hasNull)21951 bool Dbtc::appendAttrDataToSection(Uint32& sectionIVal,
21952                                    AttributeBuffer& values,
21953                                    bool withHeaders,
21954                                    Uint32& attrId,
21955                                    bool& hasNull)
21956 {
21957   AttributeBuffer::DataBufferIterator iter;
21958   bool moreData= values.first(iter);
21959   hasNull= false;
21960   const Uint32 segSize= values.getSegmentSize(); // 11
21961 
21962   while (moreData)
21963   {
21964     AttributeHeader* attrHeader = (AttributeHeader *) iter.data;
21965     Uint32 dataSize= attrHeader->getDataSize();
21966     hasNull |= (dataSize == 0);
21967 
21968     if (withHeaders)
21969     {
21970       AttributeHeader ah(*iter.data);
21971       ah.setAttributeId(attrId); // Renumber AttrIds
21972       if (unlikely(!appendToSection(sectionIVal,
21973                                     &ah.m_value,
21974                                     1)))
21975       {
21976         releaseSection(sectionIVal);
21977         sectionIVal= RNIL;
21978         return false;
21979       }
21980     }
21981 
21982     moreData= values.next(iter, 1);
21983 
21984     while (dataSize)
21985     {
21986       ndbrequire(moreData);
21987       /* Copy as many contiguous words as possible */
21988       Uint32 contigLeft= segSize - iter.ind;
21989       ndbassert(contigLeft);
21990       Uint32 contigValid= MIN(dataSize, contigLeft);
21991 
21992       if (unlikely(!appendToSection(sectionIVal,
21993                                     iter.data,
21994                                     contigValid)))
21995       {
21996         releaseSection(sectionIVal);
21997         sectionIVal= RNIL;
21998         return false;
21999       }
22000       moreData= values.next(iter, contigValid);
22001       dataSize-= contigValid;
22002     }
22003     attrId++;
22004   }
22005 
22006   return true;
22007 }
22008 
insertIntoIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)22009 void Dbtc::insertIntoIndexTable(Signal* signal,
22010                                 TcFiredTriggerData* firedTriggerData,
22011                                 ApiConnectRecordPtr const* transPtr,
22012                                 TcConnectRecordPtr* opPtr,
22013                                 TcIndexData* indexData)
22014 {
22015   ApiConnectRecord* regApiPtr = transPtr->p;
22016   TcConnectRecord* opRecord = opPtr->p;
22017   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
22018   Uint32 tcKeyRequestInfo = 0;
22019   TableRecordPtr indexTabPtr;
22020 
22021   jam();
22022 
22023   indexTabPtr.i = indexData->indexId;
22024   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
22025   tcKeyReq->apiConnectPtr = transPtr->i;
22026   tcKeyReq->senderData = opPtr->i;
22027 
22028   /* Key for insert to unique index table is the afterValues from the
22029    * base table operation (from update or insert on base).
22030    * Data for insert to unique index table is the afterValues from the
22031    * base table operation plus the fragment id and packed keyValues from
22032    * the base table operation
22033    */
22034   // Calculate key length and renumber attribute id:s
22035   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
22036   LocalAttributeBuffer afterValues(pool, firedTriggerData->afterValues);
22037   LocalAttributeBuffer keyValues(pool, firedTriggerData->keyValues);
22038 
22039   if (afterValues.getSize() == 0)
22040   {
22041     jam();
22042     ndbrequire(tc_testbit(regApiPtr->m_flags,
22043                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
22044     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
22045     /* Already executing triggers */
22046     ndbassert(regApiPtr->m_inExecuteTriggers);
22047     return;
22048   }
22049 
22050   Uint32 keyIVal= RNIL;
22051   Uint32 attrIVal= RNIL;
22052   bool appendOk= false;
22053   do
22054   {
22055     Uint32 attrId= 0;
22056     bool hasNull= false;
22057 
22058     /* Build Insert KeyInfo section from aftervalues */
22059     if (unlikely(! appendAttrDataToSection(keyIVal,
22060                                            afterValues,
22061                                            false, // No AttributeHeaders
22062                                            attrId,
22063                                            hasNull)))
22064     {
22065       jam();
22066       break;
22067     }
22068 
22069     if(ERROR_INSERTED(8086))
22070     {
22071       /* Simulate SS exhaustion */
22072       break;
22073     }
22074 
22075     /* If there's Nulls in the values that become the index table's
22076      * PK then we skip this insert
22077      */
22078     if (hasNull)
22079     {
22080       jam();
22081       releaseSection(keyIVal);
22082       trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
22083       /* Already executing triggers */
22084       ndbassert(regApiPtr->m_inExecuteTriggers);
22085       return;
22086     }
22087 
22088     /* Build Insert AttrInfo section from aftervalues,
22089      * fragment id + keyvalues
22090      */
22091     AttributeHeader ah(attrId, 0); // Length tbd.
22092     attrId= 0;
22093     if (unlikely((! appendAttrDataToSection(attrIVal,
22094                                             afterValues,
22095                                             true, // Include AttributeHeaders,
22096                                             attrId,
22097                                             hasNull)) ||
22098                  (! appendToSection(attrIVal,
22099                                     &ah.m_value,
22100                                     1))))
22101     {
22102       jam();
22103       break;
22104     }
22105 
22106     AttributeHeader* pkHeader= (AttributeHeader*) getLastWordPtr(attrIVal);
22107     Uint32 startSz= getSectionSz(attrIVal);
22108     if (unlikely((! appendToSection(attrIVal,
22109                                     &firedTriggerData->fragId,
22110                                     1)) ||
22111                  (! appendAttrDataToSection(attrIVal,
22112                                             keyValues,
22113                                             false, // No AttributeHeaders
22114                                             attrId,
22115                                             hasNull))))
22116     {
22117       jam();
22118       break;
22119     }
22120 
22121     appendOk= true;
22122 
22123     /* Now go back and set pk header length */
22124     pkHeader->setDataSize(getSectionSz(attrIVal) - startSz);
22125   } while(0);
22126 
22127   if (unlikely(!appendOk))
22128   {
22129     /* Some failure building up KeyInfo and AttrInfo */
22130     releaseSection(keyIVal);
22131     releaseSection(attrIVal);
22132     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
22133     return;
22134   }
22135 
22136   /* Now build TcKeyReq for insert */
22137   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
22138   tcKeyReq->attrLen = 0;
22139   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
22140   tcKeyReq->tableId = indexData->indexId;
22141   TcKeyReq::setOperationType(tcKeyRequestInfo, ZINSERT);
22142   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
22143   tcKeyReq->transId1 = regApiPtr->transid[0];
22144   tcKeyReq->transId2 = regApiPtr->transid[1];
22145   tcKeyReq->requestInfo = tcKeyRequestInfo;
22146 
22147   /* Attach Key and AttrInfo sections to signal */
22148   ndbrequire(signal->header.m_noOfSections == 0);
22149   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
22150   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
22151   signal->header.m_noOfSections= 2;
22152 
22153   /*
22154    * Fix savepoint id -
22155    *   fix so that insert has same savepoint id as triggering operation
22156    */
22157   const Uint32 currSavePointId = regApiPtr->currSavePointId;
22158   regApiPtr->currSavePointId = opRecord->savePointId;
22159   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
22160   /* Pass trigger Id via ApiConnectRecord (nasty) */
22161   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
22162   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
22163 
22164   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
22165   jamEntry();
22166 
22167   /*
22168    * Restore ApiConnectRecord state
22169    */
22170   regApiPtr->currSavePointId = currSavePointId;
22171   regApiPtr->immediateTriggerId = RNIL;
22172   regApiPtr->m_executing_trigger_ops++;
22173 }
22174 
deleteFromIndexTable(Signal * signal,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr,TcIndexData * indexData)22175 void Dbtc::deleteFromIndexTable(Signal* signal,
22176                                 TcFiredTriggerData* firedTriggerData,
22177                                 ApiConnectRecordPtr const* transPtr,
22178                                 TcConnectRecordPtr* opPtr,
22179                                 TcIndexData* indexData)
22180 {
22181   ApiConnectRecord* regApiPtr = transPtr->p;
22182   TcConnectRecord* opRecord = opPtr->p;
22183   TcKeyReq * const tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
22184   Uint32 tcKeyRequestInfo = 0;
22185   TableRecordPtr indexTabPtr;
22186 
22187   indexTabPtr.i = indexData->indexId;
22188   ptrCheckGuard(indexTabPtr, ctabrecFilesize, tableRecord);
22189   tcKeyReq->apiConnectPtr = transPtr->i;
22190   tcKeyReq->senderData = opPtr->i;
22191 
22192   // Calculate key length and renumber attribute id:s
22193   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
22194   LocalAttributeBuffer beforeValues(pool, firedTriggerData->beforeValues);
22195 
22196   Uint32 keyIVal= RNIL;
22197   Uint32 attrId= 0;
22198   bool hasNull= false;
22199 
22200   if (beforeValues.getSize() == 0)
22201   {
22202     jam();
22203     ndbrequire(tc_testbit(regApiPtr->m_flags,
22204                           ApiConnectRecord::TF_DEFERRED_CONSTRAINTS));
22205     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
22206     /* Already executing triggers */
22207     ndbassert(regApiPtr->m_inExecuteTriggers);
22208     return;
22209   }
22210 
22211   /* Build Delete KeyInfo section from beforevalues */
22212   if (unlikely((! appendAttrDataToSection(keyIVal,
22213                                           beforeValues,
22214                                           false, // No AttributeHeaders
22215                                           attrId,
22216                                           hasNull)) ||
22217                ERROR_INSERTED(8086)))
22218   {
22219     jam();
22220     releaseSection(keyIVal);
22221     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
22222     return;
22223   }
22224 
22225   /* If there's Nulls in the values that become the index table's
22226    * PK then we skip this delete
22227    */
22228   if (hasNull)
22229   {
22230     jam();
22231     releaseSection(keyIVal);
22232     trigger_op_finished(signal, *transPtr, RNIL, opRecord, 0);
22233     /* Already executing triggers */
22234     ndbassert(regApiPtr->m_inExecuteTriggers);
22235     return;
22236   }
22237 
22238   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
22239   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
22240   tcKeyReq->attrLen = 0;
22241   tcKeyReq->tableId = indexData->indexId;
22242   TcKeyReq::setOperationType(tcKeyRequestInfo, ZDELETE);
22243   tcKeyReq->tableSchemaVersion = indexTabPtr.p->currentSchemaVersion;
22244   tcKeyReq->transId1 = regApiPtr->transid[0];
22245   tcKeyReq->transId2 = regApiPtr->transid[1];
22246   tcKeyReq->requestInfo = tcKeyRequestInfo;
22247 
22248   /* Attach KeyInfo section to signal */
22249   ndbrequire(signal->header.m_noOfSections == 0);
22250   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
22251   signal->header.m_noOfSections= 1;
22252 
22253   /**
22254    * Fix savepoint id -
22255    *   fix so that delete has same savepoint id as triggering operation
22256    */
22257   const Uint32 currSavePointId = regApiPtr->currSavePointId;
22258   regApiPtr->currSavePointId = opRecord->savePointId;
22259   regApiPtr->m_special_op_flags = TcConnectRecord::SOF_TRIGGER;
22260   /* Pass trigger Id via ApiConnectRecord (nasty) */
22261   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
22262   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
22263   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
22264   jamEntry();
22265 
22266   /*
22267    * Restore ApiConnectRecord state
22268    */
22269   regApiPtr->currSavePointId = currSavePointId;
22270   regApiPtr->immediateTriggerId = RNIL;
22271   regApiPtr->m_executing_trigger_ops++;
22272 }
22273 
22274 Uint32
getErrorCode(Uint32 schemaVersion) const22275 Dbtc::TableRecord::getErrorCode(Uint32 schemaVersion) const {
22276   if(!get_enabled())
22277     return ZNO_SUCH_TABLE;
22278   if(get_dropping())
22279     return ZDROP_TABLE_IN_PROGRESS;
22280   if(table_version_major(schemaVersion) != table_version_major(currentSchemaVersion))
22281     return ZWRONG_SCHEMA_VERSION_ERROR;
22282   ErrorReporter::handleAssert("Dbtc::TableRecord::getErrorCode",
22283 			      __FILE__, __LINE__);
22284   return 0;
22285 }
22286 
executeReorgTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr)22287 void Dbtc::executeReorgTrigger(Signal* signal,
22288                                TcDefinedTriggerData* definedTriggerData,
22289                                TcFiredTriggerData* firedTriggerData,
22290                                ApiConnectRecordPtr const* transPtr,
22291                                TcConnectRecordPtr* opPtr)
22292 {
22293 
22294   ApiConnectRecord* regApiPtr = transPtr->p;
22295   TcConnectRecord* opRecord = opPtr->p;
22296   TcKeyReq * tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
22297 
22298   tcKeyReq->apiConnectPtr = transPtr->i;
22299   tcKeyReq->senderData = opPtr->i;
22300 
22301   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
22302   LocalAttributeBuffer keyValues(pool, firedTriggerData->keyValues);
22303   LocalAttributeBuffer attrValues(pool, firedTriggerData->afterValues);
22304 
22305   Uint32 optype;
22306   bool sendAttrInfo= true;
22307 
22308   switch (firedTriggerData->triggerEvent) {
22309   case TriggerEvent::TE_INSERT:
22310     optype = ZINSERT;
22311     break;
22312   case TriggerEvent::TE_UPDATE:
22313     /**
22314      * Only update should be write, as COPY is done as update
22315      *   a (maybe) better solution would be to have a different
22316      *   trigger event for COPY
22317      */
22318     optype = ZWRITE;
22319     break;
22320   case TriggerEvent::TE_DELETE:
22321     optype = ZDELETE;
22322     sendAttrInfo= false;
22323     break;
22324   default:
22325     ndbabort();
22326   }
22327 
22328   Ptr<TableRecord> tablePtr;
22329   tablePtr.i = definedTriggerData->tableId;
22330   ptrCheckGuard(tablePtr, ctabrecFilesize, tableRecord);
22331   Uint32 tableVersion = tablePtr.p->currentSchemaVersion;
22332 
22333   Uint32 tcKeyRequestInfo = 0;
22334   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
22335   TcKeyReq::setOperationType(tcKeyRequestInfo, optype);
22336   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
22337   tcKeyReq->attrLen = 0;
22338   tcKeyReq->tableId = tablePtr.i;
22339   tcKeyReq->requestInfo = tcKeyRequestInfo;
22340   tcKeyReq->tableSchemaVersion = tableVersion;
22341   tcKeyReq->transId1 = regApiPtr->transid[0];
22342   tcKeyReq->transId2 = regApiPtr->transid[1];
22343 
22344   Uint32 keyIVal= RNIL;
22345   Uint32 attrIVal= RNIL;
22346   Uint32 attrId= 0;
22347   bool hasNull= false;
22348 
22349   /* Prepare KeyInfo section */
22350   if (unlikely(!appendAttrDataToSection(keyIVal,
22351                                         keyValues,
22352                                         false, // No AttributeHeaders
22353                                         attrId,
22354                                         hasNull)))
22355   {
22356     releaseSection(keyIVal);
22357     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
22358     return;
22359   }
22360 
22361   ndbrequire(!hasNull);
22362 
22363   if (sendAttrInfo)
22364   {
22365     /* Prepare AttrInfo section from Key values and
22366      * After values
22367      */
22368     LocalAttributeBuffer::Iterator attrIter;
22369     LocalAttributeBuffer* buffers[2];
22370     buffers[0]= &keyValues;
22371     buffers[1]= &attrValues;
22372     const Uint32 segSize= keyValues.getSegmentSize(); // 11
22373     for (int buf=0; buf < 2; buf++)
22374     {
22375       Uint32 dataSize= buffers[buf]->getSize();
22376       bool moreData= buffers[buf]->first(attrIter);
22377 
22378       while(dataSize)
22379       {
22380         ndbrequire(moreData);
22381         Uint32 contigLeft= segSize - attrIter.ind;
22382         Uint32 contigValid= MIN(dataSize, contigLeft);
22383 
22384         if (unlikely(!appendToSection(attrIVal,
22385                                       attrIter.data,
22386                                       contigValid)))
22387         {
22388           releaseSection(keyIVal);
22389           releaseSection(attrIVal);
22390           abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
22391           return;
22392         }
22393         moreData= buffers[buf]->next(attrIter, contigValid);
22394         dataSize-= contigValid;
22395       }
22396       ndbassert(!moreData);
22397     }
22398   }
22399 
22400   /* Attach Key and optional AttrInfo sections to signal */
22401   ndbrequire(signal->header.m_noOfSections == 0);
22402   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
22403   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
22404   signal->header.m_noOfSections= sendAttrInfo? 2 : 1;
22405 
22406   /**
22407    * Fix savepoint id -
22408    *   fix so that the op has same savepoint id as triggering operation
22409    */
22410   const Uint32 currSavePointId = regApiPtr->currSavePointId;
22411   regApiPtr->currSavePointId = opRecord->savePointId;
22412   regApiPtr->m_special_op_flags =
22413     TcConnectRecord::SOF_REORG_TRIGGER |
22414     TcConnectRecord::SOF_TRIGGER;
22415   /**
22416    * The trigger is fired on this fragment id, ensure that the trigger
22417    * isn't executed on the same fragment id if the hash maps have been
22418    * swapped after starting the operation that sent FIRE_TRIG_ORD but
22419    * before we come here.
22420    */
22421   regApiPtr->firedFragId = firedTriggerData->fragId;
22422   /* Pass trigger Id via ApiConnectRecord (nasty) */
22423   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
22424 
22425   regApiPtr->immediateTriggerId= firedTriggerData->triggerId;
22426   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength);
22427   jamEntry();
22428 
22429   /*
22430    * Restore ApiConnectRecord state
22431    */
22432   regApiPtr->currSavePointId = currSavePointId;
22433   regApiPtr->immediateTriggerId = RNIL;
22434   regApiPtr->m_executing_trigger_ops++;
22435 }
22436 
22437 bool
executeFullyReplicatedTrigger(Signal * signal,TcDefinedTriggerData * definedTriggerData,TcFiredTriggerData * firedTriggerData,ApiConnectRecordPtr const * transPtr,TcConnectRecordPtr * opPtr)22438 Dbtc::executeFullyReplicatedTrigger(Signal* signal,
22439                                     TcDefinedTriggerData* definedTriggerData,
22440                                     TcFiredTriggerData* firedTriggerData,
22441                                     ApiConnectRecordPtr const* transPtr,
22442                                     TcConnectRecordPtr* opPtr)
22443 {
22444   /**
22445    * We use a special feature in DIGETNODESREQ to get the next copy fragment
22446    * given the current fragment. DIH keeps the copy fragments in an ordered
22447    * list to provide this feature for firing triggers on fully replicated
22448    * tables.
22449    *
22450    * There won't be any nodes returned in this special DIGETNODESREQ call,
22451    * we're only interested in getting the next fragment id.
22452    */
22453   jamLine((Uint16)firedTriggerData->fragId);
22454   DiGetNodesReq * diGetNodesReq =  (DiGetNodesReq *)signal->getDataPtrSend();
22455   diGetNodesReq->tableId = definedTriggerData->tableId;
22456   diGetNodesReq->hashValue = firedTriggerData->fragId;
22457   diGetNodesReq->distr_key_indicator = 0;
22458   diGetNodesReq->scan_indicator = 0;
22459   diGetNodesReq->get_next_fragid_indicator = 1;
22460   diGetNodesReq->anyNode = 0;
22461   diGetNodesReq->jamBufferPtr = jamBuffer();
22462   EXECUTE_DIRECT_MT(DBDIH, GSN_DIGETNODESREQ, signal,
22463                     DiGetNodesReq::SignalLength, 0);
22464   DiGetNodesConf * diGetNodesConf =  (DiGetNodesConf *)signal->getDataPtrSend();
22465   ndbrequire(diGetNodesConf->zero == 0);
22466   Uint32 fragId = diGetNodesConf->fragId;
22467   jamEntry();
22468   if (fragId == RNIL)
22469   {
22470     jam();
22471     /**
22472      * It is possible that the trigger is executed and done when arriving here.
22473      * This can happen in cases where there is only one node group, in this
22474      * case the fully replicated trigger will have nothing to do since there
22475      * are no more node groups to replicate to. We haven't incremented
22476      * triggerExecutionCount for fully replicated triggers, so need to check
22477      * if done here.
22478      */
22479     trigger_op_finished(signal, *transPtr, RNIL, opPtr->p, 0);
22480     /* Already executing triggers */
22481     ndbassert(transPtr->p->m_inExecuteTriggers);
22482 
22483     return true;
22484   }
22485   /* Save fragId for next time we request the next fragId. */
22486   firedTriggerData->fragId = fragId;
22487   jamLine((Uint16)fragId);
22488 
22489   ApiConnectRecord* regApiPtr = transPtr->p;
22490   TcConnectRecord* opRecord = opPtr->p;
22491   TcKeyReq * tcKeyReq =  (TcKeyReq *)signal->getDataPtrSend();
22492   tcKeyReq->apiConnectPtr = transPtr->i;
22493   tcKeyReq->senderData = opPtr->i;
22494 
22495   AttributeBuffer::DataBufferPool & pool = c_theAttributeBufferPool;
22496   LocalAttributeBuffer keyValues(pool, firedTriggerData->keyValues);
22497   LocalAttributeBuffer attrValues(pool, firedTriggerData->afterValues);
22498 
22499   Uint32 optype;
22500   bool sendAttrInfo = true;
22501 
22502   switch (firedTriggerData->triggerEvent) {
22503   case TriggerEvent::TE_INSERT:
22504     jam();
22505     optype = ZINSERT;
22506     break;
22507   case TriggerEvent::TE_UPDATE:
22508     jam();
22509     optype = ZUPDATE;
22510     break;
22511   case TriggerEvent::TE_DELETE:
22512     jam();
22513     optype = ZDELETE;
22514     sendAttrInfo = false;
22515     break;
22516   default:
22517     ndbabort();
22518   }
22519 
22520   Ptr<TableRecord> tablePtr;
22521   tablePtr.i = definedTriggerData->tableId;
22522   ptrCheckGuard(tablePtr, ctabrecFilesize, tableRecord);
22523   Uint32 tableVersion = tablePtr.p->currentSchemaVersion;
22524 
22525   Uint32 tcKeyRequestInfo = 0;
22526   TcKeyReq::setKeyLength(tcKeyRequestInfo, 0);
22527   TcKeyReq::setOperationType(tcKeyRequestInfo, optype);
22528   TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 0);
22529   TcKeyReq::setDistributionKeyFlag(tcKeyRequestInfo, 1U);
22530   tcKeyReq->attrLen = 0;
22531   tcKeyReq->tableId = tablePtr.i;
22532   tcKeyReq->requestInfo = tcKeyRequestInfo;
22533   tcKeyReq->tableSchemaVersion = tableVersion;
22534   tcKeyReq->transId1 = regApiPtr->transid[0];
22535   tcKeyReq->transId2 = regApiPtr->transid[1];
22536   tcKeyReq->scanInfo = fragId;
22537 
22538   Uint32 keyIVal = RNIL;
22539   Uint32 attrIVal = RNIL;
22540   Uint32 attrId = 0;
22541   bool hasNull = false;
22542 
22543   /* Prepare KeyInfo section */
22544   if (unlikely(!appendAttrDataToSection(keyIVal,
22545                                         keyValues,
22546                                         false, // No AttributeHeaders
22547                                         attrId,
22548                                         hasNull)))
22549   {
22550     jam();
22551     abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
22552     return true;
22553   }
22554 
22555   ndbrequire(!hasNull);
22556 
22557   if (sendAttrInfo)
22558   {
22559     /* Prepare AttrInfo section from Key values and
22560      * After values
22561      */
22562     jam();
22563     LocalAttributeBuffer::Iterator attrIter;
22564     LocalAttributeBuffer* buffers[2];
22565     buffers[0] = &keyValues;
22566     buffers[1] = &attrValues;
22567     const Uint32 segSize = keyValues.getSegmentSize(); // 11
22568     for (int buf = 0; buf < 2; buf++)
22569     {
22570       jam();
22571       Uint32 dataSize = buffers[buf]->getSize();
22572       bool moreData = buffers[buf]->first(attrIter);
22573 
22574       while(dataSize)
22575       {
22576         jam();
22577         ndbrequire(moreData);
22578         Uint32 contigLeft = segSize - attrIter.ind;
22579         Uint32 contigValid = MIN(dataSize, contigLeft);
22580 
22581         if (unlikely(!appendToSection(attrIVal,
22582                                       attrIter.data,
22583                                       contigValid)))
22584         {
22585           jam();
22586           releaseSection(keyIVal);
22587           releaseSection(attrIVal);
22588           abortTransFromTrigger(signal, *transPtr, ZGET_DATAREC_ERROR);
22589           return true;
22590         }
22591         moreData = buffers[buf]->next(attrIter, contigValid);
22592         dataSize -= contigValid;
22593       }
22594       ndbassert(!moreData);
22595     }
22596   }
22597 
22598   /* Attach Key and optional AttrInfo sections to signal */
22599   ndbrequire(signal->header.m_noOfSections == 0);
22600   signal->m_sectionPtrI[ TcKeyReq::KeyInfoSectionNum ] = keyIVal;
22601   signal->m_sectionPtrI[ TcKeyReq::AttrInfoSectionNum ] = attrIVal;
22602   signal->header.m_noOfSections = sendAttrInfo? 2 : 1;
22603 
22604   Uint32 saveOp = regApiPtr->tcConnect.getLast();
22605   Uint32 saveState = regApiPtr->apiConnectstate;
22606 
22607   /**
22608    * Fix savepoint id -
22609    *   fix so that the op has same savepoint id as triggering operation
22610    */
22611   const Uint32 currSavePointId = regApiPtr->currSavePointId;
22612   regApiPtr->currSavePointId = opRecord->savePointId;
22613   regApiPtr->m_special_op_flags =
22614     TcConnectRecord::SOF_FULLY_REPLICATED_TRIGGER |
22615     TcConnectRecord::SOF_TRIGGER;
22616   /* Pass trigger Id via ApiConnectRecord (nasty) */
22617   ndbrequire(regApiPtr->immediateTriggerId == RNIL);
22618 
22619   regApiPtr->immediateTriggerId = firedTriggerData->triggerId;
22620   EXECUTE_DIRECT(DBTC, GSN_TCKEYREQ, signal, TcKeyReq::StaticLength + 1);
22621   jamEntry();
22622 
22623   /*
22624    * Restore ApiConnectRecord state
22625    */
22626   regApiPtr->currSavePointId = currSavePointId;
22627   regApiPtr->immediateTriggerId = RNIL;
22628 
22629   Uint32 currState = regApiPtr->apiConnectstate;
22630 
22631   bool ok =
22632     ((saveState == CS_SEND_FIRE_TRIG_REQ ||
22633       saveState == CS_WAIT_FIRE_TRIG_REQ ||
22634       saveState == CS_STARTED ||
22635       saveState == CS_START_COMMITTING) &&
22636       currState == saveState);
22637 
22638   if (ok && regApiPtr->tcConnect.getLast() != saveOp)
22639   {
22640     jam();
22641     /**
22642      * We successfully added an op...continue iterating
22643      * ...and increment outstanding triggers
22644      */
22645     regApiPtr->apiConnectstate = (ConnectionState)saveState;
22646     opPtr->p->triggerExecutionCount++;
22647     regApiPtr->m_executing_trigger_ops++;
22648     return false;
22649   }
22650 
22651   ndbassert(terrorCode != 0);
22652   if (unlikely(terrorCode == 0))
22653   {
22654     jam();
22655     abortTransFromTrigger(signal, *transPtr, ZSTATE_ERROR);
22656     return true;
22657   }
22658 
22659   /**
22660    * Something went wrong...stop
22661    */
22662   return true;
22663 }
22664 
22665 void
execROUTE_ORD(Signal * signal)22666 Dbtc::execROUTE_ORD(Signal* signal)
22667 {
22668   jamEntry();
22669   if(!assembleFragments(signal)){
22670     jam();
22671     return;
22672   }
22673 
22674   SectionHandle handle(this, signal);
22675 
22676   RouteOrd* ord = (RouteOrd*)signal->getDataPtr();
22677   Uint32 dstRef = ord->dstRef;
22678   Uint32 srcRef = ord->srcRef;
22679   Uint32 gsn = ord->gsn;
22680 
22681   if (likely(getNodeInfo(refToNode(dstRef)).m_connected))
22682   {
22683     jam();
22684     Uint32 secCount = handle.m_cnt;
22685     ndbrequire(secCount >= 1 && secCount <= 3);
22686 
22687     jamLine(secCount);
22688 
22689     /**
22690      * Put section 0 in signal->theData
22691      */
22692     Uint32 sigLen = handle.m_ptr[0].sz;
22693     ndbrequire(sigLen <= 25);
22694     copy(signal->theData, handle.m_ptr[0]);
22695 
22696     SegmentedSectionPtr save = handle.m_ptr[0];
22697     for (Uint32 i = 0; i < secCount - 1; i++)
22698       handle.m_ptr[i] = handle.m_ptr[i+1];
22699     handle.m_cnt--;
22700 
22701     sendSignal(dstRef, gsn, signal, sigLen, JBB, &handle);
22702 
22703     handle.m_cnt = 1;
22704     handle.m_ptr[0] = save;
22705     releaseSections(handle);
22706     return ;
22707   }
22708 
22709   releaseSections(handle);
22710   warningEvent("Unable to route GSN: %d from %x to %x",
22711 	       gsn, srcRef, dstRef);
22712 }
22713 
22714 /**
22715  * Time track stats module
22716  * -----------------------
22717  * This module tracks response times of transactions, key operations,
22718  * scans, scans of fragments and errors of those operations.
22719  *
22720  * It tracks those times in a histogram with 32 ranges. This means that
22721  * we can get fairly detailed statistics about response times in the
22722  * system. We can also gather this information per API node or per
22723  * DB node and per TC thread.
22724  *
22725  * All data for this is currently gathered in the DBTC block. We could also
22726  * in the future make similar gathering for SPJ queries.
22727  *
22728  * The histogram ranges starts out at 50 microseconds and is incremented by
22729  * 50% for each subsequent range. We constantly increase the numbers in each
22730  * range, so in order to get the proper values for a time period one needs
22731  * to make two subsequent queries towards this table.
22732  *
22733  * The granularity of the timer for those signals depends on the granularity
22734  * of the scheduler.
22735  */
22736 void
time_track_init_histogram_limits(void)22737 Dbtc::time_track_init_histogram_limits(void)
22738 {
22739   HostRecordPtr hostPtr;
22740   /**
22741    * Calculate the boundary values, the first one is 50 microseconds,
22742    * after that we multiply by 1.5 consecutively.
22743    */
22744   Uint32 val = TIME_TRACK_INITIAL_RANGE_VALUE;
22745   for (Uint32 i = 0; i < TIME_TRACK_HISTOGRAM_RANGES; i++)
22746   {
22747     c_time_track_histogram_boundary[i] = val;
22748     val *= 3;
22749     val /= 2;
22750   }
22751   for (Uint32 node = 0; node < MAX_NODES; node++)
22752   {
22753     hostPtr.i = node;
22754     ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
22755     hostPtr.p->time_tracked = FALSE;
22756     for (Uint32 i = 0; i < TIME_TRACK_HISTOGRAM_RANGES; i++)
22757     {
22758       hostPtr.p->time_track_scan_histogram[i] = 0;
22759       hostPtr.p->time_track_scan_error_histogram[i] = 0;
22760       hostPtr.p->time_track_read_key_histogram[i] = 0;
22761       hostPtr.p->time_track_write_key_histogram[i] = 0;
22762       hostPtr.p->time_track_index_key_histogram[i] = 0;
22763       hostPtr.p->time_track_key_error_histogram[i] = 0;
22764       hostPtr.p->time_track_scan_frag_histogram[i] = 0;
22765       hostPtr.p->time_track_scan_frag_error_histogram[i] = 0;
22766       hostPtr.p->time_track_transaction_histogram[i] = 0;
22767     }
22768   }
22769 }
22770 
22771 Uint32
time_track_calculate_histogram_position(NDB_TICKS & start_ticks)22772 Dbtc::time_track_calculate_histogram_position(NDB_TICKS & start_ticks)
22773 {
22774   NDB_TICKS end_ticks = getHighResTimer();
22775   Uint32 micros_passed =
22776     (Uint32)NdbTick_Elapsed(start_ticks, end_ticks).microSec();
22777 
22778   NdbTick_Invalidate(&start_ticks);
22779 
22780   /* Perform a binary search for the correct histogram range */
22781   Uint32 pos;
22782   Uint32 upper_pos = TIME_TRACK_HISTOGRAM_RANGES - 1;
22783   Uint32 lower_pos = 0;
22784   /**
22785    * We use a small variant to the standard binary search where we
22786    * know that we will always end up with upper_pos == lower_pos
22787    * after 5 or 6 loops with 32 ranges. This saves us from comparing
22788    * lower_pos and upper_pos in each loop effectively halfing the
22789    * number of needed compares almost, we will do one extra loop
22790    * at times.
22791    */
22792   pos = (upper_pos + lower_pos) / 2;
22793   while (true)
22794   {
22795     if (micros_passed > c_time_track_histogram_boundary[pos])
22796     {
22797       /* Move to upper half in histogram ranges */
22798       lower_pos = pos + 1;
22799     }
22800     else
22801     {
22802       /* Move to lower half in histogram ranges */
22803       upper_pos = pos;
22804     }
22805     pos = (upper_pos + lower_pos) / 2;
22806     if (upper_pos == lower_pos)
22807       break;
22808   }
22809   return pos;
22810 }
22811 
22812 void
time_track_complete_scan(ScanRecord * const scanPtr,Uint32 apiNodeId)22813 Dbtc::time_track_complete_scan(ScanRecord * const scanPtr,
22814                                Uint32 apiNodeId)
22815 {
22816   HostRecordPtr hostPtr;
22817   /* Scans are recorded on the calling API node */
22818   Uint32 pos = time_track_calculate_histogram_position(scanPtr->m_start_ticks);
22819   hostPtr.i = apiNodeId;
22820   ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
22821   hostPtr.p->time_track_scan_histogram[pos]++;
22822   hostPtr.p->time_tracked = TRUE;
22823 }
22824 
22825 void
time_track_complete_scan_error(ScanRecord * const scanPtr,Uint32 apiNodeId)22826 Dbtc::time_track_complete_scan_error(ScanRecord * const scanPtr,
22827                                      Uint32 apiNodeId)
22828 {
22829   HostRecordPtr hostPtr;
22830   /* Scans are recorded on the calling API node */
22831   Uint32 pos = time_track_calculate_histogram_position(scanPtr->m_start_ticks);
22832   hostPtr.i = apiNodeId;
22833   ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
22834   hostPtr.p->time_track_scan_error_histogram[pos]++;
22835   hostPtr.p->time_tracked = TRUE;
22836 }
22837 
22838 void
time_track_complete_index_key_operation(TcConnectRecord * const regTcPtr,Uint32 apiNodeId,Uint32 dbNodeId)22839 Dbtc::time_track_complete_index_key_operation(
22840   TcConnectRecord * const regTcPtr,
22841   Uint32 apiNodeId,
22842   Uint32 dbNodeId)
22843 {
22844   HostRecordPtr apiHostPtr, dbHostPtr;
22845   /* Key ops are recorded on the calling API node and the primary DB node */
22846   if (!NdbTick_IsValid(regTcPtr->m_start_ticks))
22847   {
22848     /**
22849      * We can come here after receiving a "false" LQHKEYCONF as part
22850      * of trigger operations.
22851      */
22852     return;
22853   }
22854   Uint32 pos =
22855     time_track_calculate_histogram_position(regTcPtr->m_start_ticks);
22856 
22857   apiHostPtr.i = apiNodeId;
22858   ptrCheckGuard(apiHostPtr, chostFilesize, hostRecord);
22859   apiHostPtr.p->time_track_index_key_histogram[pos]++;
22860   apiHostPtr.p->time_tracked = TRUE;
22861 
22862   dbHostPtr.i = dbNodeId;
22863   ptrCheckGuard(dbHostPtr, chostFilesize, hostRecord);
22864   dbHostPtr.p->time_track_index_key_histogram[pos]++;
22865   dbHostPtr.p->time_tracked = TRUE;
22866 }
22867 
22868 void
time_track_complete_key_operation(struct TcConnectRecord * const regTcPtr,Uint32 apiNodeId,Uint32 dbNodeId)22869 Dbtc::time_track_complete_key_operation(
22870   struct TcConnectRecord * const regTcPtr,
22871   Uint32 apiNodeId,
22872   Uint32 dbNodeId)
22873 {
22874   HostRecordPtr apiHostPtr, dbHostPtr;
22875   /* Key ops are recorded on the calling API node and the primary DB node */
22876   if (!NdbTick_IsValid(regTcPtr->m_start_ticks))
22877   {
22878     /**
22879      * We can come here after receiving a "false" LQHKEYCONF as part
22880      * of trigger operations.
22881      */
22882     return;
22883   }
22884   Uint32 pos =
22885     time_track_calculate_histogram_position(regTcPtr->m_start_ticks);
22886   apiHostPtr.i = apiNodeId;
22887   ptrCheckGuard(apiHostPtr, chostFilesize, hostRecord);
22888   dbHostPtr.i = dbNodeId;
22889   ptrCheckGuard(dbHostPtr, chostFilesize, hostRecord);
22890 
22891   if (regTcPtr->operation == ZREAD ||
22892       regTcPtr->operation == ZUNLOCK)
22893   {
22894     apiHostPtr.p->time_track_read_key_histogram[pos]++;
22895     dbHostPtr.p->time_track_read_key_histogram[pos]++;
22896   }
22897   else
22898   {
22899     apiHostPtr.p->time_track_write_key_histogram[pos]++;
22900     dbHostPtr.p->time_track_write_key_histogram[pos]++;
22901   }
22902   apiHostPtr.p->time_tracked = TRUE;
22903   dbHostPtr.p->time_tracked = TRUE;
22904 }
22905 
22906 void
time_track_complete_key_operation_error(struct TcConnectRecord * const regTcPtr,Uint32 apiNodeId,Uint32 dbNodeId)22907 Dbtc::time_track_complete_key_operation_error(
22908   struct TcConnectRecord * const regTcPtr,
22909   Uint32 apiNodeId,
22910   Uint32 dbNodeId)
22911 {
22912   HostRecordPtr apiHostPtr, dbHostPtr;
22913   /* Scans are recorded on the calling API node and the primary DB node */
22914   Uint32 pos =
22915     time_track_calculate_histogram_position(regTcPtr->m_start_ticks);
22916   apiHostPtr.i = apiNodeId;
22917   ptrCheckGuard(apiHostPtr, chostFilesize, hostRecord);
22918   dbHostPtr.i = dbNodeId;
22919   ptrCheckGuard(dbHostPtr, chostFilesize, hostRecord);
22920 
22921   apiHostPtr.p->time_track_key_error_histogram[pos]++;
22922   dbHostPtr.p->time_track_key_error_histogram[pos]++;
22923   apiHostPtr.p->time_tracked = TRUE;
22924   dbHostPtr.p->time_tracked = TRUE;
22925 }
22926 
22927 void
time_track_complete_scan_frag(ScanFragRec * const scanFragPtr)22928 Dbtc::time_track_complete_scan_frag(
22929   ScanFragRec * const scanFragPtr)
22930 {
22931   HostRecordPtr hostPtr;
22932   /* Scan frag operations are recorded on the DB node */
22933   if (!NdbTick_IsValid(scanFragPtr->m_start_ticks))
22934   {
22935     /**
22936      * We can come here immediately after a conf message with a closed
22937      * message. So essentially we can get two SCAN_FRAGCONF after each
22938      * other without sending any SCAN_NEXTREQ in between.
22939      */
22940     jam();
22941     return;
22942   }
22943   Uint32 pos =
22944     time_track_calculate_histogram_position(scanFragPtr->m_start_ticks);
22945   Uint32 dbNodeId = refToNode(scanFragPtr->lqhBlockref);
22946   hostPtr.i = dbNodeId;
22947   ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
22948   hostPtr.p->time_track_scan_frag_histogram[pos]++;
22949   hostPtr.p->time_tracked = TRUE;
22950 }
22951 
22952 void
time_track_complete_scan_frag_error(ScanFragRec * const scanFragPtr)22953 Dbtc::time_track_complete_scan_frag_error(
22954   ScanFragRec * const scanFragPtr)
22955 {
22956   HostRecordPtr hostPtr;
22957   /* Scan frag operations are recorded on the DB node */
22958   if (!NdbTick_IsValid(scanFragPtr->m_start_ticks))
22959   {
22960     /**
22961      * We can come here after sending CLOSE flag on SCAN_FRAGREQ
22962      * while still waiting for SCAN_FRAGCONF, if SCAN_FRAGCONF
22963      * arrives before this returns and in addition we send
22964      * SCAN_FRAGREF we crash unless we check for this.
22965      */
22966     jam();
22967     return;
22968   }
22969   Uint32 pos =
22970     time_track_calculate_histogram_position(scanFragPtr->m_start_ticks);
22971   Uint32 dbNodeId = refToNode(scanFragPtr->lqhBlockref);
22972   hostPtr.i = dbNodeId;
22973   ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
22974   hostPtr.p->time_track_scan_frag_error_histogram[pos]++;
22975   hostPtr.p->time_tracked = TRUE;
22976 }
22977 
22978 void
time_track_complete_transaction(ApiConnectRecord * const regApiPtr)22979 Dbtc::time_track_complete_transaction(ApiConnectRecord* const regApiPtr)
22980 {
22981   HostRecordPtr hostPtr;
22982   /* Transactions are recorded on the API node */
22983   Uint32 pos =
22984     time_track_calculate_histogram_position(regApiPtr->m_start_ticks);
22985   Uint32 apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
22986   hostPtr.i = apiNodeId;
22987   ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
22988   hostPtr.p->time_track_transaction_histogram[pos]++;
22989   hostPtr.p->time_tracked = TRUE;
22990 }
22991 
22992 void
time_track_complete_transaction_error(ApiConnectRecord * const regApiPtr)22993 Dbtc::time_track_complete_transaction_error(
22994   ApiConnectRecord * const regApiPtr)
22995 {
22996   HostRecordPtr hostPtr;
22997   /* Transactions are recorded on the API node */
22998   if (!NdbTick_IsValid(regApiPtr->m_start_ticks))
22999   {
23000     /**
23001      * As part of handling API node failure we might abort transactions that
23002      * haven't actually started.
23003      */
23004     return;
23005   }
23006   Uint32 pos =
23007     time_track_calculate_histogram_position(regApiPtr->m_start_ticks);
23008   Uint32 apiNodeId = refToNode(regApiPtr->ndbapiBlockref);
23009   hostPtr.i = apiNodeId;
23010   ptrCheckGuard(hostPtr, chostFilesize, hostRecord);
23011   hostPtr.p->time_track_transaction_error_histogram[pos]++;
23012   hostPtr.p->time_tracked = TRUE;
23013 }
23014